Subversion Repositories Scribus

Rev

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