1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "services/data_decoder/public/cpp/decode_image.h"
6 
7 #include <utility>
8 
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/callback_helpers.h"
12 #include "mojo/public/cpp/bindings/remote.h"
13 #include "services/data_decoder/public/cpp/data_decoder.h"
14 #include "third_party/skia/include/core/SkBitmap.h"
15 
16 namespace data_decoder {
17 
18 namespace {
19 
20 // Helper callback which owns a mojo::Remote<ImageDecoder> until invoked. This
21 // keeps the ImageDecoder pipe open just long enough to dispatch a reply, at
22 // which point the reply is forwarded to the wrapped |callback|.
OnDecodeImage(mojo::Remote<mojom::ImageDecoder> decoder,mojom::ImageDecoder::DecodeImageCallback callback,const SkBitmap & bitmap)23 void OnDecodeImage(mojo::Remote<mojom::ImageDecoder> decoder,
24                    mojom::ImageDecoder::DecodeImageCallback callback,
25                    const SkBitmap& bitmap) {
26   std::move(callback).Run(bitmap);
27 }
28 
OnDecodeImages(mojo::Remote<mojom::ImageDecoder> decoder,mojom::ImageDecoder::DecodeAnimationCallback callback,std::vector<mojom::AnimationFramePtr> bitmaps)29 void OnDecodeImages(mojo::Remote<mojom::ImageDecoder> decoder,
30                     mojom::ImageDecoder::DecodeAnimationCallback callback,
31                     std::vector<mojom::AnimationFramePtr> bitmaps) {
32   std::move(callback).Run(std::move(bitmaps));
33 }
34 
35 }  // namespace
36 
DecodeImageIsolated(const std::vector<uint8_t> & encoded_bytes,mojom::ImageCodec codec,bool shrink_to_fit,uint64_t max_size_in_bytes,const gfx::Size & desired_image_frame_size,mojom::ImageDecoder::DecodeImageCallback callback)37 void DecodeImageIsolated(const std::vector<uint8_t>& encoded_bytes,
38                          mojom::ImageCodec codec,
39                          bool shrink_to_fit,
40                          uint64_t max_size_in_bytes,
41                          const gfx::Size& desired_image_frame_size,
42                          mojom::ImageDecoder::DecodeImageCallback callback) {
43   // Create a new DataDecoder that we keep alive until |callback| is invoked.
44   auto data_decoder = std::make_unique<DataDecoder>();
45   auto* raw_decoder = data_decoder.get();
46   auto wrapped_callback = base::BindOnce(
47       [](std::unique_ptr<DataDecoder>,
48          mojom::ImageDecoder::DecodeImageCallback callback,
49          const SkBitmap& bitmap) { std::move(callback).Run(bitmap); },
50       std::move(data_decoder), std::move(callback));
51   DecodeImage(raw_decoder, encoded_bytes, codec, shrink_to_fit,
52               max_size_in_bytes, desired_image_frame_size,
53               std::move(wrapped_callback));
54 }
55 
DecodeImage(DataDecoder * data_decoder,const std::vector<uint8_t> & encoded_bytes,mojom::ImageCodec codec,bool shrink_to_fit,uint64_t max_size_in_bytes,const gfx::Size & desired_image_frame_size,mojom::ImageDecoder::DecodeImageCallback callback)56 void DecodeImage(DataDecoder* data_decoder,
57                  const std::vector<uint8_t>& encoded_bytes,
58                  mojom::ImageCodec codec,
59                  bool shrink_to_fit,
60                  uint64_t max_size_in_bytes,
61                  const gfx::Size& desired_image_frame_size,
62                  mojom::ImageDecoder::DecodeImageCallback callback) {
63   mojo::Remote<mojom::ImageDecoder> decoder;
64   data_decoder->GetService()->BindImageDecoder(
65       decoder.BindNewPipeAndPassReceiver());
66 
67   // |call_once| runs |callback| on its first invocation.
68   auto call_once = base::AdaptCallbackForRepeating(std::move(callback));
69   decoder.set_disconnect_handler(base::BindOnce(call_once, SkBitmap()));
70 
71   mojom::ImageDecoder* raw_decoder = decoder.get();
72   raw_decoder->DecodeImage(
73       encoded_bytes, codec, shrink_to_fit, max_size_in_bytes,
74       desired_image_frame_size,
75       base::BindOnce(&OnDecodeImage, std::move(decoder), std::move(call_once)));
76 }
77 
DecodeAnimationIsolated(const std::vector<uint8_t> & encoded_bytes,bool shrink_to_fit,uint64_t max_size_in_bytes,mojom::ImageDecoder::DecodeAnimationCallback callback)78 void DecodeAnimationIsolated(
79     const std::vector<uint8_t>& encoded_bytes,
80     bool shrink_to_fit,
81     uint64_t max_size_in_bytes,
82     mojom::ImageDecoder::DecodeAnimationCallback callback) {
83   // Create a new DataDecoder that we keep alive until |callback| is invoked.
84   auto decoder = std::make_unique<DataDecoder>();
85   auto* raw_decoder = decoder.get();
86   auto wrapped_callback = base::BindOnce(
87       [](std::unique_ptr<DataDecoder>,
88          mojom::ImageDecoder::DecodeAnimationCallback callback,
89          std::vector<mojom::AnimationFramePtr> frames) {
90         std::move(callback).Run(std::move(frames));
91       },
92       std::move(decoder), std::move(callback));
93   DecodeAnimation(raw_decoder, encoded_bytes, shrink_to_fit, max_size_in_bytes,
94                   std::move(wrapped_callback));
95 }
96 
DecodeAnimation(DataDecoder * data_decoder,const std::vector<uint8_t> & encoded_bytes,bool shrink_to_fit,uint64_t max_size_in_bytes,mojom::ImageDecoder::DecodeAnimationCallback callback)97 void DecodeAnimation(DataDecoder* data_decoder,
98                      const std::vector<uint8_t>& encoded_bytes,
99                      bool shrink_to_fit,
100                      uint64_t max_size_in_bytes,
101                      mojom::ImageDecoder::DecodeAnimationCallback callback) {
102   mojo::Remote<mojom::ImageDecoder> decoder;
103   data_decoder->GetService()->BindImageDecoder(
104       decoder.BindNewPipeAndPassReceiver());
105 
106   // |call_once| runs |callback| on its first invocation.
107   auto call_once = base::AdaptCallbackForRepeating(std::move(callback));
108   decoder.set_disconnect_handler(
109       base::BindOnce(call_once, std::vector<mojom::AnimationFramePtr>()));
110 
111   mojom::ImageDecoder* raw_decoder = decoder.get();
112   raw_decoder->DecodeAnimation(
113       encoded_bytes, shrink_to_fit, max_size_in_bytes,
114       base::BindOnce(&OnDecodeImages, std::move(decoder),
115                      std::move(call_once)));
116 }
117 
118 }  // namespace data_decoder
119