• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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