Subversion Repositories Scribus

Rev

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