Recent

Author Topic: [SOLVED] Tiff 16 bit grayscale pixel access?  (Read 15110 times)

DomingoGP

  • New Member
  • *
  • Posts: 15
Re: Tiff 16 bit grayscale pixel access?
« Reply #15 on: May 20, 2021, 10:34:10 pm »
Hi

You can read the elevation data using the libTiff library.

You can use TIFFReadScanline for reading the raw data.

Here is a quick and dirty sample loading the raw data without color conversions.
If the format of the tiff is tiled then the sample will not work.

The code reads a 'test.tif' image in the same folder.

I don't include the image because the size is > 500kb and the forum dont allow me to attach it.

I hope this code works for you.





engkin

  • Hero Member
  • *****
  • Posts: 2923
Re: Tiff 16 bit grayscale pixel access?
« Reply #16 on: May 21, 2021, 12:22:11 am »
The image is not black. To be precise, the max value of the sample image is 1566. This value is close to black: 0. On a linear scale it is about 2.4%

The sample file is tiled 15x15 tiles. It has 9 "pages" or images. FPReadTiff is able to read it. It does not recognize 6 tags from the first image:
Quote
TFPReaderTiff.ReadTiffHeader Endian Big=FALSE ReverseEndian=FALSE
ReadIFD Start=8
TFPReaderTiff.ReadDirectoryEntry Tag 256: ImageWidth=3601
TFPReaderTiff.ReadDirectoryEntry Tag 257: ImageHeight=3601
TFPReaderTiff.ReadDirectoryEntry Tag 258: BitsPerSample: 16
TFPReaderTiff.ReadDirectoryEntry Tag 259: Compression=5=LZW
TFPReaderTiff.ReadDirectoryEntry Tag 262: PhotometricInterpretation=1=bilevel grayscale 0 is black
TFPReaderTiff.ReadDirectoryEntry Tag 277: SamplesPerPixel=1
TFPReaderTiff.ReadDirectoryEntry Tag 284: PlanarConfiguration=chunky format
TFPReaderTiff.ReadDirectoryEntry Tag 317: Predictor="1"
TFPReaderTiff.ReadDirectoryEntry Tag 322: TileWidth=256
TFPReaderTiff.ReadDirectoryEntry Tag 323: TileLength=256
TFPReaderTiff.ReadDirectoryEntry Tag 324: TileOffsets=130
TFPReaderTiff.ReadDirectoryEntry Tag 325: TileByteCounts=142
TFPReaderTiff.ReadDirectoryEntry Tag=339 Type=3 Count=1 ValuesStart=2
TFPReaderTiff.ReadDirectoryEntry Tag=33550 Type=12 Count=3 ValuesStart=2182
TFPReaderTiff.ReadDirectoryEntry Tag=33922 Type=12 Count=6 ValuesStart=2206
TFPReaderTiff.ReadDirectoryEntry Tag=34735 Type=3 Count=32 ValuesStart=2254
TFPReaderTiff.ReadDirectoryEntry Tag=34736 Type=12 Count=2 ValuesStart=2318
TFPReaderTiff.ReadDirectoryEntry Tag=34737 Type=2 Count=8 ValuesStart=2334
TFPReaderTiff.ReadDirectoryEntry Tag=42112 Type=2 Count=139 ValuesStart=2042

Sample code to read the image, find the max value, and "brighten" the image before saving it to "out1.jpg"
Code: Pascal  [Select][+][-]
  1. uses
  2. ...
  3.   FPImage, FPReadTiff;
  4.  
  5. function FindMax(Img:TFPCustomImage):word;
  6. var
  7.   y, x: Integer;
  8.   v: Word;
  9. begin
  10.   Result := 0;
  11.   for y:=0 to Img.Height-1 do
  12.   begin
  13.     for x := 0 to Img.Width-1 do
  14.     begin
  15.       v := Img.Colors[x,y].Red;
  16.       if v>Result then
  17.         Result := v;
  18.     end;
  19.   end;
  20. end;
  21.  
  22. procedure BrightenImg(Img: TFPCustomImage; maxV: word);
  23. var
  24.   y, x: Integer;
  25.   v: Word;
  26. begin
  27.   for y:=0 to Img.Height-1 do
  28.   begin
  29.     for x := 0 to Img.Width-1 do
  30.     begin
  31.       v := Img.Colors[x,y].Red;
  32.       v := (($FFFF*v) div maxV) and $FFFF;
  33.       Img.Colors[x,y] := FPColor(v,v,v);
  34.     end;
  35.   end;
  36. end;
  37.  
  38. procedure TiffToJpg(fn:String='ASTGTMV003_N45E012_dem.tif');
  39. var
  40.   r:TFPReaderTiff;
  41.   Img:TFPMemoryImage;
  42.   maxV: Word;
  43. begin
  44.  
  45.   Img:=TFPMemoryImage.Create(0,0);
  46.   try
  47.     r := TFPReaderTiff.Create;
  48.     r.Debug:=True;
  49.     try
  50.       Img.loadfromfile (fn, r);
  51.       WriteLn('Img.Width: ', Img.Width);
  52.       WriteLn('Img.Height: ', Img.Height);
  53.  
  54.       maxV := FindMax(Img);
  55.       WriteLn('Max value: ', maxV);
  56.  
  57.       BrightenImg(Img, maxV);
  58.       Img.SaveToFile('out1.jpg');
  59.     finally
  60.       r.Free;
  61.     end;
  62.   finally
  63.     Img.Free;
  64.   end;
  65. end;
« Last Edit: May 21, 2021, 12:29:51 am by engkin »

Frate

  • New Member
  • *
  • Posts: 23
Re: Tiff 16 bit grayscale pixel access?
« Reply #17 on: May 21, 2021, 01:28:24 am »
IrfanView was the only program on my PC to display this file. However, a Lazarus program based on the freeimage.dll is able to display something too, although it is in some kind of false colors - but at least it is something. I don't want to spend too much time in this, but when you play with freeimage you can probably find settings which show the image correctly.

My demo program is in the attachment. If you are on Windows you can download the pre-compiled freeimage.dll from https://freeimage.sourceforge.io/download.html; copy it into the folder with the exe of the demo program.


Working good! However i couldnt figure out the correct reading settings, tried numerous combinations but no luck. I  looked also to the raw binary value to see if i could identify some patterns in the value but its taking too much time as you said. Thanks for your help.


The image is not black. To be precise, the max value of the sample image is 1566. This value is close to black: 0. On a linear scale it is about 2.4%

The sample file is tiled 15x15 tiles. It has 9 "pages" or images. FPReadTiff is able to read it. It does not recognize 6 tags from the first image:
Quote
TFPReaderTiff.ReadTiffHeader Endian Big=FALSE ReverseEndian=FALSE
ReadIFD Start=8
TFPReaderTiff.ReadDirectoryEntry Tag 256: ImageWidth=3601
TFPReaderTiff.ReadDirectoryEntry Tag 257: ImageHeight=3601
TFPReaderTiff.ReadDirectoryEntry Tag 258: BitsPerSample: 16
TFPReaderTiff.ReadDirectoryEntry Tag 259: Compression=5=LZW
TFPReaderTiff.ReadDirectoryEntry Tag 262: PhotometricInterpretation=1=bilevel grayscale 0 is black
TFPReaderTiff.ReadDirectoryEntry Tag 277: SamplesPerPixel=1
TFPReaderTiff.ReadDirectoryEntry Tag 284: PlanarConfiguration=chunky format
TFPReaderTiff.ReadDirectoryEntry Tag 317: Predictor="1"
TFPReaderTiff.ReadDirectoryEntry Tag 322: TileWidth=256
TFPReaderTiff.ReadDirectoryEntry Tag 323: TileLength=256
TFPReaderTiff.ReadDirectoryEntry Tag 324: TileOffsets=130
TFPReaderTiff.ReadDirectoryEntry Tag 325: TileByteCounts=142
TFPReaderTiff.ReadDirectoryEntry Tag=339 Type=3 Count=1 ValuesStart=2
TFPReaderTiff.ReadDirectoryEntry Tag=33550 Type=12 Count=3 ValuesStart=2182
TFPReaderTiff.ReadDirectoryEntry Tag=33922 Type=12 Count=6 ValuesStart=2206
TFPReaderTiff.ReadDirectoryEntry Tag=34735 Type=3 Count=32 ValuesStart=2254
TFPReaderTiff.ReadDirectoryEntry Tag=34736 Type=12 Count=2 ValuesStart=2318
TFPReaderTiff.ReadDirectoryEntry Tag=34737 Type=2 Count=8 ValuesStart=2334
TFPReaderTiff.ReadDirectoryEntry Tag=42112 Type=2 Count=139 ValuesStart=2042

Sample code to read the image, find the max value, and "brighten" the image before saving it to "out1.jpg"
Code: Pascal  [Select][+][-]
  1. uses
  2. ...
  3.   FPImage, FPReadTiff;
  4.  
  5. function FindMax(Img:TFPCustomImage):word;
  6. var
  7.   y, x: Integer;
  8.   v: Word;
  9. begin
  10.   Result := 0;
  11.   for y:=0 to Img.Height-1 do
  12.   begin
  13.     for x := 0 to Img.Width-1 do
  14.     begin
  15.       v := Img.Colors[x,y].Red;
  16.       if v>Result then
  17.         Result := v;
  18.     end;
  19.   end;
  20. end;
  21.  
  22. procedure BrightenImg(Img: TFPCustomImage; maxV: word);
  23. var
  24.   y, x: Integer;
  25.   v: Word;
  26. begin
  27.   for y:=0 to Img.Height-1 do
  28.   begin
  29.     for x := 0 to Img.Width-1 do
  30.     begin
  31.       v := Img.Colors[x,y].Red;
  32.       v := (($FFFF*v) div maxV) and $FFFF;
  33.       Img.Colors[x,y] := FPColor(v,v,v);
  34.     end;
  35.   end;
  36. end;
  37.  
  38. procedure TiffToJpg(fn:String='ASTGTMV003_N45E012_dem.tif');
  39. var
  40.   r:TFPReaderTiff;
  41.   Img:TFPMemoryImage;
  42.   maxV: Word;
  43. begin
  44.  
  45.   Img:=TFPMemoryImage.Create(0,0);
  46.   try
  47.     r := TFPReaderTiff.Create;
  48.     r.Debug:=True;
  49.     try
  50.       Img.loadfromfile (fn, r);
  51.       WriteLn('Img.Width: ', Img.Width);
  52.       WriteLn('Img.Height: ', Img.Height);
  53.  
  54.       maxV := FindMax(Img);
  55.       WriteLn('Max value: ', maxV);
  56.  
  57.       BrightenImg(Img, maxV);
  58.       Img.SaveToFile('out1.jpg');
  59.     finally
  60.       r.Free;
  61.     end;
  62.   finally
  63.     Img.Free;
  64.   end;
  65. end;

Engkin this is perfect! All fp also, best solution.
It's also quite fast, I'm able to make 1000000 pixel calls a second which is more than good enough for now.
About the unrecognized tags, i'm actually not interested in them. they basically give geo position info of the tile (i guess), which i dont need.

Hi

You can read the elevation data using the libTiff library.

You can use TIFFReadScanline for reading the raw data.

Here is a quick and dirty sample loading the raw data without color conversions.
If the format of the tiff is tiled then the sample will not work.

The code reads a 'test.tif' image in the same folder.

I don't include the image because the size is > 500kb and the forum dont allow me to attach it.

I hope this code works for you.

Thanks DomingoGP, I'll compare your solution to the one from Engkin. Lets see which one is faster.
About tiled format I think I need only the first image, but I'm checking.

Thank you all for helping out!

I'll keep you posted on the final choice

Frate

Frate

  • New Member
  • *
  • Posts: 23
[Solved] Tiff 16 bit grayscale pixel access?
« Reply #18 on: May 21, 2021, 11:53:09 am »
Allright, in the end Engkin's code works the best.
It allows me to get a pretty big improvement in data quality.
See attached image (its a terrain section), green is old, red new data.

Again thanks all

Great community! Best wishes for everyone

Frate
« Last Edit: May 21, 2021, 11:57:53 am by Frate »

 

TinyPortal © 2005-2018