Add to support saving encoded bmp to buffer 62/132262/4 accepted/tizen_4.0_unified tizen_4.0 tizen_4.0_tv accepted/tizen/4.0/unified/20170816.011755 accepted/tizen/4.0/unified/20170828.222848 accepted/tizen/unified/20170605.151256 submit/tizen/20170605.022235 submit/tizen_4.0/20170811.094300 submit/tizen_4.0/20170828.100006 tizen_4.0.IoT.p1_release tizen_4.0.IoT.p2_release tizen_4.0.m2_release
authorJiyong Min <jiyong.min@samsung.com>
Fri, 2 Jun 2017 03:23:22 +0000 (12:23 +0900)
committerJiyong Min <jiyong.min@samsung.com>
Fri, 2 Jun 2017 03:37:36 +0000 (12:37 +0900)
Image-Util can not save encoded bmp to buffer

Change-Id: I130266b2841bb062ad7f18c9166e01dc67366c06
Signed-off-by: Jiyong Min <jiyong.min@samsung.com>
src/bmpfile.c [changed mode: 0644->0755]
src/bmpfile.h [changed mode: 0644->0755]

old mode 100644 (file)
new mode 100755 (executable)
index 4fb18f4..da264cf
@@ -708,3 +708,226 @@ bmp_save(bmpfile_t *bmp, const char *filename)
 
   return TRUE;
 }
+
+#define BMP_SAFE_FREE(x)       { if (x != NULL) { free(x); x = NULL; } }
+#define bmp_retm_if(expr, val) do { \
+                        if (expr) { \
+                                BMP_SAFE_FREE(val); \
+                                return; \
+                        } \
+                } while (0)
+
+#define bmp_retvm_if(expr, val, retv) do { \
+                        if (expr) { \
+                                BMP_SAFE_FREE(val); \
+                                return retv; \
+                        } \
+                } while (0)
+
+static uint16_t
+bmp_write_to_buffer(void *src, unsigned char **dst, size_t *size, size_t *offset, size_t len)
+{
+  if (src == NULL || len <= 0)
+    return -1;
+
+  *size += len;
+  if ((*offset + len) > *size)
+    return -1;
+
+  if (*dst == NULL)
+    *dst = (unsigned char *)calloc(1, *size);
+  else
+    *dst = (unsigned char *)realloc(*dst, *size);
+
+  if (*dst == NULL)
+    return -1;
+
+  memcpy(*dst + *offset, src, len);
+  *offset += len;
+
+  return len;
+}
+
+static void
+bmp_write_header2(bmpfile_t *bmp, unsigned char **ptr, size_t *size)
+{
+  uint16_t ret;
+  size_t offset = *size;
+  bmp_header_t header = bmp->header;
+
+  if (_is_big_endian()) bmp_header_swap_endianess(&header);
+
+  ret = bmp_write_to_buffer(header.magic, ptr, size, &offset, sizeof(header.magic));
+  bmp_retm_if(ret < 0, *ptr);
+  ret = bmp_write_to_buffer(&(header.filesz), ptr, size, &offset, sizeof(uint32_t));
+  bmp_retm_if(ret < 0, *ptr);
+  ret = bmp_write_to_buffer(&(header.creator1), ptr, size, &offset, sizeof(uint16_t));
+  bmp_retm_if(ret < 0, *ptr);
+  ret = bmp_write_to_buffer(&(header.creator2), ptr, size, &offset, sizeof(uint16_t));
+  bmp_retm_if(ret < 0, *ptr);
+  ret = bmp_write_to_buffer(&(header.offset), ptr, size, &offset, sizeof(uint32_t));
+  bmp_retm_if(ret < 0, *ptr);
+}
+
+static void
+bmp_write_dib2(bmpfile_t *bmp, unsigned char **ptr, size_t *size)
+{
+  uint16_t ret;
+  size_t offset = *size;
+  bmp_dib_v3_header_t dib = bmp->dib;
+
+  if (*ptr == NULL)
+    return;
+
+  if (_is_big_endian()) bmp_dib_v3_header_swap_endianess(&dib);
+
+  ret = bmp_write_to_buffer(&(dib), ptr, size, &offset, sizeof(bmp_dib_v3_header_t));
+  bmp_retm_if(ret < 0, *ptr);
+}
+
+static void
+bmp_write_palette2(bmpfile_t *bmp, unsigned char **ptr, size_t *size)
+{
+  uint16_t ret;
+  size_t offset = *size;
+
+  if (*ptr == NULL)
+    return;
+
+  if (bmp->dib.depth == 1 || bmp->dib.depth == 4 || bmp->dib.depth == 8) {
+    int i;
+    for (i = 0; i < bmp->dib.ncolors; ++i) {
+      ret = bmp_write_to_buffer(&(bmp->colors[i]), ptr, size, &offset, sizeof(rgb_pixel_t));
+      bmp_retm_if(ret < 0, *ptr);
+    }
+  }
+  else if (bmp->dib.depth == 16) { /* the bit masks, not palette */
+    uint16_t red_mask = 63488;  /* bits 1-5 */
+    uint16_t green_mask = 2016; /* bits 6-11 */
+    uint16_t blue_mask = 31;    /* bits 12-16 */
+    uint16_t zero_word = 0;
+
+    if (_is_big_endian()) {
+      red_mask = UINT16_SWAP_LE_BE_CONSTANT(red_mask);
+      green_mask = UINT16_SWAP_LE_BE_CONSTANT(green_mask);
+      blue_mask = UINT16_SWAP_LE_BE_CONSTANT(blue_mask);
+    }
+
+    ret = bmp_write_to_buffer(&red_mask, ptr, size, &offset, sizeof(uint16_t));
+    bmp_retm_if(ret < 0, *ptr);
+    ret = bmp_write_to_buffer(&zero_word, ptr, size, &offset, sizeof(uint16_t));
+    bmp_retm_if(ret < 0, *ptr);
+
+    ret = bmp_write_to_buffer(&green_mask, ptr, size, &offset, sizeof(uint16_t));
+    bmp_retm_if(ret < 0, *ptr);
+    ret = bmp_write_to_buffer(&zero_word, ptr, size, &offset, sizeof(uint16_t));
+    bmp_retm_if(ret < 0, *ptr);
+
+    ret = bmp_write_to_buffer(&blue_mask, ptr, size, &offset, sizeof(uint16_t));
+    bmp_retm_if(ret < 0, *ptr);
+    ret = bmp_write_to_buffer(&zero_word, ptr, size, &offset, sizeof(uint16_t));
+    bmp_retm_if(ret < 0, *ptr);
+  }
+}
+
+
+bool
+bmp_save2(bmpfile_t *bmp, void **buffer, size_t *size)
+{
+  int row;
+  unsigned char *buf;
+  unsigned char *ptr = NULL;
+  size_t osize = 0, offset = 0;
+  uint16_t ret;
+
+  /* Write bmp to buffer */
+  bmp_write_header2(bmp, &ptr, &osize);
+  bmp_write_dib2(bmp, &ptr, &osize);
+  bmp_write_palette2(bmp, &ptr, &osize);
+
+  if (ptr == NULL) {
+    *size = 0;
+    return FALSE;
+  }
+  offset = osize;
+
+  if (bmp->dib.depth == 16) {
+    uint32_t data_bytes = bmp->dib.width * 2;
+    uint32_t padding_bytes = 4 - data_bytes % 4;
+
+    for (row = bmp->dib.height - 1; row >= 0; --row) {
+      int i;
+      unsigned char zero_byte = 0;
+      uint32_t write_number = 0;
+
+      for (i = 0; write_number < data_bytes; ++i, write_number += 2) {
+        uint16_t red = (uint16_t)(bmp->pixels[i][row].red / 8);
+        uint16_t green = (uint16_t)(bmp->pixels[i][row].green / 4);
+        uint16_t blue = (uint16_t)(bmp->pixels[i][row].blue / 8);
+        uint16_t value = (red << 11) + (green << 5) + blue;
+
+        if (_is_big_endian()) value = UINT16_SWAP_LE_BE_CONSTANT(value);
+
+        ret = bmp_write_to_buffer(&value, &ptr, &osize, &offset, sizeof(uint16_t));
+        bmp_retvm_if(ret < 0, ptr, FALSE);
+      }
+
+      for (write_number = 0; write_number < padding_bytes; ++write_number) {
+        ret = bmp_write_to_buffer(&zero_byte, &ptr, &osize, &offset, 1);
+        bmp_retvm_if(ret < 0, ptr, FALSE);
+      }
+    }
+  }
+  else {
+    double bytes_per_pixel;
+    int bytes_per_line;
+
+    bytes_per_pixel = (bmp->dib.depth * 1.0) / 8.0;
+    bytes_per_line = (int)ceil(bytes_per_pixel * bmp->dib.width);
+    if (bytes_per_line % 4 != 0)
+      bytes_per_line += 4 - bytes_per_line % 4;
+
+    buf = malloc(bytes_per_line);
+
+    for (row = bmp->dib.height - 1; row >= 0; --row) {
+      memset(buf, 0, bytes_per_line);
+
+      switch (bmp->dib.depth) {
+      case 1:
+        bmp_get_row_data_for_1(bmp, buf, bytes_per_line, row);
+        break;
+
+      case 4:
+        bmp_get_row_data_for_4(bmp, buf, bytes_per_line, row);
+        break;
+
+      case 8:
+        bmp_get_row_data_for_8(bmp, buf, bytes_per_line, row);
+        break;
+
+      case 24:
+        bmp_get_row_data_for_24(bmp, buf, bytes_per_line, row);
+        break;
+
+      case 32:
+        bmp_get_row_data_for_32(bmp, buf, bytes_per_line, row);
+        break;
+      }
+
+      ret = bmp_write_to_buffer(buf, &ptr, &osize, &offset, bytes_per_line);
+      if (ret < 0) {
+        free(buf);
+        BMP_SAFE_FREE(ptr);
+        *size = 0;
+        return FALSE;
+      }
+    }
+    free(buf);
+  }
+
+  *buffer = (void *)ptr;
+  *size = osize;
+
+  return TRUE;
+}
+
old mode 100644 (file)
new mode 100755 (executable)
index ef537fa..b3641d3
@@ -135,6 +135,7 @@ rgb_pixel_t *bmp_get_pixel(bmpfile_t *bmp, uint32_t x, uint32_t y);
 bool bmp_set_pixel(bmpfile_t *bmp, uint32_t x, uint32_t y, rgb_pixel_t pixel);
 
 bool bmp_save(bmpfile_t *bmp, const char *filename);
+bool bmp_save2(bmpfile_t *bmp, void **buffer, size_t *size);
 
 BMP_END_DECLS