add runtime registration for encoders
If we want to make these external dependencies mix-and-match in Google3, we'll need to group together the encoders and decoders, everything that dependends on each external library. I was tempted to try to remove these generic encoder entrypoints and replace them with calls to the direct equivalents, but I'm not sure that's necessary. I think we can just register encoders like decoders. Change-Id: I41d2d1bb3ceb1daafa62c95d345eb6a70249be75 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/213880 Commit-Queue: Mike Klein <mtklein@google.com> Reviewed-by: Brian Osman <brianosman@google.com>
This commit is contained in:
parent
753836fcad
commit
940c3f136d
@ -15,6 +15,9 @@
|
||||
#include "include/core/SkDocument.h"
|
||||
#include "include/core/SkFontMgr.h"
|
||||
#include "include/core/SkGraphics.h"
|
||||
#include "include/encode/SkJpegEncoder.h"
|
||||
#include "include/encode/SkPngEncoder.h"
|
||||
#include "include/encode/SkWebpEncoder.h"
|
||||
#include "include/ports/SkTypeface_win.h"
|
||||
#include "include/private/SkChecksum.h"
|
||||
#include "include/private/SkHalf.h"
|
||||
@ -1394,6 +1397,10 @@ int main(int argc, char** argv) {
|
||||
SkCodec::Register( SkPngCodec::IsPng , SkPngCodec::MakeFromStream);
|
||||
SkCodec::Register(SkWebpCodec::IsWebp, SkWebpCodec::MakeFromStream);
|
||||
|
||||
SkRegisterEncoder(SkEncodedImageFormat::kJPEG, SkJpegEncoder::Encode);
|
||||
SkRegisterEncoder(SkEncodedImageFormat::kPNG , SkPngEncoder::Encode);
|
||||
SkRegisterEncoder(SkEncodedImageFormat::kWEBP, SkWebpEncoder::Encode);
|
||||
|
||||
initializeEventTracingForTools();
|
||||
|
||||
#if !defined(SK_BUILD_FOR_GOOGLE3) && defined(SK_BUILD_FOR_IOS)
|
||||
|
@ -44,6 +44,16 @@ inline bool SkEncodeImage(SkWStream* dst, const SkBitmap& src, SkEncodedImageFor
|
||||
return src.peekPixels(&pixmap) && SkEncodeImage(dst, pixmap, f, q);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an encoder for a given binary image format.
|
||||
*
|
||||
* This encoder may be used by SkEncodeImage / SkEncodePixmap / SkEncodeBitmap.
|
||||
*
|
||||
* Not thread safe.
|
||||
*/
|
||||
SK_API void SkRegisterEncoder(SkEncodedImageFormat fmt,
|
||||
bool(*)(SkWStream*, const SkPixmap&, int quality));
|
||||
|
||||
/**
|
||||
* Encode SkPixmap in the given binary image format.
|
||||
*
|
||||
|
@ -71,6 +71,12 @@ public:
|
||||
*/
|
||||
static bool Encode(SkWStream* dst, const SkPixmap& src, const Options& options);
|
||||
|
||||
static bool Encode(SkWStream* dst, const SkPixmap& src, int quality) {
|
||||
Options options;
|
||||
options.fQuality = quality;
|
||||
return Encode(dst, src, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a jpeg encoder that will encode the |src| pixels to the |dst| stream.
|
||||
* |options| may be used to control the encoding behavior.
|
||||
|
@ -69,6 +69,10 @@ public:
|
||||
*/
|
||||
static bool Encode(SkWStream* dst, const SkPixmap& src, const Options& options);
|
||||
|
||||
static bool Encode(SkWStream* dst, const SkPixmap& src, int /*quality*/) {
|
||||
return Encode(dst, src, Options{});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a png encoder that will encode the |src| pixels to the |dst| stream.
|
||||
* |options| may be used to control the encoding behavior.
|
||||
|
@ -43,6 +43,20 @@ namespace SkWebpEncoder {
|
||||
* Returns true on success. Returns false on an invalid or unsupported |src|.
|
||||
*/
|
||||
SK_API bool Encode(SkWStream* dst, const SkPixmap& src, const Options& options);
|
||||
|
||||
inline bool Encode(SkWStream* dst, const SkPixmap& src, int quality) {
|
||||
SkWebpEncoder::Options opts;
|
||||
if (quality == 100) {
|
||||
// fQuality acts as a signal for how much time to invest encoding a smaller file.
|
||||
// This value matches blink::ImageEncoder::ComputeWebpOptions and WebPConfigInit.
|
||||
opts.fQuality = 75;
|
||||
opts.fCompression = SkWebpEncoder::Compression::kLossless;
|
||||
} else {
|
||||
opts.fQuality = quality;
|
||||
opts.fCompression = SkWebpEncoder::Compression::kLossy;
|
||||
}
|
||||
return SkWebpEncoder::Encode(dst, src, opts);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -9,24 +9,34 @@
|
||||
#include "include/encode/SkPngEncoder.h"
|
||||
#include "include/encode/SkWebpEncoder.h"
|
||||
#include "src/images/SkImageEncoderPriv.h"
|
||||
#include <vector>
|
||||
|
||||
#ifndef SK_HAS_JPEG_LIBRARY
|
||||
bool SkJpegEncoder::Encode(SkWStream*, const SkPixmap&, const Options&) { return false; }
|
||||
std::unique_ptr<SkEncoder> SkJpegEncoder::Make(SkWStream*, const SkPixmap&, const Options&) {
|
||||
return nullptr;
|
||||
struct EncoderProc {
|
||||
SkEncodedImageFormat format;
|
||||
bool (*encode)(SkWStream*, const SkPixmap&, int quality);
|
||||
};
|
||||
|
||||
static std::vector<EncoderProc>* encoders() {
|
||||
static auto* encoders = new std::vector<EncoderProc> {
|
||||
#ifdef SK_HAS_JPEG_LIBRARY
|
||||
{ SkEncodedImageFormat::kJPEG, SkJpegEncoder::Encode },
|
||||
#endif
|
||||
|
||||
#ifdef SK_HAS_PNG_LIBRARY
|
||||
{ SkEncodedImageFormat::kPNG, SkPngEncoder::Encode },
|
||||
#endif
|
||||
|
||||
#ifdef SK_HAS_WEBP_LIBRARY
|
||||
{ SkEncodedImageFormat::kWEBP, SkWebpEncoder::Encode },
|
||||
#endif
|
||||
};
|
||||
return encoders;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SK_HAS_PNG_LIBRARY
|
||||
bool SkPngEncoder::Encode(SkWStream*, const SkPixmap&, const Options&) { return false; }
|
||||
std::unique_ptr<SkEncoder> SkPngEncoder::Make(SkWStream*, const SkPixmap&, const Options&) {
|
||||
return nullptr;
|
||||
void SkRegisterEncoder(SkEncodedImageFormat format,
|
||||
bool (*encode)(SkWStream*, const SkPixmap&, int)) {
|
||||
encoders()->push_back({format, encode});
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SK_HAS_WEBP_LIBRARY
|
||||
bool SkWebpEncoder::Encode(SkWStream*, const SkPixmap&, const Options&) { return false; }
|
||||
#endif
|
||||
|
||||
bool SkEncodeImage(SkWStream* dst, const SkPixmap& src,
|
||||
SkEncodedImageFormat format, int quality) {
|
||||
@ -36,42 +46,12 @@ bool SkEncodeImage(SkWStream* dst, const SkPixmap& src,
|
||||
#elif SK_USE_WIC_ENCODER
|
||||
return SkEncodeImageWithWIC(dst, src, format, quality);
|
||||
#else
|
||||
switch(format) {
|
||||
case SkEncodedImageFormat::kJPEG: {
|
||||
SkJpegEncoder::Options opts;
|
||||
opts.fQuality = quality;
|
||||
return SkJpegEncoder::Encode(dst, src, opts);
|
||||
for (auto encoder : *encoders()) {
|
||||
if (encoder.format == format) {
|
||||
return encoder.encode(dst, src, quality);
|
||||
}
|
||||
case SkEncodedImageFormat::kPNG: {
|
||||
SkPngEncoder::Options opts;
|
||||
return SkPngEncoder::Encode(dst, src, opts);
|
||||
}
|
||||
case SkEncodedImageFormat::kWEBP: {
|
||||
SkWebpEncoder::Options opts;
|
||||
if (quality == 100) {
|
||||
opts.fCompression = SkWebpEncoder::Compression::kLossless;
|
||||
// Note: SkEncodeImage treats 0 quality as the lowest quality
|
||||
// (greatest compression) and 100 as the highest quality (least
|
||||
// compression). For kLossy, this matches libwebp's
|
||||
// interpretation, so it is passed directly to libwebp. But
|
||||
// with kLossless, libwebp always creates the highest quality
|
||||
// image. In this case, fQuality is reinterpreted as how much
|
||||
// effort (time) to put into making a smaller file. This API
|
||||
// does not provide a way to specify this value (though it can
|
||||
// be specified by using SkWebpEncoder::Encode) so we have to
|
||||
// pick one arbitrarily. This value matches that chosen by
|
||||
// blink::ImageEncoder::ComputeWebpOptions as well
|
||||
// WebPConfigInit.
|
||||
opts.fQuality = 75;
|
||||
} else {
|
||||
opts.fCompression = SkWebpEncoder::Compression::kLossy;
|
||||
opts.fQuality = quality;
|
||||
}
|
||||
return SkWebpEncoder::Encode(dst, src, opts);
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user