-
2005.05.18 16:12 "Re: [Tiff] Another libtiff+libjpeg problem", by Bob Friesenhahn
- 2005.05.18 16:54 "RE: [Tiff] Another libtiff+libjpeg problem", by Thom DeCarlo
-
2005.05.19 14:59 "Re: [Tiff] Another libtiff+libjpeg problem", by Frank Warmerdam
- 2005.05.19 23:00 "Re: [Tiff] Another libtiff+libjpeg problem", by Thom DeCarlo
- 2005.05.25 10:12 "Re[2]: [Tiff] Another libtiff+libjpeg problem", by Jean-Yves Le Ridant
2005.05.25 10:12 "Re[2]: [Tiff] Another libtiff+libjpeg problem", by Jean-Yves Le Ridant
Sorry about that. I believe the problem is that the CVS-head of libjpeg is broken. All my work was with the MK1-branch. Try checking that out.
As I said to Bob, I prefered restart my job for 8/12 bits from libtiff 3.7.2 so tif_jpeg 1.30, and the "very original ten year old v6b from IJG" ( mainly cause I could'nt.... 'think' in a jpeglib with BITS_IN_JSAMPLE defined as cinfo.data_precision ).
I attach two diff files from tif_jpeg.c, of some job I'have done. The first is a simple fix of some troubles in the EncodeRaw DecodeRaw path.
The second add some support for 12/16 bits support. It's what I use in my own stuff to have Dual (8/12/16) support ( nb: at this point, raw interface is not supported in 12/16 bits)
With the v6b, you get support for 8 or 12/16 depending the build of jpeglib. 16 bit up/down-sampling is a simple 4 bits shift, and that clearly ( in my mind ) reflect what it is at this point: a convenient way to do some tests with 'blind' programs.
Jean-Yves
PS: Do not hesitate if you have questions, but if not in mailing list, allways at this 2 mails jeanyves.leridant@wanadoo.fr and jean-yves.leridant@culture.gouv.fr
--- 372\tif_jpeg.c 2005-03-09 10:49:44.000000000 +0100
+++ mys\tif_jpeg2.c 2005-05-25 11:13:18.781250000 +0200
@@ -136,6 +136,7 @@
JSAMPARRAY ds_buffer[MAX_COMPONENTS];
int scancount; /* number of "scanlines" accumulated */
int samplesperclump;
+ JSAMPROW line_work_buf;
TIFFVGetMethod vgetparent; /* super-class method */
TIFFVSetMethod vsetparent; /* super-class method */
@@ -144,11 +145,11 @@
/* pseudo-tag fields */
void* jpegtables; /* JPEGTables tag value, or NULL */
uint32 jpegtables_length; /* number of bytes in same */
- int jpegquality; /* Compression quality level */
- int jpegcolormode; /* Auto RGB<=>YCbCr convert? */
- int jpegtablesmode; /* What to put in JPEGTables */
+ int jpegquality; /* Compression quality level */
+ int jpegcolormode; /* Auto RGB<=>YCbCr convert? */
+ int jpegtablesmode; /* What to put in JPEGTables */
- int ycbcrsampling_fetched;
+ int ycbcrsampling_fetched;
uint32 recvparams; /* encoded Class 2 session params */
char* subaddress; /* subaddress string */
uint32 recvtime; /* time spent receiving (secs) */
@@ -190,6 +191,16 @@
};
#define N(a) (sizeof (a) / sizeof (a[0]))
+tsize_t TIFFInterleavedRowSize( JPEGState *sp, int width )
+// for 8,12,16 bps, and h_sampling at least 2, no need of howmanies
+{
+
+ uint16 hv_sampling = sp->h_sampling * sp->v_sampling;
+ tsize_t bpl = (width + sp->h_sampling-1)/sp->h_sampling * (hv_sampling + 2);
+ bpl *= sp->tif->tif_dir.td_bitspersample;
+ return ((tsize_t) TIFFhowmany8(bpl));
+}
+
/*
* libjpeg interface layer.
*
@@ -296,10 +307,33 @@
static int
TIFFjpeg_write_scanlines(JPEGState* sp, JSAMPARRAY scanlines, int num_lines)
{
+ int bps=sp->tif->tif_dir.td_bitspersample;
+ assert(num_lines == 1);
+ if (bps==12){
+ int value_pairs = (sp->bytesperline+2)/3;
+ unsigned char *in_ptr = (unsigned char *) scanlines[0];
+ int iPair, result;
+
+ for( iPair = 0; iPair < value_pairs; iPair++, in_ptr += 3 ){
+ JSAMPLE *out_ptr = sp->line_work_buf + iPair * 2;
+ out_ptr[0]= ( (in_ptr[0]<<4) & 0xff0 ) | ( (in_ptr[1] >> 4) & 0xf );
+ out_ptr[1]= ( in_ptr[2]&0xff ) | ( (in_ptr[1]<<8) & 0xf00 ) ;
+ }
+ result= CALLJPEG(sp, -1, (int) jpeg_write_scanlines(&sp->cinfo.c, &sp->line_work_buf, (JDIMENSION) num_lines));
+ return result;
+ }
+ if ( bps == 16){
+ int count = sp->bytesperline/2;
+ uint16 *row = (uint16 *) scanlines[0];
+ while ( count-- ) { *row >>= 4 ; row++; }
+ }
return CALLJPEG(sp, -1, (int) jpeg_write_scanlines(&sp->cinfo.c,
scanlines, (JDIMENSION) num_lines));
}
+
+
+
static int
TIFFjpeg_write_raw_data(JPEGState* sp, JSAMPIMAGE data, int num_lines)
{
@@ -334,8 +368,36 @@
static int
TIFFjpeg_read_scanlines(JPEGState* sp, JSAMPARRAY scanlines, int max_lines)
{
- return CALLJPEG(sp, -1, (int) jpeg_read_scanlines(&sp->cinfo.d,
- scanlines, (JDIMENSION) max_lines));
+ int bps = sp->tif->tif_dir.td_bitspersample;
+ assert(max_lines==1);
+ if(bps != 12) {
+ int result= CALLJPEG(sp, -1, (int) jpeg_read_scanlines(&sp->cinfo.d, scanlines, (JDIMENSION) max_lines));
+ if (!result || bps==8)
+ return result;
+ { /* process a 16 bits line */
+ int count= sp->bytesperline/2;
+ uint16 * row = (uint16 *) scanlines[0];
+ while ( count-- ) { *row <<= 4 ; row++; }
+ return 1;
+ }
+ }
+ { /* process 12 bits line */
+ int result;
+ result= CALLJPEG(sp, -1, (int) jpeg_read_scanlines(&sp->cinfo.d, &sp->line_work_buf, (JDIMENSION) max_lines));
+ if (result) {
+ unsigned char *out_ptr = (unsigned char *) scanlines[0];
+ JSAMPLE *in_ptr = sp->line_work_buf;
+ int out_count;
+ for( out_count=sp->bytesperline ; out_count> 0 ; out_count--, out_ptr += 3, in_ptr += 2 )
+ {
+ out_ptr[0] = (in_ptr[0] & 0xff0) >> 4;
+ out_ptr[1] = ((in_ptr[0] & 0xf) << 4) | ((in_ptr[1] & 0xf00) >> 8);
+ out_count-=2;
+ if (out_count) out_ptr[2] = ((in_ptr[1] & 0xff) >> 0);
+ }
+ }
+ return result;
+ }
}
static int
@@ -615,6 +677,15 @@
return (1);
}
+static int alloc_linework12_buffer(JPEGState* sp )
+{
+ int countpairs= (sp->bytesperline+2)/3;
+ JSAMPARRAY buf= TIFFjpeg_alloc_sarray(sp, JPOOL_IMAGE, countpairs * 2, 1);
+ if(buf==NULL) return 0;
+ sp->line_work_buf=buf[0];
+ return 1;
+}
+
/*
* JPEG Decoding.
@@ -723,7 +794,7 @@
TIFFError(module, "Improper JPEG component count");
return (0);
}
- if (sp->cinfo.d.data_precision != td->td_bitspersample) {
+ if ( (sp->cinfo.d.data_precision != td->td_bitspersample) && ! (td->td_bitspersample==16 && BITS_IN_JSAMPLE==12 ) ) {
TIFFError(module, "Improper JPEG data precision");
return (0);
}
@@ -792,6 +863,10 @@
}
if (downsampled_output) {
/* Need to use raw-data interface to libjpeg */
+ if(sp->cinfo.d.data_precision == 12){
+ TIFFError(module, "Raw mode not supported only for 8 bits mode");
+ return 0;
+ }
sp->cinfo.d.raw_data_out = TRUE;
tif->tif_decoderow = JPEGDecodeRaw;
tif->tif_decodestrip = JPEGDecodeRaw;
@@ -808,11 +883,14 @@
return (0);
/* Allocate downsampled-data buffers if needed */
if (downsampled_output) {
+ sp->bytesperline= TIFFInterleavedRowSize(sp, segment_width);
if (!alloc_downsampled_buffers(tif, sp->cinfo.d.comp_info,
sp->cinfo.d.num_components))
return (0);
sp->scancount = DCTSIZE; /* mark buffer empty */
}
+ if( tif->tif_dir.td_bitspersample == 12 && ! alloc_linework12_buffer(sp) )
+ return 0;
return (1);
}
@@ -859,15 +937,16 @@
JPEGDecodeRaw(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s)
{
JPEGState *sp = JState(tif);
- tsize_t nrows;
+ JDIMENSION clumps_per_line = sp->cinfo.d.comp_info[1].downsampled_width;
+ int samples_per_clump = sp->samplesperclump;
+ tsize_t nrows= cc / sp->bytesperline;
/* data is expected to be read in multiples of a scanline */
- if ( (nrows = sp->cinfo.d.image_height) ) {
- /* Cb,Cr both have sampling factors 1, so this is correct */
- JDIMENSION clumps_per_line = sp->cinfo.d.comp_info[1].downsampled_width;
- int samples_per_clump = sp->samplesperclump;
-
- do {
+
+ if (cc % sp->bytesperline)
+ TIFFWarning(tif->tif_name, "fractional scanline discarded");
+
+ while( nrows-- ) {
jpeg_component_info *compptr;
int ci, clumpoffset;
@@ -917,10 +996,9 @@
}
}
++sp->scancount;
- ++tif->tif_row;
+ tif->tif_row += sp->v_sampling;
buf += sp->bytesperline;
cc -= sp->bytesperline;
- } while (--nrows > 0);
}
/* Close down the decompressor if done. */
@@ -1051,12 +1129,17 @@
* depths for different components, or if libjpeg ever supports
* run-time selection of depth. Neither is imminent.
*/
- if (td->td_bitspersample != BITS_IN_JSAMPLE) {
- TIFFError(module, "BitsPerSample %d not allowed for JPEG",
- (int) td->td_bitspersample);
- return (0);
+ if (td->td_bitspersample != BITS_IN_JSAMPLE ){
+ if ( ! (td->td_bitspersample==16 && BITS_IN_JSAMPLE==12 ) ) {
+ TIFFError(module, "BitsPerSample %d not allowed for JPEG",
+ (int) td->td_bitspersample);
+ return (0);
+ }
+ else
+ sp->cinfo.c.data_precision = 12;
}
- sp->cinfo.c.data_precision = td->td_bitspersample;
+ else
+ sp->cinfo.c.data_precision = td->td_bitspersample;
if (isTiled(tif)) {
if ((td->td_tilelength % (sp->v_sampling * DCTSIZE)) != 0) {
TIFFError(module,
@@ -1189,12 +1272,19 @@
unsuppress_quant_table(sp, 0);
unsuppress_quant_table(sp, 1);
}
+ //if( BITS_IN_JSAMPLE == 12) sp->jpegtablesmode &= ( JPEGTABLESMODE_HUFF ^ 0xFFFF );
+ sp->jpegtablesmode &= ( JPEGTABLESMODE_HUFF ^ 0xFFFF );
+ /* for 8 bits also ---> anticipating some "low-speed" complains in 12 bits mode ;-))) */
if (sp->jpegtablesmode & JPEGTABLESMODE_HUFF)
sp->cinfo.c.optimize_coding = FALSE;
- else
+ else
sp->cinfo.c.optimize_coding = TRUE;
if (downsampled_input) {
/* Need to use raw-data interface to libjpeg */
+ if(sp->cinfo.c.data_precision == 12){
+ TIFFError(module, "Raw mode not supported only for 8 bits mode");
+ return 0;
+ }
sp->cinfo.c.raw_data_in = TRUE;
tif->tif_encoderow = JPEGEncodeRaw;
tif->tif_encodestrip = JPEGEncodeRaw;
@@ -1211,12 +1301,14 @@
return (0);
/* Allocate downsampled-data buffers if needed */
if (downsampled_input) {
+ sp->bytesperline= TIFFInterleavedRowSize(sp, segment_width);
if (!alloc_downsampled_buffers(tif, sp->cinfo.c.comp_info,
sp->cinfo.c.num_components))
return (0);
}
sp->scancount = 0;
-
+ if( tif->tif_dir.td_bitspersample == 12 && ! alloc_linework12_buffer(sp) )
+ return 0;
return (1);
}
@@ -1320,8 +1412,7 @@
return (0);
sp->scancount = 0;
}
- if (nrows > 0)
- tif->tif_row++;
+ tif->tif_row += sp->v_sampling;
buf += sp->bytesperline;
}
return (1);
--- 372\tif_jpeg.c 2005-03-09 10:49:44.000000000 +0100
+++ mys\tif_jpeg1.c 2005-05-20 14:39:48.500000000 +0200
@@ -190,6 +190,16 @@
};
#define N(a) (sizeof (a) / sizeof (a[0]))
+tsize_t TIFFInterleavedRowSize( JPEGState *sp, int width )
+// for 8,12,16 bps, and h_sampling at least 2, no need of howmanies
+{
+
+ uint16 hv_sampling = sp->h_sampling * sp->v_sampling;
+ tsize_t bpl = (width + sp->h_sampling-1)/sp->h_sampling * (hv_sampling + 2);
+ bpl *= sp->tif->tif_dir.td_bitspersample;
+ return ((tsize_t) TIFFhowmany8(bpl));
+}
+
/*
* libjpeg interface layer.
*
@@ -808,6 +818,7 @@
return (0);
/* Allocate downsampled-data buffers if needed */
if (downsampled_output) {
+ sp->bytesperline= TIFFInterleavedRowSize(sp, segment_width);
if (!alloc_downsampled_buffers(tif, sp->cinfo.d.comp_info,
sp->cinfo.d.num_components))
return (0);
@@ -859,15 +870,16 @@
JPEGDecodeRaw(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s)
{
JPEGState *sp = JState(tif);
- tsize_t nrows;
+ JDIMENSION clumps_per_line = sp->cinfo.d.comp_info[1].downsampled_width;
+ int samples_per_clump = sp->samplesperclump;
+ tsize_t nrows= cc / sp->bytesperline;
/* data is expected to be read in multiples of a scanline */
- if ( (nrows = sp->cinfo.d.image_height) ) {
- /* Cb,Cr both have sampling factors 1, so this is correct */
- JDIMENSION clumps_per_line = sp->cinfo.d.comp_info[1].downsampled_width;
- int samples_per_clump = sp->samplesperclump;
-
- do {
+
+ if (cc % sp->bytesperline)
+ TIFFWarning(tif->tif_name, "fractional scanline discarded");
+
+ while( nrows-- ) {
jpeg_component_info *compptr;
int ci, clumpoffset;
@@ -917,10 +929,9 @@
}
}
++sp->scancount;
- ++tif->tif_row;
+ tif->tif_row += sp->v_sampling;
buf += sp->bytesperline;
cc -= sp->bytesperline;
- } while (--nrows > 0);
}
/* Close down the decompressor if done. */
@@ -1211,6 +1222,7 @@
return (0);
/* Allocate downsampled-data buffers if needed */
if (downsampled_input) {
+ sp->bytesperline= TIFFInterleavedRowSize(sp, segment_width);
if (!alloc_downsampled_buffers(tif, sp->cinfo.c.comp_info,
sp->cinfo.c.num_components))
return (0);
@@ -1320,8 +1332,7 @@
return (0);
sp->scancount = 0;
}
- if (nrows > 0)
- tif->tif_row++;
+ tif->tif_row += sp->v_sampling;
buf += sp->bytesperline;
}
return (1);