3 * Purpose: JPG Image Class Loader and Writer
\r
5 /* ==========================================================
\r
6 * CxImageJPG (c) 07/Aug/2001 Davide Pizzolato - www.xdp.it
\r
7 * For conditions of distribution and use, see copyright notice in ximage.h
\r
9 * Special thanks to Troels Knakkergaard for new features, enhancements and bugfixes
\r
11 * Special thanks to Chris Shearer Cooper for CxFileJpg tips & code
\r
13 * EXIF support based on jhead-1.8 by Matthias Wandel <mwandel(at)rim(dot)net>
\r
15 * original CImageJPG and CImageIterator implementation are:
\r
16 * Copyright: (c) 1995, Alejandro Aguilar Sierra <asierra(at)servidor(dot)unam(dot)mx>
\r
18 * This software is based in part on the work of the Independent JPEG Group.
\r
19 * Copyright (C) 1991-1998, Thomas G. Lane.
\r
20 * ==========================================================
\r
22 #if !defined(__ximaJPEG_h)
\r
23 #define __ximaJPEG_h
\r
27 #if CXIMAGE_SUPPORT_JPG
\r
29 #define CXIMAGEJPG_SUPPORT_EXIF 1
\r
32 #include "../jpeg/jpeglib.h"
\r
33 #include "../jpeg/jerror.h"
\r
36 class DLL_EXP CxImageJPG: public CxImage
\r
42 // bool Load(const TCHAR * imageFileName){ return CxImage::Load(imageFileName,CXIMAGE_FORMAT_JPG);}
\r
43 // bool Save(const TCHAR * imageFileName){ return CxImage::Save(imageFileName,CXIMAGE_FORMAT_JPG);}
\r
44 bool Decode(CxFile * hFile);
\r
45 bool Decode(FILE *hFile) { CxIOFile file(hFile); return Decode(&file); }
\r
47 #if CXIMAGE_SUPPORT_ENCODE
\r
48 bool Encode(CxFile * hFile);
\r
49 bool Encode(FILE *hFile) { CxIOFile file(hFile); return Encode(&file); }
\r
50 #endif // CXIMAGE_SUPPORT_ENCODE
\r
53 * EXIF support based on jhead-1.8 by Matthias Wandel <mwandel(at)rim(dot)net>
\r
56 #if CXIMAGEJPG_SUPPORT_EXIF
\r
58 #define MAX_COMMENT 1000
\r
59 #define MAX_SECTIONS 20
\r
61 typedef struct tag_ExifInfo {
\r
63 char CameraMake [32];
\r
64 char CameraModel [40];
\r
73 float ApertureFNumber;
\r
79 int ExposureProgram;
\r
81 int CompressionLevel;
\r
82 float FocalplaneXRes;
\r
83 float FocalplaneYRes;
\r
84 float FocalplaneUnits;
\r
87 float ResolutionUnit;
\r
89 char Comments[MAX_COMMENT];
\r
91 unsigned char * ThumbnailPointer; /* Pointer at the thumbnail */
\r
92 unsigned ThumbnailSize; /* Size of thumbnail. */
\r
97 //--------------------------------------------------------------------------
\r
98 // JPEG markers consist of one or more 0xFF bytes, followed by a marker
\r
99 // code byte (which is not an FF). Here are the marker codes of interest
\r
100 // in this program. (See jdmarker.c for a more complete list.)
\r
101 //--------------------------------------------------------------------------
\r
103 #define M_SOF0 0xC0 // Start Of Frame N
\r
104 #define M_SOF1 0xC1 // N indicates which compression process
\r
105 #define M_SOF2 0xC2 // Only SOF0-SOF2 are now in common use
\r
106 #define M_SOF3 0xC3
\r
107 #define M_SOF5 0xC5 // NB: codes C4 and CC are NOT SOF markers
\r
108 #define M_SOF6 0xC6
\r
109 #define M_SOF7 0xC7
\r
110 #define M_SOF9 0xC9
\r
111 #define M_SOF10 0xCA
\r
112 #define M_SOF11 0xCB
\r
113 #define M_SOF13 0xCD
\r
114 #define M_SOF14 0xCE
\r
115 #define M_SOF15 0xCF
\r
116 #define M_SOI 0xD8 // Start Of Image (beginning of datastream)
\r
117 #define M_EOI 0xD9 // End Of Image (end of datastream)
\r
118 #define M_SOS 0xDA // Start Of Scan (begins compressed data)
\r
119 #define M_JFIF 0xE0 // Jfif marker
\r
120 #define M_EXIF 0xE1 // Exif marker
\r
121 #define M_COM 0xFE // COMment
\r
123 #define PSEUDO_IMAGE_MARKER 0x123; // Extra value.
\r
125 #define EXIF_READ_EXIF 0x01
\r
126 #define EXIF_READ_IMAGE 0x02
\r
127 #define EXIF_READ_ALL 0x03
\r
129 class DLL_EXP CxExifInfo
\r
132 typedef struct tag_Section_t{
\r
139 EXIFINFO* m_exifinfo;
\r
140 char m_szLastError[256];
\r
141 CxExifInfo(EXIFINFO* info = NULL);
\r
143 bool DecodeExif(CxFile * hFile, int nReadMode = EXIF_READ_EXIF);
\r
144 bool EncodeExif(CxFile * hFile);
\r
145 void DiscardAllButExif();
\r
147 bool process_EXIF(unsigned char * CharBuf, unsigned int length);
\r
148 void process_COM (const BYTE * Data, int length);
\r
149 void process_SOFn (const BYTE * Data, int marker);
\r
150 int Get16u(void * Short);
\r
151 int Get16m(void * Short);
\r
152 long Get32s(void * Long);
\r
153 unsigned long Get32u(void * Long);
\r
154 double ConvertAnyFormat(void * ValuePtr, int Format);
\r
155 void* FindSection(int SectionType);
\r
156 bool ProcessExifDir(unsigned char * DirStart, unsigned char * OffsetBase, unsigned ExifLength,
\r
157 EXIFINFO * const pInfo, unsigned char ** const LastExifRefdP, int NestingLevel=0);
\r
158 int ExifImageWidth;
\r
160 Section_t Sections[MAX_SECTIONS];
\r
165 CxExifInfo* m_exif;
\r
166 EXIFINFO m_exifinfo;
\r
167 bool DecodeExif(CxFile * hFile);
\r
168 bool DecodeExif(FILE * hFile) { CxIOFile file(hFile); return DecodeExif(&file); }
\r
170 #endif //CXIMAGEJPG_SUPPORT_EXIF
\r
172 ////////////////////////////////////////////////////////////////////////////////////////
\r
173 ////////////////////// C x F i l e J p g ////////////////////////////////
\r
174 ////////////////////////////////////////////////////////////////////////////////////////
\r
176 // thanks to Chris Shearer Cooper <cscooper(at)frii(dot)com>
\r
177 class CxFileJpg : public jpeg_destination_mgr, public jpeg_source_mgr
\r
180 enum { eBufSize = 4096 };
\r
182 CxFileJpg(CxFile* pFile)
\r
186 init_destination = InitDestination;
\r
187 empty_output_buffer = EmptyOutputBuffer;
\r
188 term_destination = TermDestination;
\r
190 init_source = InitSource;
\r
191 fill_input_buffer = FillInputBuffer;
\r
192 skip_input_data = SkipInputData;
\r
193 resync_to_restart = jpeg_resync_to_restart; // use default method
\r
194 term_source = TermSource;
\r
195 next_input_byte = NULL; //* => next byte to read from buffer
\r
196 bytes_in_buffer = 0; //* # of bytes remaining in buffer
\r
198 m_pBuffer = new unsigned char[eBufSize];
\r
202 delete [] m_pBuffer;
\r
205 static void InitDestination(j_compress_ptr cinfo)
\r
207 CxFileJpg* pDest = (CxFileJpg*)cinfo->dest;
\r
208 pDest->next_output_byte = pDest->m_pBuffer;
\r
209 pDest->free_in_buffer = eBufSize;
\r
212 static boolean EmptyOutputBuffer(j_compress_ptr cinfo)
\r
214 CxFileJpg* pDest = (CxFileJpg*)cinfo->dest;
\r
215 if (pDest->m_pFile->Write(pDest->m_pBuffer,1,eBufSize)!=(size_t)eBufSize)
\r
216 ERREXIT(cinfo, JERR_FILE_WRITE);
\r
217 pDest->next_output_byte = pDest->m_pBuffer;
\r
218 pDest->free_in_buffer = eBufSize;
\r
222 static void TermDestination(j_compress_ptr cinfo)
\r
224 CxFileJpg* pDest = (CxFileJpg*)cinfo->dest;
\r
225 size_t datacount = eBufSize - pDest->free_in_buffer;
\r
226 /* Write any data remaining in the buffer */
\r
227 if (datacount > 0) {
\r
228 if (!pDest->m_pFile->Write(pDest->m_pBuffer,1,datacount))
\r
229 ERREXIT(cinfo, JERR_FILE_WRITE);
\r
231 pDest->m_pFile->Flush();
\r
232 /* Make sure we wrote the output file OK */
\r
233 if (pDest->m_pFile->Error()) ERREXIT(cinfo, JERR_FILE_WRITE);
\r
237 static void InitSource(j_decompress_ptr cinfo)
\r
239 CxFileJpg* pSource = (CxFileJpg*)cinfo->src;
\r
240 pSource->m_bStartOfFile = TRUE;
\r
243 static boolean FillInputBuffer(j_decompress_ptr cinfo)
\r
246 CxFileJpg* pSource = (CxFileJpg*)cinfo->src;
\r
247 nbytes = pSource->m_pFile->Read(pSource->m_pBuffer,1,eBufSize);
\r
249 if (pSource->m_bStartOfFile) //* Treat empty input file as fatal error
\r
250 ERREXIT(cinfo, JERR_INPUT_EMPTY);
\r
251 WARNMS(cinfo, JWRN_JPEG_EOF);
\r
252 // Insert a fake EOI marker
\r
253 pSource->m_pBuffer[0] = (JOCTET) 0xFF;
\r
254 pSource->m_pBuffer[1] = (JOCTET) JPEG_EOI;
\r
257 pSource->next_input_byte = pSource->m_pBuffer;
\r
258 pSource->bytes_in_buffer = nbytes;
\r
259 pSource->m_bStartOfFile = FALSE;
\r
263 static void SkipInputData(j_decompress_ptr cinfo, long num_bytes)
\r
265 CxFileJpg* pSource = (CxFileJpg*)cinfo->src;
\r
266 if (num_bytes > 0){
\r
267 while (num_bytes > (long)pSource->bytes_in_buffer){
\r
268 num_bytes -= (long)pSource->bytes_in_buffer;
\r
269 FillInputBuffer(cinfo);
\r
270 // note we assume that fill_input_buffer will never return FALSE,
\r
271 // so suspension need not be handled.
\r
273 pSource->next_input_byte += (size_t) num_bytes;
\r
274 pSource->bytes_in_buffer -= (size_t) num_bytes;
\r
278 static void TermSource(j_decompress_ptr /*cinfo*/)
\r
284 unsigned char *m_pBuffer;
\r
285 bool m_bStartOfFile;
\r
291 ENCODE_BASELINE = 0x1,
\r
292 ENCODE_ARITHMETIC = 0x2,
\r
293 ENCODE_GRAYSCALE = 0x4,
\r
294 ENCODE_OPTIMIZE = 0x8,
\r
295 ENCODE_PROGRESSIVE = 0x10,
\r
296 ENCODE_LOSSLESS = 0x20,
\r
297 ENCODE_SMOOTHING = 0x40,
\r
298 DECODE_GRAYSCALE = 0x80,
\r
299 DECODE_QUANTIZE = 0x100,
\r
300 DECODE_DITHER = 0x200,
\r
301 DECODE_ONEPASS = 0x400,
\r
302 DECODE_NOSMOOTH = 0x800,
\r
303 ENCODE_SUBSAMPLE_422 = 0x1000,
\r
304 ENCODE_SUBSAMPLE_444 = 0x2000
\r
308 int m_nPointTransform;
\r
311 J_DITHER_MODE m_nDither;
\r