anim_encoder: drop a frame if it has same pixels as the prev frame.

Earlier, we stored a 1x1 frame for such frames. Now, we drop every such
frame and increase the duration of its previous frame instead.

Also, modify the anim_diff tool to handle animated images that are
equivalent, but have different number of frames.

Change-Id: I2688b1771e1f5f9f6a78e48ec81b01c3cd495403
This commit is contained in:
Urvang Joshi
2015-10-01 11:14:49 -07:00
parent df9f6ec829
commit 27933e2a8e
2 changed files with 168 additions and 46 deletions

View File

@ -13,6 +13,7 @@
//
// example: anim_diff foo.gif bar.webp
#include <limits.h>
#include <stdio.h>
#include <stdlib.h> // for 'strtod'.
#include <string.h> // for 'strcmp'.
@ -24,6 +25,31 @@
namespace {
// Return true if 'a + b' will overflow.
bool AdditionWillOverflow(int a, int b) {
return (b > 0) && (a > INT_MAX - b);
}
// Minimize number of frames by combining successive frames that have exact same
// ARGB data into a single longer duration frame.
void MinimizeAnimationFrames(AnimatedImage* const img) {
for (size_t i = 1; i < img->frames.size(); ++i) {
DecodedFrame* const frame1 = &img->frames[i - 1];
DecodedFrame* const frame2 = &img->frames[i];
// If merging frames will result in integer overflow for 'duration',
// skip merging.
if (AdditionWillOverflow(frame1->duration, frame2->duration)) continue;
const uint8_t* rgba1 = frame1->rgba.data();
const uint8_t* rgba2 = frame2->rgba.data();
if (!memcmp(rgba1, rgba2, img->canvas_width * 4 * img->canvas_height)) {
// Merge 'i+1'th frame into 'i'th frame.
frame1->duration += frame2->duration;
img->frames.erase(img->frames.begin() + i);
--i;
}
}
}
template<typename T>
bool CompareValues(T a, T b, const std::string& output_str) {
if (a != b) {
@ -163,6 +189,7 @@ int main(int argc, const char* argv[]) {
fprintf(stderr, "Error decoding file: %s\n Aborting.\n", files[i]);
return -2;
}
MinimizeAnimationFrames(&images[i]);
}
if (!CompareAnimatedImagePair(images[0], images[1],