ImageEn for Delphi and C++ Builder ImageEn for Delphi and C++ Builder

 

ImageEn Forum
Profile    Join    Active Topics    Forum FAQ    Search this forumSearch
Forum membership is Free!  Click Join to sign-up
Username:
Password:
Save Password
Forgot your Password?

 All Forums
 ImageEn Library for Delphi, C++ and .Net
 ImageEn and IEvolution Support Forum
 TIFF TileOffsets and TileByteCounts problem
 New Topic  Reply to Topic
Author Previous Topic Topic Next Topic  

timfa

USA
14 Posts

Posted - Jun 18 2025 :  18:49:43  Show Profile  Reply
Hello,

I'm having issues loading/displaying TIFF files that use tiles. I was using ImageEn v13.7.0, but updated to v14.0.1 to see if the issue has been resolved; it hasn’t. My problem can be seen using the demo TiffHandler application located at Demos\InputOutput\TiffHandler.
Following is some relevant info from the tiffdump utility:
.\LHAFTC03-1011_20240513.Tif:
Magic: 0x4949 <little-endian> Version: 0x2a
Directory 0: offset 8 (0x8) next 1311542 (0x140336)
SubFileType (254) LONG (4) 1<0>
ImageWidth (256) LONG (4) 1<1280>
ImageLength (257) LONG (4) 1<1024>
BitsPerSample (258) SHORT (3) 1<8>
Compression (259) LONG (4) 1<1>
Photometric (262) SHORT (3) 1<1>
SamplesPerPixel (277) LONG (4) 1<1>
XResolution (282) RATIONAL (5) 1<72>
YResolution (283) RATIONAL (5) 1<72>
PlanarConfig (284) SHORT (3) 1<1>
ResolutionUnit (296) SHORT (3) 1<1>
TileWidth (322) SHORT (3) 1<1280>
TileLength (323) SHORT (3) 1<1024>
TileOffsets (324) LONG (4) 1<698>
TileByteCounts (325) LONG (4) 1<702>
JPEGProcessingMode (512) SHORT (3) 1<14>
JPEGLosslessPredictors (517) SHORT (3) 1<1>
JPEGPointTransform (518) SHORT (3) 1<0>
JPEGDCTables (520) LONG (4) 1<426>
<snip of custom tags>

Directory 1: offset 1311542 (0x140336) next 0 (0)
SubFileType (254) LONG (4) 1<0>
ImageWidth (256) LONG (4) 1<1280>
ImageLength (257) LONG (4) 1<1024>
BitsPerSample (258) SHORT (3) 1<8>
Compression (259) LONG (4) 1<1>
Photometric (262) SHORT (3) 1<1>
SamplesPerPixel (277) LONG (4) 1<1>
XResolution (282) RATIONAL (5) 1<72>
YResolution (283) RATIONAL (5) 1<72>
PlanarConfig (284) SHORT (3) 1<1>
ResolutionUnit (296) SHORT (3) 1<1>
TileWidth (322) SHORT (3) 1<1280>
TileLength (323) SHORT (3) 1<1024>
TileOffsets (324) LONG (4) 1<1312232>
TileByteCounts (325) LONG (4) 1<1312236>
JPEGProcessingMode (512) SHORT (3) 1<14>
JPEGLosslessPredictors (517) SHORT (3) 1<1>
JPEGPointTransform (518) SHORT (3) 1<0>
JPEGDCTables (520) LONG (4) 1<426>
<snip of custom tags>

Note from the above that TileWidth is 1280 and TileLength is 1024 with Compression set to 1 (none). This being the case, the byte count for each tile should be 1310720 (1280 x 1024). You can see in the above data that TileByteCounts is not 1310720 which is fine because in both cases for the two IFDs the values are offsets from the beginning of the file.

I think a special case is being encounter because TileOffsets has a value/offset of 1 meaning there is only one tile per IFD. What I believe is happening is that because the data type for these tags is LONG (i.e., 4 bytes), and because there is only 1 tile per IFD, the ImageEn code is interpreting this to mean that the values are stored in the TIFF IFD Entry’s Value/Offset bytes (i.e., bytes 8 – 11) when in fact the file offset is stored. This is because TileOffsets and TileByteCounts are special and your code treats them that way in some places, but not all. If you look at your function TIETIFFIFDReader.ReadIFD, you have the following code…
<snip>
// Convert TAGS to LittleEndian (if needed)
    if not LittleEndian then
      for i := 0 to NumTags - 1 do
      begin
        if assigned(IFD) then
        begin
          // classic TIFF
          IFD[i].IdTag    := IESwapWord(IFD[i].IdTag);
          IFD[i].DataType := IESwapWord(IFD[i].DataType);
          IFD[i].DataNum  := IESwapDWordI( IFD[i].DataNum );
          if ( IFD[i].DataNum < 0 ) or
             ( IFD[i].DataNum > 4 ) or              // 11.4.0: Integer overflow catch
             ( IFD[i].DataNum * IETIFFCalcTagSize(IFD[i].DataType) > 4 ) then
            IFD[i].DataPos := IESwapDWord(IFD[i].DataPos);  // this is an offset
        End

<snip>
Not that this matters since the TIFF data in question is already Little Endian, but this code illustrates that had there been more than 1 tile in the IFD you would have treated the DataPos (or what I referred to as the Value/Offset as a file offset, the comment even says that). And in the case of the data I included, the values in question are offsets, but they aren’t being treated that way. Perhaps your code needs to use the CheckPairTag procedure, or something like it, to identify special tags that are always file offsets and handle them accordingly. I believe this is needed in ReadIFD and likely elsewhere. I think this issue only showed up for me because I have 1 tile and as such the offsets weren't handled as offsets.

In the case of my data above, your TiffHandler application shows TileOffsets as 3 and TileByteCounts as 702 for the first IFD and 7 and 1312236, respectively, for the second IFD. When I click the Show Page for the first IFD it displays an all-black image. The second IFD (page) shows the image but it clearly has a shift in the pixel alignment.

At this time I don’t have an image that I am able to upload to illustrate this issue.

I appreciate any help you can provide to resolve this issue.


Tim F

xequte

39047 Posts

Posted - Jun 19 2025 :  21:33:24  Show Profile  Reply
Thanks for the detail, Tim.

Is there are TIFF file that you can email me privately, so we can test the issue?

Nigel
Xequte Software
www.imageen.com
Go to Top of Page

xequte

39047 Posts

Posted - Jun 25 2025 :  17:43:13  Show Profile  Reply
Hi Tim

These files are not standard-compliant. They store multiple frames as tiles, whereas according to the TIFF standard, tiles should only be used to store a single large image divided into smaller sub-images (tiles).

The crash occurs because the image size stored in the TIFF matches the size of a single tile, whereas it should represent the combined size of all tiles. In the latest beta we have pushed a fix that overrides the column/row count so that only the last tile is loaded for these types of files.

From now on, applications can use TIFF_GetTile to select which tile to load, enabling full support for these unconventional TIFFs:

ImageEnView.IO.Params.TIFF_GetTile := 1; // get second tile (frame)
ImageEnView.IO.LoadFromFile('S1810_Frame6_BW.tif');




Nigel
Xequte Software
www.imageen.com
Go to Top of Page
  Previous Topic Topic Next Topic  
 New Topic  Reply to Topic
Jump To: