Discussion:
reading rgb values from 16 bits tif images
Martin Alegre
2012-01-04 10:54:57 UTC
Permalink
Dear all,

I'm trying to read the RGB values of 16 bits tif images. To do that, I'm
using the TIFFReadRGBAImage function to first load the data into memory and
store it into a buffer. Then, by calling the TIFFGet{R,G,B} functions, I
read each of the pixel values at the different channels. Although, the data
seemed to be loaded in memory correctly, when I compared the pixel values
obtained using LibTiff with those obtained in Matlab, the pixel values
don't match each other. Besides that, I've the impression that the pixel
values obtained using LibTiff span up to 2^8 and not to 2^16. Any
suggestions on what I'm doing wrong? Below, I'm adding the code snippet for
illustration purposes. Any comments/lights are really welcomed :-)
Besides that, does the LibTiff library supports now 32-bits images?

TIFF* tif = TIFFOpen("example16bits.tif", "r");
if (tif) {
uint32 imageWidth, imageLength;
uint16 bps;

TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &imageWidth);
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &imageLength);
TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bps);

uint32 npixels = imageWidth * imageLength;
uint32* raster = NULL;

raster = (uint32*) _TIFFmalloc(npixels * sizeof (uint32));

if (raster != NULL) {

if (! TIFFReadRGBAImage(tif, imageWidth, imageLength, raster,
0)) {
std::cerr << "Could not read image!" << std::endl;
return (EXIT_FAILURE);
}

d = 0;
for(e = imageLength - 1; e != -1; e--){
for(c = 0; c < imageWidth; c++){
pixel = e * imageWidth + c;

uint16 red =
static_cast<uint16>(TIFFGetR(raster[pixel]));
uint16 green =
static_cast<uint16>(TIFFGetG(raster[pixel]));
uint16 blue =
static_cast<uint16>(TIFFGetB(raster[pixel]));

std::cout << red << " " << green << " " << blue <<
std::endl;
}
}

_TIFFfree(raster);
}

TIFFClose(tif);
}

Best,

Tin
mikk
2012-01-04 12:37:01 UTC
Permalink
Hi,

When using TIFFReadRGBAImage - the raster pixels are 8-bit packed red,
green, blue, alpha samples. It converts non-8-bit images by scaling
sample values. Palette, grayscale, bilevel, CMYK and YCbCr images are
converted to RGBtransparently. Raster pixels are returned uncorrected by
any colorimetry information present in the directory.

So, you read a raster of pixels as 32-bit quads, 8-bits per component,
and you use it correctly. The pixel values are of course in 0 - 2^8
range. If you want to get unscaled 16-bit values you have to use
different function (not the RGBA interface). Try with
TIFFReadEncodedStrip/Tile.

Regards,
Michal Zaganczyk
_______________________________________________
Tiff mailing list: ***@lists.maptools.org
http://lists.maptools.org/mailman/listinfo/tiff
http://www.remotesensing.org/libtiff/
Olivier Paquet
2012-01-04 14:07:33 UTC
Permalink
Post by Martin Alegre
I'm trying to read the RGB values of 16 bits tif images. To do that, I'm
using the TIFFReadRGBAImage function to first load the data into memory and
store it into a buffer. Then, by calling the TIFFGet{R,G,B} functions, I
I'm fairly certain the TIFFReadRGBAImage function will always load
8-bit data, converting whatever is in the image to that format. To get
to the 16-bit values, try TIFFReadScanline. You'll then need to check
various tags to interpret the data correctly: number of samples per
pixel, bits per sample, etc.

Olivier
_______________________________________________
Tiff mailing list: ***@lists.maptools.org
http://lists.maptools.org/mailman/listinfo/tiff
http://www.remotesensing.org/libtiff/
Martin Alegre
2012-01-04 14:55:14 UTC
Permalink
Hi Olivier,

Thanks for your reply. I checked the libtiff tutorial (
http://www.libtiff.org/libtiff.html) and found something about
using *TIFFReadScanline* in the *Scanline-based Image I/O* section.
However, it's still not clear to me, how to adapt the code given in the
tutorial to read 16 bit RGB images.
More precisely, how to post-process the buffer (*buff*) after calling the
function* TIFFReadScanline(tif, buf, row)*?
Do you mind in illustratiing how to use the *TIFFReadScanline *for such
sort of images?

Best,

Tin
Post by Olivier Paquet
Post by Martin Alegre
I'm trying to read the RGB values of 16 bits tif images. To do that, I'm
using the TIFFReadRGBAImage function to first load the data into memory
and
Post by Martin Alegre
store it into a buffer. Then, by calling the TIFFGet{R,G,B} functions, I
I'm fairly certain the TIFFReadRGBAImage function will always load
8-bit data, converting whatever is in the image to that format. To get
to the 16-bit values, try TIFFReadScanline. You'll then need to check
various tags to interpret the data correctly: number of samples per
pixel, bits per sample, etc.
Olivier
Olivier Paquet
2012-01-04 15:08:02 UTC
Permalink
More precisely, how to post-process the buffer (buff) after calling the
function TIFFReadScanline(tif, buf, row)?
Do you mind in illustratiing how to use the TIFFReadScanline for such sort
of images?
The buffer is raw image data. If your data is 16-bit RGB then it
*might* look something like this:

for(c = 0; c < imageWidth; c++)
{
uint16 red = static_cast<uint16*>(buf)[c*nsamples+0];
uint16 green = static_cast<uint16*>(buf)[c*nsamples+1];
uint16 blue = static_cast<uint16*>(buf)[c*nsamples+2];
}

But this makes a lot of assumptions about how the TIFF is written and
will only work on a subset of images. Unless you know the files to
always have the same structure, you should definitely follow Bob's
advice and use a higher level library.

Olivier
_______________________________________________
Tiff mailing list: ***@lists.maptools.org
http://lists.maptools.org/mailman/listinfo/tiff
http://www.remotesensing.org/libtiff/
Bob Friesenhahn
2012-01-04 14:42:31 UTC
Permalink
Post by Martin Alegre
Besides that, does the LibTiff library supports now 32-bits images?
TIFF is a very flexible format and libtiff exposes most of its
flexibility to you. By using the lower-level interfaces, you can use
32-bits integer, or 16/24/32/64 bits float images. As long as you are
prepared to encode/decode the pixels, you could use completely
arbitrary integer depths.

Unless your requirements are very specific or you have substantial
time available to develop your software, you may be better off using a
higher-level library which takes care of the lower-level TIFF details
for you.

One possibility is my Magick++ C++ library, included in
GraphicsMagick. Links to other useful libraries (e.g. VIPS, VIGRA,
FreeImage, OpenImageIO) are included in the "Other Software Packages"
section of the GraphicsMagick links page:

http://www.graphicsmagick.org/links.html

Bob
--
Bob Friesenhahn
***@simple.dallas.tx.us, http://www.simplesystems.org/users/bfriesen/
GraphicsMagick Maintainer, http://www.GraphicsMagick.org/
_______________________________________________
Tiff mailing list: ***@lists.maptools.org
http://lists.maptools.org/mailman/listinfo/tiff
http://www.remotesensing.org/libtiff/
Martin Alegre
2012-01-04 15:02:06 UTC
Permalink
Hi Bob,

Thanks for your suggestions on the high-level libraries. At the beginning,
I was thniking to use Magick++ for my application, but it seemed to me that
it was going to be more faster to integrate the libtiff library into my
code, also due to time constraints. If you have any illustrations on how to
use libtiff for 16bits images, it will be great or if you also have some
good webpointers where I could get more information? I found a very
illustrative webpage on how to use libtiff (
http://bitmiracle.com/libtiff/help/samples.aspx), but it was mainly for C#,
and I'm currently working with C++.

Best,

Tin

On Wed, Jan 4, 2012 at 3:42 PM, Bob Friesenhahn <
Post by Martin Alegre
Besides that, does the LibTiff library supports now 32-bits images?
TIFF is a very flexible format and libtiff exposes most of its flexibility
to you. By using the lower-level interfaces, you can use 32-bits integer,
or 16/24/32/64 bits float images. As long as you are prepared to
encode/decode the pixels, you could use completely arbitrary integer depths.
Unless your requirements are very specific or you have substantial time
available to develop your software, you may be better off using a
higher-level library which takes care of the lower-level TIFF details for
you.
One possibility is my Magick++ C++ library, included in GraphicsMagick.
Links to other useful libraries (e.g. VIPS, VIGRA, FreeImage, OpenImageIO)
are included in the "Other Software Packages" section of the GraphicsMagick
http://www.graphicsmagick.org/**links.html<http://www.graphicsmagick.org/links.html>
Bob
--
Bob Friesenhahn
users/bfriesen/ <http://www.simplesystems.org/users/bfriesen/>
GraphicsMagick Maintainer, http://www.GraphicsMagick.org/
Bob Friesenhahn
2012-01-04 15:24:41 UTC
Permalink
Post by Martin Alegre
Hi Bob,
Thanks for your suggestions on the high-level libraries. At the beginning, I was thniking to use Magick++
for my application, but it seemed to me that it was going to be more faster to integrate the libtiff
library into my code, also due to time constraints. If you have any illustrations on how to use libtiff
for 16bits images, it will be great or if you also have some good webpointers where I could get more
information? I found a very illustrative webpage on how to use libtiff
(http://bitmiracle.com/libtiff/help/samples.aspx), but it was mainly for C#, and I'm currently working
with C++.
It makes a huge difference if you plan to accept arbitrary TIFF files
written by some other software or if you only plan to accept a very
limited set of TIFF formats. If the former, then you should expect to
do quite a lot of development (e.g. weeks, months).

You can use TIFFReadRGBAStrip() to access strip-oriented files or
TIFFReadTile() for tile-oriented files. These interfaces provide
"raw" decompressed + native-endian-swapped pixel sample data. The
swapping to native endian is only done if the sample bits are evenly
divisible by 8 (e.g. 16-bit "short" is swapped to native format).

Bob
--
Bob Friesenhahn
***@simple.dallas.tx.us, http://www.simplesystems.org/users/bfriesen/
GraphicsMagick Maintainer, http://www.GraphicsMagick.org/
_______________________________________________
Tiff mailing list: ***@lists.maptools.org
http://lists.maptools.org/mailman/listinfo/tiff
http://www.remotesensing.org/libtiff/
Martin Alegre
2012-01-05 09:12:56 UTC
Permalink
Hi Olivier & Bob,

Thanks a lot for your advices. So far, I'm dealing with very limited sort
of TIFF formats. Therefore, following the code snippet that Olivier
suggested, I'm allowed to correctly load the data into memory. However,
I'll have the suggestions of you Bob, if I need to consider more TIFF
formats. Below, I'm pasting the code, I'm using, just in case somebody in
the future might need it as well.

Best,

Tin

TIFF* tif = TIFFOpen("example.tif", "r");
if (tif) {

uint32 imagelength, imagewidth;
tdata_t buf;
uint32 row, col;
uint16 config, nsamples;

TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &imagelength);
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &imagewidth);
TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &config);
TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &nsamples);

buf = _TIFFmalloc(TIFFScanlineSize(tif));
if (config == PLANARCONFIG_CONTIG) {
for (row = 0; row < imagelength; row++){
TIFFReadScanline(tif, buf, row);

for(col=0; col < imagewidth; col++){

if (nsamples == 1){
uint16 gray =
static_cast<uint16*>(buf)[col*nsamples+0];
std::cout << gray << " ";
}
else if(nsamples == 3 ){
uint16 red =
static_cast<uint16*>(buf)[col*nsamples+0];
uint16 green =
static_cast<uint16*>(buf)[col*nsamples+1];
uint16 blue =
static_cast<uint16*>(buf)[col*nsamples+2];
std::cout << red << " " << green << " " << blue <<
std::endl;
}
}
std::cout << "\n";
}
} else if (config == PLANARCONFIG_SEPARATE) {

std::cerr << "Not yet supported!\n";
return (EXIT_FAILURE);

}
_TIFFfree(buf);
TIFFClose(tif);
}


On Wed, Jan 4, 2012 at 4:24 PM, Bob Friesenhahn <
Post by Martin Alegre
Hi Bob,
Post by Martin Alegre
Thanks for your suggestions on the high-level libraries. At the
beginning, I was thniking to use Magick++
for my application, but it seemed to me that it was going to be more
faster to integrate the libtiff
library into my code, also due to time constraints. If you have any
illustrations on how to use libtiff
for 16bits images, it will be great or if you also have some good
webpointers where I could get more
information? I found a very illustrative webpage on how to use libtiff
(http://bitmiracle.com/**libtiff/help/samples.aspx<http://bitmiracle.com/libtiff/help/samples.aspx>),
but it was mainly for C#, and I'm currently working
with C++.
It makes a huge difference if you plan to accept arbitrary TIFF files
written by some other software or if you only plan to accept a very limited
set of TIFF formats. If the former, then you should expect to do quite a
lot of development (e.g. weeks, months).
You can use TIFFReadRGBAStrip() to access strip-oriented files or
TIFFReadTile() for tile-oriented files. These interfaces provide "raw"
decompressed + native-endian-swapped pixel sample data. The swapping to
native endian is only done if the sample bits are evenly divisible by 8
(e.g. 16-bit "short" is swapped to native format).
Bob
--
Bob Friesenhahn
users/bfriesen/ <http://www.simplesystems.org/users/bfriesen/>
GraphicsMagick Maintainer, http://www.GraphicsMagick.org/
Loading...