pam.c
Go to the documentation of this file.
1 /* Copyright (C) 2013-2016, The Regents of The University of Michigan.
2 All rights reserved.
3 This software was developed in the APRIL Robotics Lab under the
4 direction of Edwin Olson, ebolson@umich.edu. This software may be
5 available under alternative licensing terms; contact the address above.
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
8 1. Redistributions of source code must retain the above copyright notice, this
9  list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright notice,
11  this list of conditions and the following disclaimer in the documentation
12  and/or other materials provided with the distribution.
13 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
17 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 The views and conclusions contained in the software and documentation are those
24 of the authors and should not be interpreted as representing official policies,
25 either expressed or implied, of the Regents of The University of Michigan.
26 */
27 
28 #include <stdio.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include <assert.h>
32 
33 #include "pam.h"
34 
35 pam_t *pam_create_from_file(const char *inpath)
36 {
37  FILE *infile = fopen(inpath, "r");
38  if (infile == NULL) {
39  printf("pam.c: couldn't open input file: %s\n", inpath);
40  return NULL;
41  }
42 
43  pam_t *pam = calloc(1, sizeof(pam_t));
44  pam->width = -1;
45  pam->height = -1;
46  pam->depth = -1;
47  pam->maxval = -1;
48  pam->type = -1;
49 
50  int linenumber = 0;
51 
52  while (1) {
53  char line[1024];
54  if (!fgets(line, sizeof(line), infile)) {
55  printf("pam.c: unexpected EOF\n");
56  goto fail;
57  }
58  linenumber++;
59 
60  char *tok0 = line;
61  char *tok1 = NULL;
62 
63  if (line[0] == '#') // comment
64  continue;
65 
66  size_t linelen = strlen(line);
67  for (int idx = 0; idx < linelen; idx++) {
68  if (line[idx] == ' ') {
69  line[idx] = 0;
70  if (tok1) {
71  printf("pam.c: More than two tokens, %s:%d\n", inpath, linenumber);
72  }
73 
74  tok1 = &line[idx+1];
75  }
76  if (line[idx] == '\n')
77  line[idx] = 0;
78  }
79 
80  if (!strcmp(tok0, "P7"))
81  continue;
82 
83  if (!strcmp(tok0, "ENDHDR"))
84  break;
85 
86  if (!strcmp(tok0, "WIDTH") && tok1) {
87  pam->width = atoi(tok1);
88  continue;
89  }
90 
91  if (!strcmp(tok0, "HEIGHT") && tok1) {
92  pam->height = atoi(tok1);
93  continue;
94  }
95 
96  if (!strcmp(tok0, "DEPTH") && tok1) {
97  pam->depth = atoi(tok1);
98  continue;
99  }
100 
101  if (!strcmp(tok0, "MAXVAL") && tok1) {
102  pam->maxval = atoi(tok1);
103  continue;
104  }
105 
106  if (!strcmp(tok0, "TUPLTYPE") && tok1) {
107  if (!strcmp(tok1, "GRAYSCALE_ALPHA")) {
108  pam->type = PAM_GRAYSCALE_ALPHA;
109  continue;
110  }
111 
112  if (!strcmp(tok1, "RGB_ALPHA")) {
113  pam->type = PAM_RGB_ALPHA;
114  continue;
115  }
116 
117  if (!strcmp(tok1, "RGB")) {
118  pam->type = PAM_RGB;
119  continue;
120  }
121 
122  if (!strcmp(tok1, "GRAYSCALE")) {
123  pam->type = PAM_GRAYSCALE;
124  continue;
125  }
126 
127  printf("pam.c: unrecognized tupl type %s\n", tok1);
128  continue;
129  }
130 
131  printf("pam.c: unrecognized attribute %s\n", tok0);
132  }
133 
134  if (pam->width < 0 || pam->height < 0 || pam->depth < 0 ||
135  pam->maxval < 0 || pam->type < 0) {
136  printf("pam.c: missing required metadata field\n");
137  goto fail;
138  }
139 
140  assert(pam->maxval == 255);
141 
142  pam->datalen = pam->width * pam->height * pam->depth;
143  pam->data = malloc(pam->datalen);
144  if (pam->datalen != fread(pam->data, 1, pam->datalen, infile)) {
145  printf("pam.c: couldn't read body\n");
146  goto fail;
147  }
148 
149  fclose(infile);
150  return pam;
151 
152  fail:
153  free(pam);
154  fclose(infile);
155  return NULL;
156 }
157 
158 int pam_write_file(pam_t *pam, const char *outpath)
159 {
160  FILE *f = fopen(outpath, "w+");
161  if (!f)
162  return -1;
163 
164  const char *tupl = NULL;
165  switch (pam->type) {
166  case PAM_GRAYSCALE_ALPHA:
167  tupl = "GRAYSCALE_ALPHA";
168  break;
169  case PAM_RGB_ALPHA:
170  tupl = "RGB_ALPHA";
171  break;
172  case PAM_RGB:
173  tupl = "RGB";
174  break;
175  case PAM_GRAYSCALE:
176  tupl = "GRAYSCALE";
177  break;
178  default:
179  assert(0);
180  }
181 
182  fprintf(f, "P7\nWIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\nTUPLTYPE %s\nENDHDR\n",
183  pam->width, pam->height, pam->depth, pam->maxval, tupl);
184  int len = pam->width * pam->height * pam->depth;
185  if (len != fwrite(pam->data, 1, len, f)) {
186  fclose(f);
187  return -2;
188  }
189 
190  fclose(f);
191 
192  return 0;
193 }
194 
196 {
197  if (!pam)
198  return;
199 
200  free(pam->data);
201  free(pam);
202 }
203 
205 {
206  pam_t *copy = calloc(1, sizeof(pam_t));
207  copy->width = pam->width;
208  copy->height = pam->height;
209  copy->depth = pam->depth;
210  copy->maxval = pam->maxval;
211  copy->type = pam->type;
212 
213  copy->datalen = pam->datalen;
214  copy->data = malloc(pam->datalen);
215  memcpy(copy->data, pam->data, pam->datalen);
216 
217  return copy;
218 }
219 
220 pam_t *pam_convert(pam_t *in, int type)
221 {
222  if (type == in->type)
223  return pam_copy(in);
224 
225  assert(type == PAM_RGB_ALPHA); // we don't support a lot yet
226  assert(in->maxval == 255);
227 
228  int w = in->width;
229  int h = in->height;
230 
231  pam_t *out = calloc(1, sizeof(pam_t));
232  out->type = type;
233  out->width = w;
234  out->height = h;
235  out->maxval = in->maxval;
236  out->depth = 4;
237  out->datalen = 4 * w * h;
238  out->data = malloc(out->datalen);
239 
240  if (in->type == PAM_RGB) {
241  assert(in->depth == 3);
242  for (int y = 0; y < h; y++) {
243  for (int x = 0; x < w; x++) {
244  out->data[y*4*w + 4*x + 0] = in->data[y*3*w + 3*x + 0];
245  out->data[y*4*w + 4*x + 1] = in->data[y*3*w + 3*x + 1];
246  out->data[y*4*w + 4*x + 2] = in->data[y*3*w + 3*x + 2];
247  out->data[y*4*w + 4*x + 3] = 255;
248  }
249  }
250  } else {
251  printf("pam.c unsupported type %d\n", in->type);
252  assert(0);
253  }
254 
255  return out;
256 }
uint8_t * data
Definition: pam.h:44
int datalen
Definition: pam.h:43
void pam_destroy(pam_t *pam)
Definition: pam.c:195
int height
Definition: pam.h:39
int type
Definition: pam.h:37
int depth
Definition: pam.h:40
pam_t * pam_create_from_file(const char *inpath)
Definition: pam.c:35
Definition: pam.h:35
int maxval
Definition: pam.h:41
pam_t * pam_convert(pam_t *in, int type)
Definition: pam.c:220
pam_t * pam_copy(pam_t *pam)
Definition: pam.c:204
Definition: pam.h:32
int width
Definition: pam.h:39
int pam_write_file(pam_t *pam, const char *outpath)
Definition: pam.c:158


apriltag
Author(s): Edwin Olson , Max Krogius
autogenerated on Mon Jun 26 2023 02:26:12