1 #include <simage_qimage.h>
2
3 #include <qglobal.h>
4 #include <qimage.h>
5 #include <qstring.h>
6 #include <stdio.h>
7 #include <string.h>
8 #include <ctype.h>
9 #include <stdlib.h>
10
11 #if QT_VERSION > 0x040000
12 #define QT4 1
13 #else // QT version >= 4.0.0
14 #define QT4 0
15 #endif // QT version < 4.0.0
16
17 #if QT4
18 #include <qimagereader.h>
19 #include <qimagewriter.h>
20 #endif // QT4
21
22 #define ERR_NO_ERROR 0
23 #define ERR_OPEN 1
24 #define ERR_MEM 2
25 #define ERR_QIMAGE_WRITE 5
26 #define ERR_UNSUPPORTED_WRITE 6
27
28 static int qimageerror = ERR_NO_ERROR;
29
30 int
simage_qimage_error(char * buffer,int buflen)31 simage_qimage_error(char * buffer, int buflen)
32 {
33 switch (qimageerror) {
34 case ERR_OPEN:
35 strncpy(buffer, "QImage loader: Error opening file", buflen);
36 break;
37 case ERR_MEM:
38 strncpy(buffer, "QImage loader: Out of memory error", buflen);
39 break;
40 case ERR_QIMAGE_WRITE:
41 strncpy(buffer, "QImage saver: Internal QImage error", buflen);
42 break;
43 case ERR_UNSUPPORTED_WRITE:
44 strncpy(buffer, "QImage saver: Unsupported file format", buflen);
45 break;
46 }
47 return qimageerror;
48 }
49
50 int
simage_qimage_identify(const char * ptr,const unsigned char * header,int headerlen)51 simage_qimage_identify(const char * ptr,
52 const unsigned char *header,
53 int headerlen)
54 {
55 #if QT4
56 return ! QImageReader::imageFormat(QString(ptr)).isEmpty();
57 #else
58 return QImage::imageFormat(QString(ptr)) != NULL;
59 #endif
60 }
61
62 unsigned char *
simage_qimage_load(const char * filename,int * width_ret,int * height_ret,int * numComponents_ret)63 simage_qimage_load(const char * filename,
64 int * width_ret,
65 int * height_ret,
66 int * numComponents_ret)
67 {
68 QImage image;
69 if (image.load(filename)) {
70 int w = image.width();
71 int h = image.height();
72 // Keep in 8-bits mode if that was what we read
73 int c;
74 if (image.depth() == 8 && image.isGrayscale())
75 c = 1;
76 else {
77 #if QT4
78 c = image.hasAlphaChannel() ? 4 : 3;
79 image = image.convertToFormat(image.hasAlphaChannel() ?
80 QImage::Format_ARGB32 : QImage::Format_RGB32);
81 #else
82 image = image.convertDepth(32);
83 c = image.hasAlphaBuffer() ? 4 : 3;
84 #endif
85 }
86
87 unsigned char *buffer = (unsigned char *)malloc(w*h*c);
88 if (buffer == NULL) {
89 qimageerror = ERR_MEM;
90 return NULL;
91 }
92
93 if (c == 1) {
94 for (int i = 0; i < h; i++) {
95 memcpy(buffer + i*w, image.scanLine(h-(i+1)), w);
96 }
97 }
98 else { // (c == 3 || c == 4)
99 QRgb * bits = (QRgb*) image.bits();
100 for (int y = 0; y < h; y++) {
101 unsigned char * line = &buffer[c*w*(h-(y+1))];
102 for (int x = 0; x < w; x++) {
103 *line++ = qRed(*bits);
104 *line++ = qGreen(*bits);
105 *line++ = qBlue(*bits);
106 if (c == 4) {
107 *line++ = qAlpha(*bits);
108 }
109 bits++;
110 }
111 }
112 }
113
114 *width_ret = w;
115 *height_ret = h;
116 *numComponents_ret = c;
117 return buffer;
118 }
119 qimageerror = ERR_OPEN;
120 return NULL;
121 }
122
123 #define MAX_EXT_LEN 255
124
125 static int
qimage_set_save_format(const char * ext,char * buf)126 qimage_set_save_format(const char * ext, char * buf)
127 {
128 strncpy(buf, ext, MAX_EXT_LEN);
129 buf[MAX_EXT_LEN] = 0;
130
131 int i = 0;
132 // convert to upper case
133 while (buf[i] != 0) {
134 buf[i] = toupper(buf[i]);
135 i++;
136 }
137
138 // Qt specifies the jpg extension as JPEG
139 if (strcmp(buf, "JPG") == 0) strcpy(buf, "JPEG");
140
141 #if QT4
142
143 QList <QByteArray> list = QImageWriter::supportedImageFormats();
144 const int n = list.size();
145 for (int i = 0; i < n; i++) {
146 if (strcmp(buf, list[i].constData()) == 0) return 1;
147 }
148 buf[0] = 0;
149 return 0;
150
151 #else // QT4
152
153 QStrList olist = QImage::outputFormats();
154 const char * qtext = olist.getFirst();
155 while (qtext) {
156 if (strcmp(buf, qtext) == 0) return 1;
157 qtext = olist.next();
158 }
159 // clear save format
160 buf[0] = 0;
161 return 0;
162
163 #endif // !QT4
164 }
165
166 char *
simage_qimage_get_savers(void)167 simage_qimage_get_savers(void)
168 {
169 #if QT4
170
171 QByteArray str;
172 QList <QByteArray> list = QImageWriter::supportedImageFormats();
173 const int n = list.size();
174 int first = 1;
175 for (int i = 0; i < n; i++) {
176 if (!first) str += ",";
177 first = 0;
178 str += list[i];
179 }
180 if (first) return NULL;
181 const char * asc = str.constData();
182 int len = strlen(asc);
183 char * dst = (char*) malloc(len+1);
184 strcpy(dst, asc);
185 return dst;
186
187 #else // QT4
188
189 QString str;
190 int first = 1;
191 QStrList olist = QImage::outputFormats();
192 const char * qtext = olist.getFirst();
193 while (qtext) {
194 if (!first) str += ",";
195 first = 0;
196 str += qtext;
197 qtext = olist.next();
198 }
199 if (first) return NULL; // no savers available
200 const char * asc = str.ascii();
201 int len = strlen(asc);
202 char * dst = (char*) malloc(len+1);
203 strcpy(dst, asc);
204 return dst;
205
206 #endif // !QT4
207 }
208
209
210 int
simage_qimage_save(const char * filename,const unsigned char * bytes,int width,int height,int numcomponents,const char * filetypeext)211 simage_qimage_save(const char * filename,
212 const unsigned char * bytes,
213 int width,
214 int height,
215 int numcomponents,
216 const char * filetypeext)
217 {
218 char ext[MAX_EXT_LEN+1];
219 qimage_set_save_format(filetypeext, ext);
220 if (ext[0] == 0) {
221 qimageerror = ERR_UNSUPPORTED_WRITE;
222 return 0;
223 }
224
225 #if QT4
226 QImage image(width, height, numcomponents == 2 || numcomponents == 4 ?
227 QImage::Format_ARGB32 : QImage::Format_RGB32);
228 #else // QT4
229 QImage image(width, height, 32);
230 if (numcomponents == 2 || numcomponents == 4) image.setAlphaBuffer(TRUE);
231 else image.setAlphaBuffer(FALSE);
232 #endif // !QT4
233 QRgb * bits = (QRgb*) image.bits();
234
235 for (int y = 0; y < height; y++) {
236 const unsigned char * line =
237 &bytes[width*numcomponents*(height-(y+1))];
238 for (int x = 0; x < width; x++) {
239 switch (numcomponents) {
240 default:
241 case 1:
242 *bits++ = qRgb(line[0], line[0], line[0]);
243 break;
244 case 2:
245 *bits++ = qRgba(line[0], line[0], line[0], line[1]);
246 break;
247 case 3:
248 *bits++ = qRgb(line[0], line[1], line[2]);
249 break;
250 case 4:
251 *bits++ = qRgba(line[0], line[1], line[2], line[3]);
252 break;
253 }
254 line += numcomponents;
255 }
256 }
257 bool ret = image.save(QString(filename), ext);
258 if (!ret) {
259 qimageerror = ERR_QIMAGE_WRITE;
260 return 0;
261 }
262 return 1;
263 }
264