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.
TestingImage(const unsigned char * inputImage,int inputHeight,int inputWidth,int inputChannel,int inputRowSpan)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.
TestingImage(const unsigned char * inputImage,int inputHeight,int inputWidth,int inputChannel,int inputRowSpan,int newHeight,int newWidth)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
~TestingImage()96 TestingImage::~TestingImage() {
97 if (mImage!=NULL) {
98 delete[] mImage;
99 }
100 }
101
getPixelValue(int row,int column,int channel) const102 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
getPixelValue(int row,int column) const109 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
getPixelValue(const Vec2i & pixelPosition) const116 Vec3i TestingImage::getPixelValue(const Vec2i &pixelPosition) const {
117 return getPixelValue(pixelPosition.x(), pixelPosition.y());
118 }
119
getPixelValue(const Vec2f & pixelPosition) const120 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.
getColorChecker(int rowStart,int rowEnd,int columnStart,int columnEnd,const std::vector<std::vector<Vec2f>> * centerAddress,const std::vector<std::vector<float>> * radiusAddress) const128 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
rgbToGrayScale(unsigned char * grayLayer) const165 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