]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-11921: [core] add switch_img_data_url_png
authorAnthony Minessale <anthm@freeswitch.org>
Mon, 4 Mar 2019 18:39:20 +0000 (18:39 +0000)
committerAndrey Volk <andywolk@gmail.com>
Wed, 17 Jul 2019 20:50:48 +0000 (00:50 +0400)
src/include/switch_core_video.h
src/switch_core_video.c
tests/unit/Makefile.am
tests/unit/switch_core_video.c [new file with mode: 0644]

index 8998d0bac5cfd8a3098c2aed597fbeb1ac2bece0..e152922675a53bb6c6c7dc15817ae8e96fed995b 100644 (file)
@@ -393,7 +393,8 @@ SWITCH_DECLARE(switch_image_t *) switch_img_read_png(const char *file_name, swit
 SWITCH_DECLARE(switch_status_t) switch_img_write_png(switch_image_t *img, char *file_name);
 SWITCH_DECLARE(switch_status_t) switch_png_open(switch_png_t **pngP, const char *file_name);
 SWITCH_DECLARE(void) switch_png_free(switch_png_t **pngP);
-
+SWITCH_DECLARE(switch_status_t) switch_img_data_url_png(switch_image_t *img, char **urlP);
+                                                                                                                               
 /*!\brief put a small img over a big IMG at position x,y, with alpha transparency
 *
 * Both IMG and img must be non-NULL
index ba9d18e9e79a2cb9aab13b7352cf79d929fe8452..54851cf8aacc9127be6037e838752cf1483d0048 100644 (file)
@@ -578,6 +578,7 @@ SWITCH_DECLARE(void) switch_img_copy(switch_image_t *img, switch_image_t **new_i
        if (img->fmt != SWITCH_IMG_FMT_I420 && img->fmt != SWITCH_IMG_FMT_ARGB) return;
 
        if (*new_img) {
+               new_fmt = (*new_img)->fmt;
                if ((*new_img)->fmt != SWITCH_IMG_FMT_I420 && (*new_img)->fmt != SWITCH_IMG_FMT_ARGB) return;
                if (img->d_w != (*new_img)->d_w || img->d_h != (*new_img)->d_h ) {
                        new_fmt = (*new_img)->fmt;
@@ -2731,6 +2732,149 @@ end:
 
 #endif
 
+static void my_png_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+       switch_buffer_t *data_buffer = (switch_buffer_t *)png_get_io_ptr(png_ptr);
+       switch_buffer_write(data_buffer, data, length);
+}
+
+static void my_png_flush(png_structp png_ptr)
+{
+}
+
+SWITCH_DECLARE(switch_status_t) switch_img_data_url_png(switch_image_t *img, char **urlP)
+{
+       int width, height;
+       png_byte color_type;
+       png_byte bit_depth;
+       png_structp png_ptr;
+       png_infop info_ptr;
+       png_bytep *row_pointers = NULL;
+       int row_bytes;
+       int y;
+       png_byte *buffer = NULL;
+       switch_status_t status = SWITCH_STATUS_FALSE;
+       switch_buffer_t *data_buffer = NULL;
+       unsigned char *head;
+
+       width = img->d_w;
+       height = img->d_h;
+       bit_depth = 8;
+       color_type = PNG_COLOR_TYPE_RGB;
+
+       if (img->fmt == SWITCH_IMG_FMT_ARGB) {
+               color_type = PNG_COLOR_TYPE_RGBA;
+       }
+
+
+       png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+
+       if (!png_ptr) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "png_create_write_struct failed");
+               goto end;
+       }
+
+       info_ptr = png_create_info_struct(png_ptr);
+       if (!info_ptr) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "png_create_info_struct failed");
+               goto end;
+       }
+       
+       if (setjmp(png_jmpbuf(png_ptr))) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error during init_io");
+               goto end;
+       }
+
+       switch_buffer_create_dynamic(&data_buffer, 1024, 1024, 0);
+       png_set_write_fn(png_ptr, data_buffer, my_png_write_data, my_png_flush);
+       //png_init_io(png_ptr, fp);
+       
+       if (setjmp(png_jmpbuf(png_ptr))) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error during writing header");
+               goto end;
+       }
+
+       png_set_IHDR(png_ptr, info_ptr, width, height,
+                                bit_depth, color_type, PNG_INTERLACE_NONE,
+                                PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+
+       png_write_info(png_ptr, info_ptr);
+
+       row_bytes = png_get_rowbytes(png_ptr, info_ptr);
+       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "size: %dx%d row_bytes:%d color_type:%d bit_dept:%d\n", width, height, row_bytes, color_type, bit_depth);
+
+       buffer = (png_byte *)malloc(row_bytes * height);
+       switch_assert(buffer);
+
+       row_pointers = (png_bytep*)malloc(sizeof(png_bytep) * height);
+       switch_assert(row_pointers);
+
+       for (y = 0; y < height; y++) {
+               row_pointers[y] = buffer + row_bytes * y;
+       }
+
+       if (img->fmt == SWITCH_IMG_FMT_I420) {
+               I420ToRAW(  img->planes[SWITCH_PLANE_Y], img->stride[SWITCH_PLANE_Y],
+                                       img->planes[SWITCH_PLANE_U], img->stride[SWITCH_PLANE_U],
+                                       img->planes[SWITCH_PLANE_V], img->stride[SWITCH_PLANE_V],
+                                       buffer, width * 3,
+                                       width, height);
+       } else if (img->fmt == SWITCH_IMG_FMT_ARGB) {
+               ARGBToABGR(img->planes[SWITCH_PLANE_PACKED], img->stride[SWITCH_PLANE_PACKED],
+                       buffer, row_bytes, width, height);
+       }
+
+       if (setjmp(png_jmpbuf(png_ptr))) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error during writing bytes");
+               goto end;
+       }
+
+       //png_set_rows(png_ptr, info_ptr, row_pointers);        
+       //png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);       
+       png_write_image(png_ptr, row_pointers);
+
+       if (setjmp(png_jmpbuf(png_ptr))) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error during end of write");
+               goto end;
+       }
+
+       png_write_end(png_ptr, info_ptr);
+
+       if ((head = (unsigned char *) switch_buffer_get_head_pointer(data_buffer))) {
+               switch_size_t olen = 0, blen = 0;
+               unsigned char *out = NULL;
+               const char *header = "data:image/png;base64,";
+               
+               blen = switch_buffer_len(data_buffer);
+               olen = blen * 4;
+               
+               if (olen > strlen(header) + 1) {
+                       switch_zmalloc(out, olen);
+
+                       switch_snprintf((char *)out, strlen(header) + 1, header);
+                       switch_b64_encode(head, blen, out + strlen(header), olen - strlen(header));
+                       *urlP = (char *)out;
+               } else {
+                       status = SWITCH_STATUS_MEMERR;
+                       goto end;
+               }
+       }
+
+       status = SWITCH_STATUS_SUCCESS;
+
+end:
+
+       if (status != SWITCH_STATUS_SUCCESS) {
+               *urlP = NULL;
+       }
+
+       switch_buffer_destroy(&data_buffer);
+       switch_safe_free(buffer);
+       switch_safe_free(row_pointers);
+       png_destroy_write_struct(&png_ptr, &info_ptr);
+
+       return status;
+}
 
 #ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED /* available from libpng 1.6.0 */
 
@@ -2777,6 +2921,7 @@ SWITCH_DECLARE(switch_status_t) switch_img_write_png(switch_image_t *img, char*
 
 #else
 
+
 SWITCH_DECLARE(switch_status_t) switch_img_write_png(switch_image_t *img, char* file_name)
 {
        int width, height;
@@ -2796,6 +2941,10 @@ SWITCH_DECLARE(switch_status_t) switch_img_write_png(switch_image_t *img, char*
        bit_depth = 8;
        color_type = PNG_COLOR_TYPE_RGB;
 
+       if (img->fmt == SWITCH_IMG_FMT_ARGB) {
+               color_type = PNG_COLOR_TYPE_RGBA;
+       }
+
        fp = fopen(file_name, "wb");
        if (!fp) {
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "File %s could not be opened for writing", file_name);
@@ -2845,15 +2994,15 @@ SWITCH_DECLARE(switch_status_t) switch_img_write_png(switch_image_t *img, char*
                row_pointers[y] = buffer + row_bytes * y;
        }
 
-       I420ToRAW(  img->planes[SWITCH_PLANE_Y], img->stride[SWITCH_PLANE_Y],
-                               img->planes[SWITCH_PLANE_U], img->stride[SWITCH_PLANE_U],
-                               img->planes[SWITCH_PLANE_V], img->stride[SWITCH_PLANE_V],
-                               buffer, width * 3,
-                               width, height);
-
-       for(y = height - 1; y > 0; y--) {
-               // todo, check overlaps
-               memcpy(row_pointers[y], buffer + row_bytes * y, width * 3);
+       if (img->fmt == SWITCH_IMG_FMT_I420) {
+               I420ToRAW(  img->planes[SWITCH_PLANE_Y], img->stride[SWITCH_PLANE_Y],
+                                       img->planes[SWITCH_PLANE_U], img->stride[SWITCH_PLANE_U],
+                                       img->planes[SWITCH_PLANE_V], img->stride[SWITCH_PLANE_V],
+                                       buffer, width * 3,
+                                       width, height);
+       } else if (img->fmt == SWITCH_IMG_FMT_ARGB) {
+               ARGBToABGR(img->planes[SWITCH_PLANE_PACKED], img->stride[SWITCH_PLANE_PACKED],
+                       buffer, row_bytes, width, height);
        }
 
        if (setjmp(png_jmpbuf(png_ptr))) {
index f0d3a06474fa1babaeb1a44ebdce39baf4b6b2c3..dff3fc3662998c2ce13d4bb48eaed7c63b60bd01 100644 (file)
@@ -2,6 +2,7 @@ include $(top_srcdir)/build/modmake.rulesam
 
 bin_PROGRAMS = switch_event switch_hash switch_ivr_originate switch_utils switch_core switch_console switch_vpx \
                           switch_ivr_play_say
+bin_PROGRAMS+= switch_core_video
 AM_LDFLAGS  = -avoid-version -no-undefined $(SWITCH_AM_LDFLAGS) $(openssl_LIBS)
 AM_LDFLAGS += $(FREESWITCH_LIBS) $(switch_builddir)/libfreeswitch.la $(CORE_LIBS) $(APR_LIBS)
 AM_CFLAGS   = $(SWITCH_AM_CPPFLAGS)
diff --git a/tests/unit/switch_core_video.c b/tests/unit/switch_core_video.c
new file mode 100644 (file)
index 0000000..cdd03cb
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005-2018, Anthony Minessale II <anthm@freeswitch.org>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is
+ * Anthony Minessale II <anthm@freeswitch.org>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Chris Rienzo <chris@signalwire.com>
+ * Seven Du <seven@signalwire.com>
+ *
+ *
+ * switch_core_video.c -- tests core_video
+ *
+ */
+#include <switch.h>
+#include <stdlib.h>
+
+#include <test/switch_test.h>
+
+FST_CORE_BEGIN("./conf")
+{
+       FST_SUITE_BEGIN(switch_ivr_originate)
+       {
+               FST_SETUP_BEGIN()
+               {
+               }
+               FST_SETUP_END()
+
+               FST_TEARDOWN_BEGIN()
+               {
+               }
+               FST_TEARDOWN_END()
+
+               FST_TEST_BEGIN(data_url_test)
+               {
+                       switch_image_t *img = switch_img_alloc(NULL, SWITCH_IMG_FMT_I420, 120, 60, 1);
+                       switch_image_t *argb_img = switch_img_alloc(NULL, SWITCH_IMG_FMT_ARGB, 120, 60, 1);
+                       switch_rgb_color_t color = { 0 };
+                       color.r = 255;
+                       // color.g = 255;
+                       // color.b = 255;
+                       char *data_url = NULL;
+
+                       switch_img_fill(img, 0, 0, img->d_w, img->d_h, &color);
+                       switch_img_add_text(img->planes[0], img->d_w, 10, 10, "-1234567890");
+                       switch_img_write_png(img, "test-rgb.png");
+
+                       switch_img_data_url_png(img, &data_url);
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "I420: %s\n", data_url);
+                       free(data_url);
+                       data_url = NULL;
+
+                       switch_img_copy(img, &argb_img);
+
+                       {
+                               uint8_t *p = argb_img->planes[0];
+                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%d %d %d %d\n", *p, *(p+1), *(p+2), *(p+3));
+                       }
+
+                       switch_img_write_png(argb_img, "test-argb.png");
+                       switch_img_data_url_png(argb_img, &data_url);
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "ARGB: %s\n", data_url);
+                       free(data_url);
+
+
+                       switch_img_free(&img);
+                       switch_img_free(&argb_img);
+               }
+               FST_TEST_END()
+       }
+       FST_SUITE_END()
+}
+FST_CORE_END()