Commit 356a4d2b authored by Alex Deymo's avatar Alex Deymo Committed by Commit Bot

Add Blink.DecodedImage.JpegDensity metric reporting JPEG bits per pixel size.

This new metric computes the image file size relative to the image
area, also called "compression density" in the compression world. This
value is the number of compressed bits per pixel, and it is only
reported for large enough images (at least 100px per side), to avoid
degenerated cases where the image is too small giving a meaningless
value.

Image compression formats and encoders for these formats use different
techniques to compress an image, discarding some of the original data
(for lossy compression). Depending on the range of the desired quality
(as measured in bits per pixel) some techniques are more efficient than
others. For example, at very low qualities (such as 0.2 bits per pixel)
typical 8x8 DCT strategies like in JPEG are not the best since the 8x8
independent blocks are too small to allow sharing information (only
12.8 bits per block).

Test: Added unittest. Checked chrome://histograms after browsing some pages.
Bug: None
Cq-Include-Trybots: luci.chromium.try:linux_layout_tests_slimming_paint_v2;master.tryserver.blink:linux_trusty_blink_rel
Change-Id: Ia4454f66f1b7bde6a1d1b2cfb533f7539f425780
Reviewed-on: https://chromium-review.googlesource.com/1177750Reviewed-by: default avatarPhilip Rogers <pdr@chromium.org>
Reviewed-by: default avatarSteven Holte <holte@chromium.org>
Commit-Queue: Philip Rogers <pdr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#584172}
parent 02781f62
......@@ -185,6 +185,15 @@ Image::SizeAvailability BitmapImage::SetData(scoped_refptr<SharedBuffer> data,
return DataChanged(all_data_received);
}
// Return the image density in 0.01 "bits per pixel" rounded to the nearest
// integer.
static inline int ImageDensityInCentiBpp(IntSize size,
size_t image_size_bytes) {
uint64_t image_area = static_cast<uint64_t>(size.Width()) * size.Height();
return (static_cast<uint64_t>(image_size_bytes) * 100 * 8 + image_area / 2) /
image_area;
}
Image::SizeAvailability BitmapImage::DataChanged(bool all_data_received) {
TRACE_EVENT0("blink", "BitmapImage::dataChanged");
......@@ -193,6 +202,17 @@ Image::SizeAvailability BitmapImage::DataChanged(bool all_data_received) {
// requires a new PaintImageGenerator instance.
cached_frame_ = PaintImage();
// Report the image density metric right after we received all the data. The
// SetData() call on the decoder_ (if there is one) should have decoded the
// images and we should know the image size at this point. We still check it
// here as a sanity check.
if (!all_data_received_ && all_data_received && decoder_ &&
decoder_->Data() && decoder_->FilenameExtension() == "jpg" &&
IsSizeAvailable() && Size().Width() >= 100 && Size().Height() >= 100) {
BitmapImageMetrics::CountImageJpegDensity(
ImageDensityInCentiBpp(Size(), decoder_->Data()->size()));
}
// Feed all the data we've seen so far to the image decoder.
all_data_received_ = all_data_received;
have_frame_count_ = false;
......
......@@ -42,6 +42,13 @@ void BitmapImageMetrics::CountImageOrientation(
orientation_histogram.Count(orientation);
}
void BitmapImageMetrics::CountImageJpegDensity(int64_t density_centi_bpp) {
DEFINE_THREAD_SAFE_STATIC_LOCAL(
CustomCountHistogram, density_histogram,
("Blink.DecodedImage.JpegDensity", 1, 1000, 100)); // 0.01 to 10 bpp
density_histogram.Count(density_centi_bpp);
}
void BitmapImageMetrics::CountImageGammaAndGamut(
const skcms_ICCProfile* color_profile) {
DEFINE_THREAD_SAFE_STATIC_LOCAL(EnumerationHistogram, gamma_named_histogram,
......
......@@ -49,6 +49,7 @@ class PLATFORM_EXPORT BitmapImageMetrics {
static void CountDecodedImageType(const String& type);
static void CountImageOrientation(const ImageOrientationEnum);
static void CountImageJpegDensity(int64_t density_centi_bpp);
static void CountImageGammaAndGamut(const skcms_ICCProfile*);
private:
......@@ -57,4 +58,4 @@ class PLATFORM_EXPORT BitmapImageMetrics {
} // namespace blink
#endif
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_BITMAP_IMAGE_METRICS_H_
......@@ -730,4 +730,22 @@ INSTANTIATE_TEST_CASE_P(
DecodedImageOrientationHistogramTest,
testing::ValuesIn(kDecodedImageOrientationHistogramTestParams));
using DecodedImageDensityHistogramTest = BitmapHistogramTest<int>;
TEST_P(DecodedImageDensityHistogramTest, ImageOrientation) {
RunTest("Blink.DecodedImage.JpegDensity");
}
const DecodedImageDensityHistogramTest::ParamType
kDecodedImageDensityHistogramTestParams[] = {
// 439x154, 23220 bytes --> 2.74 bpp
{"/images/resources/cropped_mandrill.jpg", 274},
// 320x320, 74017 bytes --> 5.78
{"/images/resources/blue-wheel-srgb-color-profile.jpg", 578}};
INSTANTIATE_TEST_CASE_P(
DecodedImageDensityHistogramTest,
DecodedImageDensityHistogramTest,
testing::ValuesIn(kDecodedImageDensityHistogramTestParams));
} // namespace blink
......@@ -8592,6 +8592,16 @@ uploading your change for review.
</summary>
</histogram>
<histogram name="Blink.DecodedImage.JpegDensity" units="0.01 bits per pixel">
<owner>deymo@google.com</owner>
<owner>compression-dev@google.com</owner>
<summary>
The compressed image density measured in 0.01 bits per pixel. This is logged
once per image load after the whole image is loaded and only for JPEGs with
at least 100 pixels on each dimension.
</summary>
</histogram>
<histogram name="Blink.DecodedImage.Orientation" enum="DecodedImageOrientation">
<owner>rob.buis@samsung.org</owner>
<summary>Image orientation inferred during decode.</summary>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment