Home | History | Annotate | Download | only in mosaic
      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