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