diff options
Diffstat (limited to 'jni/GifTranscoder.h')
-rw-r--r-- | jni/GifTranscoder.h | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/jni/GifTranscoder.h b/jni/GifTranscoder.h new file mode 100644 index 0000000..39ecc24 --- /dev/null +++ b/jni/GifTranscoder.h @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef GIF_TRANSCODER_H +#define GIF_TRANSCODER_H + +#include <sys/types.h> + +#include "gif_lib.h" + +// 24-bit color with alpha, stored in order: A, R, G, B. +// The internal GIF render buffer stores pixels using this format. +typedef uint32_t ColorARGB; + +// Compresses a GIF (probably animated) so it can be sent via MMS, which generally has a 1 MB limit +// on attachments. GIF image data is already compressed (LZW), so to achieve further reduction in +// file size, we reduce the image dimensions. +// +// Helpful GIF references: +// GIF89A spec: http://www.w3.org/Graphics/GIF/spec-gif89a.txt +// What's in a GIF: http://giflib.sourceforge.net/whatsinagif/index.html +// +class GifTranscoder { +public: + GifTranscoder() {} + ~GifTranscoder() {} + + // Resizes a GIF's width and height to 50% of their original dimensions. The new file is + // written to pathOut. + // + // The image is resized using a box filter, which averages the colors in each 2x2 box of pixels + // in the source to generate the color of the pixel in the destination. + // + // Returns GIF_OK (1) on success, or GIF_ERROR (0) on failure. + int transcode(const char* pathIn, const char* pathOut); + +private: + // Implementation of the box filter algorithm. + static bool resizeBoxFilter(GifFileType* gifIn, GifFileType* gifOut); + + // Reads the raster data for the current image of the GIF. + static bool readImage(GifFileType* gifIn, GifByteType* rasterBits); + + // Renders the current image of the GIF into the supplied render buffer. + static bool renderImage(GifFileType* gifIn, + GifByteType* rasterBits, + int imageIndex, + int transparentColorIndex, + ColorARGB* renderBuffer, + ColorARGB bgColor, + GifImageDesc prevImageDimens, + int prevImageDisposalMode); + + // Fills a rectangle in the buffer with a solid color. + static void fillRect(ColorARGB* renderBuffer, + int imageWidth, + int imageHeight, + int left, + int top, + int width, + int height, + ColorARGB color); + + // Computes the color for the pixel (x,y) in the current image in the output GIF. + static GifByteType computeNewColorIndex(GifFileType* gifIn, + int transparentColorIndex, + ColorARGB* renderBuffer, + int x, + int y); + + // Computes the average color (by averaging the per-channel (ARGB) values). + static ColorARGB computeAverage(ColorARGB c1, ColorARGB c2, ColorARGB c3, ColorARGB c4); + + // Searches a color map for the color closest (Euclidean distance) to the target color. + static GifByteType findBestColor(ColorMapObject* colorMap, int transparentColorIndex, + ColorARGB targetColor); + + // Computes distance (squared) between 2 colors, considering each channel a separate dimension. + static int computeDistance(ColorARGB c1, ColorARGB c2); + + // Returns the local color map of the current image (if any), or else the global color map. + static ColorMapObject* getColorMap(GifFileType* gifIn); + + // Returns an indexed color from the color map. + static ColorARGB getColorARGB(ColorMapObject* colorMap, int transparentColorIndex, + GifByteType colorIndex); + + // Converts a 24-bit GIF color (RGB) to a 32-bit ARGB color. + static ColorARGB gifColorToColorARGB(const GifColorType& color); +}; + +// Wrapper class that automatically closes the GIF files when the wrapper goes out of scope. +class GifFilesCloser { +public: + GifFilesCloser() {} + ~GifFilesCloser(); + + void setGifIn(GifFileType* gifIn); + void releaseGifIn(); + + void setGifOut(GifFileType* gifOut); + void releaseGifOut(); + +private: + GifFileType* mGifIn = NULL; + GifFileType* mGifOut = NULL; +}; + +#endif // GIF_TRANSCODER_H |