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