Home | History | Annotate | Download | only in jni
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef GIF_TRANSCODER_H
     18 #define GIF_TRANSCODER_H
     19 
     20 #include <sys/types.h>
     21 
     22 #include "gif_lib.h"
     23 
     24 // 24-bit color with alpha, stored in order: A, R, G, B.
     25 // The internal GIF render buffer stores pixels using this format.
     26 typedef uint32_t ColorARGB;
     27 
     28 // Compresses a GIF (probably animated) so it can be sent via MMS, which generally has a 1 MB limit
     29 // on attachments. GIF image data is already compressed (LZW), so to achieve further reduction in
     30 // file size, we reduce the image dimensions.
     31 //
     32 // Helpful GIF references:
     33 // GIF89A spec: http://www.w3.org/Graphics/GIF/spec-gif89a.txt
     34 // What's in a GIF: http://giflib.sourceforge.net/whatsinagif/index.html
     35 //
     36 class GifTranscoder {
     37 public:
     38     GifTranscoder() {}
     39     ~GifTranscoder() {}
     40 
     41     // Resizes a GIF's width and height to 50% of their original dimensions. The new file is
     42     // written to pathOut.
     43     //
     44     // The image is resized using a box filter, which averages the colors in each 2x2 box of pixels
     45     // in the source to generate the color of the pixel in the destination.
     46     //
     47     // Returns GIF_OK (1) on success, or GIF_ERROR (0) on failure.
     48     int transcode(const char* pathIn, const char* pathOut);
     49 
     50 private:
     51     // Implementation of the box filter algorithm.
     52     static bool resizeBoxFilter(GifFileType* gifIn, GifFileType* gifOut);
     53 
     54     // Reads the raster data for the current image of the GIF.
     55     static bool readImage(GifFileType* gifIn, GifByteType* rasterBits);
     56 
     57     // Renders the current image of the GIF into the supplied render buffer.
     58     static bool renderImage(GifFileType* gifIn,
     59                             GifByteType* rasterBits,
     60                             int imageIndex,
     61                             int transparentColorIndex,
     62                             ColorARGB* renderBuffer,
     63                             ColorARGB bgColor,
     64                             GifImageDesc prevImageDimens,
     65                             int prevImageDisposalMode);
     66 
     67     // Fills a rectangle in the buffer with a solid color.
     68     static void fillRect(ColorARGB* renderBuffer,
     69                          int imageWidth,
     70                          int imageHeight,
     71                          int left,
     72                          int top,
     73                          int width,
     74                          int height,
     75                          ColorARGB color);
     76 
     77     // Computes the color for the pixel (x,y) in the current image in the output GIF.
     78     static GifByteType computeNewColorIndex(GifFileType* gifIn,
     79                                             int transparentColorIndex,
     80                                             ColorARGB* renderBuffer,
     81                                             int x,
     82                                             int y);
     83 
     84     // Computes the average color (by averaging the per-channel (ARGB) values).
     85     static ColorARGB computeAverage(ColorARGB c1, ColorARGB c2, ColorARGB c3, ColorARGB c4);
     86 
     87     // Searches a color map for the color closest (Euclidean distance) to the target color.
     88     static GifByteType findBestColor(ColorMapObject* colorMap, int transparentColorIndex,
     89                                      ColorARGB targetColor);
     90 
     91     // Computes distance (squared) between 2 colors, considering each channel a separate dimension.
     92     static int computeDistance(ColorARGB c1, ColorARGB c2);
     93 
     94     // Returns the local color map of the current image (if any), or else the global color map.
     95     static ColorMapObject* getColorMap(GifFileType* gifIn);
     96 
     97     // Returns an indexed color from the color map.
     98     static ColorARGB getColorARGB(ColorMapObject* colorMap, int transparentColorIndex,
     99                                   GifByteType colorIndex);
    100 
    101     // Converts a 24-bit GIF color (RGB) to a 32-bit ARGB color.
    102     static ColorARGB gifColorToColorARGB(const GifColorType& color);
    103 };
    104 
    105 // Wrapper class that automatically closes the GIF files when the wrapper goes out of scope.
    106 class GifFilesCloser {
    107 public:
    108     GifFilesCloser() {}
    109     ~GifFilesCloser();
    110 
    111     void setGifIn(GifFileType* gifIn);
    112     void releaseGifIn();
    113 
    114     void setGifOut(GifFileType* gifOut);
    115     void releaseGifOut();
    116 
    117 private:
    118     GifFileType* mGifIn = NULL;
    119     GifFileType* mGifOut = NULL;
    120 };
    121 
    122 #endif // GIF_TRANSCODER_H
    123