00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "plstdpch.h"
00016 #include "pljpegdec.h"
00017
00018 #include "plexcept.h"
00019
00020 #include "jmemsrc.h"
00021
00022
00023 #define JPEG_INTERNALS
00024 #include <jmorecfg.h>
00025
00026
00028
00029
00030 METHODDEF(void)
00031 error_exit (j_common_ptr pcinfo)
00032
00033
00034 {
00035
00036 char sz[256];
00037 (pcinfo->err->format_message) (pcinfo, sz);
00038 strcat (sz, "\n");
00039
00040 PLPicDecoder::raiseError (PL_ERRFORMAT_NOT_SUPPORTED, sz);
00041 }
00042
00044
00045
00046 PLJPEGDecoder::PLJPEGDecoder
00047 ()
00048 : PLPicDecoder(),
00049 m_bFast(true)
00050
00051 {
00052 cinfo.err = jpeg_std_error (&jerr);
00053 jerr.error_exit = error_exit;
00054
00055 jpeg_create_decompress (&cinfo);
00056 }
00057
00058
00059 PLJPEGDecoder::~PLJPEGDecoder
00060 ()
00061 {
00062 jpeg_destroy_decompress (&cinfo);
00063 }
00064
00065 void PLJPEGDecoder::SetFast
00066 ( bool bFast
00067 )
00068
00069 {
00070 m_bFast = bFast;
00071 }
00072
00073
00074 void PLJPEGDecoder::DoDecode
00075 ( PLBmp * pBmp,
00076 PLDataSource * pDataSrc
00077 )
00078 {
00079 try
00080 {
00081
00082 JMETHOD( void, notify, (j_common_ptr));
00083 notify = JNotification;
00084
00085
00086
00087 jpeg_mem_src (&cinfo, pDataSrc->ReadEverything(),
00088 pDataSrc->GetFileSize(), (void*)pDataSrc, notify);
00089
00090 jpeg_read_header (&cinfo, true);
00091
00092 if (m_bFast)
00093 {
00094 cinfo.do_fancy_upsampling = false;
00095 }
00096
00097
00098 cinfo.dct_method = JDCT_FLOAT;
00099
00100 int w = cinfo.image_width;
00101 int h = cinfo.image_height;
00102
00103 jpeg_start_decompress (&cinfo);
00104
00105 if (cinfo.out_color_space == JCS_GRAYSCALE)
00106 decodeGray (pBmp, w, h);
00107 else
00108 decodeRGB (pBmp, w, h);
00109 jpeg_finish_decompress (&cinfo);
00110
00111 PLPoint DPI;
00112
00113 DPI.x = cinfo.X_density;
00114 if(DPI.x <= 1)
00115 DPI.x = 72;
00116
00117 DPI.y = cinfo.Y_density;
00118 if(DPI.y <= 1)
00119 DPI.y = 72;
00120 pBmp->SetResolution (DPI);
00121 }
00122 catch (PLTextException)
00123 {
00124 jpeg_abort_decompress(&cinfo);
00125 throw;
00126 }
00127
00128
00129 }
00130
00131 void PLJPEGDecoder::decodeRGB
00132 ( PLBmp * pBmp,
00133 int w,
00134 int h
00135 )
00136
00137 {
00138 int CurLine = 0;
00139 PLBYTE * pBuf;
00140 JSAMPARRAY ppBuf = &pBuf;
00141
00142 pBmp->Create (w, h, 32, false);
00143 #if ((PL_RGBA_RED!=RGB_RED)||(PL_RGBA_GREEN!=RGB_GREEN)||(PL_RGBA_BLUE!=RGB_BLUE)||(4!=RGB_PIXELSIZE))
00144 pBuf = new PLBYTE[w*sizeof (PLPixel32)];
00145 #endif
00146
00147 pBmp->Lock(false, true);
00148 PLPixel32 ** pLineArray = pBmp->GetLineArray32();
00149
00150 int readed = 0;
00151 while (CurLine < h)
00152 {
00153
00154
00155 #if ((PL_RGBA_RED!=RGB_RED)||(PL_RGBA_GREEN!=RGB_GREEN)||(PL_RGBA_BLUE!=RGB_BLUE)||(4!=RGB_PIXELSIZE))
00156 jpeg_read_scanlines (&cinfo, ppBuf, 1);
00157 int i;
00158 for (i=0;i<w;i++)
00159 {
00160 PLBYTE * pSrcPixel = pBuf+i*RGB_PIXELSIZE;
00161 PLPixel32 * pDestPixel = pLineArray[CurLine]+i;
00162 pDestPixel->SetR (pSrcPixel[RGB_RED]);
00163 pDestPixel->SetG (pSrcPixel[RGB_GREEN]);
00164 pDestPixel->SetB (pSrcPixel[RGB_BLUE]);
00165 }
00166 CurLine++;
00167 #else
00168 readed = jpeg_read_scanlines (&cinfo,&pLineArray[CurLine],32);
00169 CurLine+=min(readed,(h-CurLine));
00170 if(readed==0)
00171 break;
00172 #endif
00173 }
00174 pBmp->Unlock();
00175 if(pBuf)
00176 {
00177 delete[] pBuf;
00178 }
00179 }
00180
00181 void PLJPEGDecoder::decodeGray
00182 ( PLBmp * pBmp,
00183 int w,
00184 int h
00185 )
00186
00187 {
00188 PLBYTE * pDst;
00189 int CurLine = 0;
00190 PLBYTE * pBuf = new PLBYTE [w];
00191 try
00192 {
00193 JSAMPARRAY ppBuf = &pBuf;
00194
00195 pBmp->Create (w, h, 8, false);
00196
00197 pBmp->Lock(false, true);
00198 PLBYTE ** pLineArray = pBmp->GetLineArray();
00199
00200 while (CurLine < h)
00201 {
00202 ppBuf = &pDst;
00203 *ppBuf = pLineArray[CurLine];
00204 jpeg_read_scanlines (&cinfo, ppBuf, 1);
00205
00206 CurLine++;
00207 }
00208 pBmp->Unlock();
00209 }
00210 catch(...)
00211 {
00212 delete [] pBuf;
00213 throw;
00214 }
00215 delete [] pBuf;
00216 }
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226 void PLJPEGDecoder::JNotification (j_common_ptr cinfo)
00227 {
00228 double part;
00229 PLDataSource *pDataSrc;
00230
00231
00232
00233
00234
00235 part = ( (double)cinfo->progress->completed_passes +
00236 ((double)cinfo->progress->pass_counter/cinfo->progress->pass_limit) ) /
00237 (double)cinfo->progress->total_passes;
00238
00239
00240 pDataSrc = (PLDataSource*) cinfo->client_data;
00241 if (pDataSrc)
00242 {
00243 pDataSrc->OProgressNotification( part);
00244 }
00245
00246 }
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323