Sign in to follow this  
Amnesty2

Libtiff Reading BandW image into 2D array

Recommended Posts

ultimately i would like to have a 2D array loaded from a black and white tiff file such as

bool image[width][length];

 

where true is pixel present and false is blank, or vice versa i don't care.

Modify some bits and write it back out to a tiff

 

 

 

I'm using libtiff and C++, i attached a sample tiff

 

Basically, i followed one of the examples. Just modified it to print the buffer to a output file and it the result is bizzare

This is what the output looks like

 

   €   €T €   €T €   €   €   €   €   €   €   €   €   €   €   €   €   €   €   €   €   €   €   €   €   €

 

Looks like its still in some kind of compressed format.

 

I tried other examples on libtiff site, and some from stackoverflow and haven't got anything really working.

 

Any help would be very MUCH appreciated!!

 

 

 

#include <stdio.h> 
#include <tiffio.h>
#include <memory>
#include <fstream>
#include <iostream>
#pragma comment(lib,"libtiff.lib")
 
int main(int argc, char *argv[])
 
{   
TIFF *image; 
uint16 photo, bps, spp, fillorder;   
uint32 width;   
tsize_t stripSize; 
unsigned long imageOffset, result;   
int stripMax, stripCount;   
char *buffer, tempbyte;  
unsigned long bufferSize, count;  
// Open the TIFF image   
 
if((image = TIFFOpen("test.tiff", "r")) == NULL)
{     
std::cout << "Could not open incoming image\n" << std::endl;     
system("Pause");
return (42);   
}  
 
int imageWidth, imageLength, tileWidth, tileLength;
TIFFGetField(image, TIFFTAG_IMAGEWIDTH, &imageWidth);
TIFFGetField(image, TIFFTAG_IMAGELENGTH, &imageLength);
TIFFGetField(image, TIFFTAG_TILEWIDTH, &tileWidth);
TIFFGetField(image, TIFFTAG_TILELENGTH, &tileLength);
 
 
std::cout << "Image Width: " << imageWidth << std::endl;
std::cout << "Image Height: " << imageLength << std::endl;
std::cout << "Tile Width : " << tileWidth << std::endl;
std::cout << "Tile Height : " << tileLength << std::endl;
 
 
// Check that it is of a type that we support   
if((TIFFGetField(image, TIFFTAG_BITSPERSAMPLE, &bps) == 0) || (bps != 1))
{   
fprintf(stderr, "Either undefined or unsupported number of bits per sample\n");     
return(43);  
}  
if((TIFFGetField(image, TIFFTAG_SAMPLESPERPIXEL, &spp) == 0) || (spp != 1))
{     
fprintf(stderr, "Either undefined or unsupported number of samples per pixel\n");   
return(44);  
}  
// Read in the possibly multiple strips   
stripSize = TIFFStripSize (image);   
stripMax = TIFFNumberOfStrips (image);   
imageOffset = 0;      
bufferSize = TIFFNumberOfStrips (image) * stripSize;   
if((buffer = (char *) malloc(bufferSize)) == NULL)
{  
fprintf(stderr, "Could not allocate enough memory for the uncompressed image\n");     return(42);  
}      
for (stripCount = 0; stripCount < stripMax; stripCount++)
{     
if((result = TIFFReadEncodedStrip (image, stripCount,           buffer + imageOffset,           stripSize)) == -1)
{     
fprintf(stderr, "Read error on input strip number %d\n", stripCount);       
return(45);    
}  
imageOffset += result;   
}  
std::cout << "strip count: " << stripMax << std::endl;
 
// Deal with photometric interpretations   
if(TIFFGetField(image, TIFFTAG_PHOTOMETRIC, &photo) == 0)
{   
fprintf(stderr, "Image has an undefined photometric interpretation\n");    
return(46);  
}   
if(photo != PHOTOMETRIC_MINISWHITE)
{     
// Flip bits     
printf("Fixing the photometric interpretation\n");  
for(count = 0; count < bufferSize; count++)       
buffer[count] = ~buffer[count];  
}
 
// Deal with fillorder   
if(TIFFGetField(image, TIFFTAG_FILLORDER, &fillorder) == 0)
{     
fprintf(stderr, "Image has an undefined fillorder\n");    
// return(47);  
}     
if(fillorder != FILLORDER_MSB2LSB)
{     // We need to swap bits -- ABCDEFGH becomes HGFEDCBA     
printf("Fixing the fillorder\n");  
for(count = 0; count < bufferSize; count++)
{ 
tempbyte = 0;       
if(buffer[count] & 128) tempbyte += 1;     
if(buffer[count] & 64) tempbyte += 2;       
if(buffer[count] & 32) tempbyte += 4;   
if(buffer[count] & 16) tempbyte += 8;      
if(buffer[count] & 8) tempbyte += 16;      
if(buffer[count] & 4) tempbyte += 32;       
if(buffer[count] & 2) tempbyte += 64;     
if(buffer[count] & 1) tempbyte += 128;    
buffer[count] = tempbyte;     
}   
}        
// Do whatever it is we do with the buffer -- we dump it in hex  
if(TIFFGetField(image, TIFFTAG_IMAGEWIDTH, &width) == 0)
{    
fprintf(stderr, "Image does not define its width\n");     
return(48);  
} 
 
std::fstream file("output.txt",std::ios_base::out);
for(int i = 0; i < bufferSize; ++ i)
{
file << buffer[i];
}
file.close();
 
std::cout << bufferSize << std::endl;
system("Pause");
 
return 0;
}
 

Share this post


Link to post
Share on other sites

I think this is not compressed. It just stores the image as you asked every sample is 1 bit. So a byte contains 8 pixels. You wants every byte is a single pixel, but to that you have to convert it by yourself.

 

And the periodic letters are there because the lines are padded not to start them in the inside of a byte. (But it's possible it uses a different padding size. e.g. to start on an address dividable by 4.)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this