Coin Logo Coin3D is Free Software,
published under the BSD 3-clause license.
https://coin3d.github.io
https://www.kongsberg.com/en/kogt/
simage_write.c
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 <assert.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif /* HAVE_CONFIG_H */
24 
25 #include <simage.h>
26 #include <string.h>
27 #include <ctype.h>
28 
30 {
31  int (*save_func)(const char * name, const unsigned char * bytes,
32  int width, int height, int numcomponents);
33  int (*save_func_ext)(const char * name, const unsigned char * bytes,
34  int width, int height, int numcomponents, const char * ext);
35  int (*error_func)(char * textbuffer, int bufferlen);
36  char * extensions;
37  char * fullname;
38  char * description;
39  struct _saver_data * next;
41 };
42 
43 typedef struct _saver_data saver_data;
44 
45 /* built in image loaders */
46 #ifdef SIMAGE_GDIPLUS_SUPPORT
47 #include <simage_gdiplus.h>
48 #endif /* SIMAGE_GDIPLUS_SUPPORT */
49 #ifdef HAVE_JPEGLIB
50 #include <simage_jpeg.h>
51 static saver_data jpeg_saver;
52 #endif /* HAVE_JPEGLIB */
53 #ifdef HAVE_PNGLIB
54 #include <simage_png.h>
55 static saver_data png_saver;
56 #endif /* HAVE_PNGLIB */
57 #ifdef HAVE_TIFFLIB
58 #include <simage_tiff.h>
59 static saver_data tiff_saver;
60 #endif /* HAVE_TIFFLIB */
61 #ifdef SIMAGE_RGB_SUPPORT
62 #include <simage_rgb.h>
63 static saver_data rgb_saver;
64 #endif /* SIMAGE_RGB_SUPPORT */
65 #ifdef HAVE_GIFLIB
66 #include <simage_gif.h>
67 static saver_data gif_saver;
68 #endif /* HAVE_GIFLIB */
69 #ifdef SIMAGE_EPS_SUPPORT
70 #include <simage_eps.h>
71 static saver_data eps_saver;
72 #endif /* SIMAGE_EPS_SUPPORT */
73 #ifdef SIMAGE_QIMAGE_SUPPORT
74 #include <simage_qimage.h>
75 #endif /* SIMAGE_QIMAGE_SUPPORT */
76 #ifdef SIMAGE_QUICKTIME_SUPPORT
77 #include <simage_quicktime.h>
78 #endif /* SIMAGE_QUICKTIME_SUPPORT */
79 #ifdef SIMAGE_CGIMAGE_SUPPORT
80 #include <simage_cgimage.h>
81 #endif /* SIMAGE_CGIMAGE */
82 
83 #include <assert.h>
84 
85 static saver_data * first_saver = NULL;
86 static saver_data * last_saver = NULL;
87 
88 static char *
89 safe_strdup(const char * str)
90 {
91  char * newstr = NULL;
92  if (str != NULL) {
93  newstr = (char *) malloc(strlen(str) + 1);
94  strcpy(newstr, str);
95  }
96  return newstr;
97 }
98 
99 static void
100 safe_strfree(char * str)
101 {
102  if (str != NULL) free(str);
103 }
104 
105 /*
106  * use this instead of strcasecmp, which doesn't exist on Win32
107  * FIXME: replace with a configure test? pederb, 2001-02-07
108  */
109 static int
110 simage_strcasecmp(const char * str1, const char * str2)
111 {
112  if (str1 == NULL && str2 != NULL) return 1;
113  if (str1 != NULL && str2 == NULL) return -1;
114  while (*str1 && *str2) {
115  int tst = tolower(*str1) - tolower(*str2);
116  if (tst) return tst;
117  str1++;
118  str2++;
119  }
120  return *str1 - *str2;
121 }
122 
123 /*
124  * internal functions which adds a saver to the list of savers
125  * returns a void pointer to the saver. addbefore specifies
126  * if the saver should be added at the beginning or at the
127  * end of the linked list. useful if a user program finds
128  * a bug in this library (simply use addbefore)
129  *
130  * Note: The actual significance of is_internal is that memory is
131  * allocated for the "non internal" loaders (currently QImage and
132  * QuickTime), while the other (internal) ones are static structs. The
133  * is_internal flag is used to determine whether the memory for the
134  * loader should be freed at cleanup.
135  */
136 
137 static void
139  int (*error_func)(char *, int),
140  const char * extensions,
141  const char * fullname,
142  const char * description,
143  int is_internal,
144  int addbefore)
145 {
146  saver->extensions = is_internal ? (char*) extensions : safe_strdup(extensions);
147  saver->fullname = is_internal ? (char*) fullname : safe_strdup(fullname);
148  saver->description = is_internal ? (char*) description : safe_strdup(description);
149  saver->error_func = error_func;
150  saver->is_internal = is_internal;
151  saver->next = NULL;
152 
153  if (first_saver == NULL) first_saver = last_saver = saver;
154  else {
155  if (addbefore) {
156  saver->next = first_saver;
157  first_saver = saver;
158  }
159  else {
160  last_saver->next = saver;
161  last_saver = saver;
162  }
163  }
164 }
165 
166 
167 static void *
169  int (*save_func)(const char *,
170  const unsigned char *,
171  int, int, int),
172  int (*error_func)(char *, int),
173  const char * extensions,
174  const char * fullname,
175  const char * description,
176  int is_internal,
177  int addbefore)
178 {
179  assert(saver);
180  saver->save_func = save_func;
181  saver->save_func_ext = NULL;
182  add_saver_data(saver, error_func, extensions, fullname,
183  description, is_internal, addbefore);
184  return saver;
185 }
186 
187 static void *
189  int (*save_func)(const char *,
190  const unsigned char *,
191  int, int, int, const char *),
192  int (*error_func)(char *, int),
193  const char * extensions,
194  const char * fullname,
195  const char * description,
196  int is_internal,
197  int addbefore)
198 {
199  assert(saver);
200  saver->save_func = NULL;
201  saver->save_func_ext = save_func;
202  add_saver_data(saver, error_func, extensions, fullname,
203  description, is_internal, addbefore);
204  return saver;
205 }
206 
207 
208 
209 /*
210  * internal function which finds the correct saver. Returns
211  * NULL if none was found
212  */
213 static saver_data *
214 find_saver(const char * filenameextension)
215 {
216  saver_data * saver;
217  saver = first_saver;
218  while (saver) {
219  char * str;
220  char * ext = saver->extensions;
221  str = strchr(ext, ',');
222 
223  while (str) {
224  int cmp;
225  /* modify string while comparing. string is a copy so it should be safe */
226  *str = 0;
227  cmp = simage_strcasecmp(ext, filenameextension);
228  *str = ',';
229  if (cmp == 0) return saver;
230  ext = str + 1;
231  str = strchr(ext, ',');
232  }
233  if (!simage_strcasecmp(ext, filenameextension)) return saver;
234  saver = saver->next;
235  }
236  return NULL;
237 }
238 
239 /* don't const the ext-strings, they are modified in find_saver */
240 static char jpegext[] = "jpg,jpeg";
241 static const char jpegfull[] = "The Independent JPEG Group file format";
242 static char pngext[] = "png";
243 static const char pngfull[] = "The PNG file format";
244 static char tiffext[] = "tiff,tif";
245 static const char tifffull[] = "The Tag Image File Format";
246 static char rgbext[] = "rgb,rgba,bw,inta,int";
247 static const char rgbfull[] ="The SGI RGB file format";
248 static char gifext[] = "gif";
249 static const char giffull[] = "The Graphics Interchange Format";
250 static char epsext[] = "eps,ps";
251 static const char epsfull[] ="Encapsulated postscript";
252 
253 static void
254 str_tolower(char * str)
255 {
256  while (*str) {
257  *str = tolower(*str);
258  str++;
259  }
260 }
261 
262 static void
264 {
265  static int first = 1;
266  if (first) {
267 #if defined(SIMAGE_GDIPLUS_SUPPORT) || defined(SIMAGE_QIMAGE_SUPPORT) || \
268  defined(SIMAGE_QUICKTIME_SUPPORT) || defined(SIMAGE_CGIMAGE_SUPPORT)
269  char * qtext = NULL;
270 #endif
271  first = 0;
272 
273 #ifdef HAVE_JPEGLIB
274  add_saver(&jpeg_saver,
277  jpegext,
278  jpegfull,
279  NULL,
280  1, 0);
281 #endif /* HAVE_JPEGLIB */
282 #ifdef HAVE_PNGLIB
283  add_saver(&png_saver,
286  pngext,
287  pngfull,
288  NULL,
289  1, 0);
290 #endif /* HAVE_PNGLIB */
291 #ifdef HAVE_TIFFLIB
292  add_saver(&tiff_saver,
295  tiffext,
296  tifffull,
297  NULL,
298  1, 0);
299 #endif /* HAVE_TIFFLIB */
300 #ifdef SIMAGE_RGB_SUPPORT
301  add_saver(&rgb_saver,
304  rgbext,
305  rgbfull,
306  NULL,
307  1, 0);
308 #endif /* SIMAGE_RGB_SUPPORT */
309 #ifdef HAVE_GIFLIB
310  add_saver(&gif_saver,
313  gifext,
314  giffull,
315  NULL,
316  1, 0);
317 #endif /* HAVE_GIFLIB */
318 
319 #ifdef SIMAGE_EPS_SUPPORT
320  add_saver(&eps_saver,
323  epsext,
324  epsfull,
325  NULL,
326  1, 0);
327 #endif /* SIMAGE_EPS_SUPPORT */
328 
329 #ifdef SIMAGE_GDIPLUS_SUPPORT
330  qtext = simage_gdiplus_get_savers();
331  if (qtext) {
332  saver_data * saver;
333  char * str;
334  char * ext = qtext;
335  do {
336  str = strchr(ext, ',');
337  if (str) *str = 0;
338  str_tolower(ext);
339  saver = (saver_data*) malloc(sizeof(saver_data));
340  add_saver_ext(saver,
343  ext,
344  "GDI+ saver",
345  NULL,
346  0, 0);
347 
348  if (str) ext = str + 1;
349  } while (str);
350  free(qtext);
351  }
352 #endif /* SIMAGE_GDIPLUS_SUPPORT */
353 #ifdef SIMAGE_QIMAGE_SUPPORT
354  qtext = simage_qimage_get_savers();
355  if (qtext) {
356  saver_data * saver;
357  char * str;
358  char * ext = qtext;
359  do {
360  str = strchr(ext, ',');
361  if (str) *str = 0;
362  str_tolower(ext);
363  saver = (saver_data*) malloc(sizeof(saver_data));
364  add_saver_ext(saver,
367  ext,
368  "QImage saver",
369  NULL,
370  0, 0);
371 
372  if (str) ext = str + 1;
373  } while (str);
374  free(qtext);
375  }
376 #endif /* SIMAGE_QIMAGE_SUPPORT */
377 #ifdef SIMAGE_QUICKTIME_SUPPORT
378  qtext = simage_quicktime_get_savers();
379  if (qtext) {
380  saver_data * saver;
381  char * str;
382  char * ext = qtext;
383  do {
384  str = strchr(ext, ',');
385  if (str) *str = 0;
386  str_tolower(ext);
387  saver = (saver_data*) malloc(sizeof(saver_data));
388  add_saver_ext(saver,
391  ext,
392  "QuickTime saver",
393  NULL,
394  0, 1);
395  if (str) ext = str + 1;
396  } while (str);
397 
398  free(qtext);
399  }
400 #endif /* SIMAGE_QUICKTIME_SUPPORT */
401 #ifdef SIMAGE_CGIMAGE_SUPPORT
402  qtext = simage_cgimage_get_savers();
403  if (qtext) {
404  saver_data * saver;
405  char * str;
406  char * ext = qtext;
407  do {
408  str = strchr(ext, ',');
409  if (str) *str = 0;
410  str_tolower(ext);
411  saver = (saver_data*) malloc(sizeof(saver_data));
412  add_saver_ext(saver,
415  ext,
416  "CGImage saver",
417  NULL,
418  0, 1);
419  if (str) ext = str + 1;
420  } while (str);
421 
422  free(qtext);
423  }
424 #endif /* SIMAGE_CGIMAGE_SUPPORT */
425  }
426 }
427 
428 #define SIMAGE_ERROR_BUFSIZE 512 /* hack warning. Must match define in simage.c */
429 /* defined in simage.c */
430 extern char simage_error_msg[];
431 
432 int
433 simage_save_image(const char * filename,
434  const unsigned char * bytes,
435  int width, int height, int numcomponents,
436  const char * filenameextension)
437 {
438  saver_data * saver;
439 
440  simage_error_msg[0] = 0; /* clear error msg */
441 
443 
444  saver = find_saver(filenameextension);
445 
446  if (saver) {
447  int ret = 0;
448  if (saver->save_func_ext) {
449  ret = saver->save_func_ext(filename, bytes, width,
450  height, numcomponents,
451  filenameextension);
452  }
453  else if (saver->save_func) {
454  ret = saver->save_func(filename, bytes, width,
455  height, numcomponents);
456  }
457  if (ret == 0) {
458  (void) saver->error_func(simage_error_msg, SIMAGE_ERROR_BUFSIZE);
459  }
460  return ret;
461  }
462  else {
463  strcpy(simage_error_msg, "Unsupported image format.");
464  return 0;
465  }
466 }
467 
468 void *
469 simage_add_saver(int (*save_func)(const char * name,
470  const unsigned char * bytes,
471  int width, int height, int nc),
472  int (*error_func)(char * textbuffer, int bufferlen),
473  const char * extensions,
474  const char * fullname,
475  const char * description,
476  int addbefore)
477 {
479  return add_saver((saver_data *)malloc(sizeof(saver_data)),
480  save_func,
481  error_func,
482  extensions,
483  fullname,
484  description,
485  0, addbefore);
486 }
487 
488 void
489 simage_remove_saver(void * handle)
490 {
491  saver_data *prev = NULL;
492  saver_data *saver = first_saver;
493 
494  while (saver && saver != (saver_data*)handle) {
495  prev = saver;
496  saver = saver->next;
497  }
498  assert(saver);
499  if (saver) { /* found it! */
500  if (last_saver == saver) { /* new last_saver? */
501  last_saver = prev;
502  }
503  if (prev) prev->next = saver->next;
504  else first_saver = saver->next;
505  if (!saver->is_internal) {
506  safe_strfree(saver->extensions);
507  safe_strfree(saver->fullname);
508  safe_strfree(saver->description);
509  free(saver);
510  }
511  }
512 }
513 
514 int
515 simage_check_save_supported(const char * filenameextension)
516 {
517  saver_data * saver;
519  saver = find_saver(filenameextension);
520  return saver != NULL ? 1 : 0;
521 }
522 
523 int
525 {
526  int cnt = 0;
527  saver_data * saver;
528 
529  /* FIXME: it's ugly design that we have to call this method on all
530  public API functions for initialization. 20020215 mortene. */
532 
533  saver = first_saver; /* must be set after add_internal_savers(), obviously */
534  while (saver) {
535  cnt++;
536  saver = saver->next;
537  }
538  return cnt;
539 }
540 
541 void *
543 {
544  saver_data * saver = first_saver;
545  while (saver && idx) {
546  saver = saver->next;
547  idx--;
548  }
549  return (void*) saver;
550 }
551 
552 const char *
554 {
555  saver_data * saver = (saver_data *) handle;
556  return saver->extensions;
557 }
558 
559 const char *
561 {
562  saver_data * saver = (saver_data *) handle;
563  return saver->fullname;
564 }
565 
566 const char *
568 {
569  saver_data * saver = (saver_data *) handle;
570  return saver->description;
571 }
int simage_tiff_error(char *buffer, int bufferlen)
const char * simage_get_saver_fullname(void *handle)
Definition: simage_write.c:560
void * simage_get_saver_handle(int idx)
Definition: simage_write.c:542
static void add_saver_data(saver_data *saver, int(*error_func)(char *, int), const char *extensions, const char *fullname, const char *description, int is_internal, int addbefore)
Definition: simage_write.c:138
int simage_rgb_save(const char *filename, const unsigned char *bytes, int width, int height, int numcomponents)
int simage_png_error(char *buffer, int bufferlen)
#define SIMAGE_ERROR_BUFSIZE
Definition: simage_write.c:428
const char * simage_get_saver_extensions(void *handle)
Definition: simage_write.c:553
int simage_tiff_save(const char *filename, const unsigned char *bytes, int width, int height, int numcomponents)
int simage_rgb_error(char *buffer, int bufferlen)
int simage_gif_save(const char *filename, const unsigned char *bytes, int width, int height, int numcomponents)
char * simage_qimage_get_savers(void)
static const char tifffull[]
Definition: simage_write.c:245
const char * simage_get_saver_description(void *handle)
Definition: simage_write.c:567
struct _saver_data * next
Definition: simage_write.c:39
int simage_gif_error(char *buffer, int bufferlen)
int simage_eps_error(char *buffer, int bufferlen)
static void str_tolower(char *str)
Definition: simage_write.c:254
int(* error_func)(char *textbuffer, int bufferlen)
Definition: simage_write.c:35
int simage_cgimage_save(const char *filename, const unsigned char *bytes, int width, int height, int numcomponents, const char *ext)
static int simage_strcasecmp(const char *str1, const char *str2)
Definition: simage_write.c:110
int(* save_func)(const char *name, const unsigned char *bytes, int width, int height, int numcomponents)
Definition: simage_write.c:31
static saver_data * first_saver
Definition: simage_write.c:85
static char jpegext[]
Definition: simage_write.c:240
char * simage_quicktime_get_savers(void)
static const char rgbfull[]
Definition: simage_write.c:247
static void add_internal_savers(void)
Definition: simage_write.c:263
static const char epsfull[]
Definition: simage_write.c:251
int simage_quicktime_save(const char *filename, const unsigned char *px, int width, int height, int numcomponents, const char *filetypeext)
static char epsext[]
Definition: simage_write.c:250
int simage_qimage_error(char *buffer, int buflen)
int simage_eps_save(const char *filename, const unsigned char *bytes, int width, int height, int numcomponents)
static char * safe_strdup(const char *str)
Definition: simage_write.c:89
static saver_data * last_saver
Definition: simage_write.c:86
Windows specific information.
static const char pngfull[]
Definition: simage_write.c:243
static char tiffext[]
Definition: simage_write.c:244
int simage_cgimage_error(char *cstr, int buflen)
static const char jpegfull[]
Definition: simage_write.c:241
char * simage_cgimage_get_savers(void)
static void * add_saver(saver_data *saver, int(*save_func)(const char *, const unsigned char *, int, int, int), int(*error_func)(char *, int), const char *extensions, const char *fullname, const char *description, int is_internal, int addbefore)
Definition: simage_write.c:168
int simage_gdiplus_save(const char *filename, const unsigned char *bytes, int width, int height, int numcomponents, const char *filetypeext)
char * extensions
Definition: simage_write.c:36
int simage_check_save_supported(const char *filenameextension)
Definition: simage_write.c:515
int simage_get_num_savers(void)
Definition: simage_write.c:524
int simage_gdiplus_error(char *buffer, int buflen)
static void safe_strfree(char *str)
Definition: simage_write.c:100
void simage_remove_saver(void *handle)
Definition: simage_write.c:489
static saver_data * find_saver(const char *filenameextension)
Definition: simage_write.c:214
int simage_quicktime_error(char *cstr, int buflen)
int simage_qimage_save(const char *filename, const unsigned char *bytes, int width, int height, int numcomponents, const char *filetypeext)
int simage_save_image(const char *filename, const unsigned char *bytes, int width, int height, int numcomponents, const char *filenameextension)
Definition: simage_write.c:433
int(* save_func_ext)(const char *name, const unsigned char *bytes, int width, int height, int numcomponents, const char *ext)
Definition: simage_write.c:33
static char pngext[]
Definition: simage_write.c:242
static void * add_saver_ext(saver_data *saver, int(*save_func)(const char *, const unsigned char *, int, int, int, const char *), int(*error_func)(char *, int), const char *extensions, const char *fullname, const char *description, int is_internal, int addbefore)
Definition: simage_write.c:188
static const char giffull[]
Definition: simage_write.c:249
int simage_jpeg_save(const char *filename, const unsigned char *bytes, int width, int height, int numcomponents)
int simage_jpeg_error(char *textbuffer, int buffersize)
void * simage_add_saver(int(*save_func)(const char *name, const unsigned char *bytes, int width, int height, int nc), int(*error_func)(char *textbuffer, int bufferlen), const char *extensions, const char *fullname, const char *description, int addbefore)
Definition: simage_write.c:469
char * simage_gdiplus_get_savers(void)
char * description
Definition: simage_write.c:38
static char gifext[]
Definition: simage_write.c:248
char * fullname
Definition: simage_write.c:37
int simage_png_save(const char *filename, const unsigned char *bytes, int width, int height, int numcomponents)
static char rgbext[]
Definition: simage_write.c:246
char simage_error_msg[]
Definition: simage.c:289