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