@@ -163,15 +163,60 @@ namespace dom
163163 // back-compatibility.
164164 //
165165 // TODO(yorkie): support tweaking or disabling for different platforms?
166- float scale = std::min (static_cast <float >(transmute::ImageProcessor::DEFAULT_MAX_IMAGE_SIZE) / info.width (),
167- static_cast <float >(transmute::ImageProcessor::DEFAULT_MAX_IMAGE_SIZE) / info.height ());
168- int scaled_width = static_cast <int >(info.width () * scale);
169- int scaled_height = static_cast <int >(info.height () * scale);
170- info = info.makeWH (scaled_width, scaled_height);
171- }
166+ int original_width = info.width ();
167+ int original_height = info.height ();
168+ float scale = std::min (
169+ static_cast <float >(transmute::ImageProcessor::DEFAULT_MAX_IMAGE_SIZE) / original_width,
170+ static_cast <float >(transmute::ImageProcessor::DEFAULT_MAX_IMAGE_SIZE) / original_height);
171+ int scaled_width = static_cast <int >(original_width * scale);
172+ int scaled_height = static_cast <int >(original_height * scale);
173+ SkImageInfo scaled_info = info.makeWH (scaled_width, scaled_height);
174+
175+ // Allocate the scaled bitmap with the scaled image info.
176+ SkBitmap scaled_bitmap;
177+ scaled_bitmap.allocPixels (scaled_info);
178+
179+ // Call `getPixels()` first to check if the current codec supports scaling.
180+ auto r = codec->getPixels (scaled_info, scaled_bitmap.getPixels (), scaled_bitmap.rowBytes ());
181+ if (r == SkCodec::kSuccess )
182+ {
183+ // Returns the scaled bitmap if the scaling is successful.
184+ bitmap = scaled_bitmap;
185+ }
186+ else if (r == SkCodec::kInvalidScale )
187+ {
188+ // `InvalidScale` means the codec does not support scaling, so we need to do the scaling after decoding
189+ // the original pixels.
190+ SkBitmap original_bitmap;
191+ original_bitmap.allocPixels (info);
192+ const SkPixmap &original_pixmap = original_bitmap.pixmap ();
193+
194+ // Decoding the original image pixels.
195+ r = codec->getPixels (original_pixmap);
196+ if (r != SkCodec::kSuccess )
197+ throw runtime_error (" Could not decode the original image data." );
172198
173- bitmap.allocPixels (info);
174- codec->getPixels (info, bitmap.getPixels (), bitmap.rowBytes ());
199+ // Use linear filtering to scale the original pixmap to the scaled bitmap.
200+ if (original_pixmap.scalePixels (scaled_bitmap.pixmap (),
201+ SkSamplingOptions (SkFilterMode::kLinear )))
202+ {
203+ bitmap = scaled_bitmap;
204+ }
205+ else
206+ {
207+ // FIXME(yorkie): should use `original_bitmap` as the fallback?
208+ throw runtime_error (" Could not scale a valid bitmap." );
209+ }
210+ }
211+ }
212+ else
213+ {
214+ // No need to scale if the image size is within the maximum allowed size.
215+ bitmap.allocPixels (info);
216+ auto r = codec->getPixels (info, bitmap.getPixels (), bitmap.rowBytes ());
217+ if (r != SkCodec::kSuccess )
218+ throw runtime_error (SkCodec::ResultToString (r));
219+ }
175220 is_src_image_decoded_ = true ;
176221 }
177222 catch (const exception &e)
0 commit comments