Subversion Repositories Scribus

Rev

Rev 13960 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
13960 herm 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
*/
7
#include <QFile>
8
#include <QFileInfo>
9
#include <QObject>
10
#include <QDebug>
11
#include <setjmp.h>
12
#include "scconfig.h"
13
#include "scimgdataloader_gmagick.h"
14
#include <Magick++.h>
15
using namespace Magick;
16
 
13964 herm 17
#ifndef ScaleQuantumToChar
18
    #define MagickLib::ScaleQuantumToChar
19
#endif
20
 
13960 herm 21
static bool read_cmyk(Image *input, RawImage *output, int width, int height)
22
{
23
        /* Mapping:
24
                red:     cyan
25
                green:   magenta
26
                blue:    yellow
27
                opacity: black
28
                index:   alpha
29
        */
30
        //Copied from GraphicsMagick header and modified
31
        #define GetCyanSample(p) (p.red)
32
        #define GetMagentaSample(p) (p.green)
33
        #define GetYellowSample(p) (p.blue)
34
        #define GetCMYKBlackSample(p) (p.opacity)
35
        #define GetAlphaSample(p) (p)
36
 
37
        bool hasAlpha = input->matte();
38
        if (!output->create(width, height, hasAlpha ? 5 : 4)) return false;
39
        const PixelPacket *pixels = input->getConstPixels(0, 0, width, height);
40
        const IndexPacket *alpha  = input->getConstIndexes();
41
        unsigned char *buffer = output->bits();
42
 
43
        int i;
44
        for (i = 0; i < width*height; i++) {
45
                *buffer++ = ScaleQuantumToChar(GetCyanSample(pixels[i]));
46
                *buffer++ = ScaleQuantumToChar(GetMagentaSample(pixels[i]));
47
                *buffer++ = ScaleQuantumToChar(GetYellowSample(pixels[i]));
48
                *buffer++ = ScaleQuantumToChar(GetCMYKBlackSample(pixels[i]));
49
                if (hasAlpha) {
50
                        *buffer++ = 255 - ScaleQuantumToChar(GetAlphaSample(alpha[i]));
51
                }
52
        }
53
        return true;
54
}
55
 
56
 
57
static bool read_rgb(Image *input, QImage *output, int width, int height)
58
{
59
        //Copied from GraphicsMagick header and modified
60
        #define GetRedSample(p) (p.red)
61
        #define GetGreenSample(p) (p.green)
62
        #define GetBlueSample(p) (p.blue)
63
        #define GetRGBAlphaSample(p) (p.opacity)
64
 
65
        bool hasAlpha = input->matte();
66
        const PixelPacket *pixels = input->getConstPixels(0, 0, width, height);
67
        unsigned char *buffer = output->bits();
68
 
69
        int i;
70
        for (i = 0; i < width*height; i++) {
71
                *buffer++ = ScaleQuantumToChar(GetBlueSample(pixels[i]));
72
                *buffer++ = ScaleQuantumToChar(GetGreenSample(pixels[i]));
73
                *buffer++ = ScaleQuantumToChar(GetRedSample(pixels[i]));
74
                if (hasAlpha) {
75
                        *buffer++ = 255 - ScaleQuantumToChar(GetRGBAlphaSample(pixels[i]));
76
                } else {
77
                        *buffer++ = 255;
78
                }
79
        }
80
        return true;
81
}
82
 
83
ScImgDataLoader_GMagick::ScImgDataLoader_GMagick(void)
84
{
85
        initSupportedFormatList();
86
        m_useRawImage = true;
87
}
88
 
89
void ScImgDataLoader_GMagick::initSupportedFormatList(void)
90
{
91
        //This is unused! See util_formats.{h,cpp}
92
        m_supportedFormats.clear();
93
        m_supportedFormats.append("bmp"); //TODO
94
}
95
 
96
void ScImgDataLoader_GMagick::loadEmbeddedProfile(const QString& fn, int /*page*/)
97
{      
98
        if (!QFile::exists(fn)) {
99
                m_embeddedProfile.resize(0);
100
                m_profileComponents = 0;
101
                return;
102
        }
103
 
104
        try {
105
                Image image(std::string(fn.toUtf8()));
106
                Blob icc = image.iccColorProfile();
107
 
108
                if (image.colorSpace() == CMYKColorspace) {
109
                        m_profileComponents = 4;
110
                } else if (image.colorSpace() == RGBColorspace) {
111
                        m_profileComponents = 3;
112
                } else {
113
                        m_profileComponents = 0;
114
                        m_embeddedProfile.resize(0);
115
                }
116
 
117
                m_embeddedProfile.resize(icc.length());
118
 
119
                char *dest = m_embeddedProfile.data();
120
                const char *src = (const char *)icc.data();
121
 
122
                unsigned int i;
123
                for (i=0; i<icc.length(); i++) {
124
                        dest[i] = src[i];
125
                }
126
 
127
        } catch (std::exception &error_) {
128
                m_profileComponents = 0;
129
                m_embeddedProfile.resize(0);
130
 
131
                qDebug() << "GraphicsMagic Exception in ScImgDataLoader_GMagick::loadEmbeddedProfile("
132
                        << fn << "):" << error_.what();
133
 
134
                return;
135
        }
136
}
137
 
138
bool ScImgDataLoader_GMagick::preloadAlphaChannel(const QString& fn, int /*page*/, int res, bool& hasAlpha)
139
{
140
        qDebug() << "GMAGICK: preloadAlpha" << fn;
141
 
142
        initialize();
143
        hasAlpha = false;
144
 
145
        if (!QFile::exists(fn))
146
                return false;
147
 
148
        try {
149
                Image image(std::string(fn.toUtf8()));
150
 
151
                hasAlpha = image.matte();
152
 
153
                if (!hasAlpha) {
154
                        return true; //No need to load any image data
155
                } else {
156
                        return loadPicture(fn, 0, 0, false);
157
                }
158
 
159
        } catch (std::exception &error_) {
160
                qDebug() << "GraphicsMagic Exception in ScImgDataLoader_GMagick::preloadAlphaChannel("
161
                        << fn << "):" << error_.what();
162
                return false;
163
        }
164
        return true;
165
}
166
 
167
bool ScImgDataLoader_GMagick::loadPicture(const QString& fn, int /*page*/, int res, bool thumbnail)
168
{
169
        qDebug() << "Loading image" << fn << "Tumbnail:" << thumbnail;
170
 
171
        if (!QFile::exists(fn))
172
                return false;
173
 
174
        initialize();
175
 
176
        try {
177
                Image image(std::string(fn.toUtf8()));
178
 
179
                qDebug() << "Detected format:" << QString(image.format().c_str())
180
                        << ", has matte(alpha):" << image.matte();
181
 
182
                int width = image.baseColumns();
183
                int height = image.baseRows();
184
 
185
                image.resolutionUnits(PixelsPerInchResolution);
186
                double xres = image.xResolution();
187
                double yres = image.yResolution();
188
                int resInf = m_imageInfoRecord.lowResType;
189
 
190
                /*NOTE:
191
                        - The BGRO bit ordering was found by try'n'error
192
                        - Always use "O" for the alpha channel! "A" is inverted!
193
                        - image.write() is broken for cmyk images!
194
                */
195
                if (image.colorSpace() == CMYKColorspace) {
196
                        qDebug() << "CMYK image";
197
                        m_useRawImage = true;
198
                        if (!read_cmyk(&image, &r_image, width, height)) return false;
199
                        m_imageInfoRecord.colorspace = ColorSpaceCMYK;
200
                } else {
201
                        m_useRawImage = false;
202
                        m_image = QImage(width, height, QImage::Format_ARGB32);
203
                        if (!read_rgb(&image, &m_image, width, height)) return false;
204
                        m_imageInfoRecord.colorspace = ColorSpaceRGB;
205
                }
206
                m_imageInfoRecord.type = ImageTypeOther;
207
                m_imageInfoRecord.exifDataValid = false;
208
                m_imageInfoRecord.xres = qMax(72, qRound(xres));
209
                m_imageInfoRecord.yres = qMax(72, qRound(yres));
210
                m_imageInfoRecord.lowResType = resInf;
211
                m_imageInfoRecord.BBoxX = 0;
212
                m_imageInfoRecord.BBoxH = m_image.height();
213
                m_imageInfoRecord.valid = true;
214
        } catch (std::exception &error_) {
215
                qDebug() << "GraphicsMagic Exception in ScImgDataLoader_GMagick::loadImage("
216
                        << fn << "):" << error_.what();
217
                return false;
218
        }
219
        return true;
13964 herm 220
}
221