This source file includes following definitions.
- TIFFInitOJPEG
- OJPEGVGetField
- OJPEGVSetField
- OJPEGPrintDir
- OJPEGFixupTags
- OJPEGSetupDecode
- OJPEGPreDecode
- OJPEGPreDecodeSkipRaw
- OJPEGPreDecodeSkipScanlines
- OJPEGDecode
- OJPEGDecodeRaw
- OJPEGDecodeScanlines
- OJPEGPostDecode
- OJPEGSetupEncode
- OJPEGPreEncode
- OJPEGEncode
- OJPEGPostEncode
- OJPEGCleanup
- OJPEGSubsamplingCorrect
- OJPEGReadHeaderInfo
- OJPEGReadSecondarySos
- OJPEGWriteHeaderInfo
- OJPEGLibjpegSessionAbort
- OJPEGReadHeaderInfoSec
- OJPEGReadHeaderInfoSecStreamDri
- OJPEGReadHeaderInfoSecStreamDqt
- OJPEGReadHeaderInfoSecStreamDht
- OJPEGReadHeaderInfoSecStreamSof
- OJPEGReadHeaderInfoSecStreamSos
- OJPEGReadHeaderInfoSecTablesQTable
- OJPEGReadHeaderInfoSecTablesDcTable
- OJPEGReadHeaderInfoSecTablesAcTable
- OJPEGReadBufferFill
- OJPEGReadByte
- OJPEGReadBytePeek
- OJPEGReadByteAdvance
- OJPEGReadWord
- OJPEGReadBlock
- OJPEGReadSkip
- OJPEGWriteStream
- OJPEGWriteStreamSoi
- OJPEGWriteStreamQTable
- OJPEGWriteStreamDcTable
- OJPEGWriteStreamAcTable
- OJPEGWriteStreamDri
- OJPEGWriteStreamSof
- OJPEGWriteStreamSos
- OJPEGWriteStreamCompressed
- OJPEGWriteStreamRst
- OJPEGWriteStreamEoi
- jpeg_create_decompress_encap
- jpeg_read_header_encap
- jpeg_start_decompress_encap
- jpeg_read_scanlines_encap
- jpeg_read_raw_data_encap
- jpeg_encap_unwind
- OJPEGLibjpegJpegErrorMgrOutputMessage
- OJPEGLibjpegJpegErrorMgrErrorExit
- OJPEGLibjpegJpegSourceMgrInitSource
- OJPEGLibjpegJpegSourceMgrFillInputBuffer
- OJPEGLibjpegJpegSourceMgrSkipInputData
- OJPEGLibjpegJpegSourceMgrResyncToRestart
- OJPEGLibjpegJpegSourceMgrTermSource
#define WIN32_LEAN_AND_MEAN
#define VC_EXTRALEAN
#include "tiffiop.h"
#ifdef OJPEG_SUPPORT
#define SETJMP(jbuf) setjmp(jbuf)
#define LONGJMP(jbuf,code) longjmp(jbuf,code)
#define JMP_BUF jmp_buf
#define OJPEG_BUFFER 2048
#define JPEG_MARKER_SOF0 0xC0
#define JPEG_MARKER_SOF1 0xC1
#define JPEG_MARKER_SOF3 0xC3
#define JPEG_MARKER_DHT 0xC4
#define JPEG_MARKER_RST0 0XD0
#define JPEG_MARKER_SOI 0xD8
#define JPEG_MARKER_EOI 0xD9
#define JPEG_MARKER_SOS 0xDA
#define JPEG_MARKER_DQT 0xDB
#define JPEG_MARKER_DRI 0xDD
#define JPEG_MARKER_APP0 0xE0
#define JPEG_MARKER_COM 0xFE
#define FIELD_OJPEG_JPEGINTERCHANGEFORMAT (FIELD_CODEC+0)
#define FIELD_OJPEG_JPEGINTERCHANGEFORMATLENGTH (FIELD_CODEC+1)
#define FIELD_OJPEG_JPEGQTABLES (FIELD_CODEC+2)
#define FIELD_OJPEG_JPEGDCTABLES (FIELD_CODEC+3)
#define FIELD_OJPEG_JPEGACTABLES (FIELD_CODEC+4)
#define FIELD_OJPEG_JPEGPROC (FIELD_CODEC+5)
#define FIELD_OJPEG_JPEGRESTARTINTERVAL (FIELD_CODEC+6)
static const TIFFField ojpegFields[] = {
{TIFFTAG_JPEGIFOFFSET,1,1,TIFF_LONG8,0,TIFF_SETGET_UINT64,TIFF_SETGET_UNDEFINED,FIELD_OJPEG_JPEGINTERCHANGEFORMAT,TRUE,FALSE,"JpegInterchangeFormat",NULL},
{TIFFTAG_JPEGIFBYTECOUNT,1,1,TIFF_LONG8,0,TIFF_SETGET_UINT64,TIFF_SETGET_UNDEFINED,FIELD_OJPEG_JPEGINTERCHANGEFORMATLENGTH,TRUE,FALSE,"JpegInterchangeFormatLength",NULL},
{TIFFTAG_JPEGQTABLES,TIFF_VARIABLE2,TIFF_VARIABLE2,TIFF_LONG8,0,TIFF_SETGET_C32_UINT64,TIFF_SETGET_UNDEFINED,FIELD_OJPEG_JPEGQTABLES,FALSE,TRUE,"JpegQTables",NULL},
{TIFFTAG_JPEGDCTABLES,TIFF_VARIABLE2,TIFF_VARIABLE2,TIFF_LONG8,0,TIFF_SETGET_C32_UINT64,TIFF_SETGET_UNDEFINED,FIELD_OJPEG_JPEGDCTABLES,FALSE,TRUE,"JpegDcTables",NULL},
{TIFFTAG_JPEGACTABLES,TIFF_VARIABLE2,TIFF_VARIABLE2,TIFF_LONG8,0,TIFF_SETGET_C32_UINT64,TIFF_SETGET_UNDEFINED,FIELD_OJPEG_JPEGACTABLES,FALSE,TRUE,"JpegAcTables",NULL},
{TIFFTAG_JPEGPROC,1,1,TIFF_SHORT,0,TIFF_SETGET_UINT16,TIFF_SETGET_UNDEFINED,FIELD_OJPEG_JPEGPROC,FALSE,FALSE,"JpegProc",NULL},
{TIFFTAG_JPEGRESTARTINTERVAL,1,1,TIFF_SHORT,0,TIFF_SETGET_UINT16,TIFF_SETGET_UNDEFINED,FIELD_OJPEG_JPEGRESTARTINTERVAL,FALSE,FALSE,"JpegRestartInterval",NULL},
};
#ifndef LIBJPEG_ENCAP_EXTERNAL
#include <setjmp.h>
#endif
#ifdef FAR
#undef FAR
#endif
#if defined(__BORLANDC__) || defined(__MINGW32__)
# define XMD_H 1
#endif
#if defined(__WIN32__) && !defined(__MINGW32__)
# ifndef __RPCNDR_H__
typedef unsigned char boolean;
# endif
# define HAVE_BOOLEAN
#endif
#include "jpeglib.h"
#include "jerror.h"
typedef struct jpeg_error_mgr jpeg_error_mgr;
typedef struct jpeg_common_struct jpeg_common_struct;
typedef struct jpeg_decompress_struct jpeg_decompress_struct;
typedef struct jpeg_source_mgr jpeg_source_mgr;
typedef enum {
osibsNotSetYet,
osibsJpegInterchangeFormat,
osibsStrile,
osibsEof
} OJPEGStateInBufferSource;
typedef enum {
ososSoi,
ososQTable0,ososQTable1,ososQTable2,ososQTable3,
ososDcTable0,ososDcTable1,ososDcTable2,ososDcTable3,
ososAcTable0,ososAcTable1,ososAcTable2,ososAcTable3,
ososDri,
ososSof,
ososSos,
ososCompressed,
ososRst,
ososEoi
} OJPEGStateOutState;
typedef struct {
TIFF* tif;
#ifndef LIBJPEG_ENCAP_EXTERNAL
JMP_BUF exit_jmpbuf;
#endif
TIFFVGetMethod vgetparent;
TIFFVSetMethod vsetparent;
TIFFPrintMethod printdir;
uint64 file_size;
uint32 image_width;
uint32 image_length;
uint32 strile_width;
uint32 strile_length;
uint32 strile_length_total;
uint8 samples_per_pixel;
uint8 plane_sample_offset;
uint8 samples_per_pixel_per_plane;
uint64 jpeg_interchange_format;
uint64 jpeg_interchange_format_length;
uint8 jpeg_proc;
uint8 subsamplingcorrect;
uint8 subsamplingcorrect_done;
uint8 subsampling_tag;
uint8 subsampling_hor;
uint8 subsampling_ver;
uint8 subsampling_force_desubsampling_inside_decompression;
uint8 qtable_offset_count;
uint8 dctable_offset_count;
uint8 actable_offset_count;
uint64 qtable_offset[3];
uint64 dctable_offset[3];
uint64 actable_offset[3];
uint8* qtable[4];
uint8* dctable[4];
uint8* actable[4];
uint16 restart_interval;
uint8 restart_index;
uint8 sof_log;
uint8 sof_marker_id;
uint32 sof_x;
uint32 sof_y;
uint8 sof_c[3];
uint8 sof_hv[3];
uint8 sof_tq[3];
uint8 sos_cs[3];
uint8 sos_tda[3];
struct {
uint8 log;
OJPEGStateInBufferSource in_buffer_source;
uint32 in_buffer_next_strile;
uint64 in_buffer_file_pos;
uint64 in_buffer_file_togo;
} sos_end[3];
uint8 readheader_done;
uint8 writeheader_done;
uint16 write_cursample;
uint32 write_curstrile;
uint8 libjpeg_session_active;
uint8 libjpeg_jpeg_query_style;
jpeg_error_mgr libjpeg_jpeg_error_mgr;
jpeg_decompress_struct libjpeg_jpeg_decompress_struct;
jpeg_source_mgr libjpeg_jpeg_source_mgr;
uint8 subsampling_convert_log;
uint32 subsampling_convert_ylinelen;
uint32 subsampling_convert_ylines;
uint32 subsampling_convert_clinelen;
uint32 subsampling_convert_clines;
uint32 subsampling_convert_ybuflen;
uint32 subsampling_convert_cbuflen;
uint32 subsampling_convert_ycbcrbuflen;
uint8* subsampling_convert_ycbcrbuf;
uint8* subsampling_convert_ybuf;
uint8* subsampling_convert_cbbuf;
uint8* subsampling_convert_crbuf;
uint32 subsampling_convert_ycbcrimagelen;
uint8** subsampling_convert_ycbcrimage;
uint32 subsampling_convert_clinelenout;
uint32 subsampling_convert_state;
uint32 bytes_per_line;
uint32 lines_per_strile;
OJPEGStateInBufferSource in_buffer_source;
uint32 in_buffer_next_strile;
uint32 in_buffer_strile_count;
uint64 in_buffer_file_pos;
uint8 in_buffer_file_pos_log;
uint64 in_buffer_file_togo;
uint16 in_buffer_togo;
uint8* in_buffer_cur;
uint8 in_buffer[OJPEG_BUFFER];
OJPEGStateOutState out_state;
uint8 out_buffer[OJPEG_BUFFER];
uint8* skip_buffer;
} OJPEGState;
static int OJPEGVGetField(TIFF* tif, uint32 tag, va_list ap);
static int OJPEGVSetField(TIFF* tif, uint32 tag, va_list ap);
static void OJPEGPrintDir(TIFF* tif, FILE* fd, long flags);
static int OJPEGFixupTags(TIFF* tif);
static int OJPEGSetupDecode(TIFF* tif);
static int OJPEGPreDecode(TIFF* tif, uint16 s);
static int OJPEGPreDecodeSkipRaw(TIFF* tif);
static int OJPEGPreDecodeSkipScanlines(TIFF* tif);
static int OJPEGDecode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s);
static int OJPEGDecodeRaw(TIFF* tif, uint8* buf, tmsize_t cc);
static int OJPEGDecodeScanlines(TIFF* tif, uint8* buf, tmsize_t cc);
static void OJPEGPostDecode(TIFF* tif, uint8* buf, tmsize_t cc);
static int OJPEGSetupEncode(TIFF* tif);
static int OJPEGPreEncode(TIFF* tif, uint16 s);
static int OJPEGEncode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s);
static int OJPEGPostEncode(TIFF* tif);
static void OJPEGCleanup(TIFF* tif);
static void OJPEGSubsamplingCorrect(TIFF* tif);
static int OJPEGReadHeaderInfo(TIFF* tif);
static int OJPEGReadSecondarySos(TIFF* tif, uint16 s);
static int OJPEGWriteHeaderInfo(TIFF* tif);
static void OJPEGLibjpegSessionAbort(TIFF* tif);
static int OJPEGReadHeaderInfoSec(TIFF* tif);
static int OJPEGReadHeaderInfoSecStreamDri(TIFF* tif);
static int OJPEGReadHeaderInfoSecStreamDqt(TIFF* tif);
static int OJPEGReadHeaderInfoSecStreamDht(TIFF* tif);
static int OJPEGReadHeaderInfoSecStreamSof(TIFF* tif, uint8 marker_id);
static int OJPEGReadHeaderInfoSecStreamSos(TIFF* tif);
static int OJPEGReadHeaderInfoSecTablesQTable(TIFF* tif);
static int OJPEGReadHeaderInfoSecTablesDcTable(TIFF* tif);
static int OJPEGReadHeaderInfoSecTablesAcTable(TIFF* tif);
static int OJPEGReadBufferFill(OJPEGState* sp);
static int OJPEGReadByte(OJPEGState* sp, uint8* byte);
static int OJPEGReadBytePeek(OJPEGState* sp, uint8* byte);
static void OJPEGReadByteAdvance(OJPEGState* sp);
static int OJPEGReadWord(OJPEGState* sp, uint16* word);
static int OJPEGReadBlock(OJPEGState* sp, uint16 len, void* mem);
static void OJPEGReadSkip(OJPEGState* sp, uint16 len);
static int OJPEGWriteStream(TIFF* tif, void** mem, uint32* len);
static void OJPEGWriteStreamSoi(TIFF* tif, void** mem, uint32* len);
static void OJPEGWriteStreamQTable(TIFF* tif, uint8 table_index, void** mem, uint32* len);
static void OJPEGWriteStreamDcTable(TIFF* tif, uint8 table_index, void** mem, uint32* len);
static void OJPEGWriteStreamAcTable(TIFF* tif, uint8 table_index, void** mem, uint32* len);
static void OJPEGWriteStreamDri(TIFF* tif, void** mem, uint32* len);
static void OJPEGWriteStreamSof(TIFF* tif, void** mem, uint32* len);
static void OJPEGWriteStreamSos(TIFF* tif, void** mem, uint32* len);
static int OJPEGWriteStreamCompressed(TIFF* tif, void** mem, uint32* len);
static void OJPEGWriteStreamRst(TIFF* tif, void** mem, uint32* len);
static void OJPEGWriteStreamEoi(TIFF* tif, void** mem, uint32* len);
#ifdef LIBJPEG_ENCAP_EXTERNAL
extern int jpeg_create_decompress_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo);
extern int jpeg_read_header_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, uint8 require_image);
extern int jpeg_start_decompress_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo);
extern int jpeg_read_scanlines_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, void* scanlines, uint32 max_lines);
extern int jpeg_read_raw_data_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, void* data, uint32 max_lines);
extern void jpeg_encap_unwind(TIFF* tif);
#else
static int jpeg_create_decompress_encap(OJPEGState* sp, jpeg_decompress_struct* j);
static int jpeg_read_header_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, uint8 require_image);
static int jpeg_start_decompress_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo);
static int jpeg_read_scanlines_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, void* scanlines, uint32 max_lines);
static int jpeg_read_raw_data_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, void* data, uint32 max_lines);
static void jpeg_encap_unwind(TIFF* tif);
#endif
static void OJPEGLibjpegJpegErrorMgrOutputMessage(jpeg_common_struct* cinfo);
static void OJPEGLibjpegJpegErrorMgrErrorExit(jpeg_common_struct* cinfo);
static void OJPEGLibjpegJpegSourceMgrInitSource(jpeg_decompress_struct* cinfo);
static boolean OJPEGLibjpegJpegSourceMgrFillInputBuffer(jpeg_decompress_struct* cinfo);
static void OJPEGLibjpegJpegSourceMgrSkipInputData(jpeg_decompress_struct* cinfo, long num_bytes);
static boolean OJPEGLibjpegJpegSourceMgrResyncToRestart(jpeg_decompress_struct* cinfo, int desired);
static void OJPEGLibjpegJpegSourceMgrTermSource(jpeg_decompress_struct* cinfo);
int
TIFFInitOJPEG(TIFF* tif, int scheme)
{
static const char module[]="TIFFInitOJPEG";
OJPEGState* sp;
assert(scheme==COMPRESSION_OJPEG);
if (!_TIFFMergeFields(tif, ojpegFields, TIFFArrayCount(ojpegFields))) {
TIFFErrorExt(tif->tif_clientdata, module,
"Merging Old JPEG codec-specific tags failed");
return 0;
}
sp=_TIFFmalloc(sizeof(OJPEGState));
if (sp==NULL)
{
TIFFErrorExt(tif->tif_clientdata,module,"No space for OJPEG state block");
return(0);
}
_TIFFmemset(sp,0,sizeof(OJPEGState));
sp->tif=tif;
sp->jpeg_proc=1;
sp->subsampling_hor=2;
sp->subsampling_ver=2;
TIFFSetField(tif,TIFFTAG_YCBCRSUBSAMPLING,2,2);
tif->tif_fixuptags=OJPEGFixupTags;
tif->tif_setupdecode=OJPEGSetupDecode;
tif->tif_predecode=OJPEGPreDecode;
tif->tif_postdecode=OJPEGPostDecode;
tif->tif_decoderow=OJPEGDecode;
tif->tif_decodestrip=OJPEGDecode;
tif->tif_decodetile=OJPEGDecode;
tif->tif_setupencode=OJPEGSetupEncode;
tif->tif_preencode=OJPEGPreEncode;
tif->tif_postencode=OJPEGPostEncode;
tif->tif_encoderow=OJPEGEncode;
tif->tif_encodestrip=OJPEGEncode;
tif->tif_encodetile=OJPEGEncode;
tif->tif_cleanup=OJPEGCleanup;
tif->tif_data=(uint8*)sp;
sp->vgetparent=tif->tif_tagmethods.vgetfield;
tif->tif_tagmethods.vgetfield=OJPEGVGetField;
sp->vsetparent=tif->tif_tagmethods.vsetfield;
tif->tif_tagmethods.vsetfield=OJPEGVSetField;
sp->printdir=tif->tif_tagmethods.printdir;
tif->tif_tagmethods.printdir=OJPEGPrintDir;
tif->tif_flags|=TIFF_NOREADRAW;
return(1);
}
static int
OJPEGVGetField(TIFF* tif, uint32 tag, va_list ap)
{
OJPEGState* sp=(OJPEGState*)tif->tif_data;
switch(tag)
{
case TIFFTAG_JPEGIFOFFSET:
*va_arg(ap,uint64*)=(uint64)sp->jpeg_interchange_format;
break;
case TIFFTAG_JPEGIFBYTECOUNT:
*va_arg(ap,uint64*)=(uint64)sp->jpeg_interchange_format_length;
break;
case TIFFTAG_YCBCRSUBSAMPLING:
if (sp->subsamplingcorrect_done==0)
OJPEGSubsamplingCorrect(tif);
*va_arg(ap,uint16*)=(uint16)sp->subsampling_hor;
*va_arg(ap,uint16*)=(uint16)sp->subsampling_ver;
break;
case TIFFTAG_JPEGQTABLES:
*va_arg(ap,uint32*)=(uint32)sp->qtable_offset_count;
*va_arg(ap,void**)=(void*)sp->qtable_offset;
break;
case TIFFTAG_JPEGDCTABLES:
*va_arg(ap,uint32*)=(uint32)sp->dctable_offset_count;
*va_arg(ap,void**)=(void*)sp->dctable_offset;
break;
case TIFFTAG_JPEGACTABLES:
*va_arg(ap,uint32*)=(uint32)sp->actable_offset_count;
*va_arg(ap,void**)=(void*)sp->actable_offset;
break;
case TIFFTAG_JPEGPROC:
*va_arg(ap,uint16*)=(uint16)sp->jpeg_proc;
break;
case TIFFTAG_JPEGRESTARTINTERVAL:
*va_arg(ap,uint16*)=sp->restart_interval;
break;
default:
return (*sp->vgetparent)(tif,tag,ap);
}
return (1);
}
static int
OJPEGVSetField(TIFF* tif, uint32 tag, va_list ap)
{
static const char module[]="OJPEGVSetField";
OJPEGState* sp=(OJPEGState*)tif->tif_data;
uint32 ma;
uint64* mb;
uint32 n;
switch(tag)
{
case TIFFTAG_JPEGIFOFFSET:
sp->jpeg_interchange_format=(uint64)va_arg(ap,uint64);
break;
case TIFFTAG_JPEGIFBYTECOUNT:
sp->jpeg_interchange_format_length=(uint64)va_arg(ap,uint64);
break;
case TIFFTAG_YCBCRSUBSAMPLING:
sp->subsampling_tag=1;
sp->subsampling_hor=(uint8)va_arg(ap,uint16_vap);
sp->subsampling_ver=(uint8)va_arg(ap,uint16_vap);
tif->tif_dir.td_ycbcrsubsampling[0]=sp->subsampling_hor;
tif->tif_dir.td_ycbcrsubsampling[1]=sp->subsampling_ver;
break;
case TIFFTAG_JPEGQTABLES:
ma=(uint32)va_arg(ap,uint32);
if (ma!=0)
{
if (ma>3)
{
TIFFErrorExt(tif->tif_clientdata,module,"JpegQTables tag has incorrect count");
return(0);
}
sp->qtable_offset_count=(uint8)ma;
mb=(uint64*)va_arg(ap,uint64*);
for (n=0; n<ma; n++)
sp->qtable_offset[n]=mb[n];
}
break;
case TIFFTAG_JPEGDCTABLES:
ma=(uint32)va_arg(ap,uint32);
if (ma!=0)
{
if (ma>3)
{
TIFFErrorExt(tif->tif_clientdata,module,"JpegDcTables tag has incorrect count");
return(0);
}
sp->dctable_offset_count=(uint8)ma;
mb=(uint64*)va_arg(ap,uint64*);
for (n=0; n<ma; n++)
sp->dctable_offset[n]=mb[n];
}
break;
case TIFFTAG_JPEGACTABLES:
ma=(uint32)va_arg(ap,uint32);
if (ma!=0)
{
if (ma>3)
{
TIFFErrorExt(tif->tif_clientdata,module,"JpegAcTables tag has incorrect count");
return(0);
}
sp->actable_offset_count=(uint8)ma;
mb=(uint64*)va_arg(ap,uint64*);
for (n=0; n<ma; n++)
sp->actable_offset[n]=mb[n];
}
break;
case TIFFTAG_JPEGPROC:
sp->jpeg_proc=(uint8)va_arg(ap,uint16_vap);
break;
case TIFFTAG_JPEGRESTARTINTERVAL:
sp->restart_interval=(uint16)va_arg(ap,uint16_vap);
break;
default:
return (*sp->vsetparent)(tif,tag,ap);
}
TIFFSetFieldBit(tif,TIFFFieldWithTag(tif,tag)->field_bit);
tif->tif_flags|=TIFF_DIRTYDIRECT;
return(1);
}
static void
OJPEGPrintDir(TIFF* tif, FILE* fd, long flags)
{
OJPEGState* sp=(OJPEGState*)tif->tif_data;
uint8 m;
(void)flags;
assert(sp!=NULL);
if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGINTERCHANGEFORMAT))
fprintf(fd," JpegInterchangeFormat: " TIFF_UINT64_FORMAT "\n",(TIFF_UINT64_T)sp->jpeg_interchange_format);
if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGINTERCHANGEFORMATLENGTH))
fprintf(fd," JpegInterchangeFormatLength: " TIFF_UINT64_FORMAT "\n",(TIFF_UINT64_T)sp->jpeg_interchange_format_length);
if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGQTABLES))
{
fprintf(fd," JpegQTables:");
for (m=0; m<sp->qtable_offset_count; m++)
fprintf(fd," " TIFF_UINT64_FORMAT,(TIFF_UINT64_T)sp->qtable_offset[m]);
fprintf(fd,"\n");
}
if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGDCTABLES))
{
fprintf(fd," JpegDcTables:");
for (m=0; m<sp->dctable_offset_count; m++)
fprintf(fd," " TIFF_UINT64_FORMAT,(TIFF_UINT64_T)sp->dctable_offset[m]);
fprintf(fd,"\n");
}
if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGACTABLES))
{
fprintf(fd," JpegAcTables:");
for (m=0; m<sp->actable_offset_count; m++)
fprintf(fd," " TIFF_UINT64_FORMAT,(TIFF_UINT64_T)sp->actable_offset[m]);
fprintf(fd,"\n");
}
if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGPROC))
fprintf(fd," JpegProc: %u\n",(unsigned int)sp->jpeg_proc);
if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGRESTARTINTERVAL))
fprintf(fd," JpegRestartInterval: %u\n",(unsigned int)sp->restart_interval);
if (sp->printdir)
(*sp->printdir)(tif, fd, flags);
}
static int
OJPEGFixupTags(TIFF* tif)
{
(void) tif;
return(1);
}
static int
OJPEGSetupDecode(TIFF* tif)
{
static const char module[]="OJPEGSetupDecode";
TIFFWarningExt(tif->tif_clientdata,module,"Depreciated and troublesome old-style JPEG compression mode, please convert to new-style JPEG compression and notify vendor of writing software");
return(1);
}
static int
OJPEGPreDecode(TIFF* tif, uint16 s)
{
OJPEGState* sp=(OJPEGState*)tif->tif_data;
uint32 m;
if (sp->subsamplingcorrect_done==0)
OJPEGSubsamplingCorrect(tif);
if (sp->readheader_done==0)
{
if (OJPEGReadHeaderInfo(tif)==0)
return(0);
}
if (sp->sos_end[s].log==0)
{
if (OJPEGReadSecondarySos(tif,s)==0)
return(0);
}
if isTiled(tif)
m=tif->tif_curtile;
else
m=tif->tif_curstrip;
if ((sp->writeheader_done!=0) && ((sp->write_cursample!=s) || (sp->write_curstrile>m)))
{
if (sp->libjpeg_session_active!=0)
OJPEGLibjpegSessionAbort(tif);
sp->writeheader_done=0;
}
if (sp->writeheader_done==0)
{
sp->plane_sample_offset=(uint8)s;
sp->write_cursample=s;
sp->write_curstrile=s*tif->tif_dir.td_stripsperimage;
if ((sp->in_buffer_file_pos_log==0) ||
(sp->in_buffer_file_pos-sp->in_buffer_togo!=sp->sos_end[s].in_buffer_file_pos))
{
sp->in_buffer_source=sp->sos_end[s].in_buffer_source;
sp->in_buffer_next_strile=sp->sos_end[s].in_buffer_next_strile;
sp->in_buffer_file_pos=sp->sos_end[s].in_buffer_file_pos;
sp->in_buffer_file_pos_log=0;
sp->in_buffer_file_togo=sp->sos_end[s].in_buffer_file_togo;
sp->in_buffer_togo=0;
sp->in_buffer_cur=0;
}
if (OJPEGWriteHeaderInfo(tif)==0)
return(0);
}
while (sp->write_curstrile<m)
{
if (sp->libjpeg_jpeg_query_style==0)
{
if (OJPEGPreDecodeSkipRaw(tif)==0)
return(0);
}
else
{
if (OJPEGPreDecodeSkipScanlines(tif)==0)
return(0);
}
sp->write_curstrile++;
}
return(1);
}
static int
OJPEGPreDecodeSkipRaw(TIFF* tif)
{
OJPEGState* sp=(OJPEGState*)tif->tif_data;
uint32 m;
m=sp->lines_per_strile;
if (sp->subsampling_convert_state!=0)
{
if (sp->subsampling_convert_clines-sp->subsampling_convert_state>=m)
{
sp->subsampling_convert_state+=m;
if (sp->subsampling_convert_state==sp->subsampling_convert_clines)
sp->subsampling_convert_state=0;
return(1);
}
m-=sp->subsampling_convert_clines-sp->subsampling_convert_state;
sp->subsampling_convert_state=0;
}
while (m>=sp->subsampling_convert_clines)
{
if (jpeg_read_raw_data_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),sp->subsampling_convert_ycbcrimage,sp->subsampling_ver*8)==0)
return(0);
m-=sp->subsampling_convert_clines;
}
if (m>0)
{
if (jpeg_read_raw_data_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),sp->subsampling_convert_ycbcrimage,sp->subsampling_ver*8)==0)
return(0);
sp->subsampling_convert_state=m;
}
return(1);
}
static int
OJPEGPreDecodeSkipScanlines(TIFF* tif)
{
static const char module[]="OJPEGPreDecodeSkipScanlines";
OJPEGState* sp=(OJPEGState*)tif->tif_data;
uint32 m;
if (sp->skip_buffer==NULL)
{
sp->skip_buffer=_TIFFmalloc(sp->bytes_per_line);
if (sp->skip_buffer==NULL)
{
TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
return(0);
}
}
for (m=0; m<sp->lines_per_strile; m++)
{
if (jpeg_read_scanlines_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),&sp->skip_buffer,1)==0)
return(0);
}
return(1);
}
static int
OJPEGDecode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s)
{
OJPEGState* sp=(OJPEGState*)tif->tif_data;
(void)s;
if (sp->libjpeg_jpeg_query_style==0)
{
if (OJPEGDecodeRaw(tif,buf,cc)==0)
return(0);
}
else
{
if (OJPEGDecodeScanlines(tif,buf,cc)==0)
return(0);
}
return(1);
}
static int
OJPEGDecodeRaw(TIFF* tif, uint8* buf, tmsize_t cc)
{
static const char module[]="OJPEGDecodeRaw";
OJPEGState* sp=(OJPEGState*)tif->tif_data;
uint8* m;
tmsize_t n;
uint8* oy;
uint8* ocb;
uint8* ocr;
uint8* p;
uint32 q;
uint8* r;
uint8 sx,sy;
if (cc%sp->bytes_per_line!=0)
{
TIFFErrorExt(tif->tif_clientdata,module,"Fractional scanline not read");
return(0);
}
assert(cc>0);
m=buf;
n=cc;
do
{
if (sp->subsampling_convert_state==0)
{
if (jpeg_read_raw_data_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),sp->subsampling_convert_ycbcrimage,sp->subsampling_ver*8)==0)
return(0);
}
oy=sp->subsampling_convert_ybuf+sp->subsampling_convert_state*sp->subsampling_ver*sp->subsampling_convert_ylinelen;
ocb=sp->subsampling_convert_cbbuf+sp->subsampling_convert_state*sp->subsampling_convert_clinelen;
ocr=sp->subsampling_convert_crbuf+sp->subsampling_convert_state*sp->subsampling_convert_clinelen;
p=m;
for (q=0; q<sp->subsampling_convert_clinelenout; q++)
{
r=oy;
for (sy=0; sy<sp->subsampling_ver; sy++)
{
for (sx=0; sx<sp->subsampling_hor; sx++)
*p++=*r++;
r+=sp->subsampling_convert_ylinelen-sp->subsampling_hor;
}
oy+=sp->subsampling_hor;
*p++=*ocb++;
*p++=*ocr++;
}
sp->subsampling_convert_state++;
if (sp->subsampling_convert_state==sp->subsampling_convert_clines)
sp->subsampling_convert_state=0;
m+=sp->bytes_per_line;
n-=sp->bytes_per_line;
} while(n>0);
return(1);
}
static int
OJPEGDecodeScanlines(TIFF* tif, uint8* buf, tmsize_t cc)
{
static const char module[]="OJPEGDecodeScanlines";
OJPEGState* sp=(OJPEGState*)tif->tif_data;
uint8* m;
tmsize_t n;
if (cc%sp->bytes_per_line!=0)
{
TIFFErrorExt(tif->tif_clientdata,module,"Fractional scanline not read");
return(0);
}
assert(cc>0);
m=buf;
n=cc;
do
{
if (jpeg_read_scanlines_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),&m,1)==0)
return(0);
m+=sp->bytes_per_line;
n-=sp->bytes_per_line;
} while(n>0);
return(1);
}
static void
OJPEGPostDecode(TIFF* tif, uint8* buf, tmsize_t cc)
{
OJPEGState* sp=(OJPEGState*)tif->tif_data;
(void)buf;
(void)cc;
sp->write_curstrile++;
if (sp->write_curstrile%tif->tif_dir.td_stripsperimage==0)
{
assert(sp->libjpeg_session_active!=0);
OJPEGLibjpegSessionAbort(tif);
sp->writeheader_done=0;
}
}
static int
OJPEGSetupEncode(TIFF* tif)
{
static const char module[]="OJPEGSetupEncode";
TIFFErrorExt(tif->tif_clientdata,module,"OJPEG encoding not supported; use new-style JPEG compression instead");
return(0);
}
static int
OJPEGPreEncode(TIFF* tif, uint16 s)
{
static const char module[]="OJPEGPreEncode";
(void)s;
TIFFErrorExt(tif->tif_clientdata,module,"OJPEG encoding not supported; use new-style JPEG compression instead");
return(0);
}
static int
OJPEGEncode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s)
{
static const char module[]="OJPEGEncode";
(void)buf;
(void)cc;
(void)s;
TIFFErrorExt(tif->tif_clientdata,module,"OJPEG encoding not supported; use new-style JPEG compression instead");
return(0);
}
static int
OJPEGPostEncode(TIFF* tif)
{
static const char module[]="OJPEGPostEncode";
TIFFErrorExt(tif->tif_clientdata,module,"OJPEG encoding not supported; use new-style JPEG compression instead");
return(0);
}
static void
OJPEGCleanup(TIFF* tif)
{
OJPEGState* sp=(OJPEGState*)tif->tif_data;
if (sp!=0)
{
tif->tif_tagmethods.vgetfield=sp->vgetparent;
tif->tif_tagmethods.vsetfield=sp->vsetparent;
tif->tif_tagmethods.printdir=sp->printdir;
if (sp->qtable[0]!=0)
_TIFFfree(sp->qtable[0]);
if (sp->qtable[1]!=0)
_TIFFfree(sp->qtable[1]);
if (sp->qtable[2]!=0)
_TIFFfree(sp->qtable[2]);
if (sp->qtable[3]!=0)
_TIFFfree(sp->qtable[3]);
if (sp->dctable[0]!=0)
_TIFFfree(sp->dctable[0]);
if (sp->dctable[1]!=0)
_TIFFfree(sp->dctable[1]);
if (sp->dctable[2]!=0)
_TIFFfree(sp->dctable[2]);
if (sp->dctable[3]!=0)
_TIFFfree(sp->dctable[3]);
if (sp->actable[0]!=0)
_TIFFfree(sp->actable[0]);
if (sp->actable[1]!=0)
_TIFFfree(sp->actable[1]);
if (sp->actable[2]!=0)
_TIFFfree(sp->actable[2]);
if (sp->actable[3]!=0)
_TIFFfree(sp->actable[3]);
if (sp->libjpeg_session_active!=0)
OJPEGLibjpegSessionAbort(tif);
if (sp->subsampling_convert_ycbcrbuf!=0)
_TIFFfree(sp->subsampling_convert_ycbcrbuf);
if (sp->subsampling_convert_ycbcrimage!=0)
_TIFFfree(sp->subsampling_convert_ycbcrimage);
if (sp->skip_buffer!=0)
_TIFFfree(sp->skip_buffer);
_TIFFfree(sp);
tif->tif_data=NULL;
_TIFFSetDefaultCompressionState(tif);
}
}
static void
OJPEGSubsamplingCorrect(TIFF* tif)
{
static const char module[]="OJPEGSubsamplingCorrect";
OJPEGState* sp=(OJPEGState*)tif->tif_data;
uint8 mh;
uint8 mv;
_TIFFFillStriles( tif );
assert(sp->subsamplingcorrect_done==0);
if ((tif->tif_dir.td_samplesperpixel!=3) || ((tif->tif_dir.td_photometric!=PHOTOMETRIC_YCBCR) &&
(tif->tif_dir.td_photometric!=PHOTOMETRIC_ITULAB)))
{
if (sp->subsampling_tag!=0)
TIFFWarningExt(tif->tif_clientdata,module,"Subsampling tag not appropriate for this Photometric and/or SamplesPerPixel");
sp->subsampling_hor=1;
sp->subsampling_ver=1;
sp->subsampling_force_desubsampling_inside_decompression=0;
}
else
{
sp->subsamplingcorrect_done=1;
mh=sp->subsampling_hor;
mv=sp->subsampling_ver;
sp->subsamplingcorrect=1;
OJPEGReadHeaderInfoSec(tif);
if (sp->subsampling_force_desubsampling_inside_decompression!=0)
{
sp->subsampling_hor=1;
sp->subsampling_ver=1;
}
sp->subsamplingcorrect=0;
if (((sp->subsampling_hor!=mh) || (sp->subsampling_ver!=mv)) && (sp->subsampling_force_desubsampling_inside_decompression==0))
{
if (sp->subsampling_tag==0)
TIFFWarningExt(tif->tif_clientdata,module,"Subsampling tag is not set, yet subsampling inside JPEG data [%d,%d] does not match default values [2,2]; assuming subsampling inside JPEG data is correct",sp->subsampling_hor,sp->subsampling_ver);
else
TIFFWarningExt(tif->tif_clientdata,module,"Subsampling inside JPEG data [%d,%d] does not match subsampling tag values [%d,%d]; assuming subsampling inside JPEG data is correct",sp->subsampling_hor,sp->subsampling_ver,mh,mv);
}
if (sp->subsampling_force_desubsampling_inside_decompression!=0)
{
if (sp->subsampling_tag==0)
TIFFWarningExt(tif->tif_clientdata,module,"Subsampling tag is not set, yet subsampling inside JPEG data does not match default values [2,2] (nor any other values allowed in TIFF); assuming subsampling inside JPEG data is correct and desubsampling inside JPEG decompression");
else
TIFFWarningExt(tif->tif_clientdata,module,"Subsampling inside JPEG data does not match subsampling tag values [%d,%d] (nor any other values allowed in TIFF); assuming subsampling inside JPEG data is correct and desubsampling inside JPEG decompression",mh,mv);
}
if (sp->subsampling_force_desubsampling_inside_decompression==0)
{
if (sp->subsampling_hor<sp->subsampling_ver)
TIFFWarningExt(tif->tif_clientdata,module,"Subsampling values [%d,%d] are not allowed in TIFF",sp->subsampling_hor,sp->subsampling_ver);
}
}
sp->subsamplingcorrect_done=1;
}
static int
OJPEGReadHeaderInfo(TIFF* tif)
{
static const char module[]="OJPEGReadHeaderInfo";
OJPEGState* sp=(OJPEGState*)tif->tif_data;
assert(sp->readheader_done==0);
sp->image_width=tif->tif_dir.td_imagewidth;
sp->image_length=tif->tif_dir.td_imagelength;
if isTiled(tif)
{
sp->strile_width=tif->tif_dir.td_tilewidth;
sp->strile_length=tif->tif_dir.td_tilelength;
sp->strile_length_total=((sp->image_length+sp->strile_length-1)/sp->strile_length)*sp->strile_length;
}
else
{
sp->strile_width=sp->image_width;
sp->strile_length=tif->tif_dir.td_rowsperstrip;
sp->strile_length_total=sp->image_length;
}
if (tif->tif_dir.td_samplesperpixel==1)
{
sp->samples_per_pixel=1;
sp->plane_sample_offset=0;
sp->samples_per_pixel_per_plane=sp->samples_per_pixel;
sp->subsampling_hor=1;
sp->subsampling_ver=1;
}
else
{
if (tif->tif_dir.td_samplesperpixel!=3)
{
TIFFErrorExt(tif->tif_clientdata,module,"SamplesPerPixel %d not supported for this compression scheme",sp->samples_per_pixel);
return(0);
}
sp->samples_per_pixel=3;
sp->plane_sample_offset=0;
if (tif->tif_dir.td_planarconfig==PLANARCONFIG_CONTIG)
sp->samples_per_pixel_per_plane=3;
else
sp->samples_per_pixel_per_plane=1;
}
if (sp->strile_length<sp->image_length)
{
if (sp->strile_length%(sp->subsampling_ver*8)!=0)
{
TIFFErrorExt(tif->tif_clientdata,module,"Incompatible vertical subsampling and image strip/tile length");
return(0);
}
sp->restart_interval=((sp->strile_width+sp->subsampling_hor*8-1)/(sp->subsampling_hor*8))*(sp->strile_length/(sp->subsampling_ver*8));
}
if (OJPEGReadHeaderInfoSec(tif)==0)
return(0);
sp->sos_end[0].log=1;
sp->sos_end[0].in_buffer_source=sp->in_buffer_source;
sp->sos_end[0].in_buffer_next_strile=sp->in_buffer_next_strile;
sp->sos_end[0].in_buffer_file_pos=sp->in_buffer_file_pos-sp->in_buffer_togo;
sp->sos_end[0].in_buffer_file_togo=sp->in_buffer_file_togo+sp->in_buffer_togo;
sp->readheader_done=1;
return(1);
}
static int
OJPEGReadSecondarySos(TIFF* tif, uint16 s)
{
OJPEGState* sp=(OJPEGState*)tif->tif_data;
uint8 m;
assert(s>0);
assert(s<3);
assert(sp->sos_end[0].log!=0);
assert(sp->sos_end[s].log==0);
sp->plane_sample_offset=s-1;
while(sp->sos_end[sp->plane_sample_offset].log==0)
sp->plane_sample_offset--;
sp->in_buffer_source=sp->sos_end[sp->plane_sample_offset].in_buffer_source;
sp->in_buffer_next_strile=sp->sos_end[sp->plane_sample_offset].in_buffer_next_strile;
sp->in_buffer_file_pos=sp->sos_end[sp->plane_sample_offset].in_buffer_file_pos;
sp->in_buffer_file_pos_log=0;
sp->in_buffer_file_togo=sp->sos_end[sp->plane_sample_offset].in_buffer_file_togo;
sp->in_buffer_togo=0;
sp->in_buffer_cur=0;
while(sp->plane_sample_offset<s)
{
do
{
if (OJPEGReadByte(sp,&m)==0)
return(0);
if (m==255)
{
do
{
if (OJPEGReadByte(sp,&m)==0)
return(0);
if (m!=255)
break;
} while(1);
if (m==JPEG_MARKER_SOS)
break;
}
} while(1);
sp->plane_sample_offset++;
if (OJPEGReadHeaderInfoSecStreamSos(tif)==0)
return(0);
sp->sos_end[sp->plane_sample_offset].log=1;
sp->sos_end[sp->plane_sample_offset].in_buffer_source=sp->in_buffer_source;
sp->sos_end[sp->plane_sample_offset].in_buffer_next_strile=sp->in_buffer_next_strile;
sp->sos_end[sp->plane_sample_offset].in_buffer_file_pos=sp->in_buffer_file_pos-sp->in_buffer_togo;
sp->sos_end[sp->plane_sample_offset].in_buffer_file_togo=sp->in_buffer_file_togo+sp->in_buffer_togo;
}
return(1);
}
static int
OJPEGWriteHeaderInfo(TIFF* tif)
{
static const char module[]="OJPEGWriteHeaderInfo";
OJPEGState* sp=(OJPEGState*)tif->tif_data;
uint8** m;
uint32 n;
if (sp->libjpeg_session_active != 0)
return 0;
sp->out_state=ososSoi;
sp->restart_index=0;
jpeg_std_error(&(sp->libjpeg_jpeg_error_mgr));
sp->libjpeg_jpeg_error_mgr.output_message=OJPEGLibjpegJpegErrorMgrOutputMessage;
sp->libjpeg_jpeg_error_mgr.error_exit=OJPEGLibjpegJpegErrorMgrErrorExit;
sp->libjpeg_jpeg_decompress_struct.err=&(sp->libjpeg_jpeg_error_mgr);
sp->libjpeg_jpeg_decompress_struct.client_data=(void*)tif;
if (jpeg_create_decompress_encap(sp,&(sp->libjpeg_jpeg_decompress_struct))==0)
return(0);
sp->libjpeg_session_active=1;
sp->libjpeg_jpeg_source_mgr.bytes_in_buffer=0;
sp->libjpeg_jpeg_source_mgr.init_source=OJPEGLibjpegJpegSourceMgrInitSource;
sp->libjpeg_jpeg_source_mgr.fill_input_buffer=OJPEGLibjpegJpegSourceMgrFillInputBuffer;
sp->libjpeg_jpeg_source_mgr.skip_input_data=OJPEGLibjpegJpegSourceMgrSkipInputData;
sp->libjpeg_jpeg_source_mgr.resync_to_restart=OJPEGLibjpegJpegSourceMgrResyncToRestart;
sp->libjpeg_jpeg_source_mgr.term_source=OJPEGLibjpegJpegSourceMgrTermSource;
sp->libjpeg_jpeg_decompress_struct.src=&(sp->libjpeg_jpeg_source_mgr);
if (jpeg_read_header_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),1)==0)
return(0);
if ((sp->subsampling_force_desubsampling_inside_decompression==0) && (sp->samples_per_pixel_per_plane>1))
{
sp->libjpeg_jpeg_decompress_struct.raw_data_out=1;
#if JPEG_LIB_VERSION >= 70
sp->libjpeg_jpeg_decompress_struct.do_fancy_upsampling=FALSE;
#endif
sp->libjpeg_jpeg_query_style=0;
if (sp->subsampling_convert_log==0)
{
assert(sp->subsampling_convert_ycbcrbuf==0);
assert(sp->subsampling_convert_ycbcrimage==0);
sp->subsampling_convert_ylinelen=((sp->strile_width+sp->subsampling_hor*8-1)/(sp->subsampling_hor*8)*sp->subsampling_hor*8);
sp->subsampling_convert_ylines=sp->subsampling_ver*8;
sp->subsampling_convert_clinelen=sp->subsampling_convert_ylinelen/sp->subsampling_hor;
sp->subsampling_convert_clines=8;
sp->subsampling_convert_ybuflen=sp->subsampling_convert_ylinelen*sp->subsampling_convert_ylines;
sp->subsampling_convert_cbuflen=sp->subsampling_convert_clinelen*sp->subsampling_convert_clines;
sp->subsampling_convert_ycbcrbuflen=sp->subsampling_convert_ybuflen+2*sp->subsampling_convert_cbuflen;
sp->subsampling_convert_ycbcrbuf=_TIFFmalloc(sp->subsampling_convert_ycbcrbuflen);
if (sp->subsampling_convert_ycbcrbuf==0)
{
TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
return(0);
}
sp->subsampling_convert_ybuf=sp->subsampling_convert_ycbcrbuf;
sp->subsampling_convert_cbbuf=sp->subsampling_convert_ybuf+sp->subsampling_convert_ybuflen;
sp->subsampling_convert_crbuf=sp->subsampling_convert_cbbuf+sp->subsampling_convert_cbuflen;
sp->subsampling_convert_ycbcrimagelen=3+sp->subsampling_convert_ylines+2*sp->subsampling_convert_clines;
sp->subsampling_convert_ycbcrimage=_TIFFmalloc(sp->subsampling_convert_ycbcrimagelen*sizeof(uint8*));
if (sp->subsampling_convert_ycbcrimage==0)
{
TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
return(0);
}
m=sp->subsampling_convert_ycbcrimage;
*m++=(uint8*)(sp->subsampling_convert_ycbcrimage+3);
*m++=(uint8*)(sp->subsampling_convert_ycbcrimage+3+sp->subsampling_convert_ylines);
*m++=(uint8*)(sp->subsampling_convert_ycbcrimage+3+sp->subsampling_convert_ylines+sp->subsampling_convert_clines);
for (n=0; n<sp->subsampling_convert_ylines; n++)
*m++=sp->subsampling_convert_ybuf+n*sp->subsampling_convert_ylinelen;
for (n=0; n<sp->subsampling_convert_clines; n++)
*m++=sp->subsampling_convert_cbbuf+n*sp->subsampling_convert_clinelen;
for (n=0; n<sp->subsampling_convert_clines; n++)
*m++=sp->subsampling_convert_crbuf+n*sp->subsampling_convert_clinelen;
sp->subsampling_convert_clinelenout=((sp->strile_width+sp->subsampling_hor-1)/sp->subsampling_hor);
sp->subsampling_convert_state=0;
sp->bytes_per_line=sp->subsampling_convert_clinelenout*(sp->subsampling_ver*sp->subsampling_hor+2);
sp->lines_per_strile=((sp->strile_length+sp->subsampling_ver-1)/sp->subsampling_ver);
sp->subsampling_convert_log=1;
}
}
else
{
sp->libjpeg_jpeg_decompress_struct.jpeg_color_space=JCS_UNKNOWN;
sp->libjpeg_jpeg_decompress_struct.out_color_space=JCS_UNKNOWN;
sp->libjpeg_jpeg_query_style=1;
sp->bytes_per_line=sp->samples_per_pixel_per_plane*sp->strile_width;
sp->lines_per_strile=sp->strile_length;
}
if (jpeg_start_decompress_encap(sp,&(sp->libjpeg_jpeg_decompress_struct))==0)
return(0);
sp->writeheader_done=1;
return(1);
}
static void
OJPEGLibjpegSessionAbort(TIFF* tif)
{
OJPEGState* sp=(OJPEGState*)tif->tif_data;
assert(sp->libjpeg_session_active!=0);
jpeg_destroy((jpeg_common_struct*)(&(sp->libjpeg_jpeg_decompress_struct)));
sp->libjpeg_session_active=0;
}
static int
OJPEGReadHeaderInfoSec(TIFF* tif)
{
static const char module[]="OJPEGReadHeaderInfoSec";
OJPEGState* sp=(OJPEGState*)tif->tif_data;
uint8 m;
uint16 n;
uint8 o;
if (sp->file_size==0)
sp->file_size=TIFFGetFileSize(tif);
if (sp->jpeg_interchange_format!=0)
{
if (sp->jpeg_interchange_format>=sp->file_size)
{
sp->jpeg_interchange_format=0;
sp->jpeg_interchange_format_length=0;
}
else
{
if ((sp->jpeg_interchange_format_length==0) || (sp->jpeg_interchange_format+sp->jpeg_interchange_format_length>sp->file_size))
sp->jpeg_interchange_format_length=sp->file_size-sp->jpeg_interchange_format;
}
}
sp->in_buffer_source=osibsNotSetYet;
sp->in_buffer_next_strile=0;
sp->in_buffer_strile_count=tif->tif_dir.td_nstrips;
sp->in_buffer_file_togo=0;
sp->in_buffer_togo=0;
do
{
if (OJPEGReadBytePeek(sp,&m)==0)
return(0);
if (m!=255)
break;
OJPEGReadByteAdvance(sp);
do
{
if (OJPEGReadByte(sp,&m)==0)
return(0);
} while(m==255);
switch(m)
{
case JPEG_MARKER_SOI:
break;
case JPEG_MARKER_COM:
case JPEG_MARKER_APP0:
case JPEG_MARKER_APP0+1:
case JPEG_MARKER_APP0+2:
case JPEG_MARKER_APP0+3:
case JPEG_MARKER_APP0+4:
case JPEG_MARKER_APP0+5:
case JPEG_MARKER_APP0+6:
case JPEG_MARKER_APP0+7:
case JPEG_MARKER_APP0+8:
case JPEG_MARKER_APP0+9:
case JPEG_MARKER_APP0+10:
case JPEG_MARKER_APP0+11:
case JPEG_MARKER_APP0+12:
case JPEG_MARKER_APP0+13:
case JPEG_MARKER_APP0+14:
case JPEG_MARKER_APP0+15:
if (OJPEGReadWord(sp,&n)==0)
return(0);
if (n<2)
{
if (sp->subsamplingcorrect==0)
TIFFErrorExt(tif->tif_clientdata,module,"Corrupt JPEG data");
return(0);
}
if (n>2)
OJPEGReadSkip(sp,n-2);
break;
case JPEG_MARKER_DRI:
if (OJPEGReadHeaderInfoSecStreamDri(tif)==0)
return(0);
break;
case JPEG_MARKER_DQT:
if (OJPEGReadHeaderInfoSecStreamDqt(tif)==0)
return(0);
break;
case JPEG_MARKER_DHT:
if (OJPEGReadHeaderInfoSecStreamDht(tif)==0)
return(0);
break;
case JPEG_MARKER_SOF0:
case JPEG_MARKER_SOF1:
case JPEG_MARKER_SOF3:
if (OJPEGReadHeaderInfoSecStreamSof(tif,m)==0)
return(0);
if (sp->subsamplingcorrect!=0)
return(1);
break;
case JPEG_MARKER_SOS:
if (sp->subsamplingcorrect!=0)
return(1);
assert(sp->plane_sample_offset==0);
if (OJPEGReadHeaderInfoSecStreamSos(tif)==0)
return(0);
break;
default:
TIFFErrorExt(tif->tif_clientdata,module,"Unknown marker type %d in JPEG data",m);
return(0);
}
} while(m!=JPEG_MARKER_SOS);
if (sp->subsamplingcorrect)
return(1);
if (sp->sof_log==0)
{
if (OJPEGReadHeaderInfoSecTablesQTable(tif)==0)
return(0);
sp->sof_marker_id=JPEG_MARKER_SOF0;
for (o=0; o<sp->samples_per_pixel; o++)
sp->sof_c[o]=o;
sp->sof_hv[0]=((sp->subsampling_hor<<4)|sp->subsampling_ver);
for (o=1; o<sp->samples_per_pixel; o++)
sp->sof_hv[o]=17;
sp->sof_x=sp->strile_width;
sp->sof_y=sp->strile_length_total;
sp->sof_log=1;
if (OJPEGReadHeaderInfoSecTablesDcTable(tif)==0)
return(0);
if (OJPEGReadHeaderInfoSecTablesAcTable(tif)==0)
return(0);
for (o=1; o<sp->samples_per_pixel; o++)
sp->sos_cs[o]=o;
}
return(1);
}
static int
OJPEGReadHeaderInfoSecStreamDri(TIFF* tif)
{
static const char module[]="OJPEGReadHeaderInfoSecStreamDri";
OJPEGState* sp=(OJPEGState*)tif->tif_data;
uint16 m;
if (OJPEGReadWord(sp,&m)==0)
return(0);
if (m!=4)
{
TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DRI marker in JPEG data");
return(0);
}
if (OJPEGReadWord(sp,&m)==0)
return(0);
sp->restart_interval=m;
return(1);
}
static int
OJPEGReadHeaderInfoSecStreamDqt(TIFF* tif)
{
static const char module[]="OJPEGReadHeaderInfoSecStreamDqt";
OJPEGState* sp=(OJPEGState*)tif->tif_data;
uint16 m;
uint32 na;
uint8* nb;
uint8 o;
if (OJPEGReadWord(sp,&m)==0)
return(0);
if (m<=2)
{
if (sp->subsamplingcorrect==0)
TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DQT marker in JPEG data");
return(0);
}
if (sp->subsamplingcorrect!=0)
OJPEGReadSkip(sp,m-2);
else
{
m-=2;
do
{
if (m<65)
{
TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DQT marker in JPEG data");
return(0);
}
na=sizeof(uint32)+69;
nb=_TIFFmalloc(na);
if (nb==0)
{
TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
return(0);
}
*(uint32*)nb=na;
nb[sizeof(uint32)]=255;
nb[sizeof(uint32)+1]=JPEG_MARKER_DQT;
nb[sizeof(uint32)+2]=0;
nb[sizeof(uint32)+3]=67;
if (OJPEGReadBlock(sp,65,&nb[sizeof(uint32)+4])==0) {
_TIFFfree(nb);
return(0);
}
o=nb[sizeof(uint32)+4]&15;
if (3<o)
{
TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DQT marker in JPEG data");
_TIFFfree(nb);
return(0);
}
if (sp->qtable[o]!=0)
_TIFFfree(sp->qtable[o]);
sp->qtable[o]=nb;
m-=65;
} while(m>0);
}
return(1);
}
static int
OJPEGReadHeaderInfoSecStreamDht(TIFF* tif)
{
static const char module[]="OJPEGReadHeaderInfoSecStreamDht";
OJPEGState* sp=(OJPEGState*)tif->tif_data;
uint16 m;
uint32 na;
uint8* nb;
uint8 o;
if (OJPEGReadWord(sp,&m)==0)
return(0);
if (m<=2)
{
if (sp->subsamplingcorrect==0)
TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DHT marker in JPEG data");
return(0);
}
if (sp->subsamplingcorrect!=0)
{
OJPEGReadSkip(sp,m-2);
}
else
{
na=sizeof(uint32)+2+m;
nb=_TIFFmalloc(na);
if (nb==0)
{
TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
return(0);
}
*(uint32*)nb=na;
nb[sizeof(uint32)]=255;
nb[sizeof(uint32)+1]=JPEG_MARKER_DHT;
nb[sizeof(uint32)+2]=(m>>8);
nb[sizeof(uint32)+3]=(m&255);
if (OJPEGReadBlock(sp,m-2,&nb[sizeof(uint32)+4])==0)
return(0);
o=nb[sizeof(uint32)+4];
if ((o&240)==0)
{
if (3<o)
{
TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DHT marker in JPEG data");
return(0);
}
if (sp->dctable[o]!=0)
_TIFFfree(sp->dctable[o]);
sp->dctable[o]=nb;
}
else
{
if ((o&240)!=16)
{
TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DHT marker in JPEG data");
return(0);
}
o&=15;
if (3<o)
{
TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DHT marker in JPEG data");
return(0);
}
if (sp->actable[o]!=0)
_TIFFfree(sp->actable[o]);
sp->actable[o]=nb;
}
}
return(1);
}
static int
OJPEGReadHeaderInfoSecStreamSof(TIFF* tif, uint8 marker_id)
{
static const char module[]="OJPEGReadHeaderInfoSecStreamSof";
OJPEGState* sp=(OJPEGState*)tif->tif_data;
uint16 m;
uint16 n;
uint8 o;
uint16 p;
uint16 q;
if (sp->sof_log!=0)
{
TIFFErrorExt(tif->tif_clientdata,module,"Corrupt JPEG data");
return(0);
}
if (sp->subsamplingcorrect==0)
sp->sof_marker_id=marker_id;
if (OJPEGReadWord(sp,&m)==0)
return(0);
if (m<11)
{
if (sp->subsamplingcorrect==0)
TIFFErrorExt(tif->tif_clientdata,module,"Corrupt SOF marker in JPEG data");
return(0);
}
m-=8;
if (m%3!=0)
{
if (sp->subsamplingcorrect==0)
TIFFErrorExt(tif->tif_clientdata,module,"Corrupt SOF marker in JPEG data");
return(0);
}
n=m/3;
if (sp->subsamplingcorrect==0)
{
if (n!=sp->samples_per_pixel)
{
TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data indicates unexpected number of samples");
return(0);
}
}
if (OJPEGReadByte(sp,&o)==0)
return(0);
if (o!=8)
{
if (sp->subsamplingcorrect==0)
TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data indicates unexpected number of bits per sample");
return(0);
}
if (sp->subsamplingcorrect)
OJPEGReadSkip(sp,4);
else
{
if (OJPEGReadWord(sp,&p)==0)
return(0);
if (((uint32)p<sp->image_length) && ((uint32)p<sp->strile_length_total))
{
TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data indicates unexpected height");
return(0);
}
sp->sof_y=p;
if (OJPEGReadWord(sp,&p)==0)
return(0);
if (((uint32)p<sp->image_width) && ((uint32)p<sp->strile_width))
{
TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data indicates unexpected width");
return(0);
}
if ((uint32)p>sp->strile_width)
{
TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data image width exceeds expected image width");
return(0);
}
sp->sof_x=p;
}
if (OJPEGReadByte(sp,&o)==0)
return(0);
if (o!=n)
{
if (sp->subsamplingcorrect==0)
TIFFErrorExt(tif->tif_clientdata,module,"Corrupt SOF marker in JPEG data");
return(0);
}
for (q=0; q<n; q++)
{
if (OJPEGReadByte(sp,&o)==0)
return(0);
if (sp->subsamplingcorrect==0)
sp->sof_c[q]=o;
if (OJPEGReadByte(sp,&o)==0)
return(0);
if (sp->subsamplingcorrect!=0)
{
if (q==0)
{
sp->subsampling_hor=(o>>4);
sp->subsampling_ver=(o&15);
if (((sp->subsampling_hor!=1) && (sp->subsampling_hor!=2) && (sp->subsampling_hor!=4)) ||
((sp->subsampling_ver!=1) && (sp->subsampling_ver!=2) && (sp->subsampling_ver!=4)))
sp->subsampling_force_desubsampling_inside_decompression=1;
}
else
{
if (o!=17)
sp->subsampling_force_desubsampling_inside_decompression=1;
}
}
else
{
sp->sof_hv[q]=o;
if (sp->subsampling_force_desubsampling_inside_decompression==0)
{
if (q==0)
{
if (o!=((sp->subsampling_hor<<4)|sp->subsampling_ver))
{
TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data indicates unexpected subsampling values");
return(0);
}
}
else
{
if (o!=17)
{
TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data indicates unexpected subsampling values");
return(0);
}
}
}
}
if (OJPEGReadByte(sp,&o)==0)
return(0);
if (sp->subsamplingcorrect==0)
sp->sof_tq[q]=o;
}
if (sp->subsamplingcorrect==0)
sp->sof_log=1;
return(1);
}
static int
OJPEGReadHeaderInfoSecStreamSos(TIFF* tif)
{
static const char module[]="OJPEGReadHeaderInfoSecStreamSos";
OJPEGState* sp=(OJPEGState*)tif->tif_data;
uint16 m;
uint8 n;
uint8 o;
assert(sp->subsamplingcorrect==0);
if (sp->sof_log==0)
{
TIFFErrorExt(tif->tif_clientdata,module,"Corrupt SOS marker in JPEG data");
return(0);
}
if (OJPEGReadWord(sp,&m)==0)
return(0);
if (m!=6+sp->samples_per_pixel_per_plane*2)
{
TIFFErrorExt(tif->tif_clientdata,module,"Corrupt SOS marker in JPEG data");
return(0);
}
if (OJPEGReadByte(sp,&n)==0)
return(0);
if (n!=sp->samples_per_pixel_per_plane)
{
TIFFErrorExt(tif->tif_clientdata,module,"Corrupt SOS marker in JPEG data");
return(0);
}
for (o=0; o<sp->samples_per_pixel_per_plane; o++)
{
if (OJPEGReadByte(sp,&n)==0)
return(0);
sp->sos_cs[sp->plane_sample_offset+o]=n;
if (OJPEGReadByte(sp,&n)==0)
return(0);
sp->sos_tda[sp->plane_sample_offset+o]=n;
}
OJPEGReadSkip(sp,3);
return(1);
}
static int
OJPEGReadHeaderInfoSecTablesQTable(TIFF* tif)
{
static const char module[]="OJPEGReadHeaderInfoSecTablesQTable";
OJPEGState* sp=(OJPEGState*)tif->tif_data;
uint8 m;
uint8 n;
uint32 oa;
uint8* ob;
uint32 p;
if (sp->qtable_offset[0]==0)
{
TIFFErrorExt(tif->tif_clientdata,module,"Missing JPEG tables");
return(0);
}
sp->in_buffer_file_pos_log=0;
for (m=0; m<sp->samples_per_pixel; m++)
{
if ((sp->qtable_offset[m]!=0) && ((m==0) || (sp->qtable_offset[m]!=sp->qtable_offset[m-1])))
{
for (n=0; n<m-1; n++)
{
if (sp->qtable_offset[m]==sp->qtable_offset[n])
{
TIFFErrorExt(tif->tif_clientdata,module,"Corrupt JpegQTables tag value");
return(0);
}
}
oa=sizeof(uint32)+69;
ob=_TIFFmalloc(oa);
if (ob==0)
{
TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
return(0);
}
*(uint32*)ob=oa;
ob[sizeof(uint32)]=255;
ob[sizeof(uint32)+1]=JPEG_MARKER_DQT;
ob[sizeof(uint32)+2]=0;
ob[sizeof(uint32)+3]=67;
ob[sizeof(uint32)+4]=m;
TIFFSeekFile(tif,sp->qtable_offset[m],SEEK_SET);
p=TIFFReadFile(tif,&ob[sizeof(uint32)+5],64);
if (p!=64)
return(0);
sp->qtable[m]=ob;
sp->sof_tq[m]=m;
}
else
sp->sof_tq[m]=sp->sof_tq[m-1];
}
return(1);
}
static int
OJPEGReadHeaderInfoSecTablesDcTable(TIFF* tif)
{
static const char module[]="OJPEGReadHeaderInfoSecTablesDcTable";
OJPEGState* sp=(OJPEGState*)tif->tif_data;
uint8 m;
uint8 n;
uint8 o[16];
uint32 p;
uint32 q;
uint32 ra;
uint8* rb;
if (sp->dctable_offset[0]==0)
{
TIFFErrorExt(tif->tif_clientdata,module,"Missing JPEG tables");
return(0);
}
sp->in_buffer_file_pos_log=0;
for (m=0; m<sp->samples_per_pixel; m++)
{
if ((sp->dctable_offset[m]!=0) && ((m==0) || (sp->dctable_offset[m]!=sp->dctable_offset[m-1])))
{
for (n=0; n<m-1; n++)
{
if (sp->dctable_offset[m]==sp->dctable_offset[n])
{
TIFFErrorExt(tif->tif_clientdata,module,"Corrupt JpegDcTables tag value");
return(0);
}
}
TIFFSeekFile(tif,sp->dctable_offset[m],SEEK_SET);
p=TIFFReadFile(tif,o,16);
if (p!=16)
return(0);
q=0;
for (n=0; n<16; n++)
q+=o[n];
ra=sizeof(uint32)+21+q;
rb=_TIFFmalloc(ra);
if (rb==0)
{
TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
return(0);
}
*(uint32*)rb=ra;
rb[sizeof(uint32)]=255;
rb[sizeof(uint32)+1]=JPEG_MARKER_DHT;
rb[sizeof(uint32)+2]=((19+q)>>8);
rb[sizeof(uint32)+3]=((19+q)&255);
rb[sizeof(uint32)+4]=m;
for (n=0; n<16; n++)
rb[sizeof(uint32)+5+n]=o[n];
p=TIFFReadFile(tif,&(rb[sizeof(uint32)+21]),q);
if (p!=q)
return(0);
sp->dctable[m]=rb;
sp->sos_tda[m]=(m<<4);
}
else
sp->sos_tda[m]=sp->sos_tda[m-1];
}
return(1);
}
static int
OJPEGReadHeaderInfoSecTablesAcTable(TIFF* tif)
{
static const char module[]="OJPEGReadHeaderInfoSecTablesAcTable";
OJPEGState* sp=(OJPEGState*)tif->tif_data;
uint8 m;
uint8 n;
uint8 o[16];
uint32 p;
uint32 q;
uint32 ra;
uint8* rb;
if (sp->actable_offset[0]==0)
{
TIFFErrorExt(tif->tif_clientdata,module,"Missing JPEG tables");
return(0);
}
sp->in_buffer_file_pos_log=0;
for (m=0; m<sp->samples_per_pixel; m++)
{
if ((sp->actable_offset[m]!=0) && ((m==0) || (sp->actable_offset[m]!=sp->actable_offset[m-1])))
{
for (n=0; n<m-1; n++)
{
if (sp->actable_offset[m]==sp->actable_offset[n])
{
TIFFErrorExt(tif->tif_clientdata,module,"Corrupt JpegAcTables tag value");
return(0);
}
}
TIFFSeekFile(tif,sp->actable_offset[m],SEEK_SET);
p=TIFFReadFile(tif,o,16);
if (p!=16)
return(0);
q=0;
for (n=0; n<16; n++)
q+=o[n];
ra=sizeof(uint32)+21+q;
rb=_TIFFmalloc(ra);
if (rb==0)
{
TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
return(0);
}
*(uint32*)rb=ra;
rb[sizeof(uint32)]=255;
rb[sizeof(uint32)+1]=JPEG_MARKER_DHT;
rb[sizeof(uint32)+2]=((19+q)>>8);
rb[sizeof(uint32)+3]=((19+q)&255);
rb[sizeof(uint32)+4]=(16|m);
for (n=0; n<16; n++)
rb[sizeof(uint32)+5+n]=o[n];
p=TIFFReadFile(tif,&(rb[sizeof(uint32)+21]),q);
if (p!=q)
return(0);
sp->actable[m]=rb;
sp->sos_tda[m]=(sp->sos_tda[m]|m);
}
else
sp->sos_tda[m]=(sp->sos_tda[m]|(sp->sos_tda[m-1]&15));
}
return(1);
}
static int
OJPEGReadBufferFill(OJPEGState* sp)
{
uint16 m;
tmsize_t n;
do
{
if (sp->in_buffer_file_togo!=0)
{
if (sp->in_buffer_file_pos_log==0)
{
TIFFSeekFile(sp->tif,sp->in_buffer_file_pos,SEEK_SET);
sp->in_buffer_file_pos_log=1;
}
m=OJPEG_BUFFER;
if ((uint64)m>sp->in_buffer_file_togo)
m=(uint16)sp->in_buffer_file_togo;
n=TIFFReadFile(sp->tif,sp->in_buffer,(tmsize_t)m);
if (n==0)
return(0);
assert(n>0);
assert(n<=OJPEG_BUFFER);
assert(n<65536);
assert((uint64)n<=sp->in_buffer_file_togo);
m=(uint16)n;
sp->in_buffer_togo=m;
sp->in_buffer_cur=sp->in_buffer;
sp->in_buffer_file_togo-=m;
sp->in_buffer_file_pos+=m;
break;
}
sp->in_buffer_file_pos_log=0;
switch(sp->in_buffer_source)
{
case osibsNotSetYet:
if (sp->jpeg_interchange_format!=0)
{
sp->in_buffer_file_pos=sp->jpeg_interchange_format;
sp->in_buffer_file_togo=sp->jpeg_interchange_format_length;
}
sp->in_buffer_source=osibsJpegInterchangeFormat;
break;
case osibsJpegInterchangeFormat:
sp->in_buffer_source=osibsStrile;
case osibsStrile:
if (!_TIFFFillStriles( sp->tif )
|| sp->tif->tif_dir.td_stripoffset == NULL
|| sp->tif->tif_dir.td_stripbytecount == NULL)
return 0;
if (sp->in_buffer_next_strile==sp->in_buffer_strile_count)
sp->in_buffer_source=osibsEof;
else
{
sp->in_buffer_file_pos=sp->tif->tif_dir.td_stripoffset[sp->in_buffer_next_strile];
if (sp->in_buffer_file_pos!=0)
{
if (sp->in_buffer_file_pos>=sp->file_size)
sp->in_buffer_file_pos=0;
else if (sp->tif->tif_dir.td_stripbytecount==NULL)
sp->in_buffer_file_togo=sp->file_size-sp->in_buffer_file_pos;
else
{
if (sp->tif->tif_dir.td_stripbytecount == 0) {
TIFFErrorExt(sp->tif->tif_clientdata,sp->tif->tif_name,"Strip byte counts are missing");
return(0);
}
sp->in_buffer_file_togo=sp->tif->tif_dir.td_stripbytecount[sp->in_buffer_next_strile];
if (sp->in_buffer_file_togo==0)
sp->in_buffer_file_pos=0;
else if (sp->in_buffer_file_pos+sp->in_buffer_file_togo>sp->file_size)
sp->in_buffer_file_togo=sp->file_size-sp->in_buffer_file_pos;
}
}
sp->in_buffer_next_strile++;
}
break;
default:
return(0);
}
} while (1);
return(1);
}
static int
OJPEGReadByte(OJPEGState* sp, uint8* byte)
{
if (sp->in_buffer_togo==0)
{
if (OJPEGReadBufferFill(sp)==0)
return(0);
assert(sp->in_buffer_togo>0);
}
*byte=*(sp->in_buffer_cur);
sp->in_buffer_cur++;
sp->in_buffer_togo--;
return(1);
}
static int
OJPEGReadBytePeek(OJPEGState* sp, uint8* byte)
{
if (sp->in_buffer_togo==0)
{
if (OJPEGReadBufferFill(sp)==0)
return(0);
assert(sp->in_buffer_togo>0);
}
*byte=*(sp->in_buffer_cur);
return(1);
}
static void
OJPEGReadByteAdvance(OJPEGState* sp)
{
assert(sp->in_buffer_togo>0);
sp->in_buffer_cur++;
sp->in_buffer_togo--;
}
static int
OJPEGReadWord(OJPEGState* sp, uint16* word)
{
uint8 m;
if (OJPEGReadByte(sp,&m)==0)
return(0);
*word=(m<<8);
if (OJPEGReadByte(sp,&m)==0)
return(0);
*word|=m;
return(1);
}
static int
OJPEGReadBlock(OJPEGState* sp, uint16 len, void* mem)
{
uint16 mlen;
uint8* mmem;
uint16 n;
assert(len>0);
mlen=len;
mmem=mem;
do
{
if (sp->in_buffer_togo==0)
{
if (OJPEGReadBufferFill(sp)==0)
return(0);
assert(sp->in_buffer_togo>0);
}
n=mlen;
if (n>sp->in_buffer_togo)
n=sp->in_buffer_togo;
_TIFFmemcpy(mmem,sp->in_buffer_cur,n);
sp->in_buffer_cur+=n;
sp->in_buffer_togo-=n;
mlen-=n;
mmem+=n;
} while(mlen>0);
return(1);
}
static void
OJPEGReadSkip(OJPEGState* sp, uint16 len)
{
uint16 m;
uint16 n;
m=len;
n=m;
if (n>sp->in_buffer_togo)
n=sp->in_buffer_togo;
sp->in_buffer_cur+=n;
sp->in_buffer_togo-=n;
m-=n;
if (m>0)
{
assert(sp->in_buffer_togo==0);
n=m;
if ((uint64)n>sp->in_buffer_file_togo)
n=(uint16)sp->in_buffer_file_togo;
sp->in_buffer_file_pos+=n;
sp->in_buffer_file_togo-=n;
sp->in_buffer_file_pos_log=0;
}
}
static int
OJPEGWriteStream(TIFF* tif, void** mem, uint32* len)
{
OJPEGState* sp=(OJPEGState*)tif->tif_data;
*len=0;
do
{
assert(sp->out_state<=ososEoi);
switch(sp->out_state)
{
case ososSoi:
OJPEGWriteStreamSoi(tif,mem,len);
break;
case ososQTable0:
OJPEGWriteStreamQTable(tif,0,mem,len);
break;
case ososQTable1:
OJPEGWriteStreamQTable(tif,1,mem,len);
break;
case ososQTable2:
OJPEGWriteStreamQTable(tif,2,mem,len);
break;
case ososQTable3:
OJPEGWriteStreamQTable(tif,3,mem,len);
break;
case ososDcTable0:
OJPEGWriteStreamDcTable(tif,0,mem,len);
break;
case ososDcTable1:
OJPEGWriteStreamDcTable(tif,1,mem,len);
break;
case ososDcTable2:
OJPEGWriteStreamDcTable(tif,2,mem,len);
break;
case ososDcTable3:
OJPEGWriteStreamDcTable(tif,3,mem,len);
break;
case ososAcTable0:
OJPEGWriteStreamAcTable(tif,0,mem,len);
break;
case ososAcTable1:
OJPEGWriteStreamAcTable(tif,1,mem,len);
break;
case ososAcTable2:
OJPEGWriteStreamAcTable(tif,2,mem,len);
break;
case ososAcTable3:
OJPEGWriteStreamAcTable(tif,3,mem,len);
break;
case ososDri:
OJPEGWriteStreamDri(tif,mem,len);
break;
case ososSof:
OJPEGWriteStreamSof(tif,mem,len);
break;
case ososSos:
OJPEGWriteStreamSos(tif,mem,len);
break;
case ososCompressed:
if (OJPEGWriteStreamCompressed(tif,mem,len)==0)
return(0);
break;
case ososRst:
OJPEGWriteStreamRst(tif,mem,len);
break;
case ososEoi:
OJPEGWriteStreamEoi(tif,mem,len);
break;
}
} while (*len==0);
return(1);
}
static void
OJPEGWriteStreamSoi(TIFF* tif, void** mem, uint32* len)
{
OJPEGState* sp=(OJPEGState*)tif->tif_data;
assert(OJPEG_BUFFER>=2);
sp->out_buffer[0]=255;
sp->out_buffer[1]=JPEG_MARKER_SOI;
*len=2;
*mem=(void*)sp->out_buffer;
sp->out_state++;
}
static void
OJPEGWriteStreamQTable(TIFF* tif, uint8 table_index, void** mem, uint32* len)
{
OJPEGState* sp=(OJPEGState*)tif->tif_data;
if (sp->qtable[table_index]!=0)
{
*mem=(void*)(sp->qtable[table_index]+sizeof(uint32));
*len=*((uint32*)sp->qtable[table_index])-sizeof(uint32);
}
sp->out_state++;
}
static void
OJPEGWriteStreamDcTable(TIFF* tif, uint8 table_index, void** mem, uint32* len)
{
OJPEGState* sp=(OJPEGState*)tif->tif_data;
if (sp->dctable[table_index]!=0)
{
*mem=(void*)(sp->dctable[table_index]+sizeof(uint32));
*len=*((uint32*)sp->dctable[table_index])-sizeof(uint32);
}
sp->out_state++;
}
static void
OJPEGWriteStreamAcTable(TIFF* tif, uint8 table_index, void** mem, uint32* len)
{
OJPEGState* sp=(OJPEGState*)tif->tif_data;
if (sp->actable[table_index]!=0)
{
*mem=(void*)(sp->actable[table_index]+sizeof(uint32));
*len=*((uint32*)sp->actable[table_index])-sizeof(uint32);
}
sp->out_state++;
}
static void
OJPEGWriteStreamDri(TIFF* tif, void** mem, uint32* len)
{
OJPEGState* sp=(OJPEGState*)tif->tif_data;
assert(OJPEG_BUFFER>=6);
if (sp->restart_interval!=0)
{
sp->out_buffer[0]=255;
sp->out_buffer[1]=JPEG_MARKER_DRI;
sp->out_buffer[2]=0;
sp->out_buffer[3]=4;
sp->out_buffer[4]=(sp->restart_interval>>8);
sp->out_buffer[5]=(sp->restart_interval&255);
*len=6;
*mem=(void*)sp->out_buffer;
}
sp->out_state++;
}
static void
OJPEGWriteStreamSof(TIFF* tif, void** mem, uint32* len)
{
OJPEGState* sp=(OJPEGState*)tif->tif_data;
uint8 m;
assert(OJPEG_BUFFER>=2+8+sp->samples_per_pixel_per_plane*3);
assert(255>=8+sp->samples_per_pixel_per_plane*3);
sp->out_buffer[0]=255;
sp->out_buffer[1]=sp->sof_marker_id;
sp->out_buffer[2]=0;
sp->out_buffer[3]=8+sp->samples_per_pixel_per_plane*3;
sp->out_buffer[4]=8;
sp->out_buffer[5]=(sp->sof_y>>8);
sp->out_buffer[6]=(sp->sof_y&255);
sp->out_buffer[7]=(sp->sof_x>>8);
sp->out_buffer[8]=(sp->sof_x&255);
sp->out_buffer[9]=sp->samples_per_pixel_per_plane;
for (m=0; m<sp->samples_per_pixel_per_plane; m++)
{
sp->out_buffer[10+m*3]=sp->sof_c[sp->plane_sample_offset+m];
sp->out_buffer[10+m*3+1]=sp->sof_hv[sp->plane_sample_offset+m];
sp->out_buffer[10+m*3+2]=sp->sof_tq[sp->plane_sample_offset+m];
}
*len=10+sp->samples_per_pixel_per_plane*3;
*mem=(void*)sp->out_buffer;
sp->out_state++;
}
static void
OJPEGWriteStreamSos(TIFF* tif, void** mem, uint32* len)
{
OJPEGState* sp=(OJPEGState*)tif->tif_data;
uint8 m;
assert(OJPEG_BUFFER>=2+6+sp->samples_per_pixel_per_plane*2);
assert(255>=6+sp->samples_per_pixel_per_plane*2);
sp->out_buffer[0]=255;
sp->out_buffer[1]=JPEG_MARKER_SOS;
sp->out_buffer[2]=0;
sp->out_buffer[3]=6+sp->samples_per_pixel_per_plane*2;
sp->out_buffer[4]=sp->samples_per_pixel_per_plane;
for (m=0; m<sp->samples_per_pixel_per_plane; m++)
{
sp->out_buffer[5+m*2]=sp->sos_cs[sp->plane_sample_offset+m];
sp->out_buffer[5+m*2+1]=sp->sos_tda[sp->plane_sample_offset+m];
}
sp->out_buffer[5+sp->samples_per_pixel_per_plane*2]=0;
sp->out_buffer[5+sp->samples_per_pixel_per_plane*2+1]=63;
sp->out_buffer[5+sp->samples_per_pixel_per_plane*2+2]=0;
*len=8+sp->samples_per_pixel_per_plane*2;
*mem=(void*)sp->out_buffer;
sp->out_state++;
}
static int
OJPEGWriteStreamCompressed(TIFF* tif, void** mem, uint32* len)
{
OJPEGState* sp=(OJPEGState*)tif->tif_data;
if (sp->in_buffer_togo==0)
{
if (OJPEGReadBufferFill(sp)==0)
return(0);
assert(sp->in_buffer_togo>0);
}
*len=sp->in_buffer_togo;
*mem=(void*)sp->in_buffer_cur;
sp->in_buffer_togo=0;
if (sp->in_buffer_file_togo==0)
{
switch(sp->in_buffer_source)
{
case osibsStrile:
if (sp->in_buffer_next_strile<sp->in_buffer_strile_count)
sp->out_state=ososRst;
else
sp->out_state=ososEoi;
break;
case osibsEof:
sp->out_state=ososEoi;
break;
default:
break;
}
}
return(1);
}
static void
OJPEGWriteStreamRst(TIFF* tif, void** mem, uint32* len)
{
OJPEGState* sp=(OJPEGState*)tif->tif_data;
assert(OJPEG_BUFFER>=2);
sp->out_buffer[0]=255;
sp->out_buffer[1]=JPEG_MARKER_RST0+sp->restart_index;
sp->restart_index++;
if (sp->restart_index==8)
sp->restart_index=0;
*len=2;
*mem=(void*)sp->out_buffer;
sp->out_state=ososCompressed;
}
static void
OJPEGWriteStreamEoi(TIFF* tif, void** mem, uint32* len)
{
OJPEGState* sp=(OJPEGState*)tif->tif_data;
assert(OJPEG_BUFFER>=2);
sp->out_buffer[0]=255;
sp->out_buffer[1]=JPEG_MARKER_EOI;
*len=2;
*mem=(void*)sp->out_buffer;
}
#ifndef LIBJPEG_ENCAP_EXTERNAL
static int
jpeg_create_decompress_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo)
{
return(SETJMP(sp->exit_jmpbuf)?0:(jpeg_create_decompress(cinfo),1));
}
#endif
#ifndef LIBJPEG_ENCAP_EXTERNAL
static int
jpeg_read_header_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, uint8 require_image)
{
return(SETJMP(sp->exit_jmpbuf)?0:(jpeg_read_header(cinfo,require_image),1));
}
#endif
#ifndef LIBJPEG_ENCAP_EXTERNAL
static int
jpeg_start_decompress_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo)
{
return(SETJMP(sp->exit_jmpbuf)?0:(jpeg_start_decompress(cinfo),1));
}
#endif
#ifndef LIBJPEG_ENCAP_EXTERNAL
static int
jpeg_read_scanlines_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, void* scanlines, uint32 max_lines)
{
return(SETJMP(sp->exit_jmpbuf)?0:(jpeg_read_scanlines(cinfo,scanlines,max_lines),1));
}
#endif
#ifndef LIBJPEG_ENCAP_EXTERNAL
static int
jpeg_read_raw_data_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, void* data, uint32 max_lines)
{
return(SETJMP(sp->exit_jmpbuf)?0:(jpeg_read_raw_data(cinfo,data,max_lines),1));
}
#endif
#ifndef LIBJPEG_ENCAP_EXTERNAL
static void
jpeg_encap_unwind(TIFF* tif)
{
OJPEGState* sp=(OJPEGState*)tif->tif_data;
LONGJMP(sp->exit_jmpbuf,1);
}
#endif
static void
OJPEGLibjpegJpegErrorMgrOutputMessage(jpeg_common_struct* cinfo)
{
char buffer[JMSG_LENGTH_MAX];
(*cinfo->err->format_message)(cinfo,buffer);
TIFFWarningExt(((TIFF*)(cinfo->client_data))->tif_clientdata,"LibJpeg","%s",buffer);
}
static void
OJPEGLibjpegJpegErrorMgrErrorExit(jpeg_common_struct* cinfo)
{
char buffer[JMSG_LENGTH_MAX];
(*cinfo->err->format_message)(cinfo,buffer);
TIFFErrorExt(((TIFF*)(cinfo->client_data))->tif_clientdata,"LibJpeg","%s",buffer);
jpeg_encap_unwind((TIFF*)(cinfo->client_data));
}
static void
OJPEGLibjpegJpegSourceMgrInitSource(jpeg_decompress_struct* cinfo)
{
(void)cinfo;
}
static boolean
OJPEGLibjpegJpegSourceMgrFillInputBuffer(jpeg_decompress_struct* cinfo)
{
TIFF* tif=(TIFF*)cinfo->client_data;
OJPEGState* sp=(OJPEGState*)tif->tif_data;
void* mem=0;
uint32 len=0U;
if (OJPEGWriteStream(tif,&mem,&len)==0)
{
TIFFErrorExt(tif->tif_clientdata,"LibJpeg","Premature end of JPEG data");
jpeg_encap_unwind(tif);
}
sp->libjpeg_jpeg_source_mgr.bytes_in_buffer=len;
sp->libjpeg_jpeg_source_mgr.next_input_byte=mem;
return(1);
}
static void
OJPEGLibjpegJpegSourceMgrSkipInputData(jpeg_decompress_struct* cinfo, long num_bytes)
{
TIFF* tif=(TIFF*)cinfo->client_data;
(void)num_bytes;
TIFFErrorExt(tif->tif_clientdata,"LibJpeg","Unexpected error");
jpeg_encap_unwind(tif);
}
static boolean
OJPEGLibjpegJpegSourceMgrResyncToRestart(jpeg_decompress_struct* cinfo, int desired)
{
TIFF* tif=(TIFF*)cinfo->client_data;
(void)desired;
TIFFErrorExt(tif->tif_clientdata,"LibJpeg","Unexpected error");
jpeg_encap_unwind(tif);
return(0);
}
static void
OJPEGLibjpegJpegSourceMgrTermSource(jpeg_decompress_struct* cinfo)
{
(void)cinfo;
}
#endif