2006.01.17 18:53 "Re: [Tiff] TiffReadEncodedStrip - problem in Delphi", by Joris Van Damme
Patryk Palasz wrote:
> Why are you handling the fill order in your own code? I believe
> > that libtiff already handles that for you. So you are likely
> > scrambling the data yourself. Also, what does ChangeLinesOrder()
> > do?
This is not the point. I was using TiffReverseBits instead of ChangeBitsOrder but in case of those two pictures this code is simply not used.
Nevertheless, Bob is right. You should in no case reverse bits - LibTiff is doing it for you, and so you repeating that work in your own code is in vain and in error, even if it doesn't influence the decoding of this particular file. So it is best to note.
ChangeLinesOrder function changes line order in bitmap from up-bottom to bottom-up (TiffReadRGBA* make it automaticall but TiffReadEncodedStrip not). I was trying with and without this function - no success :(.
Yes, this is correct. You do indeed need to reverse line order. A VCL TBitmap is an object encapsulation of a windows DIB, which is stored bottom-up, and TIFFReadEncodedStrip returns data top-down.
code snippet from your original post:
BitmapBuff := FBitmap.ScanLine[ FImgHeight - 1];
i := FStripsCnt - 1 downto 0 do for
read := TiffReadEncodedStrip( FTiffFile, i, Buff, -1);
if read <> -1 then
if FFillOrder <> FILLORDER_MSB2LSB then
Buff, read); ChangeBitsOrder(
Buff, BitmapBuff, read); ChangeLinesOrder(
Apart from the unwanted bitorder swapping thing, there are at least two other problem here.
- If the decoding of a particular strip fails, your BitmapBuff pointer is not incremented. Thus, the following strip gets read in a position that is too high. A better solution would involve filling the 'error area' with an 'error color', which may be white, and reading the next strip in the proper position.
- TIFFReadEncodedStrip aligns each line on a byte boundary, as is customary in TIFF. However, in a Windows DIB lines are aligned on 32bit boundaries. Your first image is 3451 single bit pixels wide, this is 432 bytes, which is a multiple of 4. So, in the first image, this is not a problem. The second image is 3501 single bit pixels wide, this is 438 bytes, which is not a multiple of 4. So, in the second image, ignoring this line alignment issue, gets you into trouble. I think this is the main reason for what you're seeing.
- To cure your problem, I recommend reading strips into a temporary buffer. Instead of the ChangeLinesOrder routine, copy lines one by one from this temporary buffer to your bitmap, taking into account that lines in the temporary buffer are byte aligned, while lines in the TBitmap are 32bit aligned. (This last thing you might not even want to actually calculate, you can use the TBitmap.Scanline property instead.) Reuse the same temporary buffer for all strips.
Joris Van Damme
Download your free TIFF tag viewer for windows here: