-
Bitunwise
I'm trying read a bitonal image and then test each bit to see if it is 0 or 255 (black or white). I am able to do grayscale and RGB images, but bitonal images seem to be posing a difficulty to me. I know I can only access the byte, so then I must advance through each bit to check what the value is. That's where I get lost. Any help as to how to check this?
-
I think you're trying to test a single bit in a byte, correct? if so you do it as follows:
if( thebyte & flag )
//do stuff
where flag could be one of the following:
#define BIT1 0x01
#define BIT2 0x02
#define BIT3 0x04
#define BIT4 0x08
#define BIT5 0x10
#define BIT6 0x20
#define BIT7 0x40
#define BIT8 0x80
-
There are several solutions. One solution is to loop through each bit and analyze it via AND operator. Another solution is to shift each bit and compare it to a value.
Kuphryn
-
I think I tried that, but wouldn't it be backwards because of the most sig. bit being at the beginning?
-
backwards? my #define names were arbitrary. you can reverse them if you like.
but yes, for your purposes the 0x80 bit comes first
-
here:
Code:
const unsigned char bit[] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
for(int i=0; i < numbytes; i++)
{
char c = bytes[i];
for(int j=0; j < 8; j++)
{
if(c & bit[j])
{
// do something cause the bit is true
}
}
}
-
Hmm... here is my code, maybe you can tell me what I'm doing wrong. (cleaned/moved for easier viewing) I have more in case this is not sufficient.
Note: pCurr is the image buffer (data holder)
Code:
unsigned char mask[] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
for (int i = 0; i < (imageWidth * imageLength) ; i++) {
for (int j = 0; j < 8; j++) {
if (samplesPerPixel == 1) {
if ((mask[j] & pCurr[i]) == 0)
value = 19;
else
value = ' ';
if ((i % imageWidth) == 1) ret = '\n';
else ret = 0;
cout << value << ret;
}
else {
for (int j = 0; j < samplesPerPixel; j++) {
value = (int) pCurr[i * samplesPerPixel + j];
cout << value << " ";
}
}
}
}
-
often, bitmaps are stored with "padding" at the end of each scanline. You may be padded to the nearest byte, sometimes the padding is to the nearest long. what kind of results are you seeing? if it's a slanted version of the original I would suggest that not accounting for the padding is the reason.
-
It's actually a TIFF file that I'm reading, but it might seem slanty... I'm outputting it with exclaimation marks and spaces just to see if it comes close, and I can't tell if it's slanty ... just seems to be wrong, mostly because the top part should be all white and it has quite a few !s and spaces intermixed. So I don't think it's with the padding. If you want to see my reading of the image... here it is:
Code:
for (stripCount = 0; stripCount < stripMax; stripCount++){
if((result = TIFFReadEncodedStrip (tif, stripCount,
buf + imageOffset,
stripSize)) == -1){
fprintf(stderr, "Read error on input strip number %d\n", stripCount);
exit(42);
}
imageOffset += result;
}
However, I am pretty sure this is correct. I have checked with a few online sources and they seems to concurr.
-
ok, my knowledge of tiff is limited. tiff does use a form of run-length encoding though. in the y direction as well if I'm not mistaken. you'll have to look at RLE and probably the tiff specs to get that one figured out. often there is some sort of code that represents the start of a "run" that you have to look for. I'm sure you'll find that the size you expect the image to take up is bigger than the actual file size.
-
The TIFF may read in the Y direction, but there is no Y direction when reading from memory. Both the RGB and Grayscale work with my reading and outputting. Bitonal works with reading, but I think it is the outputting that is causing the trouble.
-
what I'm saying is RLE is compression. you have to decompress. It basically tells you that you are repeating a color for n-number of times. This way it can store a whole line of color in just a couple bytes. When I said Y direction I was referring to RLE in that direction. I don't know for sure that is what they're doing. Regardless, if you are getting non-white colors in the first line as you said then I submit that you are reading RLE data as if it is unencoded. That's about all I can tell you.
-
WOTSIT.ORG has info on the TIFF format if you need it.
-
I tried writing a small test program with your code, and I'm getting EVERYTHING as true. Here is the code:
Code:
int bitonal() {
uint32 imageWidth, imageLength;
int stripMax, stripCount;
unsigned long imageOffset, result, bufferSize;
tsize_t stripSize;
char* fileName = "28.tif";
TIFF* tif = TIFFOpen(fileName, "r");
if (tif) {
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &imageWidth);
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &imageLength);
m_memoryWidth = (imageWidth + (1/2)) / 8;
m_memoryLength = imageLength;
// Read in the possibly multiple strips
stripSize = TIFFStripSize(tif);
stripMax = TIFFNumberOfStrips(tif);
imageOffset = 0;
bufferSize = m_memoryWidth * m_memoryLength;
m_bufferSize = bufferSize;
unsigned char* buf = new unsigned char[bufferSize];
const unsigned char bit[] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
for (stripCount = 0; stripCount < stripMax; stripCount++){
if((result = TIFFReadEncodedStrip (tif, stripCount,
buf + imageOffset,
stripSize)) == -1){
fprintf(stderr, "Read error on input strip number %d\n", stripCount);
exit(42);
}
imageOffset += result;
}
for(int i=0; i < (imageWidth * imageLength); i++)
{
char c = buf[i];
for(int j=0; j < 8; j++)
{
if(c & bit[j])
{
cout << "!";
}
else {
cout << "";
}
}
}
}
return 0;
}
And I have uploaded the image I am working with.
-
the only thing you're outputting is an exclamation. the false case is outputting an empty string.