Board index » delphi » reading one line of a tiff file

reading one line of a tiff file


2005-03-04 07:02:20 PM
delphi159
Hi,
I'm handling large tiff files. I don't want to transfer all the file in
memory. I just want to read single lines at once. I don't know how to
proced.
What I know from the file using AsTiffTagViewer :
ImageWidth (1 Short): 17200
ImageLength (1 Short): 15560
BitsPerSample (1 Short): 8
Compression (1 Short): Uncompressed
Photometric (1 Short): MinIsBlack
stripOffsets (15560 Long): 8, 17208, 34408, 51608, 68808, 86008,...
SamplesPerPixel (1 Short): 1
RowsPerstrip (1 Short): 1
stripByteCounts (15560 Long): 17200, 17200, 17200, 17200, 17200, 17200,...
XResolution (1 Rational): 72
YResolution (1 Rational): 72
PlanarConfig (1 Short): Contig
ResolutionUnit (1 Short): Inch
33550 (3 Double):
33922 (6 Double):
34264 (16 Double):
34735 (24 Short): 1, 1, 0, 5, 1024, 0, 1, 1, 1025, 0, 1, 2,...
All files should be similar to this one i.e. 8 bit uncompressed gray scale.
Any help is wellcome...
Eric
 
 

Re:reading one line of a tiff file

Eric,
Quote
I'm handling large tiff files. I don't want to transfer all the file in
memory. I just want to read single lines at once. I don't know how to
proced.
I recommend using LibTiff for this job. That'll save you a lot of hassle.
There is a pre-compiled LibTiff for Delphi here:
www.awaresystems.be/imaging/tiff/delphi.html
This links into your delphi project as if it were a set of pre-compiled
pascal units. It isn't, of course, it is C compiled into .obj files in such a
way that it integrates in a Delphi project just like e.g. the LibJpeg
version distributed with Delphi. That means no DLL's required, no
dependencies, no distribution and versioning nightmare.
If you are indeed expecting to deal only with 8bit per pixel single channel
grayscale images, you could do the following:
** open the TIFF file **
OpenedTiff:=TIFFOpen(Filename,'r');
if OpenedTiff=nil then handle your error here, file does probably not exist
** double-check **
This will be needed to make sure that your image is what you expect it to
be. Otherwise, your code might fall over later on, buffer overruns might
occur, etc. For example, to double-check that the BitsPerSample tag is
indeed set to 8, you could use the following code:
var
BitsPerSampleValue: Word;
begin
if TIFFGetField(OpenedTiff,TIFFTAG_BITSPERSAMPLE,@BitsPerSampleValue)<>1
then
handle your error here, this is probably a bogus file
if BitsPerSampleValue<>8 then
handle your error here, file is not what you expect
Other tags to check in your situation are Photometric, and SamplesPerPixel.
For a detailed view on what datatype of variable to feed TIFFGetField a
pointer to as a third parameter, see the LibTiff man page on TIFFGetField,
here:
www.remotesensing.org/libtiff/man/TIFFGetField.3t.html
** read dimensions **
Similar to above, you can read the size of your image this way
var
Width,Height: Cardinal;
begin
if TIFFGetField(OpenedTiff,TIFFTAG_IMAGEWIDTH,@Width)<>1 then
handle your error here, this is probably a bogus file
if TIFFGetField(OpenedTiff,TIFFTAG_IMAGELENGTH,@Height)<>1 then
handle your error here, this is probably a bogus file
** use TIFFReadScanline to read the image **
Using TIFFReadScanline, you can now retrieve a single scanline at a time.
for CurrentY:=0 to Height-1 do
begin
if TIFFReadScanline(OpenedTIFF,YourBuffer,CurrentY,0)<>1 then
handle your error, this is probably a decompression error, might
be file corruption
...
end;
** close the file **
TIFFClose(OpenedTiff);
Joris Van Damme
XXXX@XXXXX.COM
www.awaresystems.be/
Download your free TIFF tag viewer for windows here:
www.awaresystems.be/imaging/tiff/astifftagviewer.html
 

Re:reading one line of a tiff file

Quote
I recommend using LibTiff for this job. That'll save you a lot of hassle.
There is a pre-compiled LibTiff for Delphi here:

www.awaresystems.be/imaging/tiff/delphi.html

Many thanks. I am able to read my tiff files line by line.
But, now, I want to write tiff file with similar caracteristics excepted
with RGB colors. So, I started like this :
DestTiff:=TIFFOpen(DestFile,'w');
BitsPerSampleValue:=24;
TIFFSetField(DestTiff,TIFFTAG_BITSPERSAMPLE,@BitsPerSampleValue);
TIFFSetField(DestTiff,TIFFTAG_IMAGEWIDTH,@Largeur);
TIFFSetField(DestTiff,TIFFTAG_IMAGELENGTH,@Hauteur);
for J:=0 to Hauteur-1 do
begin
...
TIFFWriteScanline(DestTiff,@(LigneDest[0]),J,0);
end;
TIFFClose(DestTiff);
And, the file I produce is empty...
What I am missing?
Eric
 

Re:reading one line of a tiff file

"Eric SIBERT" <XXXX@XXXXX.COM>writes
Quote
Many thanks. I am able to read my tiff files line by line.
Happy to see it works out.
Quote
But, now, I want to write tiff file with similar caracteristics excepted
with RGB colors. So, I started like this :

DestTiff:=TIFFOpen(DestFile,'w');
BitsPerSampleValue:=24;
TIFFSetField(DestTiff,TIFFTAG_BITSPERSAMPLE,@BitsPerSampleValue);
TIFFSetField(DestTiff,TIFFTAG_IMAGEWIDTH,@Largeur);
TIFFSetField(DestTiff,TIFFTAG_IMAGELENGTH,@Hauteur);
for J:=0 to Hauteur-1 do
begin
...
TIFFWriteScanline(DestTiff,@(LigneDest[0]),J,0);
end;
TIFFClose(DestTiff);

And, the file I produce is empty...

What I am missing?
The TIFFSetField function does not take pointers as a third argument, you'll
need to directly pass variables or hard coded values.
In TIFF speak, 'sample' is what us mere mortals usually call 'channel'.
Thus, for writing 24bit RGB, you will need to set the BitsPerSampleValue to 8,
not 24. Also, you will need to set proper values for these tags in order to
tell LibTiff what to write and how to write it (and to come up with a proper
TIFF that a subsequent decoder can make sense of):
SamplesPerPixel (3 in this case)
PhotometricInterpretation (RGB in this case)
Compression (Anything you see fit, possibly None, Lzw, AdobeDeflate, or
Jpeg)
From the top of my head, that is about it I think, though it might also be
necessary to set PlanarConfiguration (for LibTiff's sake, it is not required
to comply with the TIFF spec since what you write complies with the default
PlanarConfiguration value), and the RowsPerstrip tag.
You might try something along these lines:
TIFFSetField(DestTiff,TIFFTAG_IMAGEWIDTH,Largeur);
TIFFSetField(DestTiff,TIFFTAG_IMAGELENGTH,Hauteur);
TIFFSetField(DestTiff,TIFFTAG_BITSPERSAMPLE,8);
TIFFSetField(DestTiff,TIFFTAG_SAMPLESPERPIXEL,3);
TIFFSetField(DestTiff,TIFFTAG_ROWSPERstrip,Hauteur);
TIFFSetField(DestTiff,TIFFTAG_COMPRESSION,COMPRESSION_NONE);
TIFFSetField(DestTiff,TIFFTAG_PHOTOMETRIC,PHOTOMETRIC_RGB);
TIFFSetField(DestTiff,TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
This does write a single strip uncompressed TIFF, which is not a very
friendly thing to do unless your images is small, but it is a good starting
point in any case. When this works for you, next decide upon better
compression, proper RowsPerstrip value, etc.
The LibTiff man pages seem to have fallen of the edge of the earth right
now (but don't worry, they'll be back soon I am sure), and I have got a
terrible memory, so I might be missing something. If there's any problem
left, please ask.
Joris Van Damme
XXXX@XXXXX.COM
www.awaresystems.be/
Download your free TIFF tag viewer for windows here:
www.awaresystems.be/imaging/tiff/astifftagviewer.html
 

Re:reading one line of a tiff file

Quote
TIFFWriteScanline(DestTiff,@(LigneDest[0]),J,0);
...
And, the file I produce is empty...
I should probably also have mentioned that you might want to add a line to
check the return value of TIFFWriteScanline. It'll return an error
indication if a) something goes terribly unexpectedly wrong, like IO stuff
might, or b) the tag setting earlier is not sufficient to inform LibTiff
what image data to expect and what to do with it, as is the case here. Thus,
you'll know that something is wrong without the errorprone need to check the
result file.
Joris Van Damme
XXXX@XXXXX.COM
www.awaresystems.be/
Download your free TIFF tag viewer for windows here:
www.awaresystems.be/imaging/tiff/astifftagviewer.html
 

Re:reading one line of a tiff file

That's ok.
Quote
This does write a single strip uncompressed TIFF, which is not a very
friendly thing to do unless your images is small, but it is a good
starting
Quote
point in any case. When this works for you, next decide upon better
compression, proper RowsPerstrip value, etc.
Yes. And I will wait for users complaining before acting ... :-)
So, last question. How do I transfere GeoTiff Tags from one tiff file to
the other?
I tried with the first tag :
SetLength(GeoDouble,3);
assert(TIFFGETField(Bleu,33550,@(GeoDouble[0]))=1,'Erreur ?la lecture
du Tag 33550');
assert(TIFFSetField(DestTiff,33550, GeoDouble[0])=1,'Problème réglage
avec le GeoTag 33550');
And I get an error on the last line. I am not very familar with Tiff and
moreover with specific tag to understand what should I do.
Eric