BRL-CAD
fileformat.c
Go to the documentation of this file.
1 /* F I L E F O R M A T . C
2  * BRL-CAD
3  *
4  * Copyright (c) 2007-2014 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * version 2.1 as published by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; see the file named COPYING for more
18  * information.
19  */
20 
21 #include "common.h"
22 
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/stat.h> /* for file mode info in WRMODE */
26 #include <png.h>
27 
28 #include "bio.h"
29 
30 #include "bu/str.h"
31 #include "bu/log.h"
32 #include "bu/malloc.h"
33 #include "bn.h"
34 #include "vmath.h"
35 #include "icv.h"
36 
37 
38 /* c99 doesn't declare these, but C++ does */
39 #if (!defined(_WIN32) || defined(__CYGWIN__)) && !defined(__cplusplus)
40 extern FILE *fdopen(int, const char *);
41 #endif
42 
43 
44 /* this might be a little better than saying 0444 */
45 #define WRMODE S_IRUSR|S_IRGRP|S_IROTH
46 
47 /* defined in encoding.c */
48 extern double *uchar2double(unsigned char *data, long int size);
49 extern unsigned char *data2uchar(const icv_image_t *bif);
50 
51 /* defined in bw.c */
52 extern int bw_write(icv_image_t *bif, const char *filename);
53 extern icv_image_t *bw_read(const char *filename, int width, int height);
54 
55 /* defined in pix.c */
56 extern int pix_write(icv_image_t *bif, const char *filename);
57 extern icv_image_t *pix_read(const char* filename, int width, int height);
58 
59 /* defined in dpix.c */
60 extern icv_image_t *dpix_read(const char* filename, int width, int height);
61 extern int dpix_write(icv_image_t *bif, const char *filename);
62 
63 /* defined in ppm.c */
64 extern int ppm_write(icv_image_t *bif, const char *filename);
65 extern icv_image_t* ppm_read(const char *filename);
66 
67 /* private functions */
68 
69 /*
70  * Attempt to guess the file type. Understands ImageMagick style
71  * FMT:filename as being preferred, but will attempt to guess based on
72  * extension as well.
73  *
74  * I suck. I'll fix this later. Honest.
75  *
76  * FIXME: assuming trimmedname is BUFSIZ is a crash waiting to bite
77  * someone down the road. should pass a size or use a vls or have it
78  * return the string as as return type (making the int type be an int*
79  * argument instead that gets set).
80  */
82 icv_guess_file_format(const char *filename, char *trimmedname)
83 {
84  /* look for the FMT: header */
85 #define CMP(name) if (!bu_strncmp(filename, #name":", strlen(#name))) {bu_strlcpy(trimmedname, filename+strlen(#name)+1, BUFSIZ);return ICV_IMAGE_##name; }
86  CMP(PIX);
87  CMP(PNG);
88  CMP(PPM);
89  CMP(BMP);
90  CMP(BW);
91  CMP(DPIX)
92 #undef CMP
93 
94  /* no format header found, copy the name as it is */
95  bu_strlcpy(trimmedname, filename, BUFSIZ);
96 
97  /* and guess based on extension */
98 #define CMP(name, ext) if (!bu_strncmp(filename+strlen(filename)-strlen(#name)-1, "."#ext, strlen(#name)+1)) return ICV_IMAGE_##name;
99  CMP(PIX, pix);
100  CMP(PNG, png);
101  CMP(PPM, ppm);
102  CMP(BMP, bmp);
103  CMP(BW, bw);
104  CMP(DPIX, dpix);
105 #undef CMP
106  /* defaulting to PIX */
107  return ICV_IMAGE_UNKNOWN;
108 }
109 
110 HIDDEN int
111 png_write(icv_image_t *bif, const char *filename)
112 {
113  png_structp png_ptr = NULL;
114  png_infop info_ptr = NULL;
115  int i = 0;
116  int png_color_type = PNG_COLOR_TYPE_RGB;
117  unsigned char *data;
118  FILE *fh;
119 
120  fh = fopen(filename, "wb");
121  if (UNLIKELY(fh==NULL)) {
122  perror("fdopen");
123  bu_log("ERROR: png_write failed to get a FILE pointer\n");
124  return 0;
125  }
126 
127  data = data2uchar(bif);
128 
129  png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
130  if (UNLIKELY(png_ptr == NULL)) {
131  fclose(fh);
132  return 0;
133  }
134 
135  info_ptr = png_create_info_struct(png_ptr);
136  if (info_ptr == NULL || setjmp(png_jmpbuf(png_ptr))) {
137  png_destroy_read_struct(&png_ptr, info_ptr ? &info_ptr : NULL, NULL);
138  bu_log("ERROR: Unable to create png header\n");
139  fclose(fh);
140  return 0;
141  }
142 
143  png_init_io(png_ptr, fh);
144  png_set_IHDR(png_ptr, info_ptr, (unsigned)bif->width, (unsigned)bif->height, 8, png_color_type,
145  PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
146  PNG_FILTER_TYPE_DEFAULT);
147  png_write_info(png_ptr, info_ptr);
148  for (i = bif->height-1; i >= 0; --i)
149  png_write_row(png_ptr, (png_bytep) (data + bif->width*bif->channels*i));
150  png_write_end(png_ptr, info_ptr);
151 
152  png_destroy_write_struct(&png_ptr, &info_ptr);
153  fclose(fh);
154  return 1;
155 }
156 
157 /* end of private functions */
158 
159 /* begin public functions */
160 
161 icv_image_t *
162 icv_read(const char *filename, int format, int width, int height)
163 {
164  if (format == ICV_IMAGE_AUTO) {
165  /* do some voodoo with the file magic or something... */
166  format = ICV_IMAGE_PIX;
167  }
168 
169  switch (format) {
170  case ICV_IMAGE_PIX:
171  return pix_read(filename, width, height);
172  case ICV_IMAGE_BW :
173  return bw_read(filename, width, height);
174  case ICV_IMAGE_DPIX :
175  return dpix_read(filename, width, height);
176  case ICV_IMAGE_PPM :
177  return ppm_read(filename);
178  default:
179  bu_log("icv_read not implemented for this format\n");
180  return NULL;
181  }
182 }
183 
184 
185 int
186 icv_write(icv_image_t *bif, const char *filename, ICV_IMAGE_FORMAT format)
187 {
188  /* FIXME: should not be introducing fixed size buffers */
189  char buf[BUFSIZ] = {0};
190 
191  if (format == ICV_IMAGE_AUTO) {
192  format = (ICV_IMAGE_FORMAT)icv_guess_file_format(filename, buf);
193  }
194 
195  ICV_IMAGE_VAL_INT(bif);
196 
197  switch (format) {
198  /* case ICV_IMAGE_BMP:
199  return bmp_write(bif, filename); */
200  case ICV_IMAGE_PPM:
201  return ppm_write(bif, filename);
202  case ICV_IMAGE_PNG:
203  return png_write(bif, filename);
204  case ICV_IMAGE_PIX:
205  return pix_write(bif, filename);
206  case ICV_IMAGE_BW:
207  return bw_write(bif, filename);
208  case ICV_IMAGE_DPIX :
209  return dpix_write(bif, filename);
210  default:
211  bu_log("Unrecognized format. Outputting in PIX format.\n");
212  }
213 
214  return pix_write(bif, filename);
215 }
216 
217 
218 int
219 icv_writeline(icv_image_t *bif, int y, void *data, ICV_DATA type)
220 {
221  double *dst;
222  size_t width_size;
223  unsigned char *p=NULL;
224 
225  if (bif == NULL || data == NULL)
226  return -1;
227 
228  ICV_IMAGE_VAL_INT(bif);
229 
230  if (y > bif->height || y < 0)
231  return -1;
232 
233  width_size = (size_t) bif->width*bif->channels;
234  dst = bif->data + width_size*y;
235 
236  if (type == ICV_DATA_UCHAR) {
237  p = (unsigned char *)data;
238  for (; width_size > 0; width_size--) {
239  *dst = ICV_CONV_8BIT(*p);
240  p++;
241  dst++;
242  }
243  } else
244  memcpy(dst, data, width_size*sizeof(double));
245 
246 
247  return 0;
248 }
249 
250 
251 int
252 icv_writepixel(icv_image_t *bif, int x, int y, double *data)
253 {
254  double *dst;
255 
256  ICV_IMAGE_VAL_INT(bif);
257 
258  if (x > bif->width || x < 0)
259  return -1;
260 
261  if (y > bif->height || y < 0)
262  return -1;
263 
264  if (data == NULL)
265  return -1;
266 
267  dst = bif->data + (y*bif->width + x)*bif->channels;
268 
269  /* can copy float to double also double to double */
270  VMOVEN(dst, data, bif->channels);
271  return 0;
272 }
273 
274 
275 icv_image_t *
276 icv_create(int width, int height, ICV_COLOR_SPACE color_space)
277 {
278  icv_image_t *bif;
279  BU_ALLOC(bif, struct icv_image);
280  bif->width = width;
281  bif->height = height;
282  bif->color_space = color_space;
283  bif->alpha_channel = 0;
284  bif->magic = ICV_IMAGE_MAGIC;
285  switch (color_space) {
286  case ICV_COLOR_SPACE_RGB :
287  /* Add all the other three channel images here (eg. HSV, YCbCr etc.) */
288  bif->data = (double *) bu_malloc(bif->height*bif->width*3*sizeof(double), "Image Data");
289  bif->channels = 3;
290  break;
291  case ICV_COLOR_SPACE_GRAY :
292  bif->data = (double *) bu_malloc(bif->height*bif->width*1*sizeof(double), "Image Data");
293  bif->channels = 1;
294  break;
295  default :
296  bu_exit(1, "icv_create_image : Color Space Not Defined");
297  break;
298  }
299  return icv_zero(bif);
300 }
301 
302 
303 icv_image_t *
305 {
306  double *data;
307  long size, i;
308 
309  ICV_IMAGE_VAL_PTR(bif);
310 
311  data = bif->data;
312  size = bif->width * bif->height * bif->channels;
313  for (i = 0; i < size; i++)
314  *data++ = 0;
315 
316  return bif;
317 }
318 
319 
320 int
322 {
323  ICV_IMAGE_VAL_INT(bif);
324 
325  bu_free(bif->data, "Image Data");
326  bu_free(bif, "ICV IMAGE Structure");
327  return 0;
328 }
329 
330 /*
331  * Local Variables:
332  * mode: C
333  * tab-width: 8
334  * indent-tabs-mode: t
335  * c-file-style: "stroustrup"
336  * End:
337  * ex: shiftwidth=4 tabstop=8
338  */
ICV_COLOR_SPACE
Definition: icv.h:69
double * data
Definition: icv.h:89
icv_image_t * icv_read(const char *filename, int format, int width, int height)
Definition: fileformat.c:162
char filename[MAXLENGTH]
Definition: human.c:105
HIDDEN int png_write(icv_image_t *bif, const char *filename)
Definition: fileformat.c:111
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
ICV_DATA
Definition: icv.h:75
int width
Definition: icv.h:91
double * uchar2double(unsigned char *data, long int size)
uint32_t magic
Definition: icv.h:87
int bw_write(icv_image_t *bif, const char *filename)
Definition: bw.c:35
unsigned char * data2uchar(const icv_image_t *bif)
Definition: encoding.c:79
int icv_destroy(icv_image_t *bif)
Definition: fileformat.c:321
Header file for the BRL-CAD common definitions.
int channels
Definition: icv.h:91
Definition: icv.h:86
int height
Definition: icv.h:91
ustring width
#define HIDDEN
Definition: common.h:86
void * bu_malloc(size_t siz, const char *str)
Definition: malloc.c:314
int icv_write(icv_image_t *bif, const char *filename, ICV_IMAGE_FORMAT format)
Definition: fileformat.c:186
FILE * fdopen(int, const char *)
if(share_geom)
Definition: nmg_mod.c:3829
COMPLEX data[64]
Definition: fftest.c:34
#define ICV_CONV_8BIT(data)
Definition: icv.h:135
int ppm_write(icv_image_t *bif, const char *filename)
Definition: ppm.c:54
#define ICV_IMAGE_VAL_PTR(_i)
Definition: icv.h:128
void bu_exit(int status, const char *fmt,...) _BU_ATTR_NORETURN _BU_ATTR_PRINTF23
Definition: bomb.c:195
#define BU_ALLOC(_ptr, _type)
Definition: malloc.h:223
int icv_writeline(icv_image_t *bif, int y, void *data, ICV_DATA type)
Definition: fileformat.c:219
icv_image_t * pix_read(const char *filename, int width, int height)
Definition: pix.c:67
#define bu_strlcpy(dst, src, size)
Definition: str.h:60
icv_image_t * bw_read(const char *filename, int width, int height)
Definition: bw.c:74
int alpha_channel
Definition: icv.h:91
#define ICV_IMAGE_MAGIC
Definition: magic.h:216
ICV_COLOR_SPACE color_space
Definition: icv.h:88
#define CMP(name)
ICV_IMAGE_FORMAT icv_guess_file_format(const char *filename, char *trimmedname)
Definition: fileformat.c:82
icv_image_t * icv_create(int width, int height, ICV_COLOR_SPACE color_space)
Definition: fileformat.c:276
int pix_write(icv_image_t *bif, const char *filename)
Definition: pix.c:34
icv_image_t * ppm_read(const char *filename)
Definition: ppm.c:111
ICV_IMAGE_FORMAT
Definition: icv.h:50
icv_image_t * icv_zero(icv_image_t *bif)
Definition: fileformat.c:304
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
icv_image_t * dpix_read(const char *filename, int width, int height)
Definition: dpix.c:87
#define ICV_IMAGE_VAL_INT(_i)
Definition: icv.h:123
int dpix_write(icv_image_t *bif, const char *filename)
Definition: dpix.c:128
int icv_writepixel(icv_image_t *bif, int x, int y, double *data)
Definition: fileformat.c:252
#define UNLIKELY(expression)
Definition: common.h:282