[coding convention] Fixed coding rule violation
[platform/core/api/mediavision.git] / test / testsuites / common / image_helper / src / ImageHelper.cpp
1 /**
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
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 #include "ImageHelper.h"
18 #include "mv_private.h"
19
20 #include <vector>
21
22 #include <cstring>
23
24 #include <setjmp.h>
25
26 #include <opencv2/core/core.hpp>
27 #include <opencv2/highgui/highgui.hpp>
28 #include <opencv2/imgproc/imgproc.hpp>
29
30 /**
31  * @file   ImageHelper.cpp
32  * @brief  The ImageHelper class methods implementation.
33  */
34
35 namespace MediaVision
36 {
37 namespace Common
38 {
39
40 namespace
41 {
42
43 static const int OpenCVChannels = 3;
44 static const mv_colorspace_e OpenCVColor = MEDIA_VISION_COLORSPACE_RGB888;
45 static const int QuadrangleVertices = 4;
46
47 std::vector<std::string> getJPGExtensions()
48 {
49         std::vector<std::string> extensions;
50         extensions.push_back(".jpg");
51         extensions.push_back(".jpe");
52         extensions.push_back(".jpeg");
53         return extensions;
54 }
55
56 } /* anonymous namespace */
57
58 int ImageHelper::loadImageToBuffer(
59                 const char *filePath,
60                 unsigned char **pDataBuffer,
61                 unsigned long *pBufferSize,
62                 ImageData *pImageData)
63 {
64         if (filePath == NULL || pDataBuffer == NULL ||
65                 pBufferSize == NULL || pImageData == NULL)
66                 return MEDIA_VISION_ERROR_INVALID_PARAMETER;
67
68         cv::Mat image;
69         image = cv::imread(filePath);
70
71         if (!image.data)
72                 return MEDIA_VISION_ERROR_INVALID_PARAMETER;
73
74         cv::cvtColor(image, image, CV_BGR2RGB);
75
76         *pBufferSize = image.total() * image.elemSize();
77         (*pDataBuffer) = new unsigned char[*pBufferSize];
78         std::memcpy(*pDataBuffer, image.data, *pBufferSize);
79
80         pImageData->imageWidth = image.cols;
81         pImageData->imageHeight = image.rows;
82         pImageData->imageColorspace = OpenCVColor;
83
84         return MEDIA_VISION_ERROR_NONE;
85 }
86
87 int ImageHelper::saveImageFromBuffer(
88                 const char *filePath,
89                 unsigned char *pDataBuffer,
90                 const ImageData& imageData,
91                 int quality)
92 {
93         if (filePath == NULL || pDataBuffer == NULL)
94                 return MEDIA_VISION_ERROR_INVALID_PARAMETER;
95
96         static const std::string defaultFilePath = "out";
97         static const std::vector<std::string> jpgExtensions = getJPGExtensions();
98
99         bool rightExtensionFlag = false;
100
101         std::string resultFilePath(filePath);
102         if (resultFilePath.empty()) {
103                 resultFilePath = defaultFilePath;
104         } else {
105                 for (size_t extNum = 0; extNum < jpgExtensions.size(); ++extNum) {
106                         if (resultFilePath.size() >= jpgExtensions[extNum].size()) {
107                                 std::string givenExtension = resultFilePath.substr(
108                                                 resultFilePath.length() - jpgExtensions[extNum].size(),
109                                                 jpgExtensions[extNum].size());
110
111                                 std::transform(
112                                                 givenExtension.begin(), givenExtension.end(),
113                                                 givenExtension.begin(), ::tolower);
114
115                                 if (givenExtension == jpgExtensions[extNum]) {
116                                         rightExtensionFlag = true;
117                                         break;
118                                 }
119                         }
120                 }
121         }
122         if (!rightExtensionFlag)
123                 resultFilePath += jpgExtensions[0];
124
125         if (quality <= 0 || quality > 100)
126                 quality = 100;
127
128         unsigned int width = imageData.imageWidth;
129         unsigned int height = imageData.imageHeight;
130
131         /* Type of conversion from given colorspace to BGR */
132         int conversionType = -1;
133         unsigned int channelsNumber = 0;
134         switch (imageData.imageColorspace) {
135         case MEDIA_VISION_COLORSPACE_INVALID:
136                 return MEDIA_VISION_ERROR_INVALID_PARAMETER;
137         case MEDIA_VISION_COLORSPACE_Y800:
138                 channelsNumber = 1;
139                 conversionType = CV_GRAY2BGR;
140                 break;
141         case MEDIA_VISION_COLORSPACE_I420:
142                 channelsNumber = 1;
143                 height *= 1.5;
144                 conversionType = CV_YUV2BGR_I420;
145                 break;
146         case MEDIA_VISION_COLORSPACE_NV12:
147                 channelsNumber = 1;
148                 height *= 1.5;
149                 conversionType = CV_YUV2BGR_NV12;
150                 break;
151         case MEDIA_VISION_COLORSPACE_YV12:
152                 channelsNumber = 1;
153                 height *= 1.5;
154                 conversionType = CV_YUV2BGR_YV12;
155                 break;
156         case MEDIA_VISION_COLORSPACE_NV21:
157                 channelsNumber = 1;
158                 height *= 1.5;
159                 conversionType = CV_YUV2BGR_NV21;
160                 break;
161         case MEDIA_VISION_COLORSPACE_YUYV:
162                 channelsNumber = 2;
163                 conversionType = CV_YUV2BGR_YUYV;
164                 break;
165         case MEDIA_VISION_COLORSPACE_UYVY:
166                 channelsNumber = 2;
167                 conversionType = CV_YUV2BGR_UYVY;
168                 break;
169         case MEDIA_VISION_COLORSPACE_422P:
170                 channelsNumber = 2;
171                 conversionType = CV_YUV2BGR_Y422;
172                 break;
173         case MEDIA_VISION_COLORSPACE_RGB565:
174                 channelsNumber = 2;
175                 conversionType = CV_BGR5652BGR;
176                 break;
177         case MEDIA_VISION_COLORSPACE_RGB888:
178                 channelsNumber = 3;
179                 conversionType = CV_RGB2BGR;
180                 break;
181         case MEDIA_VISION_COLORSPACE_RGBA:
182                 channelsNumber = 4;
183                 conversionType = CV_RGBA2BGR;
184                 break;
185         default:
186                 return MEDIA_VISION_ERROR_NOT_SUPPORTED_FORMAT;
187         }
188
189         const int depth = CV_8U;
190         cv::Mat cvImage(cv::Size(width, height),
191                                         CV_MAKETYPE(depth, channelsNumber), pDataBuffer);
192         cv::Mat cvBGRImage;
193         cv::cvtColor(cvImage, cvBGRImage, conversionType);
194
195         std::vector<int> compression_params(2);
196         compression_params[0] = CV_IMWRITE_JPEG_QUALITY;
197         compression_params[1] = quality;
198
199         if (!cv::imwrite(resultFilePath, cvBGRImage, compression_params))
200                 return MEDIA_VISION_ERROR_INVALID_OPERATION;
201
202         return MEDIA_VISION_ERROR_NONE;
203 }
204
205 int ImageHelper::destroyLoadedBuffer(unsigned char *pDataBuffer)
206 {
207         if (!pDataBuffer)
208                 return MEDIA_VISION_ERROR_NONE;
209
210         delete [] pDataBuffer;
211         pDataBuffer = NULL;
212
213         return MEDIA_VISION_ERROR_NONE;
214 }
215
216 int ImageHelper::drawRectangleOnBuffer(
217                 int topLeftVertexX,
218                 int topLeftVertexY,
219                 int bottomRightVertexX,
220                 int bottomRightVertexY,
221                 int thickness,
222                 const cv::Scalar& color,
223                 const ImageData& imageData,
224                 unsigned char *pDataBuffer)
225 {
226         if (NULL == pDataBuffer)
227                 return MEDIA_VISION_ERROR_INVALID_PARAMETER;
228
229         cv::Mat cvImage(imageData.imageHeight, imageData.imageWidth, CV_8UC(OpenCVChannels), pDataBuffer);
230         cv::rectangle(
231                         cvImage,
232                         cv::Point(topLeftVertexX, topLeftVertexY),
233                         cv::Point(bottomRightVertexX, bottomRightVertexY),
234                         color,
235                         thickness);
236
237         return MEDIA_VISION_ERROR_NONE;
238 }
239
240 int ImageHelper::drawQuadrangleOnBuffer(
241                         mv_quadrangle_s location,
242                         int thickness,
243                         const cv::Scalar& color,
244                         const ImageData& imageData,
245                         unsigned char *pDataBuffer)
246 {
247         if (NULL == pDataBuffer)
248                 return MEDIA_VISION_ERROR_INVALID_PARAMETER;
249
250         cv::Mat cvImage(imageData.imageHeight, imageData.imageWidth, CV_8UC(OpenCVChannels), pDataBuffer);
251         for (int i = 0; i < QuadrangleVertices; ++i) {
252                 cv::line(
253                                         cvImage,
254                                         cv::Point(location.points[i].x, location.points[i].y),
255                                         cv::Point(location.points[(i + 1) % QuadrangleVertices].x,
256                                         location.points[(i + 1) % QuadrangleVertices].y),
257                                         color,
258                                         thickness);
259         }
260         return MEDIA_VISION_ERROR_NONE;
261 }
262
263 int ImageHelper::convertBufferToRGB888(
264                 const unsigned char *pInBuffer,
265                 const ImageData& imageData,
266                 unsigned char **pOutBuffer)
267 {
268         /* todo: support more colorspaces: */
269         switch (imageData.imageColorspace) {
270         case MEDIA_VISION_COLORSPACE_Y800:
271                 return convertY800ToRGB(pInBuffer, imageData, pOutBuffer);
272         case MEDIA_VISION_COLORSPACE_RGB888:
273         {
274                 int numberOfComponents = 0;
275                 getNumberOfComponents(
276                         MEDIA_VISION_COLORSPACE_RGB888, &numberOfComponents);
277                 const int dataSize =
278                         imageData.imageHeight * imageData.imageWidth * numberOfComponents;
279                 (*pOutBuffer) = new unsigned char[dataSize];
280                 std::memcpy(*pOutBuffer, pInBuffer, dataSize);
281                 return MEDIA_VISION_ERROR_NONE;
282         }
283         default:
284                 return MEDIA_VISION_ERROR_NOT_SUPPORTED;
285         }
286
287         return MEDIA_VISION_ERROR_NOT_SUPPORTED;
288 }
289
290 int ImageHelper::getNumberOfComponents(
291                 mv_colorspace_e colorspace,
292                 int *pComponentsNumber)
293 {
294         /* todo: support more colorspaces: */
295         switch (colorspace) {
296         case MEDIA_VISION_COLORSPACE_Y800:
297                 (*pComponentsNumber) = 1;
298                 return MEDIA_VISION_ERROR_NONE;
299         case MEDIA_VISION_COLORSPACE_RGB888:
300                 (*pComponentsNumber) = 3;
301                 return MEDIA_VISION_ERROR_NONE;
302         default:
303                 return MEDIA_VISION_ERROR_NOT_SUPPORTED;
304         }
305
306         return MEDIA_VISION_ERROR_NOT_SUPPORTED;
307 }
308
309 int ImageHelper::convertY800ToRGB(
310                 const unsigned char *pInBuffer,
311                 const ImageData& imageData,
312                 unsigned char **pOutBuffer)
313 {
314         if (imageData.imageColorspace != MEDIA_VISION_COLORSPACE_Y800)
315                 return MEDIA_VISION_ERROR_INVALID_PARAMETER;
316
317         const int inDataSize = imageData.imageHeight * imageData.imageWidth;
318         int numberOfComponents = 0;
319         getNumberOfComponents(MEDIA_VISION_COLORSPACE_RGB888, &numberOfComponents);
320         const int dataSize = inDataSize * numberOfComponents;
321         (*pOutBuffer) = new unsigned char[dataSize];
322         for (int i = 0; i < inDataSize; ++i) {
323                 int pixelStartIndex = i*numberOfComponents;
324                 (*pOutBuffer)[pixelStartIndex]   = pInBuffer[i];
325                 (*pOutBuffer)[pixelStartIndex+1] = pInBuffer[i];
326                 (*pOutBuffer)[pixelStartIndex+2] = pInBuffer[i];
327         }
328         return MEDIA_VISION_ERROR_NONE;
329 }
330
331 } /* namespace Common */
332 } /* namespace MediaVision */