| AWARE [SYSTEMS] | Imaging expertise for the Delphi developer | |||||||
![]() |
TIFF and LibTiff Mailing List Archive | |||||||
LibTiff Mailing List
TIFF and LibTiff Mailing List Archive Contact
The TIFF Mailing List Homepage |
Thread2006.08.30 22:01 "Re: TiffReadEncodedStrip", by Richard NoldeJoris wrote:
> Richard,
Richard Nolde wrote:
From what I have read in the current man pages and programs in the
tools directory, I assume that I can simple compute the start of each
row as an offset from the beginning of the buffer. For 1 bit per
sample data with one sample per pixel, something like ImageWidth / 8
bytes would be returned into the read buffer for each row in the
image and the offset would be (row * IMAGEWIDTH) / (8 /bps) *
samples per pixel for contiguous planes. This seems to imply that
the last byte of a scanline is padded out to fill that byte. Is this
correct?
The last statement is correct, but the formulae before that is not.
Scanlines are padded out with fillbits up to a byte boundary.
The correct expression to use goes something like this. A scanline
length is (imagewidth*bitsperpixel+7)/8. Think about it, if imagewidth
is 1 and bitsperpixel is 1, that'll round things up to 1 byte per row.
If imagewidth is 8 and bitsperpixel is 1... still 1 byte per row.
So if you need an offset for (column,row), the byteoffset would be
row*((imagewidth*bitsperpixel+7)/8)+(column*bitsperpixel/8)
and if bitsperpixel is not a multiple of 8, you'll need a bit offset
too...
((column*bitsperpixel)%8)
I would deduce from this that your row and column numbers are zero
referenced as in C arrays. It has been a while since I have had a chance
to write in C so I'm a little bit groggy on the bit shifts and masking as
it applies to libtiff.
My usage, for reasons related to the code that defines the zones to be
extracted, runs row from 1 to IMAGE_LENGTH and column from 1 to IMAGE_WIDTH
so I have to subtract one in each case. The snippet below is the code to
extract the data bytes from the input image and write them to an output
image. My code now gets the right bytes, but I am confused by your comment
on the bit offset. Assuming an image of 1658 pixels wide with 1 bit per
sample, 1 sample per pixel, there will be 207 "full bytes" and two extra
bits. Will these last bits be in the highorder bits or loworder bits, ie
128 and 64 or 2 and 1 and does the fill order matter when the image has
been extracted by ReadEncodedStrip? I had assumed a continuous bit stream
with the padding in the low order bits and planned on reading the trailing
bits followed by zeros if it is the end of the line. Of course, when
cropping from within the line, the remaining bits need to be masked off and
converted to fill bits too.
for (i = 0; i < crop->zones; i++)
{
first_row = crop->zonelist[i].y1;
last_row = crop->zonelist[i].y2;
first_col = crop->zonelist[i].x1;
last_col = crop->zonelist[i].x2;
crop_width = last_col - first_col + 1;
crop_length = last_row - first_row + 1;
crop_size = (crop_width * crop_length * spp) / (8 / bps);
full_bytes = spp * (crop_width * bps) / 8; /* number of COMPLETE
bytes per row in crop area */
padded_bytes = spp * (crop_width * bps + 7) / 8; /* total number of
bytes per row in crop area */
trailing_bits = (crop_width * bps) % 8;
fprintf (stderr, "First row: %d, Last row; %d First column: %d, Last
column: %d\n",
first_row, last_row, first_col, last_col);
fprintf (stderr, "\nZone: %d, Crop width: %u, Crop length: %u,
Compressed size in bytes: %u\n",
i + 1, crop_width, crop_length, crop_size);
fprintf (stderr, "Complete bytes in cropped row: %d, %d trailing
bits\n",
full_bytes, trailing_bits);
for (row = first_row; row <= last_row; row++)
{
/* Simple case first, all samples interleaved */
if (planar == PLANARCONFIG_CONTIG)
{
/* Offset1 is the byte offset at which the first selected pixel of
the region is found
Shift1 is the bit offset within the byte at offeset1 */
offset1 = spp * ((row - 1) * ((img_width * bps + 7) / 8) +
((first_col - 1) * bps / 8));
shift1 = spp * (((first_col - 1) * bps) % 8);
/* Offset2 is the byte offset at which the last selected pixel of the
region is found
Shift2 is the bit offset within the byte at offeset2 */
offset2 = spp * ((row - 1) * ((img_width * bps + 7) / 8) +
((last_col - 1) * bps / 8));
shift2 = spp * (((last_col - 1) * bps) % 8);
fprintf (stderr, "\nRow: %5d, Start byte: %6u, Shift: %d\n
End byte: %6u, Shift: %d\n",
row, offset1, shift1, offset2, shift2);
bytebuff1 = bytebuff2 = 0;
if (shift1 == 0) /* the region is byte and sample alligned */
{
/* fprintf (stderr, "Processing %d unshifted bytes plus final partial
byte\n", full_bytes); */
_TIFFmemcpy (crop_buff + dest_offset, read_buff + offset1,
full_bytes);
dest_offset += full_bytes;
/* pick up the final bits */
if (trailing_bits != 0)
{
for (k = 7; k >= 0; k--)
sprintf (&bitbuffer[7 - k], "%s", ((unsigned
char)read_buff[offset2] & (1 << k)) ? "1" : "0");
fprintf (stderr, "Final byte contains value %2x, %s\n",
(unsigned char)read_buff[offset2], bitbuffer);
bytebuff2 = read_buff[offset2] & ((unsigned char)255 << (8 -
shift2));
crop_buff[dest_offset] = bytebuff2;
dest_offset++;
}
}
else /* each destination byte will have to be built from two
source bytes*/
{
fprintf (stderr, "Processing %d bit shifted bytes\n", full_bytes);
for (j = 0; j <= full_bytes; j++)
{
bytebuff1 = read_buff[offset1 + j] & ((unsigned char)255 >>
(shift1));
bytebuff2 = read_buff[offset1 + j + 1] & ((unsigned char)255 << (8
- shift1));
crop_buff[dest_offset + j] = bytebuff1 | bytebuff2;
}
dest_offset += full_bytes;
/* process the final bits of the cropped row */
/* calculate how many bits are left from shift1 and how many are
needed from shift 2
pad the scanline as needed */
if (trailing_bits != 0)
{
for (k = 7; k >= 0; k--)
sprintf (&bitbuffer[7 - k], "%s", ((unsigned
char)read_buff[offset2] & (1 << k)) ? "1" : "0");
fprintf (stderr, "Final byte contains value %2x, %s\n",
(unsigned char)read_buff[offset2], bitbuffer);
if (shift2 > shift1)
{
bytebuff1 = read_buff[source_offset + full_bytes] & ((unsigned
char)255 << (8 - shift2));
bytebuff2 = bytebuff1 & ((unsigned char)255 << shift1);
crop_buff[dest_offset + j] = bytebuff2;
}
else
{
if (shift2 < shift1)
{
bytebuff2 = ((unsigned char)255 << (8 - shift2));
crop_buff[dest_offset + j] &= bytebuff2;
}
/* else
fprintf (stderr, "Shift2 equals bit borrowed from final
byte\n"); */
}
}
}
}
else
{
/* PLANARCONFIG_SEPARATE */
fprintf (stderr, "Planar config separate data not yet supported.\n");
return (-1);
}
}
Here is a log for the first two images in the input file. Since I am not
ready to write out the data, I can't tell if I have the bit shifting is
correct.
Image 1, width: 1658, Image length: 2591, Xres 300.00, Yres: 300.00
Scale: 1.000000 Requested resunit 2, Image resunit 2
Margins: Top: 0 Left: 0 Bottom: 0 Right: 0
Crop region within margins: Requested Width: 1658 Length: 2591
Crop region within margins: Adjusted Width: 1658 Length: 2591
Zone 1, width: 1658, length: 323, x1: 1 x2: 1658 y1: 1 y2: 323
Image width: 1658, Image length: 2591, Image size in pixels: 4295878
Samples per Pixel: 1, Bits per Sample: 1, Planar config: 1
Image is not byte swapped and fill order is MSB to LSB
Number of strips: 1, Strip size: 538928, RowsPerStrip 2591, Scanline size:
208
Crop buffer: 535534 pixels, 67507 bytes
First row: 1, Last row; 323 First column: 1, Last column: 1658
Zone: 1, Crop width: 1658, Crop length: 323, Compressed size in bytes:
66941
Complete bytes in cropped row: 207, 2 trailing bits
Row: 1, Start byte: 0, Shift: 0
End byte: 207, Shift: 1
Final byte contains value 0, 00000000
Row: 2, Start byte: 208, Shift: 0
End byte: 415, Shift: 1
Final byte contains value 0, 00000000
Row: 3, Start byte: 416, Shift: 0
End byte: 623, Shift: 1
Final byte contains value 0, 00000000
...
Image 2, width: 3449, Image length: 2604, Xres 300.00, Yres: 300.00
Scale: 1.000000 Requested resunit 2, Image resunit 2
Margins: Top: 0 Left: 0 Bottom: 0 Right: 0
Crop region within margins: Requested Width: 3449 Length: 2604
Crop region within margins: Adjusted Width: 3449 Length: 2604
Zone 1, width: 3449, length: 325, x1: 1 x2: 3449 y1: 1 y2: 325
Image width: 3449, Image length: 2604, Image size in pixels: 8981196
Samples per Pixel: 1, Bits per Sample: 1, Planar config: 1
Image is not byte swapped and fill order is MSB to LSB
Number of strips: 1, Strip size: 1124928, RowsPerStrip 2604, Scanline size:
432
Crop buffer: 2234952 pixels, 140400 bytes
First row: 1, Last row; 325 First column: 1, Last column: 3449
Zone: 1, Crop width: 3449, Crop length: 325, Compressed size in bytes:
140115
Complete bytes in cropped row: 431, 1 trailing bits
Row: 1, Start byte: 0, Shift: 0
End byte: 431, Shift: 0
Final byte contains value 0, 00000000
Row: 2, Start byte: 432, Shift: 0
End byte: 863, Shift: 0
Final byte contains value 0, 00000000
Richard Nolde
|
|||||||