Skip to content

Commit 340bc4c

Browse files
yorkieCopilot
andauthored
html: fix image auto downsampling if SkCodec doesn't support (#65)
Co-authored-by: Copilot <[email protected]>
1 parent e2029fd commit 340bc4c

File tree

1 file changed

+53
-8
lines changed

1 file changed

+53
-8
lines changed

src/client/html/html_image_element.cpp

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)