*/
#include <stdlib.h>
-#include <bmpfile.h>
-#include <mm_util_magick.h>
#include "mm_util_bmp.h"
-#include "mm_util_private.h"
+#include "mm_util_magick.h"
-#define BYTES_PER_PIXEL 4
-
-/* encodes color image to bmp image */
-static int __write_bmp(mm_util_image_h decoded, const char *file_path, void **buffer, size_t *src_size)
-{
- mm_image_info_s *_decoded = (mm_image_info_s *)decoded;
- bmpfile_t *bmp;
- rgb_pixel_t pixel = { 0, 0, 0, 0 };
- uint16_t row, col;
- uint8_t *image;
-
- mm_util_retvm_if(!decoded, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid image src");
- mm_util_retvm_if(!MMUTIL_STRING_VALID(file_path) && (!buffer || !src_size), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid parameter");
- mm_util_retvm_if(_decoded->color != MM_UTIL_COLOR_RGBA, MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT, "not supported color [%d]", _decoded->color);
-
- mm_util_fenter();
-
- /* header of bmp image is create at 'bmp' */
- if ((bmp = bmp_create(_decoded->width, _decoded->height, BYTES_PER_PIXEL * 8)) == NULL) {
- mm_util_error("Invalid depth value.");
- return MM_UTIL_ERROR_INVALID_OPERATION;
- }
-
- /* pixcels of bmp image is stored at 'bmp' */
- image = (uint8_t *) _decoded->data;
- for (row = 0; row != _decoded->height; row++) {
- for (col = 0; col != _decoded->width; col++) {
- size_t z = (row * _decoded->width + col) * BYTES_PER_PIXEL;
- pixel.red = image[z];
- pixel.green = image[z + 1];
- pixel.blue = image[z + 2];
- bmp_set_pixel(bmp, col, row, pixel);
- }
- }
-
- /* write 'bmp' to file or buffer */
- if (MMUTIL_STRING_VALID(file_path)) {
- mm_util_sec_debug("Save to file [%s]", file_path);
- if (!bmp_save(bmp, file_path)) {
- mm_util_error("Saving bmp was failed.");
- bmp_destroy(bmp);
- return MM_UTIL_ERROR_INVALID_OPERATION;
- }
- } else {
- mm_util_sec_debug("Save to buffer");
- if (!bmp_save2(bmp, buffer, src_size)) {
- mm_util_error("Saving bmp was failed.");
- bmp_destroy(bmp);
- MMUTIL_SAFE_FREE(*buffer);
- *src_size = 0;
- return MM_UTIL_ERROR_INVALID_OPERATION;
- }
- }
-
- bmp_destroy(bmp);
-
- mm_util_fleave();
-
- return MM_UTIL_ERROR_NONE;
-}
int mm_util_decode_from_bmp_file(const char *file_path, mm_util_image_h *decoded)
{
int mm_util_encode_bmp_to_file(mm_util_image_h decoded, const char *file_path)
{
- mm_util_retvm_if(!MMUTIL_STRING_VALID(file_path), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid file_path");
-
- return __write_bmp(decoded, file_path, NULL, NULL);
+ return mm_util_encode_image_to_file(decoded, file_path);
}
int mm_util_encode_bmp_to_memory(mm_util_image_h decoded, void **buffer, size_t *size)
{
- mm_util_retvm_if(!buffer, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid buffer");
- mm_util_retvm_if(!size, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid size");
-
- return __write_bmp(decoded, NULL, buffer, size);
+ return mm_util_encode_image_to_buffer(decoded, IMG_CODEC_BMP, buffer, size);
}
*/
#include <stdbool.h>
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <unistd.h>
+
#include <magick/api.h>
+
#include "mm_util_private.h"
#include "mm_util_magick.h"
return FALSE;
}
+static int __mm_util_make_tmp_file(mm_util_img_codec_type type, char **path)
+{
+ int fd = 0;
+ const char *template = NULL;
+ GError *error = NULL;
+
+ /* GraphicsMagick determine image codec from filename suffix */
+ switch(type) {
+ case IMG_CODEC_GIF:
+ template = "XXXXXX.gif";
+ break;
+ case IMG_CODEC_PNG:
+ template = "XXXXXX.png";
+ break;
+ case IMG_CODEC_JPEG:
+ template = "XXXXXX.jpg";
+ break;
+ case IMG_CODEC_BMP:
+ template = "XXXXXX.bmp";
+ break;
+ default:
+ mm_util_error("invalid type [%u]", type);
+ return MM_UTIL_ERROR_INVALID_PARAMETER;
+ }
+
+ fd = g_file_open_tmp(template, path, &error);
+ if (fd < 0) {
+ mm_util_sec_debug("g_file_open_tmp error [%s]", error->message);
+ g_free(error);
+ return MM_UTIL_ERROR_INVALID_OPERATION;
+ }
+
+ mm_util_sec_debug("g_file_open_tmp [%s]", *path);
+
+ close(fd);
+
+ return MM_UTIL_ERROR_NONE;
+}
+
+static int __mm_util_read_tmp_file(const char *path, void **data, size_t *length)
+{
+ int ret = MM_UTIL_ERROR_NONE;
+ FILE *fp = NULL;
+ char *_data = NULL;
+ long _length = 0;
+
+ mm_util_retvm_if(!path, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid path");
+ mm_util_retvm_if(!data, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid data");
+ mm_util_retvm_if(!length, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid length");
+
+ mm_util_sec_debug("read path [%s]", path);
+
+ fp = fopen(path, "r");
+ if (!fp) {
+ mm_util_stderror("fopen failed");
+ return MM_UTIL_ERROR_INVALID_OPERATION;
+ }
+
+ if (fseek(fp, 0, SEEK_END) < 0) {
+ mm_util_stderror("fseek failed");
+ ret = MM_UTIL_ERROR_INVALID_OPERATION;
+ goto ERROR;
+ }
+
+ _length = ftell(fp);
+ if (_length < 0) {
+ mm_util_stderror("ftell failed");
+ ret = MM_UTIL_ERROR_INVALID_OPERATION;
+ goto ERROR;
+ }
+
+ rewind(fp);
+ _data = (void *)calloc(1, _length);
+ if (!_data) {
+ mm_util_stderror("calloc failed");
+ ret = MM_UTIL_ERROR_OUT_OF_MEMORY;
+ goto ERROR;
+ }
+
+ if (fread(_data, 1, _length, fp) != _length) {
+ mm_util_stderror("fread failed");
+ ret = MM_UTIL_ERROR_INVALID_OPERATION;
+ MMUTIL_SAFE_FREE(_data);
+ goto ERROR;
+ }
+
+ *data = _data;
+ *length = (size_t)_length;
+
+ERROR:
+
+ fclose(fp);
+
+ return ret;
+}
+
int mm_util_rotate_B_B(mm_util_image_h src_handle, mm_util_magick_rotate_type angle, mm_util_image_h *dst_handle)
{
int ret = MM_UTIL_ERROR_NONE;
goto ERROR;
}
- ret = mm_image_create_image(_image->columns, _image->rows, _src_handle->color, pixels, pixels_size, dst_handle);
+ ret = mm_image_create_image(_image->columns, _image->rows, req_format, pixels, pixels_size, dst_handle);
if (ret != MM_UTIL_ERROR_NONE)
mm_util_error("Error: mm_image_create_image failed.");
return ret;
}
+
+int mm_util_encode_image_to_file(mm_util_image_h decoded_image, const char *path)
+{
+ int ret = MM_UTIL_ERROR_NONE;
+ char *extension = NULL;
+ char *map = NULL;
+ Image *_image = NULL;
+ mm_image_info_s *convert_image = NULL;
+ mm_util_color_format_e format;
+
+ mm_util_retvm_if(!decoded_image, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid decoded_image");
+ mm_util_retvm_if(!MMUTIL_STRING_VALID(path), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid path");
+
+ mm_util_sec_debug("path [%s]", path);
+
+ extension = g_strrstr(path, ".");
+ mm_util_retvm_if(!MMUTIL_STRING_VALID(extension), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid path");
+
+ if (g_ascii_strcasecmp(extension, ".bmp") == 0) {
+ /*
+ GraphicsMagick doesn't support alpha overlay(compression method:BI_ALPHABITFIELDS) for bmp.
+ Officialy BMP format supports alpha overlay since BMP4(version 4), but GraphicsMagick
+ support BMP, BMP2(v2) and BMP3(v3) except BMP4.
+ So decoded_image should be converted to RGB888(RGB24) which has not alpha overlay.
+ ps. BMP4 image does not guarantee backward compatibility. BMP4 is not visible on old devices.
+ For the reasons, BMP4 is used in certain cases of windows OS, not widely used in general cases.
+ */
+
+ if (((mm_image_info_s *)decoded_image)->color == MM_UTIL_COLOR_RGBA) {
+ ret = mm_util_convert_B_B(decoded_image, MM_UTIL_COLOR_RGB24, (mm_util_image_h *)&convert_image);
+ if (ret != MM_UTIL_ERROR_NONE) {
+ mm_util_error("Error: mm_util_convert_B_B failed.");
+ goto ERROR;
+ }
+ }
+ }
+
+ format = (convert_image) ? (convert_image->color) : (((mm_image_info_s *)decoded_image)->color);
+ ret = __mm_util_get_map(format, &map);
+ if (ret != MM_UTIL_ERROR_NONE) {
+ mm_util_error("fail to get map");
+ goto ERROR;
+ }
+
+ __mm_util_init(NULL);
+
+ _image = __mm_util_constitute_image((convert_image ? convert_image : decoded_image), map);
+ if (_image == NULL) {
+ mm_util_error("Error: __mm_util_constitute_image failed.");
+ ret = MM_UTIL_ERROR_INVALID_OPERATION;
+ goto ERROR;
+ }
+
+ ret = __mm_util_write_image_to_file(_image, path);
+
+ERROR:
+
+ __mm_util_finalize(_image, NULL, NULL);
+
+ MMUTIL_SAFE_FREE(map);
+ mm_image_destroy_image((mm_util_image_h)convert_image);
+
+ mm_util_fleave();
+
+ return ret;
+}
+
+int mm_util_encode_image_to_buffer(mm_util_image_h decoded_image, mm_util_img_codec_type type, void **buf, size_t *buf_size)
+{
+ int ret = MM_UTIL_ERROR_NONE;
+ char *tmp_file = NULL;
+
+ mm_util_retvm_if(!decoded_image, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid decoded_image");
+ mm_util_retvm_if(!buf, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid buf");
+ mm_util_retvm_if(buf_size == 0, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid buf_size");
+
+ mm_util_sec_debug("type [%d]", type);
+
+ ret = __mm_util_make_tmp_file(type, &tmp_file);
+ mm_util_retvm_if(ret != MM_UTIL_ERROR_NONE, ret, "Error: __mm_util_make_tmp_file failed.");
+
+ ret = mm_util_encode_image_to_file(decoded_image, tmp_file);
+ if (ret != MM_UTIL_ERROR_NONE) {
+ mm_util_error("Error: mm_util_encode_image_P failed.");
+ goto ERROR;
+ }
+
+ ret = __mm_util_read_tmp_file(tmp_file, buf, buf_size);
+ if (ret != MM_UTIL_ERROR_NONE)
+ mm_util_error("Error: __mm_util_read_tmp_file failed.");
+
+ERROR:
+
+ if (g_remove(tmp_file) != 0)
+ mm_util_sec_debug("Temporary file was not removed [%s]", tmp_file);
+ MMUTIL_SAFE_FREE(tmp_file);
+
+ mm_util_fleave();
+
+ return ret;
+}