2005.01.23 16:43 "[Tiff] LibTiffDelphi", by Michel Salvagniac

2005.01.24 01:17 "Re: [Tiff] LibTiffDelphi", by Sherlog


  TIFFSetField(imgtif, TIFFTAG_XRESOLUTION, 150.0);
  TIFFSetField(imgtif, TIFFTAG_YRESOLUTION, 150.0);


tiffinfo says:

  Resolution: 0, 0 pixels/inch

You have set the fields properly and flushed them properly, yet the values have not appeared in the file. I'd say there is something fishy going on in the interaction between the Delphi code and the C code - perhaps a runtime issue. Trace into the TIFFSetField() calls and watch the CPU/FPU windows for unusual things (you need a special build of LibTiffDelphi for tracing into the C code). You'll probably find some Delphi/C clashes regarding FPU use.

Have you posted this to Aware Systems? They are providing LibTiffDelphi and so they should know it better than anybody else; quite probably they can pinpoint the problem just from the description.

Apart from that, you should rework your pixel transfer code a little. The only reason that it 'sort of' works now is that you pass a pointer to the last scanline of the original bitmap to TIFFWriteRawStrip() and since bitmaps are what they are you are thus effectively passing a pointer to the whole bitmap data (since the last row on screen is the first row in memory, aka bottom-up bitmap).

However, scanlines in bitmap data are required to be aligned on DWORD boundaries (32 bits) while uncompressed 1-bit TIFF scanlines must be aligned on byte boundaries. This coincides if ImageWidth is close to multiples of 32 (25..32, 57..64, 89..96 and so on) but for other widths it does not work. Further, while bottom-up bitmaps are common there are also top-down bitmaps, so the fact that your code sort of works is mostly an accident.

The copy loop might look like this (put this *after* the code that initializes the TIFF field values):

|   with ImageBits.Picture.Bitmap do begin
|      assert(Monochrome = true, 'ImageBits.Picture.Bitmap.Monochrome = true');
|      for y := 0 to Height - 1 do
|         if 1 <> TIFFWriteScanLine(imgtif, Scanline[Height - y - 1], y, 0) then
|            raise Exception.Create('meow');  end;

This is for bottom-up bitmaps, of course. You have to search the Borland docs in order to find out whether Borland expose the bottom-up/top-down property on their Bitmap object or whether they guarantee that their bitmaps are always bottom-up or whether they simply let the chips fall where they may as usual. Note: in a raw Windows bitmap the height field is negative for a top-down bitmap, there is no separate 'bottom-up/top-down' flag.

An alternative to antisymmetric writing in the bottom-up case would be adjusting the 'Orientation' TIFF field to match the bitmap's bottom-up-ness but then there is no guarantee that simple-minded TIFF consuming programs will show your image correctly (the atrocity known as Wang/Kodak/Microsoft Imaging comes to mind).


Sherlog [Personenkennzahl 250866413515 / Stefan Otto / SO1801-RIPE]