merge with master
[platform/core/api/face.git] / src / face_image.c
1 /*
2  * Copyright (c) 2011 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 "face.h"
18 #include "face_priv.h"
19
20 #include <stdlib.h>
21
22
23
24 static void convert_RGB565_to_Y(unsigned char* pBuf, unsigned char* pGrayBuf, int width, int height)
25 {
26         unsigned char* pDst, * pEnd;
27         unsigned short* pSrc;
28
29         unsigned short R, G, B;
30         long lt;
31
32         pSrc = (unsigned short*) pBuf;
33         pDst = (unsigned char*) pGrayBuf;
34         pEnd = (unsigned char*) ((unsigned char*) pGrayBuf + height * width);
35
36         while (pDst < pEnd)
37         {
38                 R = (unsigned char) ((*pSrc >> 11) << 3);            // R
39                 G = (unsigned char) ((*pSrc & 0x07e0) >> 3);         // +G
40                 B = (unsigned char) ((*pSrc++ & 0x001f) << 3);           // +B
41
42                 // Y = 0.299 R + 0.587 G + 0.114 B
43                 lt = (306L * (long) R + 601L * (long) G + 117L * (long) B);
44                 *pDst++ = (unsigned char ) (lt >> 10);
45                 //(BYTE)(((int)R+(int)G+(int)B) /3);
46         }
47 }
48
49 static void convert_BGRA8888_to_Y(unsigned char* pBuf, unsigned char* pGrayBuf, int width, int height)
50 {
51         unsigned long* pSrc = (unsigned long*) pBuf;
52         unsigned char* pDSt = (unsigned char*) pGrayBuf;
53         unsigned char* pEnd = pDSt + height * width;
54
55         while (pDSt < pEnd)
56         {
57                 unsigned long r = (*pSrc >> 16) & 0xFF;
58                 unsigned long g = (*pSrc >> 8) & 0xFF;
59                 unsigned long b = (*pSrc++) & 0xFF;
60
61                 *pDSt++ = (308 * r + 600 * g + 116 * b) >> 10;
62         }
63 }
64
65 static void convert_RGBA8888_to_Y(unsigned char* pBuf, unsigned char* pGrayBuf, int width, int height)
66 {
67         unsigned long* pSrc = (unsigned long*) pBuf;
68         unsigned char* pDSt = (unsigned char*) pGrayBuf;
69         unsigned char* pEnd = pDSt + height * width;
70
71         while (pDSt < pEnd)
72         {
73                 unsigned long b = (*pSrc >> 16) & 0xFF;
74                 unsigned long g = (*pSrc >> 8) & 0xFF;
75                 unsigned long r = (*pSrc++) & 0xFF;
76
77                 *pDSt++ = (308 * r + 600 * g + 116 * b) >> 10;
78         }
79 }
80
81 #define CLIP(a) ((a) > 255 ? 255 : (a) < 0 ? 0 : (a))
82
83 #if 0
84 static void convert_RGB888_to_Y(unsigned char* pBuf, unsigned char* pGrayBuf, int width, int height)
85 {
86         unsigned char* pSrc = (unsigned char*) pBuf;
87         unsigned char* pDSt = (unsigned char*) pGrayBuf;
88
89         unsigned char* pEnd = pDSt + height * width;
90
91         while (pDSt < pEnd)
92         {
93                 unsigned long r = *pSrc++;
94                 unsigned long g = *pSrc++;
95                 unsigned long b = *pSrc++;
96
97                 *pDSt++ = (308 * r + 600 * g + 116 * b) >> 10;
98         }
99 }
100 #endif
101
102 static bool _validate_face_image_h(face_image_h face_image)
103 {
104         if ( face_image == NULL )
105         {
106                 return false;
107         }
108
109         if ( face_image->magic != FACE_IMAGE_MAGIC )
110         {
111                 return false;
112         }
113
114         return true;
115 }
116
117
118 EXPORT_API int face_image_create(__in face_image_colorspace_e colorspace, __in unsigned char *buffer, __in int width, __in int height, __in int size, __out face_image_h *face_image)
119 {
120         if ( face_image == NULL )
121         {
122                 LOG_ERROR("Out pointer is NULL. %s", _face_convert_error(FACE_ERROR_INVALID_PARAMTER));
123                 return FACE_ERROR_INVALID_PARAMTER;
124         }
125
126         if ( buffer == NULL )
127         {
128                 LOG_ERROR("Buffer Cannot be NULL. %s", _face_convert_error(FACE_ERROR_INVALID_PARAMTER));
129                 return FACE_ERROR_INVALID_PARAMTER;
130         }
131
132         if ( width <= 0 || height  <= 0 )
133         {
134                 LOG_ERROR("Invalid image size(%d,%d). %s", width, height, _face_convert_error(FACE_ERROR_INVALID_PARAMTER));
135                 return FACE_ERROR_INVALID_PARAMTER;
136         }
137
138         unsigned char *YBuf = NULL;
139         unsigned char *YBufRef = NULL;
140
141         switch(colorspace)
142         {
143                 case FACE_IMAGE_COLORSPACE_YUV420:
144                         YBuf = buffer;
145                         break;
146
147                 case FACE_IMAGE_COLORSPACE_RGB565:
148                         YBufRef = YBuf = (unsigned char *)calloc(1, width * height);
149                         if ( YBuf == NULL )
150                         {
151                                 LOG_ERROR("Cannot allocate FACE_IMAGE_COLORSPACE_RGB565 buffer");
152                                 return FACE_ERROR_OUT_OF_MEMORY;
153                         }
154
155                         convert_RGB565_to_Y(buffer, YBuf, width, height);
156                         break;
157
158                 case FACE_IMAGE_COLORSPACE_BGRA8888:
159                         YBufRef = YBuf = (unsigned char *)calloc(1, width * height);
160                         if ( YBuf == NULL )
161                         {
162                                 LOG_ERROR("Cannot allocate FACE_IMAGE_COLORSPACE_BGRA8888 buffer");
163                                 return FACE_ERROR_OUT_OF_MEMORY;
164                         }
165
166                         convert_BGRA8888_to_Y(buffer, YBuf, width, height);
167                         break;
168
169                 case FACE_IMAGE_COLORSPACE_RGBA8888:
170                         YBufRef = YBuf = (unsigned char *)calloc(1, width * height);
171                         if ( YBuf == NULL )
172                         {
173                                 LOG_ERROR("Cannot allocate FACE_IMAGE_COLORSPACE_RGBA8888 buffer");
174                                 return FACE_ERROR_OUT_OF_MEMORY;
175                         }
176
177                         convert_RGBA8888_to_Y(buffer, YBuf, width, height);
178                         break;
179
180
181                 case FACE_IMAGE_COLORSPACE_LUMINANCE_ONLY:
182                         YBuf = buffer;
183                         break;
184                 default:
185                         LOG_ERROR("Invalid colorspace(%d). %s", colorspace, _face_convert_error(FACE_ERROR_INVALID_PARAMTER));
186                         return FACE_ERROR_INVALID_PARAMTER;
187         }
188
189         *face_image = (FaceImage *)calloc(1, sizeof(FaceImage));
190
191         if ( *face_image == NULL )
192         {
193                 LOG_ERROR("Cannot allocate face_image_h");
194                 if ( YBufRef != NULL )
195                 {
196                         free(YBufRef);
197                 }
198                 
199                 return FACE_ERROR_OUT_OF_MEMORY;
200         }
201
202         (*face_image)->magic = FACE_IMAGE_MAGIC;
203
204         (*face_image)->pixel = YBuf;
205         (*face_image)->width = width;
206         (*face_image)->height = height;
207         (*face_image)->size = width * height;
208         (*face_image)->colorspace = colorspace;
209
210         return FACE_ERROR_NONE;
211 }
212
213
214 EXPORT_API int face_image_destroy(face_image_h face_image)
215 {
216         if ( _validate_face_image_h(face_image) == false )
217         {
218                 LOG_ERROR("Invalid image handle. %s", _face_convert_error(FACE_ERROR_INVALID_PARAMTER));
219                 return FACE_ERROR_INVALID_PARAMTER;
220         }
221
222         if ( face_image->colorspace == FACE_IMAGE_COLORSPACE_RGB565 || face_image->colorspace == FACE_IMAGE_COLORSPACE_BGRA8888 || face_image->colorspace == FACE_IMAGE_COLORSPACE_RGBA8888 )
223         {
224                 free(face_image->pixel);        // Free user buffer
225         }
226
227         face_image->pixel = NULL;
228         face_image->magic = FACE_INVALID_MAGIC;
229
230         free(face_image);
231
232         return FACE_ERROR_NONE;
233 }
234
235
236 #if 0
237 EXPORT_API int face_image_set_data( face_image_h face_image,
238                              face_image_colorspace_e colorspace, unsigned char *buffer, int width, int height, int size)
239 {
240
241 // Check Param.
242         if ( _validate_face_image_h(face_image) == false )
243         {
244                 LOG_ERROR("Invalid image handle. %s", _face_convert_error(FACE_ERROR_INVALID_PARAMTER));
245                 return FACE_ERROR_INVALID_PARAMTER;
246         }
247
248         if ( buffer == NULL )
249         {
250                 LOG_ERROR("Invalid image data. %s", width, height, _face_convert_error(FACE_ERROR_INVALID_PARAMTER));
251                 return FACE_ERROR_INVALID_PARAMTER;
252         }
253
254         if ( width <= 0 || height  <= 0 )
255         {
256                 LOG_ERROR("Invalid image size(%d,%d). %s", width, height, _face_convert_error(FACE_ERROR_INVALID_PARAMTER));
257                 return FACE_ERROR_INVALID_PARAMTER;
258         }
259
260         if ( colorspace != FACE_IMAGE_COLORSPACE_LUMINANCE_ONLY)
261         {
262                 LOG_ERROR("Invalid image format(%d). %s", colorspace , _face_convert_error(FACE_ERROR_INVALID_PARAMTER));
263                 return FACE_ERROR_INVALID_PARAMTER;
264         }
265
266         face_image->pixel = buffer;
267         face_image->width = width;
268         face_image->height = height;
269         face_image->size = width * height;
270         face_image->colorspace = colorspace;
271
272         return FACE_ERROR_NONE;
273
274 }
275
276
277
278 EXPORT_API int face_image_get_data(face_image_h face_image,
279                             face_image_colorspace_e *colorspace, unsigned char **buffer, int *width, int *height, int *size)
280 {
281         if ( _validate_face_image_h(face_image) == false )
282         {
283                 LOG_ERROR("Invalid image handle. %s", _face_convert_error(FACE_ERROR_INVALID_PARAMTER));
284                 return FACE_ERROR_INVALID_PARAMTER;
285         }
286
287         if ( colorspace == NULL || buffer == NULL || width == NULL || height == NULL )
288         {
289                 LOG_ERROR("Invalid param. 0x%08x 0x%08x 0x%08x 0x%08x", colorspace, buffer, width, height);
290                 return FACE_ERROR_INVALID_PARAMTER;
291         }
292
293         *buffer = face_image->pixel;
294         *width = face_image->width;
295         *height = face_image->height;
296         *colorspace = face_image->colorspace;
297         *size = face_image->size;
298
299         return FACE_ERROR_NONE;
300 }
301 #endif
302
303