2 * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "ImageHelper.h"
18 #include "mv_private.h"
26 #include <opencv2/core/core.hpp>
27 #include <opencv2/highgui/highgui.hpp>
28 #include <opencv2/imgproc/imgproc.hpp>
31 * @file ImageHelper.cpp
32 * @brief The ImageHelper class methods implementation.
43 static const int OpenCVChannels = 3;
44 static const mv_colorspace_e OpenCVColor = MEDIA_VISION_COLORSPACE_RGB888;
45 static const int QuadrangleVertices = 4;
47 std::vector<std::string> getJPGExtensions()
49 std::vector<std::string> extensions;
50 extensions.push_back(".jpg");
51 extensions.push_back(".jpe");
52 extensions.push_back(".jpeg");
56 } /* anonymous namespace */
58 int ImageHelper::loadImageToBuffer(
60 unsigned char **pDataBuffer,
61 unsigned long *pBufferSize,
62 ImageData *pImageData)
64 if (filePath == NULL || pDataBuffer == NULL ||
65 pBufferSize == NULL || pImageData == NULL)
66 return MEDIA_VISION_ERROR_INVALID_PARAMETER;
69 image = cv::imread(filePath);
72 return MEDIA_VISION_ERROR_INVALID_PARAMETER;
74 cv::cvtColor(image, image, CV_BGR2RGB);
76 *pBufferSize = image.total() * image.elemSize();
77 (*pDataBuffer) = new unsigned char[*pBufferSize];
78 std::memcpy(*pDataBuffer, image.data, *pBufferSize);
80 pImageData->imageWidth = image.cols;
81 pImageData->imageHeight = image.rows;
82 pImageData->imageColorspace = OpenCVColor;
84 return MEDIA_VISION_ERROR_NONE;
87 int ImageHelper::saveImageFromBuffer(
89 unsigned char *pDataBuffer,
90 const ImageData& imageData,
93 if (filePath == NULL || pDataBuffer == NULL)
94 return MEDIA_VISION_ERROR_INVALID_PARAMETER;
96 static const std::string defaultFilePath = "out";
97 static const std::vector<std::string> jpgExtensions = getJPGExtensions();
99 bool rightExtensionFlag = false;
101 std::string resultFilePath(filePath);
102 if (resultFilePath.empty()) {
103 resultFilePath = defaultFilePath;
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());
112 givenExtension.begin(), givenExtension.end(),
113 givenExtension.begin(), ::tolower);
115 if (givenExtension == jpgExtensions[extNum]) {
116 rightExtensionFlag = true;
122 if (!rightExtensionFlag)
123 resultFilePath += jpgExtensions[0];
125 if (quality <= 0 || quality > 100)
128 unsigned int width = imageData.imageWidth;
129 unsigned int height = imageData.imageHeight;
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:
139 conversionType = CV_GRAY2BGR;
141 case MEDIA_VISION_COLORSPACE_I420:
144 conversionType = CV_YUV2BGR_I420;
146 case MEDIA_VISION_COLORSPACE_NV12:
149 conversionType = CV_YUV2BGR_NV12;
151 case MEDIA_VISION_COLORSPACE_YV12:
154 conversionType = CV_YUV2BGR_YV12;
156 case MEDIA_VISION_COLORSPACE_NV21:
159 conversionType = CV_YUV2BGR_NV21;
161 case MEDIA_VISION_COLORSPACE_YUYV:
163 conversionType = CV_YUV2BGR_YUYV;
165 case MEDIA_VISION_COLORSPACE_UYVY:
167 conversionType = CV_YUV2BGR_UYVY;
169 case MEDIA_VISION_COLORSPACE_422P:
171 conversionType = CV_YUV2BGR_Y422;
173 case MEDIA_VISION_COLORSPACE_RGB565:
175 conversionType = CV_BGR5652BGR;
177 case MEDIA_VISION_COLORSPACE_RGB888:
179 conversionType = CV_RGB2BGR;
181 case MEDIA_VISION_COLORSPACE_RGBA:
183 conversionType = CV_RGBA2BGR;
186 return MEDIA_VISION_ERROR_NOT_SUPPORTED_FORMAT;
189 const int depth = CV_8U;
190 cv::Mat cvImage(cv::Size(width, height),
191 CV_MAKETYPE(depth, channelsNumber), pDataBuffer);
193 cv::cvtColor(cvImage, cvBGRImage, conversionType);
195 std::vector<int> compression_params(2);
196 compression_params[0] = CV_IMWRITE_JPEG_QUALITY;
197 compression_params[1] = quality;
199 if (!cv::imwrite(resultFilePath, cvBGRImage, compression_params))
200 return MEDIA_VISION_ERROR_INVALID_OPERATION;
202 return MEDIA_VISION_ERROR_NONE;
205 int ImageHelper::destroyLoadedBuffer(unsigned char *pDataBuffer)
208 return MEDIA_VISION_ERROR_NONE;
210 delete [] pDataBuffer;
213 return MEDIA_VISION_ERROR_NONE;
216 int ImageHelper::drawRectangleOnBuffer(
219 int bottomRightVertexX,
220 int bottomRightVertexY,
222 const cv::Scalar& color,
223 const ImageData& imageData,
224 unsigned char *pDataBuffer)
226 if (NULL == pDataBuffer)
227 return MEDIA_VISION_ERROR_INVALID_PARAMETER;
229 cv::Mat cvImage(imageData.imageHeight, imageData.imageWidth, CV_8UC(OpenCVChannels), pDataBuffer);
232 cv::Point(topLeftVertexX, topLeftVertexY),
233 cv::Point(bottomRightVertexX, bottomRightVertexY),
237 return MEDIA_VISION_ERROR_NONE;
240 int ImageHelper::drawQuadrangleOnBuffer(
241 mv_quadrangle_s location,
243 const cv::Scalar& color,
244 const ImageData& imageData,
245 unsigned char *pDataBuffer)
247 if (NULL == pDataBuffer)
248 return MEDIA_VISION_ERROR_INVALID_PARAMETER;
250 cv::Mat cvImage(imageData.imageHeight, imageData.imageWidth, CV_8UC(OpenCVChannels), pDataBuffer);
251 for (int i = 0; i < QuadrangleVertices; ++i) {
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),
260 return MEDIA_VISION_ERROR_NONE;
263 int ImageHelper::convertBufferToRGB888(
264 const unsigned char *pInBuffer,
265 const ImageData& imageData,
266 unsigned char **pOutBuffer)
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:
274 int numberOfComponents = 0;
275 getNumberOfComponents(
276 MEDIA_VISION_COLORSPACE_RGB888, &numberOfComponents);
278 imageData.imageHeight * imageData.imageWidth * numberOfComponents;
279 (*pOutBuffer) = new unsigned char[dataSize];
280 std::memcpy(*pOutBuffer, pInBuffer, dataSize);
281 return MEDIA_VISION_ERROR_NONE;
284 return MEDIA_VISION_ERROR_NOT_SUPPORTED;
287 return MEDIA_VISION_ERROR_NOT_SUPPORTED;
290 int ImageHelper::getNumberOfComponents(
291 mv_colorspace_e colorspace,
292 int *pComponentsNumber)
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;
303 return MEDIA_VISION_ERROR_NOT_SUPPORTED;
306 return MEDIA_VISION_ERROR_NOT_SUPPORTED;
309 int ImageHelper::convertY800ToRGB(
310 const unsigned char *pInBuffer,
311 const ImageData& imageData,
312 unsigned char **pOutBuffer)
314 if (imageData.imageColorspace != MEDIA_VISION_COLORSPACE_Y800)
315 return MEDIA_VISION_ERROR_INVALID_PARAMETER;
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];
328 return MEDIA_VISION_ERROR_NONE;
331 } /* namespace Common */
332 } /* namespace MediaVision */