Coin Logo Coin3D is Free Software,
published under the BSD 3-clause license.
https://coin3d.github.io
https://www.kongsberg.com/en/kogt/
simage_qimage.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) Kongsberg Oil & Gas Technologies
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 #include <simage_qimage.h>
18 
19 #include <qglobal.h>
20 #include <qimage.h>
21 #include <qstring.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <ctype.h>
25 #include <stdlib.h>
26 
27 #if QT_VERSION > 0x040000
28 #define QT4 1
29 #else // QT version >= 4.0.0
30 #define QT4 0
31 #endif // QT version < 4.0.0
32 
33 #if QT4
34 #include <qimagereader.h>
35 #include <qimagewriter.h>
36 #endif // QT4
37 
38 #define ERR_NO_ERROR 0
39 #define ERR_OPEN 1
40 #define ERR_MEM 2
41 #define ERR_QIMAGE_WRITE 5
42 #define ERR_UNSUPPORTED_WRITE 6
43 
45 
46 int
47 simage_qimage_error(char * buffer, int buflen)
48 {
49  switch (qimageerror) {
50  case ERR_OPEN:
51  strncpy(buffer, "QImage loader: Error opening file", buflen);
52  break;
53  case ERR_MEM:
54  strncpy(buffer, "QImage loader: Out of memory error", buflen);
55  break;
56  case ERR_QIMAGE_WRITE:
57  strncpy(buffer, "QImage saver: Internal QImage error", buflen);
58  break;
60  strncpy(buffer, "QImage saver: Unsupported file format", buflen);
61  break;
62  }
63  return qimageerror;
64 }
65 
66 int
67 simage_qimage_identify(const char * ptr,
68  const unsigned char *header,
69  int headerlen)
70 {
71 #if QT4
72  return ! QImageReader::imageFormat(QString(ptr)).isEmpty();
73 #else
74  return QImage::imageFormat(QString(ptr)) != NULL;
75 #endif
76 }
77 
78 unsigned char *
79 simage_qimage_load(const char * filename,
80  int * width_ret,
81  int * height_ret,
82  int * numComponents_ret)
83 {
84  QImage image;
85  if (image.load(filename)) {
86  int w = image.width();
87  int h = image.height();
88  // Keep in 8-bits mode if that was what we read
89  int c;
90  if (image.depth() == 8 && image.isGrayscale())
91  c = 1;
92  else {
93 #if QT4
94  c = image.hasAlphaChannel() ? 4 : 3;
95  image = image.convertToFormat(image.hasAlphaChannel() ?
96  QImage::Format_ARGB32 : QImage::Format_RGB32);
97 #else
98  image = image.convertDepth(32);
99  c = image.hasAlphaBuffer() ? 4 : 3;
100 #endif
101  }
102 
103  unsigned char *buffer = (unsigned char *)malloc(w*h*c);
104  if (buffer == NULL) {
106  return NULL;
107  }
108 
109  if (c == 1) {
110  for (int i = 0; i < h; i++) {
111  memcpy(buffer + i*w, image.scanLine(h-(i+1)), w);
112  }
113  }
114  else { // (c == 3 || c == 4)
115  QRgb * bits = (QRgb*) image.bits();
116  for (int y = 0; y < h; y++) {
117  unsigned char * line = &buffer[c*w*(h-(y+1))];
118  for (int x = 0; x < w; x++) {
119  *line++ = qRed(*bits);
120  *line++ = qGreen(*bits);
121  *line++ = qBlue(*bits);
122  if (c == 4) {
123  *line++ = qAlpha(*bits);
124  }
125  bits++;
126  }
127  }
128  }
129 
130  *width_ret = w;
131  *height_ret = h;
132  *numComponents_ret = c;
133  return buffer;
134  }
136  return NULL;
137 }
138 
139 #define MAX_EXT_LEN 255
140 
141 static int
142 qimage_set_save_format(const char * ext, char * buf)
143 {
144  strncpy(buf, ext, MAX_EXT_LEN);
145  buf[MAX_EXT_LEN] = 0;
146 
147  int i = 0;
148  // convert to lower case
149  while (buf[i] != 0) {
150  buf[i] = tolower(buf[i]);
151  i++;
152  }
153 
154  // Qt specifies the jpg extension as jpeg
155  if (strcmp(buf, "jpg") == 0) strcpy(buf, "jpeg");
156 
157 #if QT4
158 
159  QList <QByteArray> list = QImageWriter::supportedImageFormats();
160  const int n = list.size();
161  for (int i = 0; i < n; i++) {
162  if (strcmp(buf, list[i].toLower().constData()) == 0) {
163  strncpy(buf, list[i].constData(), MAX_EXT_LEN);
164  return 1;
165  }
166  }
167 
168 #else // QT4
169 
170  QStrList olist = QImage::outputFormats();
171  const char * qtext = olist.getFirst();
172  while (qtext) {
173  if (strcmp(buf, QString(qtext).lower().ascii()) == 0) {
174  strncpy(buf, QString(qtext).ascii(), MAX_EXT_LEN);
175  return 1;
176  }
177  qtext = olist.next();
178  }
179 
180 #endif // !QT4
181 
182  // clear save format
183  buf[0] = 0;
184  return 0;
185 }
186 
187 char *
189 {
190 #if QT4
191 
192  QByteArray str;
193  QList <QByteArray> list = QImageWriter::supportedImageFormats();
194  const int n = list.size();
195  int first = 1;
196  for (int i = 0; i < n; i++) {
197  if (!first) str += ",";
198  first = 0;
199  str += list[i];
200  }
201  if (first) return NULL;
202  const char * asc = str.constData();
203  int len = (int)strlen(asc);
204  char * dst = (char*) malloc(len+1);
205  strcpy(dst, asc);
206  return dst;
207 
208 #else // QT4
209 
210  QString str;
211  int first = 1;
212  QStrList olist = QImage::outputFormats();
213  const char * qtext = olist.getFirst();
214  while (qtext) {
215  if (!first) str += ",";
216  first = 0;
217  str += qtext;
218  qtext = olist.next();
219  }
220  if (first) return NULL; // no savers available
221  const char * asc = str.ascii();
222  int len = strlen(asc);
223  char * dst = (char*) malloc(len+1);
224  strcpy(dst, asc);
225  return dst;
226 
227 #endif // !QT4
228 }
229 
230 
231 int
232 simage_qimage_save(const char * filename,
233  const unsigned char * bytes,
234  int width,
235  int height,
236  int numcomponents,
237  const char * filetypeext)
238 {
239  char ext[MAX_EXT_LEN+1];
240  qimage_set_save_format(filetypeext, ext);
241  if (ext[0] == 0) {
243  return 0;
244  }
245 
246 #if QT4
247  QImage image(width, height, numcomponents == 2 || numcomponents == 4 ?
248  QImage::Format_ARGB32 : QImage::Format_RGB32);
249 #else // QT4
250  QImage image(width, height, 32);
251  if (numcomponents == 2 || numcomponents == 4) image.setAlphaBuffer(TRUE);
252  else image.setAlphaBuffer(FALSE);
253 #endif // !QT4
254  QRgb * bits = (QRgb*) image.bits();
255 
256  for (int y = 0; y < height; y++) {
257  const unsigned char * line =
258  &bytes[width*numcomponents*(height-(y+1))];
259  for (int x = 0; x < width; x++) {
260  switch (numcomponents) {
261  default:
262  case 1:
263  *bits++ = qRgb(line[0], line[0], line[0]);
264  break;
265  case 2:
266  *bits++ = qRgba(line[0], line[0], line[0], line[1]);
267  break;
268  case 3:
269  *bits++ = qRgb(line[0], line[1], line[2]);
270  break;
271  case 4:
272  *bits++ = qRgba(line[0], line[1], line[2], line[3]);
273  break;
274  }
275  line += numcomponents;
276  }
277  }
278  bool ret = image.save(QString(filename), ext);
279  if (!ret) {
281  return 0;
282  }
283  return 1;
284 }
#define ERR_QIMAGE_WRITE
unsigned char * simage_qimage_load(const char *filename, int *width_ret, int *height_ret, int *numComponents_ret)
char * simage_qimage_get_savers(void)
#define ERR_OPEN
int simage_qimage_error(char *buffer, int buflen)
int simage_qimage_identify(const char *ptr, const unsigned char *header, int headerlen)
#define ERR_MEM
static int qimageerror
int simage_qimage_save(const char *filename, const unsigned char *bytes, int width, int height, int numcomponents, const char *filetypeext)
#define ERR_NO_ERROR
static int qimage_set_save_format(const char *ext, char *buf)
#define ERR_UNSUPPORTED_WRITE
#define MAX_EXT_LEN