1/* 2 * Copyright (c) 2011, Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31#include "config.h" 32#include "platform/image-encoders/skia/WEBPImageEncoder.h" 33 34#include "SkBitmap.h" 35#include "platform/geometry/IntSize.h" 36#include "platform/graphics/ImageBuffer.h" 37#include "webp/encode.h" 38 39typedef int (*WebPImporter)(WebPPicture* const, const uint8_t* const data, int rowStride); 40 41namespace WebCore { 42 43static int writeOutput(const uint8_t* data, size_t size, const WebPPicture* const picture) 44{ 45 static_cast<Vector<unsigned char>*>(picture->custom_ptr)->append(data, size); 46 return 1; 47} 48 49static bool rgbPictureImport(const unsigned char* pixels, bool premultiplied, WebPImporter importRGBX, WebPImporter importRGB, WebPPicture* picture) 50{ 51 if (premultiplied) 52 return importRGBX(picture, pixels, picture->width * 4); 53 54 // Write the RGB pixels to an rgb data buffer, alpha premultiplied, then import the rgb data. 55 56 Vector<unsigned char> rgb; 57 size_t pixelCount = picture->height * picture->width; 58 rgb.reserveInitialCapacity(pixelCount * 3); 59 60 for (unsigned char* data = rgb.data(); pixelCount-- > 0; pixels += 4) { 61 unsigned char alpha = pixels[3]; 62 if (alpha != 255) { 63 *data++ = SkMulDiv255Round(pixels[0], alpha); 64 *data++ = SkMulDiv255Round(pixels[1], alpha); 65 *data++ = SkMulDiv255Round(pixels[2], alpha); 66 } else { 67 *data++ = pixels[0]; 68 *data++ = pixels[1]; 69 *data++ = pixels[2]; 70 } 71 } 72 73 return importRGB(picture, rgb.data(), picture->width * 3); 74} 75 76template <bool Premultiplied> inline bool importPictureBGRX(const unsigned char* pixels, WebPPicture* picture) 77{ 78 return rgbPictureImport(pixels, Premultiplied, &WebPPictureImportBGRX, &WebPPictureImportBGR, picture); 79} 80 81template <bool Premultiplied> inline bool importPictureRGBX(const unsigned char* pixels, WebPPicture* picture) 82{ 83 return rgbPictureImport(pixels, Premultiplied, &WebPPictureImportRGBX, &WebPPictureImportRGB, picture); 84} 85 86static bool encodePixels(IntSize imageSize, const unsigned char* pixels, bool premultiplied, int quality, Vector<unsigned char>* output) 87{ 88 WebPConfig config; 89 if (!WebPConfigInit(&config)) 90 return false; 91 WebPPicture picture; 92 if (!WebPPictureInit(&picture)) 93 return false; 94 95 imageSize.clampNegativeToZero(); 96 if (!imageSize.width() || imageSize.width() > WEBP_MAX_DIMENSION) 97 return false; 98 picture.width = imageSize.width(); 99 if (!imageSize.height() || imageSize.height() > WEBP_MAX_DIMENSION) 100 return false; 101 picture.height = imageSize.height(); 102 103 if (premultiplied && !importPictureBGRX<true>(pixels, &picture)) 104 return false; 105 if (!premultiplied && !importPictureRGBX<false>(pixels, &picture)) 106 return false; 107 108 picture.custom_ptr = output; 109 picture.writer = &writeOutput; 110 config.quality = quality; 111 config.method = 3; 112 113 bool success = WebPEncode(&config, &picture); 114 WebPPictureFree(&picture); 115 return success; 116} 117 118bool WEBPImageEncoder::encode(const SkBitmap& bitmap, int quality, Vector<unsigned char>* output) 119{ 120 SkAutoLockPixels bitmapLock(bitmap); 121 122 if (bitmap.colorType() != kPMColor_SkColorType || !bitmap.getPixels()) 123 return false; // Only support 32 bit/pixel skia bitmaps. 124 125 return encodePixels(IntSize(bitmap.width(), bitmap.height()), static_cast<unsigned char *>(bitmap.getPixels()), true, quality, output); 126} 127 128bool WEBPImageEncoder::encode(const ImageDataBuffer& imageData, int quality, Vector<unsigned char>* output) 129{ 130 return encodePixels(imageData.size(), imageData.data(), false, quality, output); 131} 132 133} // namespace WebCore 134