mirror of
https://github.com/webmproject/libwebp.git
synced 2024-12-26 05:38:22 +01:00
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:
parent
552c121715
commit
2e3e8b2ef5
15
README
15
README
@ -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
|
||||
|
||||
|
||||
|
@ -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")) {
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user