Commits

Fredrik Lundh committed c2ca2b6

Added WebP write support (work in progress).

Comments (0)

Files changed (3)

PIL/WebPImagePlugin.py

 # The Python Imaging Library.
 # $Id$
 #
-# (Limited) WebP support for PIL
+# Basic WebP support for PIL
 #
 # History:
 # 2011-06-26 fl     Created
         self.tile = [(d, e, o, a)]
         return self
 
+
+def _save(im, fp, filename):
+    if im.mode != "RGB":
+        raise IOError("cannot write mode %s as WEBP" % im.mode)
+    ImageFile._save(im, fp, [("webp", (0, 0) + im.size, 0, (im.mode,))])
+
 #
 # --------------------------------------------------------------------
 
 Image.register_open("WEBP", WebPImageFile, _accept)
-# Image.register_save("WEBP", _save)
+Image.register_save("WEBP", _save)
 
 Image.register_extension("WEBP", ".webp")

libImaging/WebPDecode.c

     int y, xsize, ysize;
     UINT8* p;
 
-    if (bytes < 20)
+    /* wait until we have enough data */
+
+    if (bytes < 8)
         return 0;
 
-    image_size = (buf[4] | (buf[5] << 8) | (buf[6] << 16) | (buf[7] << 24)) + 8;
+    image_size = (buf[4] | (buf[5] << 8) | (buf[6] << 16) | (buf[7] << 24));
 
-    if (bytes < image_size)
+    if (bytes < 8 + image_size)
         return 0;
 
+    /* decode and unpack everything in one go */
+
     image_data = WebPDecodeRGB(buf, bytes, &xsize, &ysize);
 
     if (!image_data) {

libImaging/WebPEncode.c

 int
 ImagingWebPEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
 {
-  return 0;
+    UINT8* buffer;
+    UINT8* ptr;
+    uint8_t* output_data;
+    size_t output_size;
+    int y, stride;
+
+    /* do this in state 0 */
+
+    stride = state->xsize * 3;
+
+    buffer = malloc(im->ysize * stride);
+    if (!buffer) {
+	state->errcode = IMAGING_CODEC_MEMORY;
+        return -1;
+    }
+
+    for (ptr = buffer, y = 0; y < state->ysize; ptr += stride, y++) {
+        state->shuffle(ptr, (UINT8*) im->image[y + state->yoff] +
+		       state->xoff * im->pixelsize, state->xsize);
+    }
+
+    output_size = WebPEncodeRGB(buffer, state->xsize, state->ysize, stride,
+				75.f, &output_data);
+
+    if (!output_size) {
+	state->errcode = IMAGING_CODEC_BROKEN;
+	return -1;
+    }
+
+    /* return data piecewise in state 1 */
+
+    state->errcode = IMAGING_CODEC_END;
+
+    ptr = buf;
+
+    if (output_size < bytes) {
+        memcpy(buf, output_data, output_size);
+	ptr += output_size;
+    }
+
+    return ptr - buf;
 }
 
 #endif