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 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 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 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 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 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 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 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 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 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 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 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 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. 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