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