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