Page MenuHomePhabricator

Add VIPS image scaling support to MediaWiki
Closed, ResolvedPublic

Description

Author: Bryan.TongMinh

Description:
VIPS support should be added to MediaWiki. VIPS is a free image processing system. It is good with large images (images larger than the amount of RAM you have available), according to its website http://www.vips.ecs.soton.ac.uk/.

This would solve our 12.5MP limit for PNGs and other large files.

I believe that this has been discussed with somebody from WMF, most likely Tim, and that person I believe had done some tests with it.


Version: 1.17.x
Severity: enhancement
URL: http://www.vips.ecs.soton.ac.uk/

Details

Reference
bz25990

Event Timeline

bzimport raised the priority of this task from to Low.Nov 21 2014, 11:11 PM
bzimport set Reference to bz25990.
bzimport added a subscriber: Unknown Object (MLST).

RSYQFIOJGWZA wrote:

Bug 24984#c13 seems to indicate that Tim supports it. Lack of support for >12.5MP images, including PNG and TIFF, is negatively impacting multiple projects' scalability. VIPS implementation should save much RAM on the image scalers, allowing them to be more efficient and effective in RAM bottleneck situations. I have reverted the unexplained downgrade in importance.

Bryan.TongMinh wrote:

It's done as extension VipsScaler (r84281), but needs a bit of workaround for non RGBA images as VIPS is broken. I already know the workaround of greyscale images, but I'm waiting on the reply of the maintainers for palette based images.

Bryan.TongMinh wrote:

The palette and grayscale handling has been fixed in the latest unreleased VIPS version, so this is done.

(In reply to comment #1)

Bug 24984#c13 seems to indicate that Tim supports it.

My initial comments about VIPS were on bug 23258.

Bryan.TongMinh wrote:

I've changed to im_shrink in r84471. The problem however is that due to rounding, the results may be inaccurate, i.e. images of 179px wide instead of 180px. The result is then that the browser upsizes the image again.

Other options would be im_affine, but that uses a bilinear interpolation, which if I understand correctly is causing poor results similar to im_resize_linear.

(In reply to comment #6)

I've changed to im_shrink in r84471. The problem however is that due to
rounding, the results may be inaccurate, i.e. images of 179px wide instead of
180px. The result is then that the browser upsizes the image again.

There's 53 bits of precision in a floating-point number, you should be able to manipulate these tiny integers without rounding errors.

/* Prepare output. Note: we round the output width down!

	 */

...
out->Xsize = in->Xsize / xshrink;
out->Ysize = in->Ysize / yshrink;

typedef struct im__IMAGE {
...
int Xsize;
int Ysize;

If you offset the destination sizes by 0.5px, then the output size should always be accurate.

You need to add sharpening. I discussed sharpening on bug 23258. Note that sharpening is only necessary for images which are resized by significant factor, see $wgSharpenReductionThreshold.

For small images that are resized to a size that is only slightly smaller, you should use a VIPS function that has interpolation. For PagedTiffHandler, we could get away with ignoring this case, but if we use VIPS to scale all images, then we have to think about every possible case.

Bryan.TongMinh wrote:

Fixed the scaling in r84635.

I was made aware of the vipsthumbnail program. This uses the sharpening that is also done in IM. See http://www.vips.ecs.soton.ac.uk/index.php?title=What%27s_New_in_7.22#vipsthumbnail

(In reply to comment #8)

Fixed the scaling in r84635.

I was made aware of the vipsthumbnail program. This uses the sharpening that is
also done in IM. See
http://www.vips.ecs.soton.ac.uk/index.php?title=What%27s_New_in_7.22#vipsthumbnail

The problem with vipsthumbnail is that it stores the uncompressed image. For a large image, it could take gigabytes of disk space. ImageMagick does this also, that's one of the reasons we want to get rid of it.

RSYQFIOJGWZA wrote:

(In reply to comment #9)

The problem with vipsthumbnail is that it stores the uncompressed image. For a
large image, it could take gigabytes of disk space. ImageMagick does this also,
that's one of the reasons we want to get rid of it.

Can either one be made to use a compressed filesystem for storage, or modified to store compressed images?

Bryan.TongMinh wrote:

(In reply to comment #9)

(In reply to comment #8)

Fixed the scaling in r84635.

I was made aware of the vipsthumbnail program. This uses the sharpening that is
also done in IM. See
http://www.vips.ecs.soton.ac.uk/index.php?title=What%27s_New_in_7.22#vipsthumbnail

The problem with vipsthumbnail is that it stores the uncompressed image. For a
large image, it could take gigabytes of disk space. ImageMagick does this also,
that's one of the reasons we want to get rid of it.

Well, we'll have to do that anyway for non random accessible images (PNG, non tiled TIFF); they need to be converted to a .v file on disk, and as far as I know .v is uncompressed.
So if that is your objection to VIPS we need to find another solution, such as writing a PNG reader that supports random access. Should be possible as the PNG format is line based (but I don't know about zlib).

(In reply to comment #11)

So if that is your objection to VIPS we need to find another solution, such as
writing a PNG reader that supports random access. Should be possible as the PNG
format is line based (but I don't know about zlib).

libpng supports line-by-line reading. As the matter of fact, VIPS uses it to handle PNGs. I uses it for my pngds rewrite, which stopped on downscaling.

(In reply to comment #12)

libpng supports line-by-line reading. As the matter of fact, VIPS uses it to
handle PNGs. I uses it for my pngds rewrite, which stopped on downscaling.

Right, VIPS can buffer several lines from libpng, do a block average, and then write out a line of output. Almost no intermediate storage space is required. That's why we want it.

Sharpening is done on the downscaled image, not the original image. It's feasible to store the downscaled unsharpened image so that it can be fed into another run of VIPS or into ImageMagick. We just want to avoid storing the uncompressed unscaled image.

Bryan.TongMinh wrote:

I poked a bit at sharpening in r85207. It still looks a bit worse than ImageMagick, even though the convolution matrix should match the IM sharpening parameters.

As for the libpng thing, PNG is not marked as PIO in VIPS, so it might be that it will just try to decompress the entire file into memory. Somebody should look into the peak memory usage when scaling PNGs. I have no clue on how to do so unfortunately.

(In reply to comment #14)

As for the libpng thing, PNG is not marked as PIO in VIPS, so it might be that
it will just try to decompress the entire file into memory. Somebody should
look into the peak memory usage when scaling PNGs. I have no clue on how to do
so unfortunately.

Using the same source image as my tests in bug 23258, except pre-converted to PNG, the memory usage was 18MB for VIPS, and 411MB for ImageMagick. Memory usage in VIPS was low even if I used interlaced encoding in the source image.

Note that im_tiff2vips and im_jpeg2vips are also marked "WIO", but reading TIFF and JPEG images uses a small amount of memory nonetheless. I think file format handlers are a special case.

Gilles raised the priority of this task from Low to Unbreak Now!.Dec 4 2014, 10:12 AM
Gilles moved this task from Untriaged to Done on the Multimedia board.
Gilles lowered the priority of this task from Unbreak Now! to Low.Dec 4 2014, 11:21 AM