1 /*
2 * Copyright 2023 Google LLC
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 "tools/EncodeUtils.h"
9
10 #include "include/core/SkBitmap.h"
11 #include "include/core/SkData.h"
12 #include "include/core/SkDataTable.h"
13 #include "include/core/SkPixmap.h"
14 #include "include/core/SkRefCnt.h"
15 #include "include/core/SkStream.h"
16 #include "include/core/SkString.h"
17 #include "include/encode/SkPngEncoder.h"
18 #include "src/base/SkBase64.h"
19
20 #include <cstddef>
21 #include <cstdint>
22
23 namespace ToolUtils {
24
BitmapToBase64DataURI(const SkBitmap & bitmap,SkString * dst)25 bool BitmapToBase64DataURI(const SkBitmap& bitmap, SkString* dst) {
26 SkPixmap pm;
27 if (!bitmap.peekPixels(&pm)) {
28 dst->set("peekPixels failed");
29 return false;
30 }
31
32 // We're going to embed this PNG in a data URI, so make it as small as possible
33 SkPngEncoder::Options options;
34 options.fFilterFlags = SkPngEncoder::FilterFlag::kAll;
35 options.fZLibLevel = 9;
36
37 SkDynamicMemoryWStream wStream;
38 if (!SkPngEncoder::Encode(&wStream, pm, options)) {
39 dst->set("SkPngEncoder::Encode failed");
40 return false;
41 }
42
43 sk_sp<SkData> pngData = wStream.detachAsData();
44 size_t len = SkBase64::EncodedSize(pngData->size());
45
46 // The PNG can be almost arbitrarily large. We don't want to fill our logs with enormous URLs.
47 // Infra says these can be pretty big, as long as we're only outputting them on failure.
48 static const size_t kMaxBase64Length = 1024 * 1024;
49 if (len > kMaxBase64Length) {
50 dst->printf("Encoded image too large (%u bytes)", static_cast<uint32_t>(len));
51 return false;
52 }
53
54 dst->resize(len);
55 SkBase64::Encode(pngData->data(), pngData->size(), dst->data());
56 dst->prepend("data:image/png;base64,");
57 return true;
58 }
59
EncodeImageToPngFile(const char * path,const SkBitmap & src)60 bool EncodeImageToPngFile(const char* path, const SkBitmap& src) {
61 SkFILEWStream file(path);
62 return file.isValid() && SkPngEncoder::Encode(&file, src.pixmap(), {});
63 }
64
EncodeImageToPngFile(const char * path,const SkPixmap & src)65 bool EncodeImageToPngFile(const char* path, const SkPixmap& src) {
66 SkFILEWStream file(path);
67 return file.isValid() && SkPngEncoder::Encode(&file, src, {});
68 }
69
70 } // namespace ToolUtils
71