]> Creatis software - clitk.git/blob - utilities/CxImage/ximajpg.h
899c6bc123beb2fd3e268809850736faa8b9b7d4
[clitk.git] / utilities / CxImage / ximajpg.h
1 /*\r
2  * File:        ximajpg.h\r
3  * Purpose:     JPG Image Class Loader and Writer\r
4  */\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
8  *\r
9  * Special thanks to Troels Knakkergaard for new features, enhancements and bugfixes\r
10  *\r
11  * Special thanks to Chris Shearer Cooper for CxFileJpg tips & code\r
12  *\r
13  * EXIF support based on jhead-1.8 by Matthias Wandel <mwandel(at)rim(dot)net>\r
14  *\r
15  * original CImageJPG  and CImageIterator implementation are:\r
16  * Copyright:   (c) 1995, Alejandro Aguilar Sierra <asierra(at)servidor(dot)unam(dot)mx>\r
17  *\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
21  */\r
22 #if !defined(__ximaJPEG_h)\r
23 #define __ximaJPEG_h\r
24 \r
25 #include "ximage.h"\r
26 \r
27 #if CXIMAGE_SUPPORT_JPG\r
28 \r
29 #define CXIMAGEJPG_SUPPORT_EXIF 1\r
30 \r
31 extern "C" {\r
32  #include "../jpeg/jpeglib.h"\r
33  #include "../jpeg/jerror.h"\r
34 }\r
35 \r
36 class DLL_EXP CxImageJPG: public CxImage\r
37 {\r
38 public:\r
39         CxImageJPG();\r
40         ~CxImageJPG();\r
41 \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
46 \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
51 \r
52 /*\r
53  * EXIF support based on jhead-1.8 by Matthias Wandel <mwandel(at)rim(dot)net>\r
54  */\r
55 \r
56 #if CXIMAGEJPG_SUPPORT_EXIF\r
57 \r
58 #define MAX_COMMENT 1000\r
59 #define MAX_SECTIONS 20\r
60 \r
61 typedef struct tag_ExifInfo {\r
62         char  Version      [5];\r
63     char  CameraMake   [32];\r
64     char  CameraModel  [40];\r
65     char  DateTime     [20];\r
66     int   Height, Width;\r
67     int   Orientation;\r
68     int   IsColor;\r
69     int   Process;\r
70     int   FlashUsed;\r
71     float FocalLength;\r
72     float ExposureTime;\r
73     float ApertureFNumber;\r
74     float Distance;\r
75     float CCDWidth;\r
76     float ExposureBias;\r
77     int   Whitebalance;\r
78     int   MeteringMode;\r
79     int   ExposureProgram;\r
80     int   ISOequivalent;\r
81     int   CompressionLevel;\r
82         float FocalplaneXRes;\r
83         float FocalplaneYRes;\r
84         float FocalplaneUnits;\r
85         float Xresolution;\r
86         float Yresolution;\r
87         float ResolutionUnit;\r
88         float Brightness;\r
89     char  Comments[MAX_COMMENT];\r
90 \r
91     unsigned char * ThumbnailPointer;  /* Pointer at the thumbnail */\r
92     unsigned ThumbnailSize;     /* Size of thumbnail. */\r
93 \r
94         bool  IsExif;\r
95 } EXIFINFO;\r
96 \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
102 \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
122 \r
123 #define PSEUDO_IMAGE_MARKER 0x123; // Extra value.\r
124 \r
125 #define EXIF_READ_EXIF  0x01\r
126 #define EXIF_READ_IMAGE 0x02\r
127 #define EXIF_READ_ALL   0x03\r
128 \r
129 class DLL_EXP CxExifInfo\r
130 {\r
131 \r
132 typedef struct tag_Section_t{\r
133     BYTE*    Data;\r
134     int      Type;\r
135     unsigned Size;\r
136 } Section_t;\r
137 \r
138 public:\r
139         EXIFINFO* m_exifinfo;\r
140         char m_szLastError[256];\r
141         CxExifInfo(EXIFINFO* info = NULL);\r
142         ~CxExifInfo();\r
143         bool DecodeExif(CxFile * hFile, int nReadMode = EXIF_READ_EXIF);\r
144         bool EncodeExif(CxFile * hFile);\r
145         void DiscardAllButExif();\r
146 protected:\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
159         int MotorolaOrder;\r
160         Section_t Sections[MAX_SECTIONS];\r
161         int SectionsRead;\r
162         bool freeinfo;\r
163 };\r
164 \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
169 \r
170 #endif //CXIMAGEJPG_SUPPORT_EXIF\r
171 \r
172 ////////////////////////////////////////////////////////////////////////////////////////\r
173 //////////////////////        C x F i l e J p g         ////////////////////////////////\r
174 ////////////////////////////////////////////////////////////////////////////////////////\r
175 \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
178         {\r
179 public:\r
180         enum { eBufSize = 4096 };\r
181 \r
182         CxFileJpg(CxFile* pFile)\r
183         {\r
184         m_pFile = pFile;\r
185 \r
186                 init_destination = InitDestination;\r
187                 empty_output_buffer = EmptyOutputBuffer;\r
188                 term_destination = TermDestination;\r
189 \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
197 \r
198                 m_pBuffer = new unsigned char[eBufSize];\r
199         }\r
200         ~CxFileJpg()\r
201         {\r
202                 delete [] m_pBuffer;\r
203         }\r
204 \r
205         static void InitDestination(j_compress_ptr cinfo)\r
206         {\r
207                 CxFileJpg* pDest = (CxFileJpg*)cinfo->dest;\r
208                 pDest->next_output_byte = pDest->m_pBuffer;\r
209                 pDest->free_in_buffer = eBufSize;\r
210         }\r
211 \r
212         static boolean EmptyOutputBuffer(j_compress_ptr cinfo)\r
213         {\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
219                 return TRUE;\r
220         }\r
221 \r
222         static void TermDestination(j_compress_ptr cinfo)\r
223         {\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
230                 }\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
234                 return;\r
235         }\r
236 \r
237         static void InitSource(j_decompress_ptr cinfo)\r
238         {\r
239                 CxFileJpg* pSource = (CxFileJpg*)cinfo->src;\r
240                 pSource->m_bStartOfFile = TRUE;\r
241         }\r
242 \r
243         static boolean FillInputBuffer(j_decompress_ptr cinfo)\r
244         {\r
245                 size_t nbytes;\r
246                 CxFileJpg* pSource = (CxFileJpg*)cinfo->src;\r
247                 nbytes = pSource->m_pFile->Read(pSource->m_pBuffer,1,eBufSize);\r
248                 if (nbytes <= 0){\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
255                         nbytes = 2;\r
256                 }\r
257                 pSource->next_input_byte = pSource->m_pBuffer;\r
258                 pSource->bytes_in_buffer = nbytes;\r
259                 pSource->m_bStartOfFile = FALSE;\r
260                 return TRUE;\r
261         }\r
262 \r
263         static void SkipInputData(j_decompress_ptr cinfo, long num_bytes)\r
264         {\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
272                         }\r
273                         pSource->next_input_byte += (size_t) num_bytes;\r
274                         pSource->bytes_in_buffer -= (size_t) num_bytes;\r
275                 }\r
276         }\r
277 \r
278         static void TermSource(j_decompress_ptr /*cinfo*/)\r
279         {\r
280                 return;\r
281         }\r
282 protected:\r
283     CxFile  *m_pFile;\r
284         unsigned char *m_pBuffer;\r
285         bool m_bStartOfFile;\r
286 };\r
287 \r
288 public:\r
289         enum CODEC_OPTION\r
290         {\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
305         }; \r
306 \r
307         int m_nPredictor;\r
308         int m_nPointTransform;\r
309         int m_nSmoothing;\r
310         int m_nQuantize;\r
311         J_DITHER_MODE m_nDither;\r
312 \r
313 };\r
314 \r
315 #endif\r
316 \r
317 #endif\r