BRL-CAD
ppm.c
Go to the documentation of this file.
1 /* P P M . C
2  * BRL-CAD
3  *
4  * Copyright (c) 2013-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 /** @file ppm.c
21  *
22  * This file contains reading and writing routines for ppm format.
23  *
24  */
25 
26 #include "common.h"
27 #include <string.h>
28 
29 #include "bu/log.h"
30 #include "bu/malloc.h"
31 #include "icv.h"
32 
33 /* defined in encoding.c */
34 extern unsigned char *data2uchar(const icv_image_t *bif);
35 extern double *uchar2double(unsigned char *data, long int size);
36 
37 /* flip an image vertically */
38 int
39 image_flip(unsigned char *buf, int width, int height)
40 {
41  unsigned char *buf2;
42  int i;
43  size_t pitch = width * 3 * sizeof(char);
44 
45  buf2 = (unsigned char *)bu_malloc((size_t)(height * pitch), "image flip");
46  for (i=0 ; i<height ; i++)
47  memcpy(buf2+i*pitch, buf+(height-i)*pitch, pitch);
48  memcpy(buf, buf2, height * pitch);
49  bu_free(buf2, "image flip");
50  return 0;
51 }
52 
53 int
54 ppm_write(icv_image_t *bif, const char *filename)
55 {
56  unsigned char *data;
57  FILE *fp;
58  size_t ret, size;
59 
60  if (bif->color_space == ICV_COLOR_SPACE_GRAY) {
61  icv_gray2rgb(bif);
62  } else if (bif->color_space != ICV_COLOR_SPACE_RGB) {
63  bu_log("ppm_write : Color Space conflict");
64  return -1;
65  }
66 
67  if (filename==NULL) {
68  fp = stdout;
69  } else if ((fp = fopen(filename, "wb")) == NULL) {
70  bu_log("ERROR : Cannot open file for saving\n");
71  return -1;
72  }
73  data = data2uchar(bif);
74  size = (size_t) bif->width*bif->height*3;
75  image_flip(data, bif->width, bif->height);
76  ret = fprintf(fp, "P6 %d %d 255\n", bif->width, bif->height);
77 
78  ret = fwrite(data, 1, size, fp);
79 
80  fclose(fp);
81  if (ret != size) {
82  bu_log("ERROR : Short Write");
83  return -1;
84  }
85  return 0;
86 }
87 
88 
89 HIDDEN void
90 ppm_nextline(FILE *fp)
91 {
92  int c;
93 
94  /* skip to the binary data section, starting on next line.
95  * supports mac, unix, windows line endings.
96  */
97  do {
98  c = fgetc(fp);
99  if (c == '\r') {
100  c = fgetc(fp);
101  if (c != '\n') {
102  ungetc(c, fp);
103  c = '\n'; /* pretend we're not an old mac file */
104  }
105  }
106  } while (c != '\n');
107 }
108 
109 
111 ppm_read(const char *filename)
112 {
113  char buff[3]; /* To ensure that the format. And thus read "P6" */
114  FILE *fp;
115  char c;
116  icv_image_t *bif;
117  int rgb_comp_color;
118  unsigned char *data;
119  size_t size,ret;
120 
121  if (filename == NULL) {
122  fp = stdin;
123  } else if ((fp = fopen(filename, "rb")) == NULL) {
124  bu_log("ERROR: Cannot open file for reading\n");
125  return NULL;
126  }
127 
128  if (!bu_fgets(buff, sizeof(buff), fp)) {
129  bu_log("ERROR : Invalid Image");
130  return NULL;
131  }
132 
133  /* check the image format */
134  if (buff[0] != 'P' || buff[1] != '6') {
135  bu_log("ERROR: Invalid image format (must be 'P6')\n");
136  return NULL;
137  }
138 
139  BU_ALLOC(bif, struct icv_image);
140  ICV_IMAGE_INIT(bif);
141 
142  /* check for comments lines in PPM image header */
143  c = getc(fp);
144  while (c == '#') {
145  /* encountered comment, skip to next line */
146  ppm_nextline(fp);
147  c = getc(fp);
148  }
149 
150  ungetc(c, fp);
151 
152  /* read image size information */
153  if (fscanf(fp, "%d %d", &bif->width, &bif->height) != 2) {
154  fprintf(stderr, "Invalid image size (error loading '%s')\n", filename);
155  bu_free(bif, "icv_image structure");
156  return NULL;
157  }
158 
159  /* read rgb component */
160  if (fscanf(fp, "%d", &rgb_comp_color) != 1) {
161  bu_log("ERROR: Invalid rgb component\n");
162  bu_free(bif, "icv_image structure");
163  return NULL;
164  }
165 
166  /* check rgb component depth */
167  if (rgb_comp_color!= 255) {
168  bu_log("ERROR: Image does not have 8-bits components\n");
169  bu_free(bif, "icv_image structure");
170  return NULL;
171  }
172 
173  /* skip to the binary data section, starting on next line.
174  * supports mac, unix, windows line endings.
175  */
176  ppm_nextline(fp);
177 
178  /* memory allocation for pixel data */
179  data = (unsigned char*) bu_malloc(bif->width * bif->height * 3, "image data");
180 
181  size = 3 * bif->width * bif->height;
182  /* read pixel data from file */
183  ret = fread(data, 1, size, fp);
184  if (ret!=0 && ferror(fp)) {
185  bu_log("Error Occurred while Reading\n");
186  bu_free(data, "icv_image data");
187  bu_free(bif, "icv_structure");
188  fclose(fp);
189  return NULL;
190  }
191 
192  fclose(fp);
193 
194  image_flip(data, bif->width, bif->height);
195 
196  bif->data = uchar2double(data, size);
197  bu_free(data, "ppm_read : unsigned char data");
198  bif->magic = ICV_IMAGE_MAGIC;
199  bif->channels = 3;
201  fclose(fp);
202  return bif;
203 }
204 
205 /*
206  * Local Variables:
207  * tab-width: 8
208  * mode: C
209  * indent-tabs-mode: t
210  * c-file-style: "stroustrup"
211  * End:
212  * ex: shiftwidth=4 tabstop=8
213  */
unsigned char * data2uchar(const icv_image_t *bif)
Definition: encoding.c:79
double * data
Definition: icv.h:89
char filename[MAXLENGTH]
Definition: human.c:105
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
#define ICV_IMAGE_INIT(_i)
Definition: icv.h:107
int width
Definition: icv.h:91
int ppm_write(icv_image_t *bif, const char *filename)
Definition: ppm.c:54
uint32_t magic
Definition: icv.h:87
int image_flip(unsigned char *buf, int width, int height)
Definition: ppm.c:39
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
icv_image_t * ppm_read(const char *filename)
Definition: ppm.c:111
COMPLEX data[64]
Definition: fftest.c:34
double * uchar2double(unsigned char *data, long int size)
#define BU_ALLOC(_ptr, _type)
Definition: malloc.h:223
int icv_gray2rgb(icv_image_t *img)
Definition: color_space.c:37
#define ICV_IMAGE_MAGIC
Definition: magic.h:216
ICV_COLOR_SPACE color_space
Definition: icv.h:88
HIDDEN void ppm_nextline(FILE *fp)
Definition: ppm.c:90
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
char * bu_fgets(char *s, int size, FILE *stream)
Definition: fgets.c:31