[FFmpeg-devel,5/7] Reimplement optimization for transparency

Submitted by Bjorn Roche on Oct. 2, 2017, 5:24 p.m.

Details

Message ID 20171002172439.65628-6-bjorn@giphy.com
State New
Headers show

Commit Message

Bjorn Roche Oct. 2, 2017, 5:24 p.m.
From: Bjorn Roche <bjorn@xowave.com>

---
 libavcodec/gif.c | 131 +++++++++++++++++++++++++++++++++----------------------
 1 file changed, 78 insertions(+), 53 deletions(-)

Patch hide | download patch | download mbox

diff --git a/libavcodec/gif.c b/libavcodec/gif.c
index db2193a718..3838aa7592 100644
--- a/libavcodec/gif.c
+++ b/libavcodec/gif.c
@@ -80,7 +80,7 @@  static int is_image_translucent(AVCodecContext *avctx,
                                 const uint8_t *buf, const int linesize)
 {
     GIFContext *s = avctx->priv_data;
-    int trans = s->transparent_index;
+    uint8_t trans = s->transparent_index;
     int p;
     const int m = avctx->width * avctx->height ;
 
@@ -88,7 +88,6 @@  static int is_image_translucent(AVCodecContext *avctx,
         return 0;
     }
 
-    // FIXME: this might be faster with strchr
     for( p=0; p<m; ++p ) {
         if( buf[p] == trans ) {
             return 1;
@@ -254,60 +253,86 @@  static int gif_image_write_translucent(AVCodecContext *avctx,
                                        AVPacket *pkt)
 {
     GIFContext *s = avctx->priv_data;
-    int len = 0, height = avctx->height, width = avctx->width, x, y;
+    int len = 0, height = avctx->height, width = avctx->width, y;
     int x_start = 0, y_start = 0, trans = s->transparent_index;
-    int honor_transparency = (s->flags & GF_TRANSDIFF) && s->last_frame && !palette;
+    //int honor_transparency = (s->flags & GF_TRANSDIFF) && s->last_frame && !palette;
     const uint8_t *ptr;
 
-    // /* Crop image */
-    // if ((s->flags & GF_OFFSETTING) && s->last_frame && !palette) {
-    //     const uint8_t *ref = s->last_frame->data[0];
-    //     const int ref_linesize = s->last_frame->linesize[0];
-    //     int x_end = avctx->width  - 1,
-    //         y_end = avctx->height - 1;
-
-    //     /* skip common lines */
-    //     while (y_start < y_end) {
-    //         if (memcmp(ref + y_start*ref_linesize, buf + y_start*linesize, width))
-    //             break;
-    //         y_start++;
-    //     }
-    //     while (y_end > y_start) {
-    //         if (memcmp(ref + y_end*ref_linesize, buf + y_end*linesize, width))
-    //             break;
-    //         y_end--;
-    //     }
-    //     height = y_end + 1 - y_start;
-
-    //     /* skip common columns */
-    //     while (x_start < x_end) {
-    //         int same_column = 1;
-    //         for (y = y_start; y <= y_end; y++) {
-    //             if (ref[y*ref_linesize + x_start] != buf[y*linesize + x_start]) {
-    //                 same_column = 0;
-    //                 break;
-    //             }
-    //         }
-    //         if (!same_column)
-    //             break;
-    //         x_start++;
-    //     }
-    //     while (x_end > x_start) {
-    //         int same_column = 1;
-    //         for (y = y_start; y <= y_end; y++) {
-    //             if (ref[y*ref_linesize + x_end] != buf[y*linesize + x_end]) {
-    //                 same_column = 0;
-    //                 break;
-    //             }
-    //         }
-    //         if (!same_column)
-    //             break;
-    //         x_end--;
-    //     }
-    //     width = x_end + 1 - x_start;
-
-    //     av_log(avctx, AV_LOG_DEBUG,"%dx%d image at pos (%d;%d) [area:%dx%d]\n",
-    //            width, height, x_start, y_start, avctx->width, avctx->height);
+    /* Crop Image */
+    if ( (s->flags & GF_OFFSETTING) && trans >=0 ) {
+        const int w = avctx->width;
+        const int h = avctx->height;
+        int x_end = w - 1,
+            y_end = h - 1;
+
+        // top
+        while (y_start < y_end) {
+            int i;
+            int is_trans = 1;
+            for( i=0; i<w; ++i ) {
+                if( buf[w*y_start+i] != trans ) {
+                    is_trans = 0;
+                    break;
+                }
+            }
+            if( !is_trans )
+                break;
+            ++y_start;
+        }
+
+        // bottom
+        while (y_end < h) {
+            int i;
+            int is_trans = 1;
+            for( i=0; i<w; ++i ) {
+                if( buf[w*y_end+i] != trans ) {
+                    is_trans = 0;
+                    break;
+                }
+            }
+            if( !is_trans )
+                break;
+            --y_end;
+        }
+
+        // left
+        while (x_start < x_end) {
+            int i;
+            int is_trans = 1;
+            for( i=y_start; i<y_end; ++i ) {
+                if( buf[w*i+x_start] != trans ) {
+                    is_trans = 0;
+                    break;
+                }
+            }
+            if( !is_trans )
+                break;
+            ++x_start;
+        }
+
+        // right
+        while (x_end < w) {
+            int i;
+            int is_trans = 1;
+            for( i=y_start; i<y_end; ++i ) {
+                if( buf[w*i+x_end] != trans ) {
+                    is_trans = 0;
+                    break;
+                }
+            }
+            if( !is_trans )
+                break;
+            --x_end;
+        }
+
+        height = y_end + 1 - y_start;
+        width = x_end + 1 - x_start;
+        av_log(avctx, AV_LOG_DEBUG,"%dx%d image at pos (%d;%d) [area:%dx%d]\n",
+               width, height, x_start, y_start, avctx->width, avctx->height);
+    }
+
+    // for( int i=0; i<avctx->width*avctx->height; ++i ) {
+    //     ((uint8_t *)buf)[i] = 120;
     // }