image_u8x3.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 #include <math.h>
27 
28 #include "math_util.h"
29 #include "pnm.h"
30 
31 #include "image_u8x3.h"
32 
33 // least common multiple of 64 (sandy bridge cache line) and 48 (stride needed
34 // for 16byte-wide RGB processing). (It's possible that 48 would be enough).
35 #define DEFAULT_ALIGNMENT_U8X3 192
36 
37 image_u8x3_t *image_u8x3_create(unsigned int width, unsigned int height)
38 {
40 }
41 
42 image_u8x3_t *image_u8x3_create_alignment(unsigned int width, unsigned int height, unsigned int alignment)
43 {
44  int stride = 3*width;
45 
46  if ((stride % alignment) != 0)
47  stride += alignment - (stride % alignment);
48 
49  uint8_t *buf = calloc(height*stride, sizeof(uint8_t));
50 
51  // const initializer
52  image_u8x3_t tmp = { .width = width, .height = height, .stride = stride, .buf = buf };
53 
54  image_u8x3_t *im = calloc(1, sizeof(image_u8x3_t));
55  memcpy(im, &tmp, sizeof(image_u8x3_t));
56  return im;
57 }
58 
60 {
61  uint8_t *buf = malloc(in->height*in->stride*sizeof(uint8_t));
62  memcpy(buf, in->buf, in->height*in->stride*sizeof(uint8_t));
63 
64  // const initializer
65  image_u8x3_t tmp = { .width = in->width, .height = in->height, .stride = in->stride, .buf = buf };
66 
67  image_u8x3_t *copy = calloc(1, sizeof(image_u8x3_t));
68  memcpy(copy, &tmp, sizeof(image_u8x3_t));
69  return copy;
70 }
71 
73 {
74  if (!im)
75  return;
76 
77  free(im->buf);
78  free(im);
79 }
80 
82 // PNM file i/o
83 
84 // Create an RGB image from PNM
86 {
88  if (pnm == NULL)
89  return NULL;
90 
91  image_u8x3_t *im = NULL;
92 
93  switch (pnm->format) {
94  case PNM_FORMAT_GRAY: {
95  im = image_u8x3_create(pnm->width, pnm->height);
96 
97  for (int y = 0; y < im->height; y++) {
98  for (int x = 0; x < im->width; x++) {
99  uint8_t gray = pnm->buf[y*im->width + x];
100  im->buf[y*im->stride + x*3 + 0] = gray;
101  im->buf[y*im->stride + x*3 + 1] = gray;
102  im->buf[y*im->stride + x*3 + 2] = gray;
103  }
104  }
105 
106  break;
107  }
108 
109  case PNM_FORMAT_RGB: {
110  im = image_u8x3_create(pnm->width, pnm->height);
111 
112  for (int y = 0; y < im->height; y++) {
113  for (int x = 0; x < im->width; x++) {
114  uint8_t r = pnm->buf[y*im->width*3 + 3*x];
115  uint8_t g = pnm->buf[y*im->width*3 + 3*x+1];
116  uint8_t b = pnm->buf[y*im->width*3 + 3*x+2];
117 
118  im->buf[y*im->stride + x*3 + 0] = r;
119  im->buf[y*im->stride + x*3 + 1] = g;
120  im->buf[y*im->stride + x*3 + 2] = b;
121  }
122  }
123 
124  break;
125  }
126  }
127 
128  pnm_destroy(pnm);
129  return im;
130 }
131 
132 int image_u8x3_write_pnm(const image_u8x3_t *im, const char *path)
133 {
134  FILE *f = fopen(path, "wb");
135  int res = 0;
136 
137  if (f == NULL) {
138  res = -1;
139  goto finish;
140  }
141 
142  // Only outputs to RGB
143  fprintf(f, "P6\n%d %d\n255\n", im->width, im->height);
144  int linesz = im->width * 3;
145  for (int y = 0; y < im->height; y++) {
146  if (linesz != fwrite(&im->buf[y*im->stride], 1, linesz, f)) {
147  res = -1;
148  goto finish;
149  }
150  }
151 
152 finish:
153  if (f != NULL)
154  fclose(f);
155 
156  return res;
157 }
158 
159 // only width 1 supported
160 void image_u8x3_draw_line(image_u8x3_t *im, float x0, float y0, float x1, float y1, uint8_t rgb[3], int width)
161 {
162  double dist = sqrtf((y1-y0)*(y1-y0) + (x1-x0)*(x1-x0));
163  double delta = 0.5 / dist;
164 
165  // terrible line drawing code
166  for (float f = 0; f <= 1; f += delta) {
167  int x = ((int) (x1 + (x0 - x1) * f));
168  int y = ((int) (y1 + (y0 - y1) * f));
169 
170  if (x < 0 || y < 0 || x >= im->width || y >= im->height)
171  continue;
172 
173  int idx = y*im->stride + 3*x;
174  for (int i = 0; i < 3; i++)
175  im->buf[idx + i] = rgb[i];
176  }
177 }
178 
179 static void convolve(const uint8_t *x, uint8_t *y, int sz, const uint8_t *k, int ksz)
180 {
181  assert((ksz&1)==1);
182 
183  for (int i = 0; i < ksz/2 && i < sz; i++)
184  y[i] = x[i];
185 
186  for (int i = 0; i < sz - ksz; i++) {
187  uint32_t acc = 0;
188 
189  for (int j = 0; j < ksz; j++)
190  acc += k[j]*x[i+j];
191 
192  y[ksz/2 + i] = acc >> 8;
193  }
194 
195  for (int i = sz - ksz + ksz/2; i < sz; i++)
196  y[i] = x[i];
197 }
198 
199 void image_u8x3_gaussian_blur(image_u8x3_t *im, double sigma, int ksz)
200 {
201  if (sigma == 0)
202  return;
203 
204  assert((ksz & 1) == 1); // ksz must be odd.
205 
206  // build the kernel.
207  double dk[ksz];
208 
209  // for kernel of length 5:
210  // dk[0] = f(-2), dk[1] = f(-1), dk[2] = f(0), dk[3] = f(1), dk[4] = f(2)
211  for (int i = 0; i < ksz; i++) {
212  int x = -ksz/2 + i;
213  double v = exp(-.5*sq(x / sigma));
214  dk[i] = v;
215  }
216 
217  // normalize
218  double acc = 0;
219  for (int i = 0; i < ksz; i++)
220  acc += dk[i];
221 
222  for (int i = 0; i < ksz; i++)
223  dk[i] /= acc;
224 
225  uint8_t k[ksz];
226  for (int i = 0; i < ksz; i++)
227  k[i] = dk[i]*255;
228 
229  if (0) {
230  for (int i = 0; i < ksz; i++)
231  printf("%d %15f %5d\n", i, dk[i], k[i]);
232  }
233 
234  for (int c = 0; c < 3; c++) {
235  for (int y = 0; y < im->height; y++) {
236 
237  uint8_t in[im->stride];
238  uint8_t out[im->stride];
239 
240  for (int x = 0; x < im->width; x++)
241  in[x] = im->buf[y*im->stride + 3 * x + c];
242 
243  convolve(in, out, im->width, k, ksz);
244 
245  for (int x = 0; x < im->width; x++)
246  im->buf[y*im->stride + 3 * x + c] = out[x];
247  }
248 
249  for (int x = 0; x < im->width; x++) {
250  uint8_t in[im->height];
251  uint8_t out[im->height];
252 
253  for (int y = 0; y < im->height; y++)
254  in[y] = im->buf[y*im->stride + 3*x + c];
255 
256  convolve(in, out, im->height, k, ksz);
257 
258  for (int y = 0; y < im->height; y++)
259  im->buf[y*im->stride + 3*x + c] = out[y];
260  }
261  }
262 }
int height
Definition: pnm.h:51
int format
Definition: pnm.h:52
static void convolve(const uint8_t *x, uint8_t *y, int sz, const uint8_t *k, int ksz)
Definition: image_u8x3.c:179
const int32_t height
Definition: image_types.h:24
#define PNM_FORMAT_RGB
Definition: pnm.h:44
int image_u8x3_write_pnm(const image_u8x3_t *im, const char *path)
Definition: image_u8x3.c:132
uint8_t * buf
Definition: pnm.h:56
Definition: pnm.h:49
image_u8x3_t * image_u8x3_create_alignment(unsigned int width, unsigned int height, unsigned int alignment)
Definition: image_u8x3.c:42
uint8_t * buf
Definition: image_types.h:27
image_u8x3_t * image_u8x3_create(unsigned int width, unsigned int height)
Definition: image_u8x3.c:37
int width
Definition: pnm.h:51
static double sq(double v)
Definition: math_util.h:84
void image_u8x3_gaussian_blur(image_u8x3_t *im, double sigma, int ksz)
Definition: image_u8x3.c:199
const int32_t stride
Definition: image_types.h:25
void image_u8x3_draw_line(image_u8x3_t *im, float x0, float y0, float x1, float y1, uint8_t rgb[3], int width)
Definition: image_u8x3.c:160
#define DEFAULT_ALIGNMENT_U8X3
Definition: image_u8x3.c:35
pnm_t * pnm_create_from_file(const char *path)
Definition: pnm.c:40
void pnm_destroy(pnm_t *pnm)
Definition: pnm.c:153
static TTYPENAME *TFN() copy(TTYPENAME *hash)
Definition: thash_impl.h:322
const int32_t width
Definition: image_types.h:23
image_u8x3_t * image_u8x3_copy(const image_u8x3_t *in)
Definition: image_u8x3.c:59
#define PNM_FORMAT_GRAY
Definition: pnm.h:43
image_u8x3_t * image_u8x3_create_from_pnm(const char *path)
Definition: image_u8x3.c:85
void image_u8x3_destroy(image_u8x3_t *im)
Definition: image_u8x3.c:72


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