]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-7500: refactor and implemnt patch_rect
authorSeven Du <dujinfang@gmail.com>
Wed, 22 Apr 2015 03:49:41 +0000 (11:49 +0800)
committerMichael Jerris <mike@jerris.com>
Thu, 28 May 2015 17:47:23 +0000 (12:47 -0500)
fix stride side when patching strided img
implement switch_img_patch_rect to patch partial of an img to a bigger IMG
refactor switch_img_copy_rect to support ARGB

src/include/switch_core_video.h
src/switch_core_video.c

index ce2476761e01a09005c3830b37af76edc46ba4c3..bbe1b6e1f3b46c5c41c775aeec7401a4309886c5 100644 (file)
@@ -140,7 +140,7 @@ SWITCH_DECLARE(switch_image_t *)switch_img_wrap(switch_image_t  *img,
                                                unsigned int d_w,
                                                unsigned int d_h,
                                                unsigned int align,
-                                               unsigned char      *img_data);
+                                               unsigned char *img_data);
 
 
 /*!\brief Set the rectangle identifying the displayed portion of the image
@@ -162,9 +162,34 @@ SWITCH_DECLARE(int) switch_img_set_rect(switch_image_t  *img,
                                   unsigned int  w,
                                   unsigned int  h);
 
-
+/*!\brief patch a small img to a big IMG at position x,y
+*
+* Both IMG and img must be non-NULL
+*
+* \param[in]    IMG       The BIG Image descriptor
+* \param[in]    img       The small Image descriptor
+* \param[in]    x         Leftmost pos to patch to
+* \param[in]    y         Topmost pos to patch to
+*/
 SWITCH_DECLARE(void) switch_img_patch(switch_image_t *IMG, switch_image_t *img, int x, int y);
 
+
+/*!\brief patch part of a small img (x,y,w,h) to a big IMG at position X,Y
+*
+* Both IMG and img must be non-NULL
+*
+* \param[in]    IMG       The BIG Image descriptor
+* \param[in]    X         Leftmost pos to patch to IMG
+* \param[in]    Y         Topmost pos to patch to IMG
+* \param[in]    img       The small Image descriptor
+* \param[in]    x         Leftmost pos to be read from img
+* \param[in]    y         Topmost pos to be read from
+* \param[in]    w         Max width to be read from img
+* \param[in]    h         Max height to be read from img
+*/
+
+SWITCH_DECLARE(void) switch_img_patch_rect(switch_image_t *IMG, int X, int Y, switch_image_t *img, uint32_t x, uint32_t y, uint32_t w, uint32_t h);
+
 /*!\brief Copy image to a new image
 *
 * if new_img is NULL, a new image is allocated
@@ -173,6 +198,7 @@ SWITCH_DECLARE(void) switch_img_patch(switch_image_t *IMG, switch_image_t *img,
 * else, copy the img data to the new_img
 *
 * \param[in]    img       Image descriptor
+* \param[out]   new_img   New Image descriptor, NULL if out of memory
 */
 
 SWITCH_DECLARE(void) switch_img_copy(switch_image_t *img, switch_image_t **new_img);
@@ -184,6 +210,8 @@ SWITCH_DECLARE(void) switch_img_copy(switch_image_t *img, switch_image_t **new_i
 * be referenced upside-down.
 *
 * \param[in]    img       Image descriptor
+*
+* \return 0 if the requested rectangle is valid, nonzero otherwise.
 */
 SWITCH_DECLARE(void) switch_img_flip(switch_image_t *img);
 
@@ -199,22 +227,104 @@ SWITCH_DECLARE(void) switch_img_draw_text(switch_image_t *IMG, int x, int y, swi
 
 SWITCH_DECLARE(void) switch_img_add_text(void *buffer, int w, int x, int y, char *s);
 
-SWITCH_DECLARE(switch_image_t *) switch_img_copy_rect(switch_image_t *img, int x, int y, int w, int h);
+/*!\brief Copy part of an image to a new image
+*
+*
+* \param[in]    img       Image descriptor
+* \param[in]    x         Leftmost pos to be read from
+* \param[in]    y         Topmost pos to be read from
+* \param[in]    w         Max width to be read from
+* \param[in]    h         Max height to be read from
+*
+* \return NULL if failed to copy, otherwise a valid image descriptor.
+*/
+SWITCH_DECLARE(switch_image_t *) switch_img_copy_rect(switch_image_t *img, uint32_t x, uint32_t y, uint32_t w, uint32_t h);
 
+/*!\brief Fill image with color
+*
+* \param[in]    img       Image descriptor
+* \param[in]    x         Leftmost pos to be read from
+* \param[in]    y         Topmost pos to be read from
+* \param[in]    w         Max width to be read from
+* \param[in]    h         Max height to be read from
+* \param[in]    color     RGB color
+*/
 SWITCH_DECLARE(void) switch_img_fill(switch_image_t *img, int x, int y, int w, int h, switch_rgb_color_t *color);
 
+/*!\brief Draw a pixel on an image
+*
+* \param[in]    img       Image descriptor
+* \param[in]    x         leftmost pos
+* \param[in]    y         topmost pos
+* \param[in]    color     YUV color
+*/
 SWITCH_DECLARE(void) switch_img_draw_pixel(switch_image_t *img, int x, int y, switch_yuv_color_t *color);
 
+/*!\brief Set RGB color with a string
+*
+* Color string should be in #RRGGBB format
+*
+* \param[out]   color     RGB color pointer
+* \param[in]    color_str Color string in #RRGGBB format
+*/
 SWITCH_DECLARE(void) switch_color_set_rgb(switch_rgb_color_t *color, const char *color_str);
+
+/*!\brief Set YUV color with a string
+*
+* Color string should be in #RRGGBB format
+*
+* \param[out]   color     YUV color pointer
+* \param[in]    color_str Color string in #RRGGBB format
+*/
 SWITCH_DECLARE(void) switch_color_set_yuv(switch_yuv_color_t *color, const char *color_str);
+
+/*!\brief Convert RGB color to YUV
+*
+* \param[in]    rgb       RGB color pointer
+* \param[out]   yuv       YUV color pointer
+*/
 SWITCH_DECLARE(void) switch_color_rgb2yuv(switch_rgb_color_t *rgb, switch_yuv_color_t *yuv);
+
+/*!\brief Convert YUV color to RGB
+*
+* \param[in]    yuv       YUV color pointer
+* \param[out]   rgb       RGB color pointer
+*/
 SWITCH_DECLARE(void) switch_color_yuv2rgb(switch_yuv_color_t *yuv, switch_rgb_color_t *rgb);
 
+/*!\brief Created a text handle
+*
+* \param[out]   handleP     Pointer to the text handle pointer
+* \param[in]    font_family Font family
+* \param[in]    font_color  Font color in #RRGGBB format
+* \param[in]    bgcolor     Background color in #RRGGBB format
+* \param[in]    font_size   Font size in point
+* \param[in]    angle       Angle to rotate
+* \param[in]    pool        APR memory pool
+*/
 SWITCH_DECLARE(switch_status_t) switch_img_txt_handle_create(switch_img_txt_handle_t **handleP, const char *font_family,
                                                                                                                         const char *font_color, const char *bgcolor, uint16_t font_size, double angle, switch_memory_pool_t *pool);
 
+/*!\brief Free a text handle
+*
+* \param[in]   handleP     Pointer to the text handle pointer
+*/
 SWITCH_DECLARE(void) switch_img_txt_handle_destroy(switch_img_txt_handle_t **handleP);
 
+/*!\brief Render text to an img
+*
+* \param[in]    handle      Pointer to the text handle pointer
+* \param[in]    img         The image to be render text on
+* \param[in]    x           Leftmost position
+* \param[in]    y           Topmost position
+* \param[in]    text        Text to render
+* \param[in]    font_family Font to use, NULL to use the handle font
+* \param[in]    font_color  Font color, NULL to use the handle color
+* \param[in]    bgcolor     Background color, NULL for transparency
+* \param[in]    font_size   Font size in point
+* \param[in]    angle       Angle to rotate
+*/
+
 SWITCH_DECLARE(switch_status_t) switch_img_txt_handle_render(switch_img_txt_handle_t *handle, switch_image_t *img,
                                                                                                                         int x, int y, const char *text,
                                                                                                                         const char *font_family, const char *font_color, const char *bgcolor, uint16_t font_size, double angle);
@@ -232,6 +342,16 @@ SWITCH_DECLARE(void) switch_img_get_yuv_pixel(switch_image_t *img, switch_yuv_co
 
 SWITCH_DECLARE(void) switch_img_get_rgb_pixel(switch_image_t *img, switch_rgb_color_t *rgb, int x, int y);
 
+/*!\brief put a small img over a big IMG at position x,y, with alpha transparency
+*
+* Both IMG and img must be non-NULL
+*
+* \param[in]    IMG       The BIG Image descriptor
+* \param[in]    img       The small Image descriptor
+* \param[in]    x         Leftmost pos
+* \param[in]    y         Topmost pos
+* \param[in]    alpha     Alaha value from 0(completely transparent) to 255(opaque)
+*/
 SWITCH_DECLARE(void) switch_img_overlay(switch_image_t *IMG, switch_image_t *img, int x, int y, uint8_t alpha);
 
 SWITCH_DECLARE(switch_status_t) switch_img_scale(switch_image_t *src, switch_image_t **destP, int width, int height);
index 7f63b675eebd7c70fef11939bb911d949ca6b4ee..fa305bc3eb418865d458810de59c8647e29f7e7f 100644 (file)
@@ -121,7 +121,6 @@ SWITCH_DECLARE(void) switch_img_free(switch_image_t **img)
 #define MAX(a,b) ((a) > (b) ? (a) : (b))
 #endif
 
-// simple implementation to patch a small img to a big IMG at position x,y
 SWITCH_DECLARE(void) switch_img_patch(switch_image_t *IMG, switch_image_t *img, int x, int y)
 {
        int i, len, max_h;
@@ -139,11 +138,11 @@ SWITCH_DECLARE(void) switch_img_patch(switch_image_t *IMG, switch_image_t *img,
 
                for (i = 0; i < max_h; i++) {
                        for (j = 0; j < max_w; j++) {
-                               alpha = img->planes[SWITCH_PLANE_PACKED][i * img->d_w * 4 + j * 4];
+                               alpha = img->planes[SWITCH_PLANE_PACKED][i * img->stride[SWITCH_PLANE_PACKED] + j * 4];
                                // printf("%d, %d alpha: %d\n", j, i, alpha);
 
                                if (alpha > 127) { // todo: mux alpha with the underlying pixel ?
-                                       rgb_color = (switch_rgb_color_t *)(img->planes[SWITCH_PLANE_PACKED] + i * img->d_w * 4 + j * 4 + 1);
+                                       rgb_color = (switch_rgb_color_t *)(img->planes[SWITCH_PLANE_PACKED] + i * img->stride[SWITCH_PLANE_PACKED] + j * 4 + 1);
                                        switch_color_rgb2yuv(rgb_color, &yuv_color);
                                        switch_img_draw_pixel(IMG, x + j, y + i, &yuv_color);
                                }
@@ -185,6 +184,32 @@ SWITCH_DECLARE(void) switch_img_patch(switch_image_t *IMG, switch_image_t *img,
        }
 }
 
+SWITCH_DECLARE(void) switch_img_patch_rect(switch_image_t *IMG, int X, int Y, switch_image_t *img, uint32_t x, uint32_t y, uint32_t w, uint32_t h)
+{
+       switch_image_t *tmp;
+       uint8_t *data;
+
+       if (x >= img->d_w || y >= img->d_h) return;
+
+       if (!(img->fmt & SWITCH_IMG_FMT_PLANAR)) {
+               data = img->planes[SWITCH_PLANE_PACKED];
+       } else {
+               data = img->planes[SWITCH_PLANE_Y];
+       }
+
+       tmp = (switch_image_t *)vpx_img_wrap(NULL, img->fmt, img->d_w, img->d_h, 1, data);
+       if (!tmp) return;
+
+       w = MIN(img->d_w - x, w);
+       h = MIN(img->d_h - y, h);
+
+       if (!switch_img_set_rect(tmp, x, y, w, h)) {
+               switch_img_patch(IMG, tmp, X, Y);
+       }
+
+       switch_img_free(&tmp);
+}
+
 SWITCH_DECLARE(void) switch_img_copy(switch_image_t *img, switch_image_t **new_img)
 {
        int i = 0;
@@ -216,38 +241,53 @@ SWITCH_DECLARE(void) switch_img_copy(switch_image_t *img, switch_image_t **new_i
                        memcpy((*new_img)->planes[SWITCH_PLANE_V] + (*new_img)->stride[SWITCH_PLANE_V] * i, img->planes[SWITCH_PLANE_V] + img->stride[SWITCH_PLANE_V] * i, img->d_w / 2);
                }
        } else if (img->fmt == SWITCH_IMG_FMT_ARGB) {
-               memcpy((*new_img)->planes[SWITCH_PLANE_PACKED], img->planes[SWITCH_PLANE_PACKED], img->d_w * img->d_h * 4);
+               if (img->stride[SWITCH_PLANE_PACKED] == img->d_w * 4 &&
+                       (*new_img)->stride[SWITCH_PLANE_PACKED] == (*new_img)->d_w * 4) { // fast copy
+                       memcpy((*new_img)->planes[SWITCH_PLANE_PACKED], img->planes[SWITCH_PLANE_PACKED], img->d_w * img->d_h * 4);
+               } else if (img->stride[SWITCH_PLANE_PACKED] > img->d_w * 4) {
+                       uint8_t *dst = (*new_img)->planes[SWITCH_PLANE_PACKED];
+                       uint8_t *src = img->planes[SWITCH_PLANE_PACKED];
+                       int i;
+
+                       for (i = 0; i < img->d_h; i++) {
+                               memcpy(dst, src, img->d_w * 4);
+                               dst += (*new_img)->stride[SWITCH_PLANE_PACKED];
+                               src += img->stride[SWITCH_PLANE_PACKED];
+                       }
+               } else { //should not happen
+                       abort();
+               }
        }
 
 }
 
-SWITCH_DECLARE(switch_image_t *) switch_img_copy_rect(switch_image_t *img, int x, int y, int w, int h)
+SWITCH_DECLARE(switch_image_t *) switch_img_copy_rect(switch_image_t *img, uint32_t x, uint32_t y, uint32_t w, uint32_t h)
 {
-       switch_image_t *new_img = NULL;
-       int i = 0;
-       int len;
+       switch_image_t *new_img = NULL, *tmp;
+       uint8_t *data;
 
        switch_assert(img);
-       switch_assert(x >= 0 && y >= 0 && w >= 0 && h >= 0);
 
-       if (!(img->fmt == SWITCH_IMG_FMT_I420)) return NULL;
+       if (x >= img->d_w || y >= img->d_h) return NULL;
 
-       new_img = switch_img_alloc(NULL, SWITCH_IMG_FMT_I420, w, h, 1);
-       if (new_img == NULL) return NULL;
+       if (!(img->fmt & SWITCH_IMG_FMT_PLANAR)) {
+               data = img->planes[SWITCH_PLANE_PACKED];
+       } else {
+               data = img->planes[SWITCH_PLANE_Y];
+       }
+
+       tmp = (switch_image_t *)vpx_img_wrap(NULL, img->fmt, img->d_w, img->d_h, 1, data);
+       if (!tmp) return NULL;
 
-       len = MIN(img->d_w - x, w);
-       if (len <= 0) return NULL;
+       w = MIN(img->d_w - x, w);
+       h = MIN(img->d_h - y, h);
 
-       for (i = 0; i < (img->d_h - y) && i < h; i++) {
-               memcpy(new_img->planes[SWITCH_PLANE_Y] + new_img->stride[SWITCH_PLANE_Y] * i, img->planes[SWITCH_PLANE_Y] + img->stride[SWITCH_PLANE_Y] * (y + i) + x, len);
+       if (!switch_img_set_rect(tmp, x, y, w, h)) {
+               switch_img_copy(tmp, &new_img);
        }
 
-       len /= 2;
+       switch_img_free(&tmp);
 
-       for (i = 0; i < (img->d_h - y) && i < h; i += 2) {
-               memcpy(new_img->planes[SWITCH_PLANE_U] + new_img->stride[SWITCH_PLANE_U] * i / 2, img->planes[SWITCH_PLANE_U] + img->stride[SWITCH_PLANE_U] * (y + i) / 2 + x / 2, len);
-               memcpy(new_img->planes[SWITCH_PLANE_V] + new_img->stride[SWITCH_PLANE_V] * i / 2, img->planes[SWITCH_PLANE_V] + img->stride[SWITCH_PLANE_V] * (y + i) / 2 + x / 2, len);
-       }
        return new_img;
 }