image_u8x4.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 
4 This software was developed in the APRIL Robotics Lab under the
5 direction of Edwin Olson, ebolson@umich.edu. This software may be
6 available under alternative licensing terms; contact the address above.
7 
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 2.1 of the License, or (at your option) any later version.
12 
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17 
18 You should have received a copy of the GNU Lesser General Public
19 License along with this library; if not, see <http://www.gnu.org/licenses/>.
20 */
21 
22 #include <assert.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 
27 #include "pam.h"
28 #include "pnm.h"
29 #include "image_u8x4.h"
30 
31 // least common multiple of 64 (sandy bridge cache line) and 64 (stride needed
32 // for 16byte-wide RGBA processing).
33 #define DEFAULT_ALIGNMENT_U8X4 64
34 
35 image_u8x4_t *image_u8x4_create(unsigned int width, unsigned int height)
36 {
38 }
39 
40 image_u8x4_t *image_u8x4_create_alignment(unsigned int width, unsigned int height, unsigned int alignment)
41 {
42  int stride = 4*width;
43 
44  if ((stride % alignment) != 0)
45  stride += alignment - (stride % alignment);
46 
47  uint8_t *buf = calloc(height*stride, sizeof(uint8_t));
48 
49  // const initializer
50  image_u8x4_t tmp = { .width = width, .height = height, .stride = stride, .buf = buf };
51 
52  image_u8x4_t *im = calloc(1, sizeof(image_u8x4_t));
53  memcpy(im, &tmp, sizeof(image_u8x4_t));
54  return im;
55 }
56 
58 {
59  uint8_t *buf = malloc(in->height*in->stride*sizeof(uint8_t));
60  memcpy(buf, in->buf, in->height*in->stride*sizeof(uint8_t));
61 
62  // const initializer
63  image_u8x4_t tmp = { .width = in->width, .height = in->height, .stride = in->stride, .buf = buf };
64 
65  image_u8x4_t *copy = calloc(1, sizeof(image_u8x4_t));
66  memcpy(copy, &tmp, sizeof(image_u8x4_t));
67  return copy;
68 }
69 
71 {
72  if (!im)
73  return;
74 
75  free(im->buf);
76  free(im);
77 }
78 
81 {
82  pam_t *pam = pam_create_from_file(inpath);
83  if (!pam)
84  return NULL;
85 
86  image_u8x4_t *im = image_u8x4_create(pam->width, pam->height);
87 
88  for (int y = 0; y < pam->height; y++) {
89  if (pam->depth == 1) {
90  for (int x = 0; x < pam->width; x++) {
91  im->buf[y*im->stride + 4*x + 0] = pam->data[pam->width*y + x + 0];
92  im->buf[y*im->stride + 4*x + 1] = pam->data[pam->width*y + x + 0];
93  im->buf[y*im->stride + 4*x + 2] = pam->data[pam->width*y + x + 0];
94  im->buf[y*im->stride + 4*x + 3] = 255;
95  }
96  } else if (pam->depth == 3) {
97  for (int x = 0; x < pam->width; x++) {
98  im->buf[y*im->stride + 4*x + 0] = pam->data[3*pam->width*y + 3*x + 0];
99  im->buf[y*im->stride + 4*x + 1] = pam->data[3*pam->width*y + 3*x + 1];
100  im->buf[y*im->stride + 4*x + 2] = pam->data[3*pam->width*y + 3*x + 2];
101  im->buf[y*im->stride + 4*x + 3] = 255;
102  }
103  } else if (pam->depth == 4) {
104  memcpy(&im->buf[y*im->stride], &pam->data[4*pam->width*y], 4*pam->width);
105  } else {
106  assert(0); // not implemented
107  }
108  }
109 
110  pam_destroy(pam);
111  return im;
112 }
114 // PNM file i/o
115 
116 // Create an RGBA image from PNM
118 {
119  pnm_t *pnmp = pnm_create_from_file(path);
120  if (pnmp == NULL)
121  return NULL;
122 
123  pnm_t pnm = *pnmp;
124  image_u8x4_t *imp = NULL;
125 
126  switch (pnm.format) {
127  case PNM_FORMAT_GRAY: {
128  imp = image_u8x4_create(pnm.width, pnm.height);
129 
130  // copy struct by value for common subexpression elimination
131  const image_u8x4_t im = *imp;
132 
133  for (int y = 0; y < im.height; y++) {
134  for (int x = 0; x < im.width; x++) {
135  uint8_t gray = pnm.buf[y*pnm.width + x];
136  im.buf[y*im.stride + 4*x + 0] = gray;
137  im.buf[y*im.stride + 4*x + 1] = gray;
138  im.buf[y*im.stride + 4*x + 2] = gray;
139  im.buf[y*im.stride + 4*x + 3] = 0xff;
140  }
141  }
142 
143  break;
144  }
145 
146  case PNM_FORMAT_RGB: {
147  imp = image_u8x4_create(pnm.width, pnm.height);
148 
149  // copy struct by value for common subexpression elimination
150  const image_u8x4_t im = *imp;
151 
152  // Gray conversion for RGB is gray = (r + g + g + b)/4
153  for (int y = 0; y < im.height; y++) {
154  for (int x = 0; x < im.width; x++) {
155 
156  uint8_t r = pnm.buf[y*pnm.width*3 + 3*x + 0];
157  uint8_t g = pnm.buf[y*pnm.width*3 + 3*x + 1];
158  uint8_t b = pnm.buf[y*pnm.width*3 + 3*x + 2];
159 
160  im.buf[y*im.stride + 4*x + 0] = r;
161  im.buf[y*im.stride + 4*x + 1] = g;
162  im.buf[y*im.stride + 4*x + 2] = b;
163  im.buf[y*im.stride + 4*x + 3] = 0xff;
164  }
165  }
166 
167  break;
168  }
169  }
170 
171  pnm_destroy(pnmp);
172  return imp;
173 }
174 
175 int image_u8x4_write_pnm(const image_u8x4_t *imp, const char *path)
176 {
177  // copy struct by value to ensure common subexpression elimination occurs
178  const image_u8x4_t im = *imp;
179 
180  FILE *f = fopen(path, "wb");
181  int res = 0;
182 
183  if (f == NULL) {
184  res = -1;
185  goto finish;
186  }
187 
188  // Only outputs to RGB
189  fprintf(f, "P6\n%d %d\n255\n", im.width, im.height);
190 
191  for (int y = im.height-1; y >= 0; y--) {
192  for (int x = 0; x < im.width; x++) {
193 
194  uint8_t r = im.buf[y*im.stride + 4*x + 0];
195  uint8_t g = im.buf[y*im.stride + 4*x + 1];
196  uint8_t b = im.buf[y*im.stride + 4*x + 2];
197 
198  fwrite(&r, 1, 1, f);
199  fwrite(&g, 1, 1, f);
200  fwrite(&b, 1, 1, f);
201  }
202  }
203 
204  finish:
205  if (f != NULL)
206  fclose(f);
207 
208  return res;
209 }
210 
211 void image_u8x4_write_pam(const image_u8x4_t *im, const char *path)
212 {
213  FILE *f = fopen(path, "w");
214  fprintf(f, "P7\n");
215  fprintf(f, "WIDTH %d\n", im->width);
216  fprintf(f, "HEIGHT %d\n", im->height);
217  fprintf(f, "DEPTH 4\n");
218  fprintf(f, "MAXVAL 255\n");
219  fprintf(f, "TUPLTYPE RGB_ALPHA\n");
220  fprintf(f, "ENDHDR\n");
221 
222  for (int y = 0; y < im->height; y++)
223  fwrite(&im->buf[y*im->stride], 1, 4*im->width, f);
224 
225  fclose(f);
226 
227 }
int height
Definition: pnm.h:51
uint8_t * data
Definition: pam.h:39
int format
Definition: pnm.h:52
const int32_t height
Definition: image_types.h:34
int height
Definition: pam.h:34
#define PNM_FORMAT_RGB
Definition: pnm.h:44
image_u8x4_t * image_u8x4_copy(const image_u8x4_t *in)
Definition: image_u8x4.c:57
uint8_t * buf
Definition: pnm.h:56
image_u8x4_t * image_u8x4_create_alignment(unsigned int width, unsigned int height, unsigned int alignment)
Definition: image_u8x4.c:40
Definition: pnm.h:49
void image_u8x4_destroy(image_u8x4_t *im)
Definition: image_u8x4.c:70
int depth
Definition: pam.h:35
int width
Definition: pnm.h:51
Definition: pam.h:30
uint8_t * buf
Definition: image_types.h:37
void image_u8x4_write_pam(const image_u8x4_t *im, const char *path)
Definition: image_u8x4.c:211
const int32_t stride
Definition: image_types.h:35
image_u8x4_t * image_u8x4_create_from_pnm(const char *path)
Definition: image_u8x4.c:117
const int32_t width
Definition: image_types.h:33
pam_t * pam_create_from_file(const char *inpath)
Definition: pam.c:29
#define DEFAULT_ALIGNMENT_U8X4
Definition: image_u8x4.c:33
image_u8x4_t * image_u8x4_create(unsigned int width, unsigned int height)
Definition: image_u8x4.c:35
int image_u8x4_write_pnm(const image_u8x4_t *imp, const char *path)
Definition: image_u8x4.c:175
pnm_t * pnm_create_from_file(const char *path)
Definition: pnm.c:40
void pnm_destroy(pnm_t *pnm)
Definition: pnm.c:153
void pam_destroy(pam_t *pam)
Definition: pam.c:189
int width
Definition: pam.h:34
static TTYPENAME *TFN() copy(TTYPENAME *hash)
Definition: thash_impl.h:322
#define PNM_FORMAT_GRAY
Definition: pnm.h:43
image_u8x4_t * image_u8x4_create_from_pam(const char *inpath)
Definition: image_u8x4.c:80


apriltags2
Author(s): Danylo Malyuta
autogenerated on Fri Oct 19 2018 04:02:32