add a WebPCleanupTransparentArea() method

to 'clean up' the fully-transparent area and make it more compressible
new cwebp flags: -alpha_cleanup (off by default, since gain is not 100% guaranteed)

Change-Id: I74d77e1915eee146584cd61c9c1132a41db922eb
This commit is contained in:
Pascal Massimino 2012-01-17 08:18:22 +00:00 committed by James Zern
parent 552c121715
commit 2e3e8b2ef5
5 changed files with 93 additions and 8 deletions

15
README
View File

@ -121,19 +121,21 @@ A longer list of options is available using the -longhelp command line flag:
Usage:
cwebp [-preset <...>] [options] in_file [-o out_file]
If input size (-s) for an image is not specified, it is assumed to be a either
PNG or JPEG format file.
If input size (-s) for an image is not specified, it is assumed to be a
PNG or JPEG file.
options:
-h / -help ............ short help
-H / -longhelp ........ long help
-q <float> ............. quality factor (0:small..100:big)
-alpha_q <int> ......... Transparency-compression quality (0..100)
-alpha_q <int> ......... Transparency-compression quality (0..100).
-preset <string> ....... Preset setting, one of:
default, photo, picture,
drawing, icon, text
-preset must come first, as it overwrites other parameters.
-m <int> ............... compression method (0=fast, 6=slowest)
-segments <int> ........ number of segments to use (1..4)
-size <int> ............ Target size (in bytes)
-psnr <float> .......... Target PSNR (in dB. typically: 42)
-s <int> <int> ......... Input size (width x height) for YUV
-sns <int> ............. Spatial Noise Shaping (0:off, 100:max)
@ -143,7 +145,6 @@ options:
-partition_limit <int> . limit quality to fit the 512k limit on
the first partition (0=no degradation ... 100=full)
-pass <int> ............ analysis pass number (1..10)
-partitions <int> ...... number of partitions to use (0..3)
-crop <x> <y> <w> <h> .. crop picture with the given rectangle
-resize <w> <h> ........ resize picture (after any cropping)
-map <int> ............. print map of extra info.
@ -151,6 +152,7 @@ options:
-alpha_method <int> .... Transparency-compression method (0..1)
-alpha_filter <string> . predictive filtering for alpha plane.
One of: none, fast (default) or best.
-alpha_cleanup ......... Clean RGB values in transparent area.
-noalpha ............... discard any transparency information.
-short ................. condense printed message
@ -160,11 +162,8 @@ options:
-v ..................... verbose, e.g. print encoding/decoding times
-progress .............. report encoding progress
Experimental Options:
-size <int> ............ Target size (in bytes)
-psnr <float> .......... Target PSNR (in dB. typically: 42)
-af <int> .............. adjust filter strength (0=off, 1=on)
-af .................... auto-adjust filter strength.
-pre <int> ............. pre-processing filter

View File

@ -206,6 +206,11 @@ static HRESULT ReadPictureWithWIC(const char* filename,
if (!ok)
hr = E_FAIL;
}
if (SUCCEEDED(hr)) {
if (has_alpha && keep_alpha == 2) {
WebPCleanupTransparentArea(pic);
}
}
// Cleanup.
if (pConverter != NULL) IUnknown_Release(pConverter);
@ -416,6 +421,10 @@ static int ReadPNG(FILE* in_file, WebPPicture* const pic, int keep_alpha) {
: WebPPictureImportRGB(pic, rgb, stride);
free(rgb);
if (ok && has_alpha && keep_alpha == 2) {
WebPCleanupTransparentArea(pic);
}
End:
return ok;
}
@ -702,6 +711,7 @@ static void HelpLong(void) {
printf(" -alpha_method <int> .... Transparency-compression method (0..1)\n");
printf(" -alpha_filter <string> . predictive filtering for alpha plane.\n");
printf(" One of: none, fast (default) or best.\n");
printf(" -alpha_cleanup ......... Clean RGB values in transparent area.\n");
printf(" -noalpha ............... discard any transparency information.\n");
printf("\n");
@ -795,6 +805,8 @@ int main(int argc, const char *argv[]) {
config.alpha_quality = strtol(argv[++c], NULL, 0);
} else if (!strcmp(argv[c], "-alpha_method") && c < argc - 1) {
config.alpha_compression = strtol(argv[++c], NULL, 0);
} else if (!strcmp(argv[c], "-alpha_cleanup")) {
keep_alpha = keep_alpha ? 2 : 0;
} else if (!strcmp(argv[c], "-alpha_filter") && c < argc - 1) {
++c;
if (!strcmp(argv[c], "none")) {

View File

@ -155,6 +155,10 @@ Specify the algorithm used for alpha compression: 0 or 1. Algorithm 0 denotes
no compression, 1 uses uses backward reference counts encoded with arithmetic
encoder. The default is 1.
.TP
.B \-alpha_cleanup
Modify unseen RGB values under fully transparent area, to help compressibility.
The default is off.
.TP
.B \-noalpha
Using this option will discard the alpha channel.
.TP

View File

@ -593,6 +593,71 @@ int WebPPictureImportBGRA(WebPPicture* const picture,
return Import(picture, rgba, rgba_stride, 4, 1, 1);
}
//------------------------------------------------------------------------------
// Helper: clean up fully transparent area to help compressibility.
#define SIZE 8
#define SIZE2 (SIZE / 2)
static int is_transparent_area(const uint8_t* ptr, int stride, int size) {
int y, x;
for (y = 0; y < size; ++y) {
for (x = 0; x < size; ++x) {
if (ptr[x]) {
return 0;
}
}
ptr += stride;
}
return 1;
}
static WEBP_INLINE void flatten(uint8_t* ptr, int v, int stride, int size) {
int y;
for (y = 0; y < size; ++y) {
memset(ptr, v, size);
ptr += stride;
}
}
void WebPCleanupTransparentArea(WebPPicture* const pic) {
int x, y, w, h;
const uint8_t* a_ptr;
int values[3] = { 0 };
if (pic == NULL) return;
a_ptr = pic->a;
if (a_ptr == NULL) return; // nothing to do
w = pic->width / SIZE;
h = pic->height / SIZE;
for (y = 0; y < h; ++y) {
int need_reset = 1;
for (x = 0; x < w; ++x) {
const int off_a = (y * pic->a_stride + x) * SIZE;
const int off_y = (y * pic->y_stride + x) * SIZE;
const int off_uv = (y * pic->uv_stride + x) * SIZE2;
if (is_transparent_area(a_ptr + off_a, pic->a_stride, SIZE)) {
if (need_reset) {
values[0] = pic->y[off_y];
values[1] = pic->u[off_uv];
values[2] = pic->v[off_uv];
need_reset = 0;
}
flatten(pic->y + off_y, values[0], pic->y_stride, SIZE);
flatten(pic->u + off_uv, values[1], pic->uv_stride, SIZE2);
flatten(pic->v + off_uv, values[2], pic->uv_stride, SIZE2);
} else {
need_reset = 1;
}
}
// ignore the left-overs on right/bottom
}
}
#undef SIZE
#undef SIZE2
//------------------------------------------------------------------------------
// Simplest call:

View File

@ -276,6 +276,11 @@ WEBP_EXTERN(int) WebPPictureImportBGR(
WEBP_EXTERN(int) WebPPictureImportBGRA(
WebPPicture* const picture, const uint8_t* const bgra, int bgra_stride);
// Helper function: given a width x height plane of YUV(A) samples
// (with stride 'stride'), clean-up the YUV samples under fully transparent
// area, to help compressibility (no guarantee, though).
WEBP_EXTERN(void) WebPCleanupTransparentArea(WebPPicture* const picture);
//------------------------------------------------------------------------------
// Main call