Subversion Repositories Scribus

Rev

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