Home | History | Annotate | Download | only in colorchecker
      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 #define LOG_NDEBUG 0
     17 
     18 #define LOG_TAG "TestingImage"
     19 #include <utils/Log.h>
     20 #include <utils/Timers.h>
     21 #include <string.h>
     22 #include <cmath>
     23 #include <vector>
     24 #include <assert.h>
     25 #include "vec3.h"
     26 
     27 #include "testingimage.h"
     28 
     29 const float GAMMA_CORRECTION = 2.2f;
     30 
     31 // Constructs an instance with the given image byte array.
     32 TestingImage::TestingImage(const unsigned char* inputImage,
     33                            int inputHeight, int inputWidth,
     34                            int inputChannel, int inputRowSpan) {
     35     mImage = new unsigned char[inputRowSpan * inputHeight];
     36 
     37     ALOGV("mImage format created! with size as %d, %d, %d",
     38          inputRowSpan, inputHeight, inputChannel);
     39     mWidth = inputWidth;
     40     mHeight = inputHeight;
     41     mChannels = inputChannel;
     42     mRowSpan = mWidth * mChannels;
     43 
     44     for (int i = 0; i < mHeight; ++i) {
     45         for (int j = 0; j < mWidth; ++j) {
     46             for (int k = 0; k < mChannels; ++k) {
     47                 mImage[i * mRowSpan + j* mChannels + k] =
     48                         inputImage[i * inputRowSpan + j * inputChannel + k];
     49             }
     50         }
     51     }
     52     ALOGV("mImage converted!");
     53 }
     54 
     55 // Constructs an instance with the given image and resize it to a new size.
     56 TestingImage::TestingImage(const unsigned char* inputImage,
     57                            int inputHeight, int inputWidth,
     58                            int inputChannel, int inputRowSpan,
     59                            int newHeight, int newWidth) {
     60     mImage = new unsigned char[newHeight * newWidth * inputChannel];
     61 
     62     ALOGV("mImage format created! with size as %d, %d, %d",
     63          newHeight, newWidth, inputChannel);
     64     mHeight = newHeight;
     65     mWidth = newWidth;
     66     mChannels = inputChannel;
     67     mRowSpan = mWidth * mChannels;
     68 
     69     // Computes how many pixels in the original image corresponds to one pixel
     70     // in the new image.
     71     int heightScale = inputHeight / newHeight;
     72     int widthScale = inputWidth / newWidth;
     73 
     74     // Average the corresponding pixels in the original image to compute the
     75     // pixel value of the new image.
     76     for (int i = 0; i < mHeight; ++i) {
     77         for (int j = 0; j < mWidth; ++j) {
     78             for (int k = 0; k < mChannels; ++k) {
     79                 int pixelValue = 0;
     80 
     81                 for (int l = 0; l < heightScale; ++l) {
     82                     for (int m = 0; m < widthScale; ++m) {
     83                         pixelValue += inputImage[
     84                                 (i * heightScale + l) * inputRowSpan
     85                                 + (j * widthScale + m) * inputChannel + k];
     86                     }
     87                 }
     88                 pixelValue = pixelValue / (heightScale * widthScale);
     89                 mImage[i * mRowSpan + j * mChannels + k] =
     90                         (unsigned char) pixelValue;
     91             }
     92         }
     93     }
     94 }
     95 
     96 TestingImage::~TestingImage() {
     97     if (mImage!=NULL) {
     98         delete[] mImage;
     99     }
    100 }
    101 
    102 int TestingImage::getPixelValue(int row, int column, int channel) const {
    103     assert ((row >= 0) && (row < mHeight));
    104     assert ((column >= 0) && (column < mWidth));
    105     assert ((channel >= 0) && (channel < mChannels));
    106     return (int)mImage[row * mRowSpan + column * mChannels + channel];
    107 }
    108 
    109 Vec3i TestingImage::getPixelValue(int row, int column) const {
    110     Vec3i current_color(getPixelValue(row, column, 0),
    111                         getPixelValue(row, column, 1),
    112                         getPixelValue(row, column, 2));
    113     return current_color;
    114 }
    115 
    116 Vec3i TestingImage::getPixelValue(const Vec2i &pixelPosition) const {
    117     return getPixelValue(pixelPosition.x(), pixelPosition.y());
    118 }
    119 
    120 Vec3i TestingImage::getPixelValue(const Vec2f &pixelPosition) const {
    121     return getPixelValue(static_cast<int>(pixelPosition.x()),
    122                          static_cast<int>(pixelPosition.y()));
    123 }
    124 
    125 // Returns a vector of the colors in the requested block of color checkers.
    126 // The vector is formatted by going through the block from left to right and
    127 // from top to bottom.
    128 const std::vector<Vec3f>* TestingImage::getColorChecker(
    129       int rowStart, int rowEnd, int columnStart, int columnEnd,
    130       const std::vector<std::vector< Vec2f > >* centerAddress,
    131       const std::vector<std::vector< float > >* radiusAddress) const {
    132     std::vector<Vec3f>* checkerColors = new std::vector<Vec3f>;
    133 
    134     // Average the pixel values of the pixels within the given radius to the
    135     // given center position.
    136     for (int i = rowStart; i < rowEnd; ++i) {
    137         for (int j = columnStart; j < columnEnd; ++j) {
    138             float radius = sqrt((*radiusAddress)[i][j]);
    139             Vec2f center((*centerAddress)[i][j].x(),
    140                                (*centerAddress)[i][j].y());
    141             Vec3f meanColor(0.f, 0.f, 0.f);
    142             int numPixels = 0;
    143 
    144             for (int ii = static_cast<int>(center.x() - radius);
    145                  ii < static_cast<int>(center.x() + radius); ++ii) {
    146                 for (int jj = static_cast<int>(center.y() - radius);
    147                      jj < static_cast<int>(center.y() + radius); ++jj) {
    148 
    149                     Vec2i pixelPosition(ii,jj);
    150                     if (pixelPosition.squareDistance<float>(center) <
    151                         (*radiusAddress)[i][j]) {
    152                         meanColor = meanColor + getPixelValue(pixelPosition);
    153                         ++numPixels;
    154                     }
    155                 }
    156             }
    157             meanColor = meanColor / numPixels;
    158             checkerColors->push_back(meanColor);
    159         }
    160     }
    161 
    162     return checkerColors;
    163 }
    164 
    165 bool TestingImage::rgbToGrayScale(unsigned char* grayLayer) const {
    166     if (mChannels == 4) {
    167         for (int i = 0; i < mWidth; i++) {
    168             for (int j = 0; j < mHeight; j++) {
    169                 float redLinear = pow(getPixelValue(j, i, 0),
    170                                        GAMMA_CORRECTION);
    171                 float greenLinear = pow(getPixelValue(j,i,1),
    172                                          GAMMA_CORRECTION);
    173                 float blueLinear = pow(getPixelValue(j,i,2),
    174                                         GAMMA_CORRECTION);
    175 
    176                 // Computes the luminance value
    177                 grayLayer[j * mWidth + i] =
    178                         (unsigned char)((int)pow((0.299f * redLinear
    179                                                   + 0.587f * greenLinear
    180                                                   + 0.114f * blueLinear),
    181                                                   1/GAMMA_CORRECTION));
    182             }
    183         }
    184 
    185         return true;
    186     } else {
    187 
    188         return false;
    189     }
    190 }
    191