Skip to content

Add 10-12-14bit (integer) TIFF decoding support#21701

Merged
alalek merged 10 commits intoopencv:4.xfrom
chacha21:tiff_10_12_14
Mar 11, 2022
Merged

Add 10-12-14bit (integer) TIFF decoding support#21701
alalek merged 10 commits intoopencv:4.xfrom
chacha21:tiff_10_12_14

Conversation

@chacha21
Copy link
Copy Markdown
Contributor

@chacha21 chacha21 commented Mar 8, 2022

Merge with extra: opencv/opencv_extra#962

Proposal for #21700

A (slow) unpacking step is inserted when the native bpp is not equal to the dst_bpp

Currently, I do not know if there can be several packing flavours in TIFF data.

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

  • I agree to contribute to the project under Apache 2 License.
  • To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
  • The PR is proposed to the proper branch
  • There is a reference to the original bug report and related work

chacha21 added 3 commits March 8, 2022 16:57
An (slow) unpacking step is inserted when the native bpp is not equal to the dst_bpp

Currently, I do not know if there can be several packing flavours in TIFF data.
@chacha21 chacha21 changed the title Add 12bit (integer) TIFF decoding support Add 10-12-14bit (integer) TIFF decoding support Mar 10, 2022
cv::Mat tmp;
double diff = 0;

if (!img16UC1.empty())
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.empty() is a test failure.

Copy link
Copy Markdown
Contributor Author

@chacha21 chacha21 Mar 10, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was unsure about what to do, because the real test with actual images will fail on the buildbot as long as the sample files #962 are not commited

if (!img16UC1.empty())
img8UC1.convertTo(tmp, img16UC1.type(), (1<<(16-8)));
diff = tmp.empty() ? 0. : cv::norm(tmp.reshape(1), img16UC1.reshape(1), cv::NORM_INF);
ASSERT_TRUE(img16UC1.empty() || (diff <= maxDiff));
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ASSERT_TRUE with complex checks provides almost useless messages about failure.
Use appropriate EXPECT_LE() macro instead.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

AutoBuffer<uchar> _buffer(buffer_size);
uchar* buffer = _buffer.data();
ushort* buffer16 = (ushort*)buffer;
const size_t src_buffer_bytes_per_row = ((ncn * tile_width0 * bpp + bitsPerByte - 1)/bitsPerByte);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use divUp() here

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

}
}

static void _unpack10To16(const uchar* src, const uchar* srcEnd, ushort* dst, ushort* dstEnd, size_t expectedDstElements)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expectedDstElements

We should have both limits here (dst and src) to ensure avoiding out of buffer access.

Copy link
Copy Markdown
Contributor Author

@chacha21 chacha21 Mar 10, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is already the case.
expectedDstElements is the width of the currently decoded tile, without any assumptions about src/dst bounds limits. Then, the fullPacketsCount computation ensures that no OOB will occur for the "fullPackets" loop, while the last loop with "remainingElements" performs explicit bounds checking

for(size_t i = 0 ; i<fullPacketsCount ; ++i)
{
for(size_t j = 0 ; j<srcElementsPerPacket ; ++j)
buf.u8[srcElementsPerPacket-1-j] = *src++;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need access limitation with buffer boundary check.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the min() in fullPacketsCountcomputation ensures that no OOB will occur

// What about 32, 64 bit?
}

TEST(Imgcodecs_Tiff, decode_12)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

decode_12
12

Below test cases for 10/14 bits too,

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Comment on lines +128 to +133
cv::Mat img10UC1 = imread(root + "readwrite/pattern_10uc1.tif", cv::IMREAD_UNCHANGED);
cv::Mat img10UC3 = imread(root + "readwrite/pattern_10uc3.tif", cv::IMREAD_UNCHANGED);
cv::Mat img10UC4 = imread(root + "readwrite/pattern_10uc4.tif", cv::IMREAD_UNCHANGED);
cv::Mat img12UC1 = imread(root + "readwrite/pattern_12uc1.tif", cv::IMREAD_UNCHANGED);
cv::Mat img12UC3 = imread(root + "readwrite/pattern_12uc3.tif", cv::IMREAD_UNCHANGED);
cv::Mat img12UC4 = imread(root + "readwrite/pattern_12uc4.tif", cv::IMREAD_UNCHANGED);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please interleave reading and checks (group code of dedicated cases).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@alalek alalek merged commit 6390b50 into opencv:4.x Mar 11, 2022
@opencv-pushbot opencv-pushbot mentioned this pull request Apr 23, 2022
@alalek alalek mentioned this pull request Oct 15, 2022
a-sajjad72 pushed a commit to a-sajjad72/opencv that referenced this pull request Mar 30, 2023
Add 10-12-14bit (integer) TIFF decoding support

* Add 12bit (integer) TIFF decoding support

An (slow) unpacking step is inserted when the native bpp is not equal to the dst_bpp

Currently, I do not know if there can be several packing flavours in TIFF data.

* added tests

* move sample files to opencv_extra

* added 10b and 14b unpacking

* fix compilation for non MSVC compilers by using more standard typedefs

* yet another typdef usage change to fix buildbot Mac compilation

* fixed unpacking of partial packets

* fixed warnings returned by buildbot

* modifications as suggested by reviewer
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TIFFDecoder does not support 12 bits (integer)

2 participants