4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Vineeth T M <vineeth.tm@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
29 #include "mm_util_bmp.h"
30 #include "mm_util_private.h"
32 #define BYTES_PER_PIXEL 4
34 /* for bmp_bitmap_callback_vt of nsbmp */
35 void *__bitmap_create(int width, int height, unsigned int state);
36 unsigned char *__bitmap_get_buffer(void *bitmap);
37 size_t __bitmap_get_bpp(void *bitmap);
38 void __bitmap_destroy(void *bitmap);
40 void *__bitmap_create(int width, int height, unsigned int state)
42 return calloc(width * height, BYTES_PER_PIXEL);
45 unsigned char *__bitmap_get_buffer(void *bitmap)
50 size_t __bitmap_get_bpp(void *bitmap)
52 return BYTES_PER_PIXEL;
55 void __bitmap_destroy(void *bitmap)
57 MMUTIL_SAFE_FREE(bitmap);
60 static unsigned char *__load_file(const char *path, size_t * data_size)
64 unsigned char *buffer;
68 if (MM_UTIL_ERROR_NONE != mm_util_safe_fopen(path, "rb", &fd)) {
69 mm_util_error("mm_util_safe_fopen failed");
73 if (stat(path, &sb)) {
74 mm_util_error("file stat failed");
75 mm_util_safe_fclose(fd);
80 buffer = calloc(1, size);
82 mm_util_error("Unable to allocate %lld bytes", (long long)size);
83 mm_util_safe_fclose(fd);
87 n = fread(buffer, 1, size, fd);
89 mm_util_error("file read failed");
90 MMUTIL_SAFE_FREE(buffer);
91 mm_util_safe_fclose(fd);
95 mm_util_safe_fclose(fd);
100 static void __print_error(const char *context, bmp_result code)
103 case BMP_INSUFFICIENT_MEMORY:
104 mm_util_error("%s failed: BMP_INSUFFICIENT_MEMORY", context);
106 case BMP_INSUFFICIENT_DATA:
107 mm_util_error("%s failed: BMP_INSUFFICIENT_DATA", context);
110 mm_util_error("%s failed: BMP_DATA_ERROR", context);
113 mm_util_error("%s failed: unknown code %i", context, code);
118 /* decodes bmp image to color image */
119 static int __read_bmp(const char *file_path, void *memory, size_t src_size, mm_util_image_h *decoded)
121 bmp_bitmap_callback_vt bitmap_callbacks = {
130 int res = MM_UTIL_ERROR_NONE;
131 unsigned char *data = NULL;
133 mm_util_retvm_if(!MMUTIL_STRING_VALID(file_path) && !memory, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid bmp image");
134 mm_util_retvm_if(!decoded, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid image handle");
138 if (MMUTIL_STRING_VALID(file_path)) {
139 mm_util_sec_debug("read from file [%s]", file_path);
140 data = __load_file(file_path, &size);
142 return MM_UTIL_ERROR_INVALID_OPERATION;
144 mm_util_debug("read from memory");
145 data = (unsigned char *)memory;
149 nsbmp_create(&bmp, &bitmap_callbacks);
151 code = bmp_analyse(&bmp, size, data);
152 if (code != BMP_OK) {
153 __print_error("bmp_analyse", code);
154 res = MM_UTIL_ERROR_INVALID_OPERATION;
158 code = bmp_decode(&bmp);
160 if ((code != BMP_OK) || (bmp.bitmap == NULL)) {
161 __print_error("bmp_decode", code);
162 /* allow partially decoded images */
163 if (code != BMP_INSUFFICIENT_DATA) {
164 res = MM_UTIL_ERROR_INVALID_OPERATION;
169 res = mm_image_create_image(bmp.width, bmp.height, MM_UTIL_COLOR_RGBA, bmp.bitmap, bmp.width * bmp.height * BYTES_PER_PIXEL, decoded);
174 MMUTIL_SAFE_FREE(data);
181 /* encodes color image to bmp image */
182 static int __write_bmp(mm_util_image_h decoded, const char *file_path, void **buffer, size_t *src_size)
184 mm_image_info_s *_decoded = (mm_image_info_s *)decoded;
186 rgb_pixel_t pixel = { 0, 0, 0, 0 };
190 mm_util_retvm_if(!decoded, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid image src");
191 mm_util_retvm_if(!MMUTIL_STRING_VALID(file_path) && (!buffer || !src_size), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid parameter");
192 mm_util_retvm_if(_decoded->color != MM_UTIL_COLOR_RGBA, MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT, "not supported color [%d]", _decoded->color);
196 /* header of bmp image is create at 'bmp' */
197 if ((bmp = bmp_create(_decoded->width, _decoded->height, BYTES_PER_PIXEL * 8)) == NULL) {
198 mm_util_error("Invalid depth value.");
199 return MM_UTIL_ERROR_INVALID_OPERATION;
202 /* pixcels of bmp image is stored at 'bmp' */
203 image = (uint8_t *) _decoded->data;
204 for (row = 0; row != _decoded->height; row++) {
205 for (col = 0; col != _decoded->width; col++) {
206 size_t z = (row * _decoded->width + col) * BYTES_PER_PIXEL;
207 pixel.red = image[z];
208 pixel.green = image[z + 1];
209 pixel.blue = image[z + 2];
210 bmp_set_pixel(bmp, col, row, pixel);
214 /* write 'bmp' to file or buffer */
215 if (MMUTIL_STRING_VALID(file_path)) {
216 mm_util_sec_debug("Save to file [%s]", file_path);
217 if (bmp_save(bmp, file_path) == false) {
218 mm_util_error("Saving bmp was failed.");
220 return MM_UTIL_ERROR_INVALID_OPERATION;
223 mm_util_sec_debug("Save to buffer");
224 if (bmp_save2(bmp, buffer, src_size) == false) {
225 mm_util_error("Saving bmp was failed.");
227 MMUTIL_SAFE_FREE(*buffer);
229 return MM_UTIL_ERROR_INVALID_OPERATION;
237 return MM_UTIL_ERROR_NONE;
240 int mm_util_decode_from_bmp_file(const char *file_path, mm_util_image_h *decoded)
242 mm_util_retvm_if(!MMUTIL_STRING_VALID(file_path), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid file_path");
244 return __read_bmp(file_path, NULL, 0, decoded);
247 int mm_util_decode_from_bmp_memory(void *memory, const size_t src_size, mm_util_image_h *decoded)
249 mm_util_retvm_if(!memory, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid bmp image");
250 mm_util_retvm_if(!src_size, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid src_size");
252 return __read_bmp(NULL, memory, src_size, decoded);
255 int mm_util_encode_bmp_to_file(mm_util_image_h decoded, const char *file_path)
257 mm_util_retvm_if(!MMUTIL_STRING_VALID(file_path), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid file_path");
259 return __write_bmp(decoded, file_path, NULL, NULL);
262 int mm_util_encode_bmp_to_memory(mm_util_image_h decoded, void **buffer, size_t *size)
264 mm_util_retvm_if(!buffer, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid buffer");
265 mm_util_retvm_if(!size, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid size");
267 return __write_bmp(decoded, NULL, buffer, size);