1 /*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 ///////////////////////////////////////////////////
18 // ImageUtils.cpp
19 // $Id: ImageUtils.cpp,v 1.12 2011/06/17 13:35:48 mbansal Exp $
20
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <sys/time.h>
25
26 #include "ImageUtils.h"
27
rgba2yvu(ImageType out,ImageType in,int width,int height)28 void ImageUtils::rgba2yvu(ImageType out, ImageType in, int width, int height)
29 {
30 int r,g,b, a;
31 ImageType yimg = out;
32 ImageType vimg = yimg + width*height;
33 ImageType uimg = vimg + width*height;
34 ImageType image = in;
35
36 for (int ii = 0; ii < height; ii++) {
37 for (int ij = 0; ij < width; ij++) {
38 r = (*image++);
39 g = (*image++);
40 b = (*image++);
41 a = (*image++);
42
43 if (r < 0) r = 0;
44 if (r > 255) r = 255;
45 if (g < 0) g = 0;
46 if (g > 255) g = 255;
47 if (b < 0) b = 0;
48 if (b > 255) b = 255;
49
50 int val = (int) (REDY * r + GREENY * g + BLUEY * b) / 1000 + 16;
51 if (val < 0) val = 0;
52 if (val > 255) val = 255;
53 *(yimg) = val;
54
55 val = (int) (REDV * r - GREENV * g - BLUEV * b) / 1000 + 128;
56 if (val < 0) val = 0;
57 if (val > 255) val = 255;
58 *(vimg) = val;
59
60 val = (int) (-REDU * r - GREENU * g + BLUEU * b) / 1000 + 128;
61 if (val < 0) val = 0;
62 if (val > 255) val = 255;
63 *(uimg) = val;
64
65 yimg++;
66 uimg++;
67 vimg++;
68 }
69 }
70 }
71
72
rgb2yvu(ImageType out,ImageType in,int width,int height)73 void ImageUtils::rgb2yvu(ImageType out, ImageType in, int width, int height)
74 {
75 int r,g,b;
76 ImageType yimg = out;
77 ImageType vimg = yimg + width*height;
78 ImageType uimg = vimg + width*height;
79 ImageType image = in;
80
81 for (int ii = 0; ii < height; ii++) {
82 for (int ij = 0; ij < width; ij++) {
83 r = (*image++);
84 g = (*image++);
85 b = (*image++);
86
87 if (r < 0) r = 0;
88 if (r > 255) r = 255;
89 if (g < 0) g = 0;
90 if (g > 255) g = 255;
91 if (b < 0) b = 0;
92 if (b > 255) b = 255;
93
94 int val = (int) (REDY * r + GREENY * g + BLUEY * b) / 1000 + 16;
95 if (val < 0) val = 0;
96 if (val > 255) val = 255;
97 *(yimg) = val;
98
99 val = (int) (REDV * r - GREENV * g - BLUEV * b) / 1000 + 128;
100 if (val < 0) val = 0;
101 if (val > 255) val = 255;
102 *(vimg) = val;
103
104 val = (int) (-REDU * r - GREENU * g + BLUEU * b) / 1000 + 128;
105 if (val < 0) val = 0;
106 if (val > 255) val = 255;
107 *(uimg) = val;
108
109 yimg++;
110 uimg++;
111 vimg++;
112 }
113 }
114 }
115
rgb2gray(ImageType in,int width,int height)116 ImageType ImageUtils::rgb2gray(ImageType in, int width, int height)
117 {
118 int r,g,b, nr, ng, nb, val;
119 ImageType gray = NULL;
120 ImageType image = in;
121 ImageType out = ImageUtils::allocateImage(width, height, 1);
122 ImageType outCopy = out;
123
124 for (int ii = 0; ii < height; ii++) {
125 for (int ij = 0; ij < width; ij++) {
126 r = (*image++);
127 g = (*image++);
128 b = (*image++);
129
130 if (r < 0) r = 0;
131 if (r > 255) r = 255;
132 if (g < 0) g = 0;
133 if (g > 255) g = 255;
134 if (b < 0) b = 0;
135 if (b > 255) b = 255;
136
137 (*outCopy) = ( 0.3*r + 0.59*g + 0.11*b);
138
139 outCopy++;
140 }
141 }
142
143 return out;
144 }
145
rgb2gray(ImageType out,ImageType in,int width,int height)146 ImageType ImageUtils::rgb2gray(ImageType out, ImageType in, int width, int height)
147 {
148 int r,g,b, nr, ng, nb, val;
149 ImageType gray = out;
150 ImageType image = in;
151 ImageType outCopy = out;
152
153 for (int ii = 0; ii < height; ii++) {
154 for (int ij = 0; ij < width; ij++) {
155 r = (*image++);
156 g = (*image++);
157 b = (*image++);
158
159 if (r < 0) r = 0;
160 if (r > 255) r = 255;
161 if (g < 0) g = 0;
162 if (g > 255) g = 255;
163 if (b < 0) b = 0;
164 if (b > 255) b = 255;
165
166 (*outCopy) = ( 0.3*r + 0.59*g + 0.11*b);
167
168 outCopy++;
169 }
170 }
171
172 return out;
173
174 }
175
imageTypeToRowPointers(ImageType in,int width,int height)176 ImageType *ImageUtils::imageTypeToRowPointers(ImageType in, int width, int height)
177 {
178 int i;
179 int m_h = height;
180 int m_w = width;
181
182 ImageType *m_rows = new ImageType[m_h];
183
184 for (i=0;i<m_h;i++) {
185 m_rows[i] = &in[(m_w)*i];
186 }
187 return m_rows;
188 }
189
yvu2rgb(ImageType out,ImageType in,int width,int height)190 void ImageUtils::yvu2rgb(ImageType out, ImageType in, int width, int height)
191 {
192 int y,v,u, r, g, b;
193 unsigned char *yimg = in;
194 unsigned char *vimg = yimg + width*height;
195 unsigned char *uimg = vimg + width*height;
196 unsigned char *image = out;
197
198 for (int i = 0; i < height; i++) {
199 for (int j = 0; j < width; j++) {
200
201 y = (*yimg);
202 v = (*vimg);
203 u = (*uimg);
204
205 if (y < 0) y = 0;
206 if (y > 255) y = 255;
207 if (u < 0) u = 0;
208 if (u > 255) u = 255;
209 if (v < 0) v = 0;
210 if (v > 255) v = 255;
211
212 b = (int) ( 1.164*(y - 16) + 2.018*(u-128));
213 g = (int) ( 1.164*(y - 16) - 0.813*(v-128) - 0.391*(u-128));
214 r = (int) ( 1.164*(y - 16) + 1.596*(v-128));
215
216 if (r < 0) r = 0;
217 if (r > 255) r = 255;
218 if (g < 0) g = 0;
219 if (g > 255) g = 255;
220 if (b < 0) b = 0;
221 if (b > 255) b = 255;
222
223 *(image++) = r;
224 *(image++) = g;
225 *(image++) = b;
226
227 yimg++;
228 uimg++;
229 vimg++;
230
231 }
232 }
233 }
234
yvu2bgr(ImageType out,ImageType in,int width,int height)235 void ImageUtils::yvu2bgr(ImageType out, ImageType in, int width, int height)
236 {
237 int y,v,u, r, g, b;
238 unsigned char *yimg = in;
239 unsigned char *vimg = yimg + width*height;
240 unsigned char *uimg = vimg + width*height;
241 unsigned char *image = out;
242
243 for (int i = 0; i < height; i++) {
244 for (int j = 0; j < width; j++) {
245
246 y = (*yimg);
247 v = (*vimg);
248 u = (*uimg);
249
250 if (y < 0) y = 0;
251 if (y > 255) y = 255;
252 if (u < 0) u = 0;
253 if (u > 255) u = 255;
254 if (v < 0) v = 0;
255 if (v > 255) v = 255;
256
257 b = (int) ( 1.164*(y - 16) + 2.018*(u-128));
258 g = (int) ( 1.164*(y - 16) - 0.813*(v-128) - 0.391*(u-128));
259 r = (int) ( 1.164*(y - 16) + 1.596*(v-128));
260
261 if (r < 0) r = 0;
262 if (r > 255) r = 255;
263 if (g < 0) g = 0;
264 if (g > 255) g = 255;
265 if (b < 0) b = 0;
266 if (b > 255) b = 255;
267
268 *(image++) = b;
269 *(image++) = g;
270 *(image++) = r;
271
272 yimg++;
273 uimg++;
274 vimg++;
275
276 }
277 }
278 }
279
280
readBinaryPPM(const char * filename,int & width,int & height)281 ImageType ImageUtils::readBinaryPPM(const char *filename, int &width, int &height)
282 {
283
284 FILE *imgin = NULL;
285 int mval=0, format=0, eret;
286 ImageType ret = IMAGE_TYPE_NOIMAGE;
287
288 imgin = fopen(filename, "r");
289 if (imgin == NULL) {
290 fprintf(stderr, "Error: Filename %s not found\n", filename);
291 return ret;
292 }
293
294 eret = fscanf(imgin, "P%d\n", &format);
295 if (format != 6) {
296 fprintf(stderr, "Error: readBinaryPPM only supports PPM format (P6)\n");
297 return ret;
298 }
299
300 eret = fscanf(imgin, "%d %d\n", &width, &height);
301 eret = fscanf(imgin, "%d\n", &mval);
302 ret = allocateImage(width, height, IMAGE_TYPE_NUM_CHANNELS);
303 eret = fread(ret, sizeof(ImageTypeBase), IMAGE_TYPE_NUM_CHANNELS*width*height, imgin);
304
305 fclose(imgin);
306
307 return ret;
308
309 }
310
writeBinaryPPM(ImageType image,const char * filename,int width,int height,int numChannels)311 void ImageUtils::writeBinaryPPM(ImageType image, const char *filename, int width, int height, int numChannels)
312 {
313 FILE *imgout = fopen(filename, "w");
314
315 if (imgout == NULL) {
316 fprintf(stderr, "Error: Filename %s could not be opened for writing\n", filename);
317 return;
318 }
319
320 if (numChannels == 3) {
321 fprintf(imgout, "P6\n%d %d\n255\n", width, height);
322 } else if (numChannels == 1) {
323 fprintf(imgout, "P5\n%d %d\n255\n", width, height);
324 } else {
325 fprintf(stderr, "Error: writeBinaryPPM: Unsupported number of channels\n");
326 }
327 fwrite(image, sizeof(ImageTypeBase), numChannels*width*height, imgout);
328
329 fclose(imgout);
330
331 }
332
allocateImage(int width,int height,int numChannels,short int border)333 ImageType ImageUtils::allocateImage(int width, int height, int numChannels, short int border)
334 {
335 int overallocation = 256;
336 return (ImageType) calloc(width*height*numChannels+overallocation, sizeof(ImageTypeBase));
337 }
338
339
freeImage(ImageType image)340 void ImageUtils::freeImage(ImageType image)
341 {
342 free(image);
343 }
344
345
346 // allocation of one color image used for tmp buffers, etc.
347 // format of contiguous memory block:
348 // YUVInfo struct (type + BimageInfo for Y,U, and V),
349 // Y row pointers
350 // U row pointers
351 // V row pointers
352 // Y image pixels
353 // U image pixels
354 // V image pixels
allocateImage(unsigned short width,unsigned short height)355 YUVinfo *YUVinfo::allocateImage(unsigned short width, unsigned short height)
356 {
357 unsigned short heightUV, widthUV;
358
359 widthUV = width;
360 heightUV = height;
361
362 // figure out how much space to hold all pixels...
363 int size = ((width * height * 3) + 8);
364 unsigned char *position = 0;
365
366 // VC 8 does not like calling free on yuv->Y.ptr since it is in
367 // the middle of a block. So rearrange the memory layout so after
368 // calling mapYUVInforToImage yuv->Y.ptr points to the begginning
369 // of the calloc'ed block.
370 YUVinfo *yuv = (YUVinfo *) calloc(sizeof(YUVinfo), 1);
371 if (yuv) {
372 yuv->Y.width = yuv->Y.pitch = width;
373 yuv->Y.height = height;
374 yuv->Y.border = yuv->U.border = yuv->V.border = (unsigned short) 0;
375 yuv->U.width = yuv->U.pitch = yuv->V.width = yuv->V.pitch = widthUV;
376 yuv->U.height = yuv->V.height = heightUV;
377
378 unsigned char* block = (unsigned char*) calloc(
379 sizeof(unsigned char *) * (height + heightUV + heightUV) +
380 sizeof(unsigned char) * size, 1);
381
382 position = block;
383 unsigned char **y = (unsigned char **) (block + size);
384
385 /* Initialize and assign row pointers */
386 yuv->Y.ptr = y;
387 yuv->V.ptr = &y[height];
388 yuv->U.ptr = &y[height + heightUV];
389 }
390 if (size)
391 mapYUVInfoToImage(yuv, position);
392 return yuv;
393 }
394
395 // wrap YUVInfo row pointers around 3 contiguous image (color component) planes.
396 // position = starting pixel in image.
mapYUVInfoToImage(YUVinfo * img,unsigned char * position)397 void YUVinfo::mapYUVInfoToImage(YUVinfo *img, unsigned char *position)
398 {
399 int i;
400 for (i = 0; i < img->Y.height; i++, position += img->Y.width)
401 img->Y.ptr[i] = position;
402 for (i = 0; i < img->V.height; i++, position += img->V.width)
403 img->V.ptr[i] = position;
404 for (i = 0; i < img->U.height; i++, position += img->U.width)
405 img->U.ptr[i] = position;
406 }
407
408
409