Skip to content

Commit

Permalink
TRPX prints all the warnings and exits when there is an incompatible …
Browse files Browse the repository at this point in the history
…TIFF format
  • Loading branch information
senikm committed Jul 11, 2024
1 parent ca785cf commit c09ce4c
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 63 deletions.
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
..idea/
..vscode/
.vscode/
cmake-build-debug/
.build/
build/
html/
42 changes: 28 additions & 14 deletions include/Grey_tif.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ namespace jpa {
* - Compact code, optimized for high-speed performance and minimal memory foorprint.
* - Accommodating images with varying types and sizes.
* - Support for signed and unsigned integral values, and float and double values.
* - Flexible bit depths: 8, 16, 32, or (four double precision values) 64 bits.
* - Flexible bit depths: 8, 16, 32, or (for double precision values) 64 bits.
* - Accomodates raw TIFF data with runtinme pixel type identification.
* - Allows regularizing pixel types to a compile-time determined type.
* - The first (or only) image managed by a Grey_tif object is directly available as a readonly std::span
Expand Down Expand Up @@ -242,7 +242,7 @@ class Grey_tif_image : public std::span<T> {
POD_type_traits const& type() const noexcept {return d_image_type;}

private:
Grey_tif_image(POD_type_traits const& image_type, std::array<long,2> const& dim, std::span<T> const& data) noexcept :
Grey_tif_image(POD_type_traits const& image_type, std::array<long,2> const& dim, std::span<T> const& data) :
std::span<T>(data),
d_image_type(image_type),
d_dim(dim) {}
Expand Down Expand Up @@ -308,7 +308,7 @@ class Grey_tif_image<T> {
}

private:
Grey_tif_image(POD_type_traits const& image_type, std::array<long,2> const& dim, std::span<T> const& data) noexcept :
Grey_tif_image(POD_type_traits const& image_type, std::array<long,2> const& dim, std::span<T> const& data) :
d_data(reinterpret_cast<T*>(&data.begin()[0])),
d_image_type(image_type),
d_dim(dim) { }
Expand Down Expand Up @@ -361,7 +361,7 @@ class Grey_tif : public Grey_tif_image<T const> {
*
* @param is The input stream containing TIFF data.
*/
Grey_tif(std::istream& is) noexcept : Grey_tif() {
Grey_tif(std::istream& is) : Grey_tif() {
is.seekg(0, std::ios::end);
std::streampos fileSize = is.tellg();
is.seekg(0, std::ios::beg);
Expand All @@ -381,7 +381,7 @@ class Grey_tif : public Grey_tif_image<T const> {
* @param other The Grey_tif object to be swapped.
*/
template <typename Tother>
void swap(Grey_tif<Tother>&& other) noexcept {
void swap(Grey_tif<Tother>&& other) {
d_last_ifd_offset = other.d_last_ifd_offset = 4;
std::swap(d_tif, other.d_tif);
f_scan_images();
Expand All @@ -401,7 +401,7 @@ class Grey_tif : public Grey_tif_image<T const> {
* @param other The Grey_tif object to be swapped.
*/
template <typename Tother>
void swap(Grey_tif<Tother>& other) noexcept { swap(std::move(other)); }
void swap(Grey_tif<Tother>& other) { swap(std::move(other)); }

/**
* @brief Read/write accessor to images from a single or multi-image Grey_tif object.
Expand Down Expand Up @@ -528,8 +528,8 @@ class Grey_tif : public Grey_tif_image<T const> {
reinterpret_cast<std::uint32_t&>(d_tif[d_last_ifd_offset]) = index;
reinterpret_cast<std::uint16_t&>(d_tif[index]) = 7;
index += 2;
f_set_ifd(index, 0x0100, 3, static_cast<uint32_t>(dim[0]));
f_set_ifd(index, 0x0101, 3, static_cast<uint32_t>(dim[1]));
f_set_ifd(index, 0x0100, 3, static_cast<uint32_t>(dim[1]));
f_set_ifd(index, 0x0101, 3, static_cast<uint32_t>(dim[0]));
f_set_ifd(index, 0x0102, 3, 8 * (std::is_same_v<std::byte, T> ? sizeof(CT) : sizeof(T)));
f_set_ifd(index, 0x0103, 3, 1);
f_set_ifd(index, 0x0106, 3, 1);
Expand Down Expand Up @@ -708,7 +708,8 @@ class Grey_tif : public Grey_tif_image<T const> {
}

template <bool NATIVE = true>
void f_make_Image(std::uint32_t& index) noexcept {
void f_make_Image(std::uint32_t& index) {
bool compatible_tif = true;
std::array<long,2> dim = {0,0};
std::size_t bits_per_pixel = 0;
std::byte* cursor = d_tif.data() + index;
Expand Down Expand Up @@ -754,15 +755,23 @@ class Grey_tif : public Grey_tif_image<T const> {
else if (tag == 0x0102 ) {
if ((val == 8 || val == 16 || val == 32 || val == 64))
bits_per_pixel = val;
else
else {
std::cerr << "Warning: Grey_tif can only read greyscale tiff files with 8-, 16-, 32-, or 64-bit pixels" << std::endl;
compatible_tif = false;
}
}
else if (tag == 0x0103 && val != 1)
else if (tag == 0x0103 && val != 1) {
std::cerr << "Warning: Grey_tif cannot read compressed tiff files"<< std::endl;
else if (tag == 0x0106 && val > 1)
compatible_tif = false;
}
else if (tag == 0x0106 && val > 1) {
std::cerr << "Warning: Grey_tif cannot read colour tiff files"<< std::endl;
else if ((tag == 0x0107 || tag == 0x0108 || tag == 0x0109 || tag == 0x010A) && val != 1)
compatible_tif = false;
}
else if ((tag == 0x0107 || tag == 0x0108 || tag == 0x0109 || tag == 0x010A) && val != 1) {
std::cerr << "Warning: Grey_tif cannot read black & white tiff files"<< std::endl;
compatible_tif = false;
}
else if (tag == 0x0111) {
if (count == 1) strip_offsets[0] = val;
else {
Expand All @@ -772,8 +781,10 @@ class Grey_tif : public Grey_tif_image<T const> {
strip_offsets[i] = f_int32<NATIVE>(p);
}
}
else if (tag == 0x0115 && val != 1)
else if (tag == 0x0115 && val != 1) {
std::cerr << "Warning: Grey_tif cannot read RGB colour tiff files"<< std::endl;
compatible_tif = false;
}
else if (tag == 0x0116) rows_per_strip = val;
else if (tag == 0x0117) {
if (count == 1) strip_byte_counts[0] = val;
Expand All @@ -793,8 +804,11 @@ class Grey_tif : public Grey_tif_image<T const> {
if (strip_byte_counts[i] != strip_offsets[i + 1] - strip_offsets[i]) {
std::cerr << "Warning: Grey_tif cannot read tiff files with non-consecutive strips" << std::endl;
std::cerr << " most likely the tiff file is corrupted" << std::endl;
compatible_tif = false;
break;
}
if (!compatible_tif)
throw std::runtime_error("Incompatible TIFF file\n");
d_last_ifd_offset = static_cast<std::uint32_t>(cursor - d_tif.data());
index = f_int32<NATIVE>(cursor);
if constexpr (!NATIVE) {
Expand Down
8 changes: 4 additions & 4 deletions src/prolix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,25 +69,25 @@ int main(int argc, char const* argv[]) {
if (trpx_data.bits_per_val() <= 16 && trpx_data.is_signed()) {
for (int i = 0; i != trpx_data.number_of_frames(); ++i) {
tif_data.push_back<std::int16_t>(dim);
trpx_data.prolix(tif_data.image<std::int16_t>(i));
trpx_data.prolix(tif_data.image<std::int16_t>(i), i);
}
}
else if (trpx_data.bits_per_val() <= 16 && !trpx_data.is_signed()) {
for (int i = 0; i != trpx_data.number_of_frames(); ++i) {
tif_data.push_back<std::uint16_t>(dim);
trpx_data.prolix(tif_data.image<std::uint16_t>(i));
trpx_data.prolix(tif_data.image<std::uint16_t>(i), i);
}
}
else if (trpx_data.bits_per_val() <= 32 && trpx_data.is_signed()) {
for (int i = 0; i != trpx_data.number_of_frames(); ++i) {
tif_data.push_back<std::int32_t>(dim);
trpx_data.prolix(tif_data.image<std::int16_t>(i));
trpx_data.prolix(tif_data.image<std::int16_t>(i), i);
}
}
else if (trpx_data.bits_per_val() <= 32 && !trpx_data.is_signed()) {
for (int i = 0; i != trpx_data.number_of_frames(); ++i) {
tif_data.push_back<std::uint32_t>(dim);
trpx_data.prolix(tif_data.image<std::uint16_t>(i));
trpx_data.prolix(tif_data.image<std::uint16_t>(i), i);
}
}
else {
Expand Down
76 changes: 33 additions & 43 deletions src/terse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,64 +42,54 @@ int main(int argc, char const* argv[]) {

// Loop over all input file names
for (fs::path tif_filename : input.params()) {

// Only tif files will be compressed
if (fs::is_regular_file(tif_filename) && (tif_filename.extension() == ".tiff" ||
tif_filename.extension() == ".tif" ||
tif_filename.extension() == ".TIFF" ||
tif_filename.extension() == ".TIF")) {
try {
auto start_IO_time = std::chrono::high_resolution_clock::now();
std::ifstream tif_file(tif_filename, std::ios::binary);
if (!tif_file.is_open()) {
std::cerr << "Failed to open input file " << tif_filename << std::endl;
continue; // Skip to next file
}

// Start the IO timer and open the next file
auto start_IO_time = std::chrono::high_resolution_clock::now();
std::ifstream tif_file(tif_filename, std::ios::binary);
if (!tif_file.is_open())
std::cerr << "Failed to open input file " << tif_filename << std::endl;
else {

// A tiff file was opened. Read its data. It may contain one or more images in a stack.
jpa::Grey_tif<std::byte> tif_data(tif_file);
tif_file.close();

total_tiff_size += tif_data.raw_data_size();

// stop the IO timer, start the user timer
IO_time += std::chrono::high_resolution_clock::now() - start_IO_time;
auto start_user_time = std::chrono::high_resolution_clock::now();

Terse compressed;

for (int i = 0; i != tif_data.image_stack_size(); ++i)
if (tif_data.dim() == tif_data.image(i).dim())
Terse_pushback(compressed, tif_data.image(i));
else {
std::cerr << "Tiff file " << tif_filename << " contains a stack of images with varying sizes." << std::endl;
std::cerr << "Terse cannot process such tiff-stacks. First unstack this tiff file and compress the images separately." << std::endl;
return 0;
for (int i = 0; i != tif_data.image_stack_size(); ++i) {
if (tif_data.dim() != tif_data.image(i).dim()) {
throw std::runtime_error("TIFF file contains a stack of images with varying sizes.");
}
total_trpx_size += compressed.terse_size();

// Stop the user timer, start the IO timer
user_time += std::chrono::high_resolution_clock::now() - start_user_time;
start_IO_time = std::chrono::high_resolution_clock::now();

// Write the compressed data to the trpx file
auto trpx_filename = tif_filename;
std::ofstream trpx_file(trpx_filename.replace_extension(".trpx"), std::ios::binary);
if (!trpx_file.is_open())
std::cerr << "Failed to open trpx file " << trpx_filename << std::endl;
else {
compressed.write(trpx_file);
trpx_file.close();
fs::remove(tif_filename);
++compressed_files;
Terse_pushback(compressed, tif_data.image(i));
}
total_trpx_size += compressed.terse_size();

fs::path trpx_filename = tif_filename;
trpx_filename.replace_extension(".trpx");
std::ofstream trpx_file(trpx_filename, std::ios::binary);
if (!trpx_file.is_open()) {
throw std::runtime_error("Failed to open trpx file for output.");
}

compressed.write(trpx_file);
trpx_file.close();
std::cout << "Deleting original TIFF file: " << tif_filename << std::endl;
fs::remove(tif_filename);
++compressed_files;

auto end_user_time = std::chrono::high_resolution_clock::now();
user_time += end_user_time - start_user_time;
IO_time += start_user_time - start_IO_time;
} catch (const std::exception& e) {
std::cerr << "Error processing " << tif_filename << ": " << e.what() << std::endl;
}

// stop the IO timer
IO_time += std::chrono::high_resolution_clock::now() - start_IO_time;
}
}

// If required, provide verbose output
if (input.option("-verbose").found()) {
for (fs::path tif_filename : input.params())
Expand Down

0 comments on commit c09ce4c

Please sign in to comment.