Coin Logo Coin3D is Free Software,
published under the BSD 3-clause license.
https://coin3d.github.io
https://www.kongsberg.com/en/kogt/
simage.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 <simage_private.h>
27 #include <string.h>
28 
30 {
32  struct _loader_data *next;
34  /* simage 1.6 */
36 };
37 
38 typedef struct _loader_data loader_data;
39 
40 /* Note: if any more internal formats are added, please update the
41  documentation on the "filename" field of Coin's SoTexture2 node in
42  Coin/src/nodes/SoTexture2.cpp. */
43 
44 /* built in image loaders */
45 #ifdef SIMAGE_GDIPLUS_SUPPORT
46 #include <simage_gdiplus.h>
47 static loader_data gdiplus_loader;
48 #endif /* SIMAGE_GDIPLUS_SUPPORT */
49 #ifdef HAVE_JPEGLIB
50 #include <simage_jpeg.h>
51 static loader_data jpeg_loader;
52 #endif /* HAVE_JPEGLIB */
53 #ifdef HAVE_JASPER
54 #include <simage_jasper.h>
55 static loader_data jasper_loader;
56 #endif /* HAVE_JASPER */
57 #ifdef HAVE_PNGLIB
58 #include <simage_png.h>
59 static loader_data png_loader;
60 #endif /* HAVE_PNGLIB */
61 #ifdef SIMAGE_TGA_SUPPORT
62 #include <simage_tga.h>
63 static loader_data targa_loader;
64 #endif /* SIMAGE_TGA_SUPPORT */
65 #ifdef HAVE_TIFFLIB
66 #include <simage_tiff.h>
67 static loader_data tiff_loader;
68 #endif /* HAVE_TIFFLIB */
69 #ifdef SIMAGE_PIC_SUPPORT
70 #include <simage_pic.h>
71 static loader_data pic_loader;
72 #endif /* SIMAGE_PIC_SUPPORT */
73 #ifdef SIMAGE_RGB_SUPPORT
74 #include <simage_rgb.h>
75 static loader_data rgb_loader;
76 #endif /* SIMAGE_PIC_SUPPORT */
77 #ifdef HAVE_GIFLIB
78 #include <simage_gif.h>
79 static loader_data gif_loader;
80 #endif /* HAVE_GIFLIB */
81 #ifdef SIMAGE_XWD_SUPPORT
82 #include <simage_xwd.h>
83 static loader_data xwd_loader;
84 #endif /* SIMAGE_XWD_SUPPORT */
85 #ifdef SIMAGE_QIMAGE_SUPPORT
86 #include <simage_qimage.h>
87 static loader_data qimage_loader;
88 #endif /* SIMAGE_QIMAGE_SUPPORT */
89 #ifdef SIMAGE_QUICKTIME_SUPPORT
90 #include <simage_quicktime.h>
91 static loader_data quicktime_loader;
92 #endif /* SIMAGE_QUICKTIME */
93 #ifdef SIMAGE_CGIMAGE_SUPPORT
94 #include <simage_cgimage.h>
95 static loader_data cgimage_loader;
96 #endif /* SIMAGE_CGIMAGE */
97 
98 #include <assert.h>
99 
100 static loader_data *first_loader = NULL;
101 static loader_data *last_loader = NULL;
102 
103 /*
104  * internal function which adds a loader to the list of loaders
105  * returns a void pointer to the loader. addbefore specifies
106  * if the loader should be added at the beginning or at the
107  * end of the linked list. useful if a user program finds
108  * a bug in this library (simply use addbefore)
109  */
110 static void *
112  unsigned char *(*load_func)(const char *,
113  int *,
114  int *,
115  int *),
116  int (*identify_func)(const char *,
117  const unsigned char *,
118  int headerlen),
119  int (*error_func)(char *, int),
120  int is_internal,
121  int addbefore)
122 {
123  assert(loader);
124  loader->funcs.load_func = load_func;
125  loader->funcs.identify_func = identify_func;
126  loader->funcs.error_func = error_func;
127  loader->is_internal = is_internal;
128  loader->next = NULL;
129  memset(&loader->openfuncs, 0, sizeof(struct simage_open_funcs));
130 
131  if (first_loader == NULL) first_loader = last_loader = loader;
132  else {
133  if (addbefore) {
134  loader->next = first_loader;
135  first_loader = loader;
136  }
137  else {
138  last_loader->next = loader;
139  last_loader = loader;
140  }
141  }
142  return (void*) loader;
143 }
144 
145 /*
146  * internal function which finds the correct loader. Returns
147  * NULL if none was found
148  */
149 static loader_data *
150 find_loader(const char *filename)
151 {
152  loader_data *loader;
153  size_t readlen;
154  int err;
155  unsigned char buf[256] = {0};
156  FILE *fp = fopen(filename, "rb");
157  if (!fp) return NULL;
158 
159  readlen = fread(buf, 1, 256, fp);
160  err = ferror(fp);
161  fclose(fp);
162  if (err) return NULL;
163 
164  loader = first_loader;
165  while (loader) {
166  if (loader->funcs.identify_func(filename, buf, readlen)) break;
167  loader = loader->next;
168  }
169  return loader;
170 }
171 
172 
173 static void
175 {
176  static int first = 1;
177  if (first) {
178  first = 0;
179 #ifdef SIMAGE_GDIPLUS_SUPPORT
180  add_loader(&gdiplus_loader,
184  1, 0);
185  gdiplus_loader.openfuncs.open_func = simage_gdiplus_open;
186  gdiplus_loader.openfuncs.close_func = simage_gdiplus_close;
187  gdiplus_loader.openfuncs.read_line_func = simage_gdiplus_read_line;
188 #endif /* SIMAGE_GDIPLUS_SUPPORT */
189 #ifdef HAVE_JPEGLIB
190  add_loader(&jpeg_loader,
194  1, 0);
195 #endif /* HAVE_JPEGLIB */
196 #ifdef HAVE_PNGLIB
197  add_loader(&png_loader,
201  1, 0);
202 #endif /* HAVE_PNGLIB */
203 #ifdef SIMAGE_TGA_SUPPORT
204  add_loader(&targa_loader,
208  1, 0);
209 #endif /* SIMAGE_TGA_SUPPORT */
210 #ifdef HAVE_TIFFLIB
211  add_loader(&tiff_loader,
215  1, 0);
216  tiff_loader.openfuncs.open_func = simage_tiff_open;
217  tiff_loader.openfuncs.close_func = simage_tiff_close;
219 #endif /* HAVE_TIFFLIB */
220 #ifdef HAVE_JASPER
221  add_loader(&jasper_loader,
225  1, 0);
226  /* read_line API not supported by JASPER */
227  /* jasper_loader.openfuncs.open_func = simage_jasper_open;
228  * jasper_loader.openfuncs.close_func = simage_jasper_close;
229  * jasper_loader.openfuncs.read_line_func = simage_jasper_read_line; */
230 #endif /* HAVE_JASPER */
231 #ifdef SIMAGE_RGB_SUPPORT
232  add_loader(&rgb_loader,
236  1, 0);
237  rgb_loader.openfuncs.open_func = simage_rgb_open;
240 #endif /* SIMAGE_RGB_SUPPORT */
241 #ifdef SIMAGE_PIC_SUPPORT
242  add_loader(&pic_loader,
246  1, 0);
247 #endif /* SIMAGE_PIC_SUPPORT */
248 #ifdef HAVE_GIFLIB
249  add_loader(&gif_loader,
253  1, 0);
254 #endif /* HAVE_GIFLIB */
255 #ifdef SIMAGE_XWD_SUPPORT
256  add_loader(&xwd_loader,
260  1, 0);
261 #endif /* SIMAGE_XWD_SUPPORT */
262 #ifdef SIMAGE_QIMAGE_SUPPORT
263  add_loader(&qimage_loader,
267  1, 0);
268 #endif /* SIMAGE_QIMAGE_SUPPORT */
269 #ifdef SIMAGE_QUICKTIME_SUPPORT
270  add_loader(&quicktime_loader,
274  1,
275  1); // add_before -- if we can use QuickTime, makeitso
276 #endif /* SIMAGE_QUICKTIME_SUPPORT */
277 #ifdef SIMAGE_CGIMAGE_SUPPORT
278  add_loader(&cgimage_loader,
282  1,
283  1); // add_before -- if we can use CGImage, makeitso
284 #endif /* SIMAGE_CGIMAGE_SUPPORT */
285  }
286 }
287 
288 #define SIMAGE_ERROR_BUFSIZE 512
290 
291 unsigned char *
292 simage_read_image(const char *filename,
293  int *width, int *height,
294  int *numComponents)
295 {
296  loader_data *loader;
297 
298  simage_error_msg[0] = 0; /* clear error msg */
300 
301  loader = find_loader(filename);
302 
303  if (loader) {
304  unsigned char * data =
305  loader->funcs.load_func(filename, width,
306  height, numComponents);
307  if (data == NULL) {
308  (void) loader->funcs.error_func(simage_error_msg, SIMAGE_ERROR_BUFSIZE);
309  }
310  return data;
311  }
312  else {
313  strcpy(simage_error_msg, "Unsupported image format.");
314  return NULL;
315  }
316 }
317 
318 const char *
320 {
321  return simage_error_msg;
322 }
323 
324 void
325 simage_clear_error(void);
326 
327 int
328 simage_check_supported(const char *filename)
329 {
331  return find_loader(filename) != NULL;
332 }
333 
334 void *
335 simage_add_loader(const struct simage_plugin * plugin, int addbefore)
336 {
338  return add_loader((loader_data *)malloc(sizeof(loader_data)),
339  plugin->load_func,
340  plugin->identify_func,
341  plugin->error_func,
342  0, addbefore);
343 }
344 
345 void
346 simage_remove_loader(void * handle)
347 {
348  loader_data *prev = NULL;
349  loader_data *loader = first_loader;
350 
351  while (loader && loader != (loader_data*)handle) {
352  prev = loader;
353  loader = loader->next;
354  }
355  assert(loader);
356  if (loader) { /* found it! */
357  if (last_loader == loader) { /* new last_loader? */
358  last_loader = prev;
359  }
360  if (prev) prev->next = loader->next;
361  else first_loader = loader->next;
362  if (loader) free(loader);
363  }
364 }
365 
366 /*
367  * a helpful function
368  */
369 static int
370 cnt_bits(int val, int * highbit)
371 {
372  int cnt = 0;
373  *highbit = 0;
374  while (val) {
375  if (val & 1) cnt++;
376  val>>=1;
377  (*highbit)++;
378  }
379  return cnt;
380 }
381 
382 int
384 {
385  /* FIXME: this is done in a more elegant way in Coin's tidbits.c
386  file. 20021210 mortene.
387  Note that if "x" is already a power of two, we will return x
388  (unlike the corresponding Coin function). */
389 
390  int highbit;
391  if (cnt_bits(val, &highbit) > 1) {
392  return 1<<highbit;
393  }
394  return val;
395 }
396 
397 void
398 simage_version(int * major, int * minor, int * micro)
399 {
400  if ( major != NULL ) *major = SIMAGE_MAJOR_VERSION;
401  if ( minor != NULL ) *minor = SIMAGE_MINOR_VERSION;
402  if ( micro != NULL ) *micro = SIMAGE_MICRO_VERSION;
403 }
404 
405 void
406 simage_free_image(unsigned char * imagedata)
407 {
408  if (imagedata) free(imagedata);
409 }
410 
411 
412 /* new simage 1.6 methods */
413 
414 s_image *
415 s_image_open(const char * filename, int oktoreadall)
416 {
417  loader_data * loader;
418 
419  simage_error_msg[0] = 0; /* clear error msg */
421 
422  loader = find_loader(filename);
423 
424  /* check if plugin supports open_funcs */
425  if (loader && loader->openfuncs.open_func) {
426  int w, h, nc;
427  void * opendata = loader->openfuncs.open_func(filename, &w, &h, &nc);
428  if (opendata) {
429  s_image * image = (s_image*) malloc(sizeof(s_image));
430  image->width = w;
431  image->height = h;
432  image->components = nc;
433  image->order = SIMAGE_ORDER_RGB;
434  image->didalloc = 0;
435  image->data = NULL;
436  image->opendata = opendata;
437  image->oktoreadall = oktoreadall;
438  image->openfilename = (char*) malloc(strlen(filename)+1);
439  strcpy(image->openfilename, filename);
440  memcpy(&image->openfuncs, &loader->openfuncs, sizeof(struct simage_open_funcs));
441  return image;
442  }
443  }
444 
445  if (oktoreadall) {
446  /* just load everything */
447  return s_image_load(filename, NULL);
448  }
449  return NULL;
450 }
451 
452 int
454  int line,
455  unsigned char * buf)
456 {
457  if (image->data) {
458  int bpr = image->width*image->components;
459  memcpy(buf, image->data + bpr*line, bpr);
460  return 1;
461  }
462  else if (image->opendata && image->openfuncs.read_line_func) {
463  int ret = image->openfuncs.read_line_func(image->opendata, line, buf);
464  /* for some file formats, the line read order can be important when
465  fetching data from the file. If read-line fails, fall back to
466  reading the entire image */
467 
468  if (!ret && image->oktoreadall && image->openfilename) {
469  /* close old image handle first */
470  image->openfuncs.close_func(image->opendata);
471  image->opendata = NULL;
472 
473  /* just load everything and call function again to read line */
474  image->data = simage_read_image(image->openfilename,
475  &image->width,
476  &image->height,
477  &image->components);
478 
479  if (image->data) {
480  return s_image_read_line(image, line, buf);
481  }
482  }
483  return ret;
484  }
485  return 0;
486 }
487 
488 /* new simage 1.7 methods */
489 
490 static s_dlopen_func *dlopen = NULL;
491 static s_dlsym_func *dlsym = NULL;
492 static s_dlclose_func *dlclose = NULL;
493 
494 void
496  s_dlsym_func *dlsym_func,
497  s_dlclose_func *dlclose_func)
498 {
499 }
int simage_png_identify(const char *filename, const unsigned char *header, int headerlen)
unsigned char * simage_rgb_load(const char *filename, int *width, int *height, int *numcomponents)
void * simage_tiff_open(const char *filename, int *width, int *height, int *numcomponents)
int simage_next_power_of_two(int val)
Definition: simage.c:383
int is_internal
Definition: simage.c:33
int simage_tiff_error(char *buffer, int bufferlen)
int(* read_line_func)(void *opendata, int y, unsigned char *buf)
struct simage_plugin funcs
Definition: simage.c:31
int simage_tga_error(char *buffer, int bufferlen)
int simage_rgb_read_line(void *opendata, int y, unsigned char *buf)
void s_dlclose_func(void *handle)
Definition: simage.h:496
int simage_png_error(char *buffer, int bufferlen)
static s_dlsym_func * dlsym
Definition: simage.c:491
void simage_rgb_close(void *opendata)
int simage_rgb_error(char *buffer, int bufferlen)
void * s_dlopen_func(const char *filename)
Definition: simage.h:494
unsigned char * simage_qimage_load(const char *filename, int *width_ret, int *height_ret, int *numComponents_ret)
void * simage_add_loader(const struct simage_plugin *plugin, int addbefore)
Definition: simage.c:335
int simage_gif_identify(const char *filename, const unsigned char *header, int headerlen)
unsigned char * simage_pic_load(const char *filename, int *width, int *height, int *numComponents)
unsigned char * simage_quicktime_load(const char *file, int *width, int *height, int *numcomponents)
int simage_gif_error(char *buffer, int bufferlen)
unsigned char * data
char simage_error_msg[512+1]
Definition: simage.c:289
static loader_data * first_loader
Definition: simage.c:100
#define SIMAGE_ERROR_BUFSIZE
Definition: simage.c:288
static loader_data * last_loader
Definition: simage.c:101
int simage_pic_identify(const char *filename, const unsigned char *header, int headerlen)
struct simage_open_funcs openfuncs
Definition: simage.c:35
static s_dlopen_func * dlopen
Definition: simage.c:490
void simage_free_image(unsigned char *imagedata)
Definition: simage.c:406
int simage_jpeg_identify(const char *filename, const unsigned char *header, int headerlen)
void simage_remove_loader(void *handle)
Definition: simage.c:346
unsigned char * simage_tga_load(const char *filename, int *width, int *height, int *numComponents)
int simage_qimage_error(char *buffer, int buflen)
int(* identify_func)(const char *filename, const unsigned char *header, int headerlen)
Definition: simage.h:239
struct simage_open_funcs openfuncs
int simage_cgimage_identify(const char *file, const unsigned char *header, int headerlen)
void simage_tiff_close(void *opendata)
void simage_gdiplus_close(void *opendata)
int simage_qimage_identify(const char *ptr, const unsigned char *header, int headerlen)
unsigned char * simage_tiff_load(const char *filename, int *width, int *height, int *numComponents)
int simage_xwd_identify(const char *filename, const unsigned char *header, int headerlen)
unsigned char * simage_gif_load(const char *filename, int *width, int *height, int *numComponents)
Windows specific information.
unsigned char * simage_xwd_load(const char *filename, int *width, int *height, int *numcomponents)
int simage_rgb_identify(const char *filename, const unsigned char *header, int headerlen)
int s_image_read_line(s_image *image, int line, unsigned char *buf)
Definition: simage.c:453
void(* close_func)(void *opendata)
int simage_cgimage_error(char *cstr, int buflen)
void * simage_gdiplus_open(const char *filename, int *width, int *height, int *numcomponents)
void s_set_dynamic_loader_interface(s_dlopen_func *dlopen_func, s_dlsym_func *dlsym_func, s_dlclose_func *dlclose_func)
Definition: simage.c:495
int simage_tiff_read_line(void *opendata, int y, unsigned char *buf)
void * s_dlsym_func(void *handle, const char *symbolname)
Definition: simage.h:495
static int cnt_bits(int val, int *highbit)
Definition: simage.c:370
s_image * s_image_load(const char *filename, s_image *prealloc)
Definition: simage12.c:163
static s_dlclose_func * dlclose
Definition: simage.c:492
int simage_gdiplus_error(char *buffer, int buflen)
static void add_internal_loaders(void)
Definition: simage.c:174
const char * simage_get_last_error(void)
Definition: simage.c:319
s_image * s_image_open(const char *filename, int oktoreadall)
Definition: simage.c:415
int simage_quicktime_error(char *cstr, int buflen)
unsigned char * simage_png_load(const char *filename, int *width, int *height, int *numComponents)
int simage_jasper_error(char *buffer, int bufferlen)
int simage_tga_identify(const char *filename, const unsigned char *header, int headerlen)
unsigned char * simage_gdiplus_load(const char *filename, int *width, int *height, int *numcomponents)
int simage_pic_error(char *buffer, int bufferlen)
int simage_gdiplus_read_line(void *opendata, int y, unsigned char *buf)
int simage_xwd_error(char *buffer, int bufferlen)
int simage_gdiplus_identify(const char *ptr, const unsigned char *header, int headerlen)
static loader_data * find_loader(const char *filename)
Definition: simage.c:150
int simage_jasper_identify(const char *filename, const unsigned char *header, int headerlen)
struct _loader_data * next
Definition: simage.c:32
static void * add_loader(loader_data *loader, unsigned char *(*load_func)(const char *, int *, int *, int *), int(*identify_func)(const char *, const unsigned char *, int headerlen), int(*error_func)(char *, int), int is_internal, int addbefore)
Definition: simage.c:111
unsigned char *(* load_func)(const char *name, int *width, int *height, int *numcomponents)
Definition: simage.h:237
void simage_clear_error(void)
unsigned char * simage_jasper_load(const char *filename, int *width, int *height, int *numComponents)
int simage_jpeg_error(char *textbuffer, int buffersize)
int simage_quicktime_identify(const char *file, const unsigned char *header, int headerlen)
void * simage_rgb_open(const char *filename, int *width, int *height, int *numcomponents)
unsigned char * simage_jpeg_load(const char *filename, int *width, int *height, int *numcomponents)
unsigned char * simage_read_image(const char *filename, int *width, int *height, int *numComponents)
Definition: simage.c:292
void *(* open_func)(const char *filename, int *w, int *h, int *nc)
unsigned char * simage_cgimage_load(const char *file, int *width, int *height, int *numcomponents)
int simage_check_supported(const char *filename)
Definition: simage.c:328
void simage_version(int *major, int *minor, int *micro)
Definition: simage.c:398
int simage_tiff_identify(const char *filename, const unsigned char *header, int headerlen)
int(* error_func)(char *textbuffer, int bufferlen)
Definition: simage.h:241