Home | History | Annotate | Download | only in images
      1 /*
      2  * Copyright 2009 The Android Open Source Project
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkImageEncoderPriv.h"
      9 #include "SkJpegEncoder.h"
     10 #include "SkPngEncoder.h"
     11 #include "SkWebpEncoder.h"
     12 
     13 #ifndef SK_HAS_JPEG_LIBRARY
     14 bool SkJpegEncoder::Encode(SkWStream*, const SkPixmap&, const Options&) { return false; }
     15 std::unique_ptr<SkEncoder> SkJpegEncoder::Make(SkWStream*, const SkPixmap&, const Options&) {
     16     return nullptr;
     17 }
     18 #endif
     19 
     20 #ifndef SK_HAS_PNG_LIBRARY
     21 bool SkPngEncoder::Encode(SkWStream*, const SkPixmap&, const Options&) { return false; }
     22 std::unique_ptr<SkEncoder> SkPngEncoder::Make(SkWStream*, const SkPixmap&, const Options&) {
     23     return nullptr;
     24 }
     25 #endif
     26 
     27 #ifndef SK_HAS_WEBP_LIBRARY
     28 bool SkWebpEncoder::Encode(SkWStream*, const SkPixmap&, const Options&) { return false; }
     29 #endif
     30 
     31 bool SkEncodeImage(SkWStream* dst, const SkPixmap& src,
     32                    SkEncodedImageFormat format, int quality) {
     33     #ifdef SK_USE_CG_ENCODER
     34         (void)quality;
     35         return SkEncodeImageWithCG(dst, src, format);
     36     #elif SK_USE_WIC_ENCODER
     37         return SkEncodeImageWithWIC(dst, src, format, quality);
     38     #else
     39         switch(format) {
     40             case SkEncodedImageFormat::kJPEG: {
     41                 SkJpegEncoder::Options opts;
     42                 opts.fQuality = quality;
     43                 return SkJpegEncoder::Encode(dst, src, opts);
     44             }
     45             case SkEncodedImageFormat::kPNG: {
     46                 SkPngEncoder::Options opts;
     47                 return SkPngEncoder::Encode(dst, src, opts);
     48             }
     49             case SkEncodedImageFormat::kWEBP: {
     50                 SkWebpEncoder::Options opts;
     51                 if (quality == 100) {
     52                     opts.fCompression = SkWebpEncoder::Compression::kLossless;
     53                     // Note: SkEncodeImage treats 0 quality as the lowest quality
     54                     // (greatest compression) and 100 as the highest quality (least
     55                     // compression). For kLossy, this matches libwebp's
     56                     // interpretation, so it is passed directly to libwebp. But
     57                     // with kLossless, libwebp always creates the highest quality
     58                     // image. In this case, fQuality is reinterpreted as how much
     59                     // effort (time) to put into making a smaller file. This API
     60                     // does not provide a way to specify this value (though it can
     61                     // be specified by using SkWebpEncoder::Encode) so we have to
     62                     // pick one arbitrarily. This value matches that chosen by
     63                     // blink::ImageEncoder::ComputeWebpOptions as well
     64                     // WebPConfigInit.
     65                     opts.fQuality = 75;
     66                 } else {
     67                     opts.fCompression = SkWebpEncoder::Compression::kLossy;
     68                     opts.fQuality = quality;
     69                 }
     70                 return SkWebpEncoder::Encode(dst, src, opts);
     71             }
     72             default:
     73                 return false;
     74         }
     75     #endif
     76 }
     77 
     78 bool SkEncoder::encodeRows(int numRows) {
     79     SkASSERT(numRows > 0 && fCurrRow < fSrc.height());
     80     if (numRows <= 0 || fCurrRow >= fSrc.height()) {
     81         return false;
     82     }
     83 
     84     if (fCurrRow + numRows > fSrc.height()) {
     85         numRows = fSrc.height() - fCurrRow;
     86     }
     87 
     88     if (!this->onEncodeRows(numRows)) {
     89         // If we fail, short circuit any future calls.
     90         fCurrRow = fSrc.height();
     91         return false;
     92     }
     93 
     94     return true;
     95 }
     96 
     97 sk_sp<SkData> SkEncodePixmap(const SkPixmap& src, SkEncodedImageFormat format, int quality) {
     98     SkDynamicMemoryWStream stream;
     99     return SkEncodeImage(&stream, src, format, quality) ? stream.detachAsData() : nullptr;
    100 }
    101 
    102 sk_sp<SkData> SkEncodeBitmap(const SkBitmap& src, SkEncodedImageFormat format, int quality) {
    103     SkPixmap pixmap;
    104     return src.peekPixels(&pixmap) ? SkEncodePixmap(pixmap, format, quality) : nullptr;
    105 }
    106