Commit 4aa71c2d authored by Stephen Chenney's avatar Stephen Chenney Committed by Commit Bot

[Image Orientation] Pipe orientation through from worker-decoded images

The image orientation is not applied when creating a CanvasImageSource
directly from an uploaded file. This is because we do not extract and
pass on the orientation from the decoder.

Fix it by obtaining orientation from the decoder on the worker thread
and passing it back to the original thread to create the image.

Bug: 1069965
Change-Id: I3f64519ed8b91e97bfa9afc802fe90ceb7eb2c3e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2160353Reviewed-by: default avatarFernando Serboncini <fserb@chromium.org>
Commit-Queue: Stephen Chenney <schenney@chromium.org>
Cr-Commit-Position: refs/heads/master@{#761954}
parent b08d5a32
......@@ -923,7 +923,8 @@ void ImageBitmap::ResolvePromiseOnOriginalThread(
ScriptPromiseResolver* resolver,
bool origin_clean,
std::unique_ptr<ParsedOptions> parsed_options,
sk_sp<SkImage> skia_image) {
sk_sp<SkImage> skia_image,
const ImageOrientationEnum orientation) {
if (!skia_image) {
resolver->Reject(
ScriptValue(resolver->GetScriptState()->GetIsolate(),
......@@ -931,7 +932,8 @@ void ImageBitmap::ResolvePromiseOnOriginalThread(
return;
}
scoped_refptr<StaticBitmapImage> image =
UnacceleratedStaticBitmapImage::Create(std::move(skia_image));
UnacceleratedStaticBitmapImage::Create(std::move(skia_image),
orientation);
DCHECK(IsMainThread());
if (!parsed_options->premultiply_alpha) {
image = GetImageWithAlphaDisposition(std::move(image), kUnpremultiplyAlpha);
......@@ -958,7 +960,8 @@ void ImageBitmap::RasterizeImageOnBackgroundThread(
sk_sp<PaintRecord> paint_record,
const IntRect& dst_rect,
scoped_refptr<base::SequencedTaskRunner> task_runner,
WTF::CrossThreadOnceFunction<void(sk_sp<SkImage>)> callback) {
WTF::CrossThreadOnceFunction<void(sk_sp<SkImage>,
const ImageOrientationEnum)> callback) {
DCHECK(!IsMainThread());
SkImageInfo info =
SkImageInfo::MakeN32Premul(dst_rect.Width(), dst_rect.Height());
......@@ -970,7 +973,8 @@ void ImageBitmap::RasterizeImageOnBackgroundThread(
}
PostCrossThreadTask(
*task_runner, FROM_HERE,
CrossThreadBindOnce(std::move(callback), std::move(skia_image)));
CrossThreadBindOnce(std::move(callback), std::move(skia_image),
kDefaultImageOrientation));
}
ScriptPromise ImageBitmap::CreateAsync(ImageElementBase* image,
......
......@@ -145,12 +145,14 @@ class CORE_EXPORT ImageBitmap final : public ScriptWrappable,
static void ResolvePromiseOnOriginalThread(ScriptPromiseResolver*,
bool origin_clean,
std::unique_ptr<ParsedOptions>,
sk_sp<SkImage>);
sk_sp<SkImage>,
const ImageOrientationEnum);
static void RasterizeImageOnBackgroundThread(
sk_sp<PaintRecord>,
const IntRect&,
scoped_refptr<base::SequencedTaskRunner>,
WTF::CrossThreadOnceFunction<void(sk_sp<SkImage>)> callback);
WTF::CrossThreadOnceFunction<void(sk_sp<SkImage>,
const ImageOrientationEnum)> callback);
scoped_refptr<StaticBitmapImage> image_;
bool is_neutered_ = false;
int32_t memory_usage_ = 0;
......
......@@ -314,7 +314,8 @@ void DecodeImageOnDecoderThread(
ArrayBufferContents contents,
ImageDecoder::AlphaOption alpha_option,
ColorBehavior color_behavior,
WTF::CrossThreadOnceFunction<void(sk_sp<SkImage>)> result_callback) {
WTF::CrossThreadOnceFunction<
void(sk_sp<SkImage>, const ImageOrientationEnum)> result_callback) {
const bool data_complete = true;
std::unique_ptr<ImageDecoder> decoder = ImageDecoder::Create(
SegmentReader::CreateFromSkData(
......@@ -322,12 +323,14 @@ void DecodeImageOnDecoderThread(
data_complete, alpha_option, ImageDecoder::kDefaultBitDepth,
color_behavior, ImageDecoder::OverrideAllowDecodeToYuv::kDeny);
sk_sp<SkImage> frame;
ImageOrientationEnum orientation = kDefaultImageOrientation;
if (decoder) {
orientation = decoder->Orientation().Orientation();
frame = ImageBitmap::GetSkImageFromDecoder(std::move(decoder));
}
PostCrossThreadTask(
*task_runner, FROM_HERE,
CrossThreadBindOnce(std::move(result_callback), std::move(frame)));
PostCrossThreadTask(*task_runner, FROM_HERE,
CrossThreadBindOnce(std::move(result_callback),
std::move(frame), orientation));
}
} // namespace
......@@ -354,7 +357,8 @@ void ImageBitmapFactories::ImageBitmapLoader::ScheduleAsyncImageBitmapDecoding(
}
void ImageBitmapFactories::ImageBitmapLoader::ResolvePromiseOnOriginalThread(
sk_sp<SkImage> frame) {
sk_sp<SkImage> frame,
const ImageOrientationEnum orientation) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!frame) {
RejectPromise(kUndecodableImageBitmapRejectionReason);
......@@ -362,9 +366,9 @@ void ImageBitmapFactories::ImageBitmapLoader::ResolvePromiseOnOriginalThread(
}
DCHECK(frame->width());
DCHECK(frame->height());
scoped_refptr<StaticBitmapImage> image =
UnacceleratedStaticBitmapImage::Create(std::move(frame));
UnacceleratedStaticBitmapImage::Create(std::move(frame), orientation);
image->SetOriginClean(true);
auto* image_bitmap =
MakeGarbageCollected<ImageBitmap>(image, crop_rect_, options_);
......
......@@ -141,7 +141,8 @@ class ImageBitmapFactories final
void RejectPromise(ImageBitmapRejectionReason);
void ScheduleAsyncImageBitmapDecoding(ArrayBufferContents);
void ResolvePromiseOnOriginalThread(sk_sp<SkImage>);
void ResolvePromiseOnOriginalThread(sk_sp<SkImage>,
const ImageOrientationEnum);
// ExecutionContextLifecycleObserver
void ContextDestroyed() override;
......
<!DOCTYPE html>
<html class="reftest-wait">
<head>
<meta charset="utf-8">
<title>createImageBitmap and drawImage from a blob with image orientation: from-image</title>
<link rel="author" title="Stephen Chenney" href="mailto:schenney@chromium.org">
<link rel="help" href="https://drafts.csswg.org/css-images-3/#propdef-image-orientation">
<link rel="match" href="reference/drawImage-from-blob-ref.html">
<script>
function makeBlob() {
return new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open("GET", '/css/css-images/image-orientation/support/exif-orientation-3-lr.jpg');
xhr.responseType = 'blob';
xhr.send();
xhr.onload = function() {
resolve(xhr.response);
};
});
}
window.onload = function() {
var cfb = document.getElementById("canvasWithFileBitmap");
makeBlob().then(function(blob){createImageBitmap(blob).then(bitmap => {
cfb.getContext("2d").drawImage(bitmap, 0, 0);
window.requestAnimationFrame(() => {
document.documentElement.removeAttribute("class");
});
});
});
}
</script>
</head>
<body>
<canvas id="canvasWithFileBitmap" width="300" height="300"></canvas>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>createImageBitmap and drawImage from a blob with image orientation: from-image, reference</title>
</head>
<body>
<img id="img-element" src="../../../../css/css-images/image-orientation/support/exif-orientation-3-lr.jpg">
</body>
</html>
\ No newline at end of file
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