Skip to content

Lossless conversion for webp #7348

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ext/gd/config.m4
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ AC_DEFUN([PHP_GD_AVIF],[

AC_DEFUN([PHP_GD_WEBP],[
if test "$PHP_WEBP" != "no"; then
PKG_CHECK_MODULES([WEBP], [libwebp])
PKG_CHECK_MODULES([WEBP], [libwebp >= 0.2.0])
PHP_EVAL_LIBLINE($WEBP_LIBS, GD_SHARED_LIBADD)
PHP_EVAL_INCLINE($WEBP_CFLAGS)
AC_DEFINE(HAVE_LIBWEBP, 1, [ ])
Expand Down
15 changes: 14 additions & 1 deletion ext/gd/libgd/gd.h
Original file line number Diff line number Diff line change
Expand Up @@ -619,7 +619,20 @@ void *gdImageWBMPPtr(gdImagePtr im, int *size, int fg);
void gdImageJpeg(gdImagePtr im, FILE *out, int quality);
void gdImageJpegCtx(gdImagePtr im, gdIOCtx *out, int quality);

void gdImageWebpCtx (gdImagePtr im, gdIOCtx * outfile, int quantization);
/**
* Group: WebP
*
* Constant: gdWebpLossless
*
* Lossless quality threshold. When image quality is greater than or equal to
* <gdWebpLossless>, the image will be written in the lossless WebP format.
*
* See also:
* - <gdImageWebpCtx>
*/
#define gdWebpLossless 101

void gdImageWebpCtx (gdImagePtr im, gdIOCtx * outfile, int quality);

/* Best to free this memory with gdFree(), not free() */
void *gdImageJpegPtr(gdImagePtr im, int *size, int quality);
Expand Down
22 changes: 14 additions & 8 deletions ext/gd/libgd/gd_webp.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ gdImagePtr gdImageCreateFromWebpCtx (gdIOCtx * infile)
return im;
}

void gdImageWebpCtx (gdImagePtr im, gdIOCtx * outfile, int quantization)
void gdImageWebpCtx (gdImagePtr im, gdIOCtx * outfile, int quality)
{
uint8_t *argb;
int x, y;
Expand All @@ -117,8 +117,8 @@ void gdImageWebpCtx (gdImagePtr im, gdIOCtx * outfile, int quantization)
return;
}

if (quantization == -1) {
quantization = 80;
if (quality == -1) {
quality = 80;
}

if (overflow2(gdImageSX(im), 4)) {
Expand Down Expand Up @@ -151,7 +151,13 @@ void gdImageWebpCtx (gdImagePtr im, gdIOCtx * outfile, int quantization)
*(p++) = a;
}
}
out_size = WebPEncodeRGBA(argb, gdImageSX(im), gdImageSY(im), gdImageSX(im) * 4, quantization, &out);

if (quality >= gdWebpLossless) {
out_size = WebPEncodeLosslessRGBA(argb, gdImageSX(im), gdImageSY(im), gdImageSX(im) * 4, &out);
} else {
out_size = WebPEncodeRGBA(argb, gdImageSX(im), gdImageSY(im), gdImageSX(im) * 4, quality, &out);
}

if (out_size == 0) {
zend_error(E_ERROR, "gd-webp encoding failed");
goto freeargb;
Expand All @@ -163,10 +169,10 @@ void gdImageWebpCtx (gdImagePtr im, gdIOCtx * outfile, int quantization)
gdFree(argb);
}

void gdImageWebpEx (gdImagePtr im, FILE * outFile, int quantization)
void gdImageWebpEx (gdImagePtr im, FILE * outFile, int quality)
{
gdIOCtx *out = gdNewFileCtx(outFile);
gdImageWebpCtx(im, out, quantization);
gdImageWebpCtx(im, out, quality);
out->gd_free(out);
}

Expand All @@ -188,11 +194,11 @@ void * gdImageWebpPtr (gdImagePtr im, int *size)
return rv;
}

void * gdImageWebpPtrEx (gdImagePtr im, int *size, int quantization)
void * gdImageWebpPtrEx (gdImagePtr im, int *size, int quality)
{
void *rv;
gdIOCtx *out = gdNewDynamicCtx(2048, NULL);
gdImageWebpCtx(im, out, quantization);
gdImageWebpCtx(im, out, quality);
rv = gdDPExtractData(out, size);
out->gd_free(out);
return rv;
Expand Down
12 changes: 11 additions & 1 deletion ext/gd/tests/webp_basic.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ if (!function_exists('imagewebp') || !function_exists('imagecreatefromwebp'))
<?php
require_once __DIR__ . '/similarity.inc';

define("WEBP_LOSSLESS", 101);

$filename = __DIR__ . '/webp_basic.webp';

$im1 = imagecreatetruecolor(75, 75);
Expand All @@ -29,11 +31,19 @@ imagewebp($im1, $filename);

$im2 = imagecreatefromwebp($filename);
imagewebp($im2, $filename);
echo 'Is lossy conversion close enough? ';
var_dump(calc_image_dissimilarity($im1, $im2) < 10e5);

imagewebp($im1, $filename, WEBP_LOSSLESS);
$im_lossless = imagecreatefromwebp($filename);
echo 'Does lossless conversion work? ';
var_dump(calc_image_dissimilarity($im1, $im_lossless) == 0);

?>
--CLEAN--
<?php
@unlink(__DIR__ . '/webp_basic.webp');
?>
--EXPECT--
bool(true)
Is lossy conversion close enough? bool(true)
Does lossless conversion work? bool(true)