Subversion Repositories Scribus

Rev

Rev 20871 | Rev 21678 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
5977 jghali 1
/*
2
For general Scribus (>=1.3.2) copyright and licensing information please refer
3
to the COPYING file provided with the program. Following this notice may exist
4
a copyright and/or license notice that predates the release of Scribus 1.3.2
5
for which a new license (GPL+exception) is in place.
6
*/
10223 cbradney 7
#include <QFile>
8
#include <QFileInfo>
9
#include <QObject>
5937 jghali 10
#include <setjmp.h>
11
#include "scconfig.h"
12
#include "scimgdataloader_jpeg.h"
15706 jghali 13
#include "colormgmt/sccolormgmtengine.h"
5937 jghali 14
#include "exif.h"
15
 
16
typedef struct my_error_mgr
17
{
18
        struct jpeg_error_mgr pub;            /* "public" fields */
19
        jmp_buf setjmp_buffer;  /* for return to caller */
20
} *my_error_ptr;
21
 
22
static void my_error_exit (j_common_ptr cinfo)
23
{
24
        my_error_ptr myerr = (my_error_ptr) cinfo->err;
25
        (*cinfo->err->output_message) (cinfo);
26
        longjmp (myerr->setjmp_buffer, 1);
27
}
28
 
29
#define ICC_MARKER  (JPEG_APP0 + 2)     /* JPEG marker code for ICC */
30
#define PHOTOSHOP_MARKER  (JPEG_APP0 + 13)      /* JPEG marker code for PHOTOSHOP */
31
#define ICC_OVERHEAD_LEN  14            /* size of non-profile data in APP2 */
32
#define MAX_BYTES_IN_MARKER  65533      /* maximum data len of a JPEG marker */
33
#define MAX_DATA_BYTES_IN_MARKER  (MAX_BYTES_IN_MARKER - ICC_OVERHEAD_LEN)
34
 
35
 
36
ScImgDataLoader_JPEG::ScImgDataLoader_JPEG(void)
37
{
38
        initSupportedFormatList();
39
}
40
 
41
void ScImgDataLoader_JPEG::initSupportedFormatList(void)
42
{
43
        m_supportedFormats.clear();
44
        m_supportedFormats.append( "jpg" );
45
        m_supportedFormats.append( "jpeg" );
46
}
47
 
12141 avox 48
void ScImgDataLoader_JPEG::loadEmbeddedProfile(const QString& fn, int /*page*/)
5937 jghali 49
{
50
        m_embeddedProfile.resize(0);
51
        m_profileComponents = 0;
52
        if (!QFile::exists(fn))
53
                return;
54
        struct jpeg_decompress_struct cinfo;
55
        struct my_error_mgr         jerr;
56
        FILE     *infile;
57
        cinfo.err = jpeg_std_error (&jerr.pub);
58
        jerr.pub.error_exit = my_error_exit;
59
        infile = NULL;
60
        if (setjmp (jerr.setjmp_buffer))
61
        {
62
                jpeg_destroy_decompress (&cinfo);
63
                if (infile)
64
                        fclose (infile);
65
                return;
66
        }
67
        jpeg_create_decompress (&cinfo);
20719 jghali 68
#if defined(Q_OS_WIN32)
69
        if ((infile = _wfopen((const wchar_t*) fn.utf16(), L"rb")) == NULL)
70
                return;
71
#else
10493 fschmid 72
        if ((infile = fopen (fn.toLocal8Bit(), "rb")) == NULL)
5937 jghali 73
                return;
20719 jghali 74
#endif
5937 jghali 75
        jpeg_stdio_src(&cinfo, infile);
76
        jpeg_save_markers(&cinfo, ICC_MARKER, 0xFFFF);
77
        jpeg_read_header(&cinfo, true);
78
        unsigned int EmbedLen = 0;
20871 jghali 79
        unsigned char* EmbedBuffer = 0;
5937 jghali 80
        if (read_jpeg_marker(ICC_MARKER,&cinfo, &EmbedBuffer, &EmbedLen))
81
        {
15706 jghali 82
                QByteArray profArray = QByteArray((const char*) EmbedBuffer, EmbedLen);
83
                ScColorProfile prof  = ScColorMgmtEngine::openProfileFromMem(profArray);
5937 jghali 84
                if (prof)
85
                {
15706 jghali 86
                        if (prof.colorSpace() == ColorSpace_Rgb)
5937 jghali 87
                                m_profileComponents = 3;
15706 jghali 88
                        if (prof.colorSpace() == ColorSpace_Cmyk)
5937 jghali 89
                                m_profileComponents = 4;
15706 jghali 90
                        if (prof.colorSpace() == ColorSpace_Gray)
12732 fschmid 91
                                m_profileComponents = 1;
15706 jghali 92
                        m_embeddedProfile = profArray;
5937 jghali 93
                }
94
                free(EmbedBuffer);
95
        }
96
        fclose (infile);
97
        jpeg_destroy_decompress (&cinfo);
98
}
99
 
12141 avox 100
bool ScImgDataLoader_JPEG::preloadAlphaChannel(const QString& fn, int /*page*/, int res, bool& hasAlpha)
5937 jghali 101
{
102
        // No support for aplha in jpeg pictures
103
        initialize();
11468 fschmid 104
        hasAlpha = false;
105
        return true;
5937 jghali 106
}
107
 
12141 avox 108
bool ScImgDataLoader_JPEG::loadPicture(const QString& fn, int /*page*/, int res, bool thumbnail)
5937 jghali 109
{
110
        bool isCMYK = false;
7041 fschmid 111
        bool fromPS = false;
5937 jghali 112
        float xres = 72.0, yres = 72.0;
113
        if (!QFile::exists(fn))
114
                return false;
115
        ExifData ExifInf;
116
        struct jpeg_decompress_struct cinfo;
117
        struct my_error_mgr         jerr;
118
        FILE     *infile;
119
        cinfo.err = jpeg_std_error (&jerr.pub);
120
        jerr.pub.error_exit = my_error_exit;
121
        infile = NULL;
122
 
123
        initialize();
11331 jghali 124
        m_imageInfoRecord.type = ImageTypeJPG;
5937 jghali 125
        m_imageInfoRecord.exifInfo.thumbnail = QImage();
126
        if (setjmp (jerr.setjmp_buffer))
127
        {
128
                jpeg_destroy_decompress (&cinfo);
129
                if (infile)
130
                        fclose (infile);
131
                return false;
132
        }
133
        jpeg_create_decompress (&cinfo);
20719 jghali 134
#if defined(Q_OS_WIN32)
135
        if ((infile = _wfopen((const wchar_t*) fn.utf16(), L"rb")) == NULL)
136
                return false;
137
#else
10493 fschmid 138
        if ((infile = fopen (fn.toLocal8Bit(), "rb")) == NULL)
5937 jghali 139
                return false;
20719 jghali 140
#endif
5937 jghali 141
        jpeg_stdio_src(&cinfo, infile);
142
        jpeg_save_markers(&cinfo, ICC_MARKER, 0xFFFF);
143
        jpeg_save_markers(&cinfo, PHOTOSHOP_MARKER, 0xFFFF);
144
        jpeg_read_header(&cinfo, true);
145
        jpeg_start_decompress(&cinfo);
146
        bool exi = ExifInf.scan(fn);
147
        if ((exi) && (ExifInf.exifDataValid))
148
        {
6716 fschmid 149
                if (cinfo.output_components == 4)
11331 jghali 150
                        m_imageInfoRecord.colorspace = ColorSpaceCMYK;
6716 fschmid 151
                else if (cinfo.output_components == 3)
11331 jghali 152
                        m_imageInfoRecord.colorspace = ColorSpaceRGB;
6716 fschmid 153
                else if (cinfo.output_components == 1)
11331 jghali 154
                        m_imageInfoRecord.colorspace = ColorSpaceGray;
10911 fschmid 155
                if ((!ExifInf.Thumbnail.isNull()) && thumbnail)
6716 fschmid 156
                {
5937 jghali 157
                        m_image = ExifInf.getThumbnail();
6716 fschmid 158
                        m_imageInfoRecord.exifInfo.thumbnail = ExifInf.getThumbnail();
159
                        if (cinfo.output_components == 4)
160
                        {
7175 fschmid 161
                                QRgb *s;
162
                                unsigned char cc, cm, cy, ck;
6716 fschmid 163
                                for( int yit=0; yit < m_image.height(); ++yit )
164
                                {
7175 fschmid 165
                                        s = (QRgb*)(m_image.scanLine( yit ));
6716 fschmid 166
                                        for(int xit=0; xit < m_image.width(); ++xit )
167
                                        {
7175 fschmid 168
                                                cc = 255 - qRed(*s);
169
                                                cm = 255 - qGreen(*s);
170
                                                cy = 255 - qBlue(*s);
8562 jghali 171
                                                ck = qMin(qMin(cc, cm), cy);
6716 fschmid 172
                                                *s = qRgba(cc-ck,cm-ck,cy-ck,ck);
7040 fschmid 173
                                                s++;
6716 fschmid 174
                                        }
175
                                }
176
                        }
177
                }
178
                else
179
                        m_imageInfoRecord.exifInfo.thumbnail = QImage();
5937 jghali 180
                m_imageInfoRecord.exifInfo.cameraName = ExifInf.getCameraModel();
181
                m_imageInfoRecord.exifInfo.cameraVendor = ExifInf.getCameraMake();
182
                m_imageInfoRecord.exifInfo.comment = ExifInf.getComment();
183
                m_imageInfoRecord.exifInfo.width = ExifInf.getWidth();
184
                m_imageInfoRecord.exifInfo.height = ExifInf.getHeight();
185
                m_imageInfoRecord.exifInfo.userComment = ExifInf.getUserComment();
186
                m_imageInfoRecord.exifInfo.dateTime = ExifInf.getDateTime();
7362 fschmid 187
                m_imageInfoRecord.exifInfo.ApertureFNumber = ExifInf.getApertureFNumber();
188
                m_imageInfoRecord.exifInfo.ExposureTime = ExifInf.getExposureTime();
189
                m_imageInfoRecord.exifInfo.ISOequivalent = ExifInf.getISOequivalent();
5937 jghali 190
                m_imageInfoRecord.exifDataValid = true;
191
                if (cinfo.density_unit == 0)
192
                {
193
                        xres = 72;
194
                        yres = 72;
195
                }
196
                else if ( cinfo.density_unit == 1 )
197
                {
198
                        xres = cinfo.X_density;
199
                        yres = cinfo.Y_density;
200
                }
201
                else if ( cinfo.density_unit == 2 )
202
                {
203
                        xres = cinfo.X_density * 2.54;
204
                        yres = cinfo.Y_density * 2.54;
205
                }
6650 fschmid 206
                if( xres <= 1.0 || yres <= 1.0 || xres > 3000.0 || yres > 3000.0 )
5947 jghali 207
                {
208
                        xres = yres = 72.0;
209
                        QFileInfo qfi(fn);
6650 fschmid 210
                        m_message = QObject::tr("%1 may be corrupted : missing or wrong resolution tags").arg(qfi.fileName());
5977 jghali 211
                        m_msgType = warningMsg;
5947 jghali 212
                }
5937 jghali 213
                m_imageInfoRecord.xres = qRound(xres);
214
                m_imageInfoRecord.yres = qRound(yres);
215
                m_imageInfoRecord.progressive = jpeg_has_multiple_scans(&cinfo);
10911 fschmid 216
                if ((!ExifInf.Thumbnail.isNull()) && thumbnail)
5937 jghali 217
                {
218
                        jpeg_destroy_decompress(&cinfo);
219
                        fclose(infile);
220
                        return true;
221
                }
222
        }
223
        else
224
                m_imageInfoRecord.exifDataValid = false;
6716 fschmid 225
        m_imageInfoRecord.exifInfo.thumbnail = QImage();
5937 jghali 226
        unsigned int EmbedLen = 0;
20871 jghali 227
        unsigned char* EmbedBuffer = 0;
5937 jghali 228
        if (read_jpeg_marker(ICC_MARKER,&cinfo, &EmbedBuffer, &EmbedLen))
229
        {
15706 jghali 230
                QByteArray profArray = QByteArray((const char*) EmbedBuffer, EmbedLen);
231
                ScColorProfile prof = ScColorMgmtEngine::openProfileFromMem(profArray);
232
                m_embeddedProfile   = profArray;
233
                m_imageInfoRecord.profileName = prof.productDescription();
234
                m_imageInfoRecord.isEmbedded  = true;
5937 jghali 235
                free(EmbedBuffer);
236
        }
237
        else
238
        {
239
                m_imageInfoRecord.isEmbedded = false;
240
                m_imageInfoRecord.profileName = "";
241
        }
20871 jghali 242
 
5937 jghali 243
        if (cinfo.density_unit == 0)
244
        {
245
                xres = 72;
246
                yres = 72;
247
                m_image.setDotsPerMeterX(2834);
248
                m_image.setDotsPerMeterY(2834);
249
        }
20871 jghali 250
        else if (cinfo.density_unit == 1)
5937 jghali 251
        {
252
                xres = cinfo.X_density;
253
                yres = cinfo.Y_density;
254
                m_image.setDotsPerMeterX( int(100. * cinfo.X_density / 2.54) );
255
                m_image.setDotsPerMeterY( int(100. * cinfo.Y_density / 2.54) );
256
        }
20871 jghali 257
        else if (cinfo.density_unit == 2)
5937 jghali 258
        {
259
                xres = cinfo.X_density * 2.54;
260
                yres = cinfo.Y_density * 2.54;
261
                m_image.setDotsPerMeterX( int(100. * cinfo.X_density) );
262
                m_image.setDotsPerMeterY( int(100. * cinfo.Y_density) );
263
        }
20871 jghali 264
        if (xres <= 1.0 || yres <= 1.0 || xres > 3000.0 || yres > 3000.0)
5947 jghali 265
        {
266
                xres = yres = 72.0;
6650 fschmid 267
                m_image.setDotsPerMeterX(2834);
268
                m_image.setDotsPerMeterY(2834);
5947 jghali 269
                QFileInfo qfi(fn);
6650 fschmid 270
                m_message = QObject::tr("%1 may be corrupted : missing or wrong resolution tags").arg(qfi.fileName());
5977 jghali 271
                m_msgType = warningMsg;
5947 jghali 272
        }
5937 jghali 273
        m_imageInfoRecord.xres = qRound(xres);
274
        m_imageInfoRecord.yres = qRound(yres);
275
        if (cinfo.output_components == 4)
276
        {
277
                isCMYK = true;
11331 jghali 278
                m_imageInfoRecord.colorspace = ColorSpaceCMYK;
5937 jghali 279
        }
280
        else if (cinfo.output_components == 3)
11331 jghali 281
                m_imageInfoRecord.colorspace = ColorSpaceRGB;
5937 jghali 282
        else if (cinfo.output_components == 1)
11331 jghali 283
                m_imageInfoRecord.colorspace = ColorSpaceGray;
5937 jghali 284
        m_imageInfoRecord.progressive = jpeg_has_multiple_scans(&cinfo);
285
 
20871 jghali 286
        unsigned int PhotoshopLen = 0;
287
        unsigned char * PhotoshopBuffer = 0;
5937 jghali 288
        if (read_jpeg_marker(PHOTOSHOP_MARKER,&cinfo, &PhotoshopBuffer, &PhotoshopLen) )
289
        {
20871 jghali 290
                bool savEx = m_imageInfoRecord.exifDataValid;
291
                QByteArray arrayPhot(PhotoshopLen, ' ');
292
                arrayPhot = QByteArray::fromRawData((const char*)PhotoshopBuffer,PhotoshopLen);
293
                QDataStream strPhot(&arrayPhot,QIODevice::ReadOnly);
294
                strPhot.setByteOrder( QDataStream::BigEndian );
295
                PSDHeader fakeHeader;
296
                fakeHeader.width = cinfo.output_width;
297
                fakeHeader.height = cinfo.output_height;
298
                if (cinfo.output_components == 4)
299
                        m_imageInfoRecord.colorspace = ColorSpaceCMYK;
300
                else if (cinfo.output_components == 3)
301
                        m_imageInfoRecord.colorspace = ColorSpaceRGB;
302
                else if (cinfo.output_components == 1)
303
                        m_imageInfoRecord.colorspace = ColorSpaceGray;
304
                m_imageInfoRecord.progressive = jpeg_has_multiple_scans(&cinfo);
305
                parseRessourceData(strPhot, fakeHeader, PhotoshopLen);
306
                // Photoshop resolution is more accurate than jpeg header resolution
307
                xres = m_imageInfoRecord.xres;
308
                yres = m_imageInfoRecord.yres;
309
                m_image.setDotsPerMeterX( int(100. * m_imageInfoRecord.xres / 2.54) );
310
                m_image.setDotsPerMeterY( int(100. * m_imageInfoRecord.yres / 2.54) );
311
                if (xres <= 1.0 || yres <= 1.0 || xres > 3000.0 || yres > 3000.0)
5937 jghali 312
                {
20871 jghali 313
                        xres = yres = 72.0;
314
                        m_imageInfoRecord.xres = qRound(xres);
315
                        m_imageInfoRecord.yres = qRound(yres);
316
                        m_image.setDotsPerMeterX(2834);
317
                        m_image.setDotsPerMeterY(2834);
318
                        QFileInfo qfi(fn);
319
                        m_message = QObject::tr("%1 may be corrupted : missing or wrong resolution tags").arg(qfi.fileName());
320
                        m_msgType = warningMsg;
321
                }
322
                if (m_imageInfoRecord.exifDataValid && !m_imageInfoRecord.exifInfo.thumbnail.isNull() && thumbnail)
323
                {
324
                        m_image = QImage(m_imageInfoRecord.exifInfo.width, m_imageInfoRecord.exifInfo.height, QImage::Format_ARGB32 );
325
                        m_imageInfoRecord.exifInfo.width = cinfo.output_width;
326
                        m_imageInfoRecord.exifInfo.height = cinfo.output_height;
5937 jghali 327
                        if (cinfo.output_components == 4)
6650 fschmid 328
                        {
20871 jghali 329
                                QRgb *d;
330
                                QRgb *s;
331
                                unsigned char cc, cm, cy, ck;
332
                                for (int yit=0; yit < m_image.height(); ++yit)
7040 fschmid 333
                                {
20871 jghali 334
                                        d = (QRgb*)(m_image.scanLine( yit ));
335
                                        s = (QRgb*)(m_imageInfoRecord.exifInfo.thumbnail.scanLine( yit ));
336
                                        for (int xit=0; xit < m_image.width(); ++xit)
7040 fschmid 337
                                        {
20871 jghali 338
                                                cc = 255 - qRed(*s);
339
                                                cm = 255 - qGreen(*s);
340
                                                cy = 255 - qBlue(*s);
341
                                                ck = qMin(qMin(cc, cm), cy);
342
                                                *d = qRgba(cc-ck,cm-ck,cy-ck,ck);
343
                                                s++;
344
                                                d++;
7040 fschmid 345
                                        }
346
                                }
347
                        }
20871 jghali 348
                        else
349
                                m_image = m_imageInfoRecord.exifInfo.thumbnail.copy();
5937 jghali 350
                }
20871 jghali 351
                m_imageInfoRecord.valid = (m_imageInfoRecord.PDSpathData.size())>0?true:false; // The only interest is vectormask
352
                arrayPhot.clear();
353
                free( PhotoshopBuffer );
354
                PhotoshopBuffer = 0;
355
                if (m_imageInfoRecord.exifDataValid && !m_imageInfoRecord.exifInfo.thumbnail.isNull() && thumbnail)
356
                {
357
                        jpeg_destroy_decompress(&cinfo);
358
                        fclose(infile);
359
                        return true;
360
                }
361
                m_imageInfoRecord.exifInfo.thumbnail = QImage();
362
                m_imageInfoRecord.exifDataValid = savEx;
363
                fromPS = true;
5937 jghali 364
        }
20871 jghali 365
        if (cinfo.output_components == 3 || cinfo.output_components == 4)
10561 fschmid 366
                m_image = QImage( cinfo.output_width, cinfo.output_height, QImage::Format_ARGB32 );
20871 jghali 367
        else if (cinfo.output_components == 1 )
5937 jghali 368
        {
10561 fschmid 369
                m_image = QImage( cinfo.output_width, cinfo.output_height, QImage::Format_Indexed8 );
10826 fschmid 370
                m_image.setNumColors(256);
5937 jghali 371
                for (int i=0; i<256; i++)
372
                        m_image.setColor(i, qRgb(i,i,i));
373
        }
374
        if (!m_image.isNull())
375
        {
10561 fschmid 376
                uchar* data = m_image.bits();
377
                int bpl = m_image.bytesPerLine();
5937 jghali 378
                while (cinfo.output_scanline < cinfo.output_height)
10561 fschmid 379
                {
380
                        uchar *d = data + cinfo.output_scanline * bpl;
381
                        (void) jpeg_read_scanlines(&cinfo, &d, 1);
382
                }
20871 jghali 383
                if (cinfo.output_components == 3)
5937 jghali 384
                {
7175 fschmid 385
                        uchar *in;
386
                        QRgb *out;
5937 jghali 387
                        for (uint j=0; j<cinfo.output_height; j++)
388
                        {
7175 fschmid 389
                                in = m_image.scanLine(j) + cinfo.output_width * 3;
390
                                out = (QRgb*) m_image.scanLine(j);
5937 jghali 391
                                for (uint i=cinfo.output_width; i--; )
392
                                {
393
                                        in -= 3;
394
                                        out[i] = qRgb(in[0], in[1], in[2]);
395
                                }
396
                        }
397
                }
20871 jghali 398
                if (cinfo.output_components == 4)
5937 jghali 399
                {
7041 fschmid 400
                        int method = 0;
21037 jghali 401
                        if ((cinfo.jpeg_color_space == JCS_YCCK) || (cinfo.out_color_space == JCS_CMYK))
7041 fschmid 402
                                method = 1;
403
                        else if (fromPS)
404
                        {
405
                                if ((cinfo.jpeg_color_space == JCS_CMYK) && (cinfo.saw_Adobe_marker) && (cinfo.Adobe_transform == 0))
406
                                        method = 2;
407
                        }
408
                        else if ((cinfo.jpeg_color_space == JCS_CMYK) && (cinfo.saw_Adobe_marker))
409
                                method = 1;
7175 fschmid 410
                        QRgb *ptr;
411
                        unsigned char c, m, y ,k;
412
                        unsigned char *p;
5937 jghali 413
                        for (int i = 0; i < m_image.height(); i++)
414
                        {
7175 fschmid 415
                                ptr = (QRgb*)  m_image.scanLine(i);
7041 fschmid 416
                                if (method == 1)
5937 jghali 417
                                {
418
                                        for (int j = 0; j <  m_image.width(); j++)
419
                                        {
7175 fschmid 420
                                                p = (unsigned char *) ptr;
5937 jghali 421
                                                c = p[0];
422
                                                m = p[1];
423
                                                y =  p[2];
424
                                                k =  p[3];
425
                                                *ptr = qRgba(255 - c, 255 - m, 255 - y, 255 - k);
426
                                                ptr++;
427
                                        }
428
                                }
7041 fschmid 429
                                else if (method == 2)
430
                                {
431
                                        for (int j = 0; j <  m_image.width(); j++)
432
                                        {
7175 fschmid 433
                                                p = (unsigned char *) ptr;
7041 fschmid 434
                                                c = p[0];
435
                                                m = p[1];
436
                                                y =  p[2];
437
                                                k =  p[3];
438
                                                *ptr = qRgba(255 - c, 255 - m, 255 - y, k);
439
                                                ptr++;
440
                                        }
441
                                }
5937 jghali 442
                                else
443
                                {
444
                                        for (int j = 0; j <  m_image.width(); j++)
445
                                        {
7175 fschmid 446
                                                p = (unsigned char *) ptr;
5937 jghali 447
                                                c = p[0];
448
                                                m = p[1];
449
                                                y =  p[2];
450
                                                k =  p[3];
451
                                                *ptr = qRgba(y, m, c, k);
452
                                                ptr++;
453
                                        }
454
                                }
455
                        }
456
                        isCMYK = true;
457
                }
458
                else
459
                        isCMYK = false;
20871 jghali 460
                if (cinfo.output_components == 1)
5937 jghali 461
                {
10561 fschmid 462
                        QImage tmpImg = m_image.convertToFormat(QImage::Format_ARGB32);
463
                        m_image = QImage( cinfo.output_width, cinfo.output_height, QImage::Format_ARGB32 );
7175 fschmid 464
                        QRgb *s;
465
                        QRgb *d;
5937 jghali 466
                        for( int yi=0; yi < tmpImg.height(); ++yi )
467
                        {
7175 fschmid 468
                                s = (QRgb*)(tmpImg.scanLine( yi ));
469
                                d = (QRgb*)(m_image.scanLine( yi ));
5937 jghali 470
                                for(int xi=0; xi < tmpImg.width(); ++xi )
471
                                {
472
                                        (*d) = (*s);
473
                                        s++;
474
                                        d++;
475
                                }
476
                        }
477
                }
478
        }
479
        (void) jpeg_finish_decompress(&cinfo);
480
        fclose (infile);
481
        jpeg_destroy_decompress (&cinfo);
482
        m_imageInfoRecord.layerInfo.clear();
483
        m_imageInfoRecord.BBoxX = 0;
484
        m_imageInfoRecord.BBoxH = m_image.height();
485
        return (!m_image.isNull());
486
}
487
 
488
bool ScImgDataLoader_JPEG::marker_is_icc (jpeg_saved_marker_ptr marker)
489
{
490
        return
491
            marker->marker == ICC_MARKER &&
492
            marker->data_length >= ICC_OVERHEAD_LEN &&
493
            /* verify the identifying string */
494
            GETJOCTET(marker->data[0]) == 0x49 &&
495
            GETJOCTET(marker->data[1]) == 0x43 &&
496
            GETJOCTET(marker->data[2]) == 0x43 &&
497
            GETJOCTET(marker->data[3]) == 0x5F &&
498
            GETJOCTET(marker->data[4]) == 0x50 &&
499
            GETJOCTET(marker->data[5]) == 0x52 &&
500
            GETJOCTET(marker->data[6]) == 0x4F &&
501
            GETJOCTET(marker->data[7]) == 0x46 &&
502
            GETJOCTET(marker->data[8]) == 0x49 &&
503
            GETJOCTET(marker->data[9]) == 0x4C &&
504
            GETJOCTET(marker->data[10]) == 0x45 &&
505
            GETJOCTET(marker->data[11]) == 0x0;
506
}
507
 
508
bool ScImgDataLoader_JPEG::marker_is_photoshop (jpeg_saved_marker_ptr marker)
509
{
510
        return
511
            marker->marker == PHOTOSHOP_MARKER &&
512
            marker->data_length >= ICC_OVERHEAD_LEN &&
513
            /* verify the identifying string */
514
            GETJOCTET(marker->data[0]) == 0x50 &&
515
            GETJOCTET(marker->data[1]) == 0x68 &&
516
            GETJOCTET(marker->data[2]) == 0x6F &&
517
            GETJOCTET(marker->data[3]) == 0x74 &&
518
            GETJOCTET(marker->data[4]) == 0x6F &&
519
            GETJOCTET(marker->data[5]) == 0x73 &&
520
            GETJOCTET(marker->data[6]) == 0x68 &&
521
            GETJOCTET(marker->data[7]) == 0x6F &&
522
            GETJOCTET(marker->data[8]) == 0x70 &&
523
            GETJOCTET(marker->data[9]) == 0x20 &&
524
            GETJOCTET(marker->data[10]) == 0x33 &&
525
            GETJOCTET(marker->data[11]) == 0x2E &&
526
            GETJOCTET(marker->data[12]) == 0x30 &&
527
            GETJOCTET(marker->data[13]) == 0x0;
528
}
529
 
530
/* Small modification of original read_icc_profile method from jpegicc of lcms project
531
 * to enable read of Photoshop marker
532
 */
533
bool ScImgDataLoader_JPEG::read_jpeg_marker (UINT8 requestmarker, j_decompress_ptr cinfo, JOCTET **icc_data_ptr, unsigned int *icc_data_len)
534
{
535
        jpeg_saved_marker_ptr marker;
536
        int num_markers = 0;
537
        int seq_no;
538
        JOCTET *icc_data;
539
        unsigned int total_length;
540
#define MAX_SEQ_NO  255         /* sufficient since marker numbers are bytes */
541
        char marker_present[MAX_SEQ_NO+1];        /* 1 if marker found */
542
        unsigned int data_length[MAX_SEQ_NO+1]; /* size of profile data in marker */
543
        unsigned int data_offset[MAX_SEQ_NO+1]; /* offset for data in marker */
544
 
545
        *icc_data_ptr = NULL;           /* avoid confusion if false return */
546
        *icc_data_len = 0;
547
 
548
        /* This first pass over the saved markers discovers whether there are
549
         * any ICC markers and verifies the consistency of the marker numbering.
550
         */
551
 
552
        for (seq_no = 1; seq_no <= MAX_SEQ_NO; seq_no++)
553
                marker_present[seq_no] = 0;
554
        seq_no = 0;
555
        for (marker = cinfo->marker_list; marker != NULL; marker = marker->next)
556
        {
557
                if (requestmarker == ICC_MARKER && marker_is_icc(marker))
558
                {
559
                        if (num_markers == 0)
560
                                num_markers = GETJOCTET(marker->data[13]);
561
                        else if (num_markers != GETJOCTET(marker->data[13]))
562
                                return false;           /* inconsistent num_markers fields */
563
                        seq_no = GETJOCTET(marker->data[12]);
564
                        if (seq_no <= 0 || seq_no > num_markers)
565
                                return false;           /* bogus sequence number */
566
                        if (marker_present[seq_no])
567
                                return false;           /* duplicate sequence numbers */
568
                        marker_present[seq_no] = 1;
569
                        data_length[seq_no] = marker->data_length - ICC_OVERHEAD_LEN;
570
                }
571
                else if(requestmarker == PHOTOSHOP_MARKER && marker_is_photoshop(marker))
572
                {
573
                        num_markers = ++seq_no;
574
                        marker_present[seq_no] = 1;
575
                        data_length[seq_no] = marker->data_length - ICC_OVERHEAD_LEN;
576
                }
577
        }
578
 
579
        if (num_markers == 0)
580
                return false;
581
 
582
        /* Check for missing markers, count total space needed,
583
         * compute offset of each marker's part of the data.
584
         */
585
 
586
        total_length = 0;
587
        for (seq_no = 1; seq_no <= num_markers; seq_no++)
588
        {
589
                if (marker_present[seq_no] == 0)
590
                        return false;           /* missing sequence number */
591
                data_offset[seq_no] = total_length;
592
                total_length += data_length[seq_no];
593
        }
594
 
595
        if (total_length <= 0)
596
                return false;           /* found only empty markers? */
597
 
598
        /* Allocate space for assembled data */
599
        icc_data = (JOCTET *) malloc(total_length * sizeof(JOCTET));
600
        if (icc_data == NULL)
601
                return false;           /* oops, out of memory */
602
        seq_no=0;
603
        /* and fill it in */
604
        for (marker = cinfo->marker_list; marker != NULL; marker = marker->next)
605
        {
606
                if ( (requestmarker == ICC_MARKER && marker_is_icc(marker)) ||
607
                        (requestmarker == PHOTOSHOP_MARKER && marker_is_photoshop(marker)) || (requestmarker == 0xE1))
608
                {
609
                        JOCTET FAR *src_ptr;
610
                        JOCTET *dst_ptr;
611
                        unsigned int length;
612
                        if(requestmarker == ICC_MARKER)
613
                                seq_no = GETJOCTET(marker->data[12]);
614
                        else if(requestmarker == PHOTOSHOP_MARKER)
615
                                seq_no++;
616
                        dst_ptr = icc_data + data_offset[seq_no];
617
                        src_ptr = marker->data + ICC_OVERHEAD_LEN;
618
                        length = data_length[seq_no];
619
                        while (length--)
620
                        {
621
                                *dst_ptr++ = *src_ptr++;
622
                        }
623
                }
624
        }
625
 
626
        *icc_data_ptr = icc_data;
627
        *icc_data_len = total_length;
628
 
629
        return true;
6650 fschmid 630
}