blob: 2c3501a6241014ecd6270b58c3a6d4cf0abd48ca [file] [log] [blame]
markusheintzc7570762016-06-15 10:17:251// 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 <algorithm>
6#include <vector>
7
rockot2a0f4fb32016-11-11 18:44:198#include "base/callback.h"
Brandon Wylie7debc712019-04-10 00:27:589#include "chrome/browser/image_fetcher/image_decoder_impl.h"
tschumann30ee1082017-03-02 19:37:5310#include "ui/gfx/geometry/size.h"
markusheintzc7570762016-06-15 10:17:2511#include "ui/gfx/image/image.h"
12
markusheintzc7570762016-06-15 10:17:2513// A request for decoding an image.
14class ImageDecoderImpl::DecodeImageRequest
15 : public ::ImageDecoder::ImageRequest {
16 public:
17 DecodeImageRequest(ImageDecoderImpl* decoder,
Brandon Wylieb8bf92d2019-04-10 19:18:2618 image_fetcher::ImageDecodedCallback callback)
19 : decoder_(decoder), callback_(std::move(callback)) {}
Peter Boström53c6c5952021-09-17 09:41:2620
21 DecodeImageRequest(const DecodeImageRequest&) = delete;
22 DecodeImageRequest& operator=(const DecodeImageRequest&) = delete;
23
markusheintzc7570762016-06-15 10:17:2524 ~DecodeImageRequest() override {}
25
26 private:
27 // Runs the callback and remove the request from the internal request queue.
28 void RunCallbackAndRemoveRequest(const gfx::Image& image);
29
30 // Methods inherited from ImageDecoder::ImageRequest
31
32 void OnImageDecoded(const SkBitmap& decoded_image) override;
33
34 void OnDecodeImageFailed() override;
35
36 ImageDecoderImpl* decoder_;
37
38 // The callback to call after the request completed.
39 image_fetcher::ImageDecodedCallback callback_;
markusheintzc7570762016-06-15 10:17:2540};
41
42void ImageDecoderImpl::DecodeImageRequest::OnImageDecoded(
43 const SkBitmap& decoded_bitmap) {
44 // TODO(markusheintz): Check whether high res displays that require 2x and 3x
45 // image versions need to be supported here.
46 gfx::Image image(gfx::Image::CreateFrom1xBitmap(decoded_bitmap));
47 RunCallbackAndRemoveRequest(image);
48}
49
50// Called when decoding image failed.
51void ImageDecoderImpl::DecodeImageRequest::OnDecodeImageFailed() {
52 RunCallbackAndRemoveRequest(gfx::Image());
53}
54
55void ImageDecoderImpl::DecodeImageRequest::RunCallbackAndRemoveRequest(
56 const gfx::Image& image) {
Brandon Wylieb8bf92d2019-04-10 19:18:2657 std::move(callback_).Run(image);
markusheintzc7570762016-06-15 10:17:2558
59 // This must be the last line in the method body.
60 decoder_->RemoveDecodeImageRequest(this);
61}
62
Brandon Wylie7debc712019-04-10 00:27:5863ImageDecoderImpl::ImageDecoderImpl() {}
markusheintzc7570762016-06-15 10:17:2564
65ImageDecoderImpl::~ImageDecoderImpl() {}
66
67void ImageDecoderImpl::DecodeImage(
68 const std::string& image_data,
tschumann30ee1082017-03-02 19:37:5369 const gfx::Size& desired_image_frame_size,
Brandon Wylieb8bf92d2019-04-10 19:18:2670 image_fetcher::ImageDecodedCallback callback) {
markusheintzc7570762016-06-15 10:17:2571 std::unique_ptr<DecodeImageRequest> decode_image_request(
Brandon Wylieb8bf92d2019-04-10 19:18:2672 new DecodeImageRequest(this, std::move(callback)));
markusheintzc7570762016-06-15 10:17:2573
tschumann30ee1082017-03-02 19:37:5374 ::ImageDecoder::StartWithOptions(
75 decode_image_request.get(),
76 std::vector<uint8_t>(image_data.begin(), image_data.end()),
77 ::ImageDecoder::DEFAULT_CODEC,
78 /*shrink_to_fit=*/false, desired_image_frame_size);
markusheintzc7570762016-06-15 10:17:2579
80 decode_image_requests_.push_back(std::move(decode_image_request));
81}
82
83void ImageDecoderImpl::RemoveDecodeImageRequest(DecodeImageRequest* request) {
84 // Remove the finished request from the request queue.
85 auto request_it =
Brandon Wylie7debc712019-04-10 00:27:5886 std::find_if(decode_image_requests_.begin(), decode_image_requests_.end(),
markusheintzc7570762016-06-15 10:17:2587 [request](const std::unique_ptr<DecodeImageRequest>& r) {
88 return r.get() == request;
89 });
90 DCHECK(request_it != decode_image_requests_.end());
91 decode_image_requests_.erase(request_it);
92}