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 upper case
149  while (buf[i] != 0) {
150  buf[i] = toupper(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].constData()) == 0) return 1;
163  }
164  buf[0] = 0;
165  return 0;
166 
167 #else // QT4
168 
169  QStrList olist = QImage::outputFormats();
170  const char * qtext = olist.getFirst();
171  while (qtext) {
172  if (strcmp(buf, qtext) == 0) return 1;
173  qtext = olist.next();
174  }
175  // clear save format
176  buf[0] = 0;
177  return 0;
178 
179 #endif // !QT4
180 }
181 
182 char *
184 {
185 #if QT4
186 
187  QByteArray str;
188  QList <QByteArray> list = QImageWriter::supportedImageFormats();
189  const int n = list.size();
190  int first = 1;
191  for (int i = 0; i < n; i++) {
192  if (!first) str += ",";
193  first = 0;
194  str += list[i];
195  }
196  if (first) return NULL;
197  const char * asc = str.constData();
198  int len = (int)strlen(asc);
199  char * dst = (char*) malloc(len+1);
200  strcpy(dst, asc);
201  return dst;
202 
203 #else // QT4
204 
205  QString str;
206  int first = 1;
207  QStrList olist = QImage::outputFormats();
208  const char * qtext = olist.getFirst();
209  while (qtext) {
210  if (!first) str += ",";
211  first = 0;
212  str += qtext;
213  qtext = olist.next();
214  }
215  if (first) return NULL; // no savers available
216  const char * asc = str.ascii();
217  int len = strlen(asc);
218  char * dst = (char*) malloc(len+1);
219  strcpy(dst, asc);
220  return dst;
221 
222 #endif // !QT4
223 }
224 
225 
226 int
227 simage_qimage_save(const char * filename,
228  const unsigned char * bytes,
229  int width,
230  int height,
231  int numcomponents,
232  const char * filetypeext)
233 {
234  char ext[MAX_EXT_LEN+1];
235  qimage_set_save_format(filetypeext, ext);
236  if (ext[0] == 0) {
238  return 0;
239  }
240 
241 #if QT4
242  QImage image(width, height, numcomponents == 2 || numcomponents == 4 ?
243  QImage::Format_ARGB32 : QImage::Format_RGB32);
244 #else // QT4
245  QImage image(width, height, 32);
246  if (numcomponents == 2 || numcomponents == 4) image.setAlphaBuffer(TRUE);
247  else image.setAlphaBuffer(FALSE);
248 #endif // !QT4
249  QRgb * bits = (QRgb*) image.bits();
250 
251  for (int y = 0; y < height; y++) {
252  const unsigned char * line =
253  &bytes[width*numcomponents*(height-(y+1))];
254  for (int x = 0; x < width; x++) {
255  switch (numcomponents) {
256  default:
257  case 1:
258  *bits++ = qRgb(line[0], line[0], line[0]);
259  break;
260  case 2:
261  *bits++ = qRgba(line[0], line[0], line[0], line[1]);
262  break;
263  case 3:
264  *bits++ = qRgb(line[0], line[1], line[2]);
265  break;
266  case 4:
267  *bits++ = qRgba(line[0], line[1], line[2], line[3]);
268  break;
269  }
270  line += numcomponents;
271  }
272  }
273  bool ret = image.save(QString(filename), ext);
274  if (!ret) {
276  return 0;
277  }
278  return 1;
279 }
#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