Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(585)

Side by Side Diff: third_party/WebKit/Source/core/frame/ImageBitmap.cpp

Issue 2522693002: Color correct ImageBitmap(HTMLImageElement*) constructor (Closed)
Patch Set: Minor correctinos Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "core/frame/ImageBitmap.h" 5 #include "core/frame/ImageBitmap.h"
6 6
7 #include "core/html/HTMLCanvasElement.h" 7 #include "core/html/HTMLCanvasElement.h"
8 #include "core/html/HTMLVideoElement.h" 8 #include "core/html/HTMLVideoElement.h"
9 #include "core/html/ImageData.h" 9 #include "core/html/ImageData.h"
10 #include "platform/graphics/skia/SkiaUtils.h" 10 #include "platform/graphics/skia/SkiaUtils.h"
11 #include "platform/image-decoders/ImageDecoder.h" 11 #include "platform/image-decoders/ImageDecoder.h"
12 #include "third_party/skia/include/core/SkCanvas.h" 12 #include "third_party/skia/include/core/SkCanvas.h"
13 #include "third_party/skia/include/core/SkImageInfo.h"
13 #include "third_party/skia/include/core/SkSurface.h" 14 #include "third_party/skia/include/core/SkSurface.h"
14 #include "wtf/CheckedNumeric.h" 15 #include "wtf/CheckedNumeric.h"
15 #include "wtf/PtrUtil.h" 16 #include "wtf/PtrUtil.h"
16 #include "wtf/RefPtr.h" 17 #include "wtf/RefPtr.h"
17 #include <memory> 18 #include <memory>
18 19
19 namespace blink { 20 namespace blink {
20 21
21 static const char* imageOrientationFlipY = "flipY"; 22 static const char* imageOrientationFlipY = "flipY";
22 static const char* imageBitmapOptionNone = "none"; 23 static const char* imageBitmapOptionNone = "none";
23 24
24 namespace { 25 namespace {
25 26
26 struct ParsedOptions { 27 struct ParsedOptions {
27 bool flipY = false; 28 bool flipY = false;
28 bool premultiplyAlpha = true; 29 bool premultiplyAlpha = true;
29 bool shouldScaleInput = false; 30 bool shouldScaleInput = false;
30 unsigned resizeWidth = 0; 31 unsigned resizeWidth = 0;
31 unsigned resizeHeight = 0; 32 unsigned resizeHeight = 0;
32 IntRect cropRect; 33 IntRect cropRect;
33 SkFilterQuality resizeQuality = kLow_SkFilterQuality; 34 SkFilterQuality resizeQuality = kLow_SkFilterQuality;
34 // This value should be changed in the future when we support 35 sk_sp<SkColorSpace> dstColorSpace = nullptr;
35 // createImageBitmap with higher bit depth, in the parseOptions() function. 36 sk_sp<SkColorSpace> latestColorSpace = nullptr;
36 // For now, it is always 4. 37 SkColorType dstColorType = SkColorType::kN32_SkColorType;
msarett1 2016/11/30 21:32:39 FWIW, I don't think the SkColorType:: is necessary
zakerinasab 2016/12/01 19:49:46 Removed.
37 int bytesPerPixel = 4; 38 SkColorType latestColorType = SkColorType::kN32_SkColorType;
38 }; 39 };
39 40
41 ParsedOptions defaultOptions() {
42 return ParsedOptions();
43 }
44
40 // The following two functions are helpers used in cropImage 45 // The following two functions are helpers used in cropImage
41 static inline IntRect normalizeRect(const IntRect& rect) { 46 static inline IntRect normalizeRect(const IntRect& rect) {
42 return IntRect(std::min(rect.x(), rect.maxX()), 47 return IntRect(std::min(rect.x(), rect.maxX()),
43 std::min(rect.y(), rect.maxY()), 48 std::min(rect.y(), rect.maxY()),
44 std::max(rect.width(), -rect.width()), 49 std::max(rect.width(), -rect.width()),
45 std::max(rect.height(), -rect.height())); 50 std::max(rect.height(), -rect.height()));
46 } 51 }
47 52
48 ParsedOptions parseOptions(const ImageBitmapOptions& options, 53 ParsedOptions parseOptions(const ImageBitmapOptions& options,
49 Optional<IntRect> cropRect, 54 Optional<IntRect> cropRect,
50 IntSize sourceSize) { 55 IntSize sourceSize) {
51 ParsedOptions parsedOptions; 56 ParsedOptions parsedOptions;
52 if (options.imageOrientation() == imageOrientationFlipY) { 57 if (options.imageOrientation() == imageOrientationFlipY) {
53 parsedOptions.flipY = true; 58 parsedOptions.flipY = true;
54 } else { 59 } else {
55 parsedOptions.flipY = false; 60 parsedOptions.flipY = false;
56 DCHECK(options.imageOrientation() == imageBitmapOptionNone); 61 DCHECK(options.imageOrientation() == imageBitmapOptionNone);
57 } 62 }
58 if (options.premultiplyAlpha() == imageBitmapOptionNone) { 63 if (options.premultiplyAlpha() == imageBitmapOptionNone) {
59 parsedOptions.premultiplyAlpha = false; 64 parsedOptions.premultiplyAlpha = false;
60 } else { 65 } else {
61 parsedOptions.premultiplyAlpha = true; 66 parsedOptions.premultiplyAlpha = true;
62 DCHECK(options.premultiplyAlpha() == "default" || 67 DCHECK(options.premultiplyAlpha() == "default" ||
63 options.premultiplyAlpha() == "premultiply"); 68 options.premultiplyAlpha() == "premultiply");
64 } 69 }
65 70
71 if (options.colorSpaceConversion() != "none") {
72 if (!RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled() ||
73 !RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) {
74 DCHECK_EQ(options.colorSpaceConversion(), "default");
75 // TODO(zakerinasab): Replace sRGB with a call to
76 // ImageDecoder::globalTargetColorSpace() when the crash problem on Mac
77 // is fixed. crbug.com/668546.
78 parsedOptions.dstColorSpace =
79 SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named);
80 parsedOptions.dstColorType = SkColorType::kN32_SkColorType;
81 } else {
82 if (options.colorSpaceConversion() == "default" ||
83 options.colorSpaceConversion() == "srgb") {
84 parsedOptions.dstColorSpace =
85 SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named);
86 parsedOptions.dstColorType = SkColorType::kN32_SkColorType;
87 } else if (options.colorSpaceConversion() == "linear-rgb") {
88 parsedOptions.dstColorSpace =
89 SkColorSpace::MakeNamed(SkColorSpace::kSRGBLinear_Named);
90 parsedOptions.dstColorType = SkColorType::kRGBA_F16_SkColorType;
91 } else {
92 NOTREACHED()
93 << "Invalid ImageBitmap creation attribute colorSpaceConversion: "
94 << options.colorSpaceConversion();
95 }
96 }
97 }
98
66 int sourceWidth = sourceSize.width(); 99 int sourceWidth = sourceSize.width();
67 int sourceHeight = sourceSize.height(); 100 int sourceHeight = sourceSize.height();
68 if (!cropRect) { 101 if (!cropRect) {
69 parsedOptions.cropRect = IntRect(0, 0, sourceWidth, sourceHeight); 102 parsedOptions.cropRect = IntRect(0, 0, sourceWidth, sourceHeight);
70 } else { 103 } else {
71 parsedOptions.cropRect = normalizeRect(*cropRect); 104 parsedOptions.cropRect = normalizeRect(*cropRect);
72 } 105 }
73 if (!options.hasResizeWidth() && !options.hasResizeHeight()) { 106 if (!options.hasResizeWidth() && !options.hasResizeHeight()) {
74 parsedOptions.resizeWidth = parsedOptions.cropRect.width(); 107 parsedOptions.resizeWidth = parsedOptions.cropRect.width();
75 parsedOptions.resizeHeight = parsedOptions.cropRect.height(); 108 parsedOptions.resizeHeight = parsedOptions.cropRect.height();
(...skipping 27 matching lines...) Expand all
103 else if (options.resizeQuality() == "pixelated") 136 else if (options.resizeQuality() == "pixelated")
104 parsedOptions.resizeQuality = kNone_SkFilterQuality; 137 parsedOptions.resizeQuality = kNone_SkFilterQuality;
105 else 138 else
106 parsedOptions.resizeQuality = kLow_SkFilterQuality; 139 parsedOptions.resizeQuality = kLow_SkFilterQuality;
107 return parsedOptions; 140 return parsedOptions;
108 } 141 }
109 142
110 bool dstBufferSizeHasOverflow(ParsedOptions options) { 143 bool dstBufferSizeHasOverflow(ParsedOptions options) {
111 CheckedNumeric<unsigned> totalBytes = options.cropRect.width(); 144 CheckedNumeric<unsigned> totalBytes = options.cropRect.width();
112 totalBytes *= options.cropRect.height(); 145 totalBytes *= options.cropRect.height();
113 totalBytes *= options.bytesPerPixel; 146 totalBytes *= SkColorTypeBytesPerPixel(options.latestColorType);
114 if (!totalBytes.IsValid()) 147 if (!totalBytes.IsValid())
115 return true; 148 return true;
116 149
117 if (!options.shouldScaleInput) 150 if (!options.shouldScaleInput)
118 return false; 151 return false;
119 totalBytes = options.resizeWidth; 152 totalBytes = options.resizeWidth;
120 totalBytes *= options.resizeHeight; 153 totalBytes *= options.resizeHeight;
121 totalBytes *= options.bytesPerPixel; 154 totalBytes *= SkColorTypeBytesPerPixel(options.latestColorType);
122 if (!totalBytes.IsValid()) 155 if (!totalBytes.IsValid())
123 return true; 156 return true;
124 157
125 return false; 158 return false;
126 } 159 }
127 160
128 } // namespace 161 } // namespace
129 162
130 static PassRefPtr<Uint8Array> copySkImageData(SkImage* input, 163 static PassRefPtr<Uint8Array> copySkImageData(SkImage* input,
131 const SkImageInfo& info) { 164 const SkImageInfo& info) {
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 srcAddr + bottomRowStartPosition); 213 srcAddr + bottomRowStartPosition);
181 } 214 }
182 } 215 }
183 } else { 216 } else {
184 if (kN32_SkColorType == kBGRA_8888_SkColorType) // needs to swizzle 217 if (kN32_SkColorType == kBGRA_8888_SkColorType) // needs to swizzle
185 for (unsigned i = 0; i < height * bytesPerRow; i += 4) 218 for (unsigned i = 0; i < height * bytesPerRow; i += 4)
186 std::swap(srcAddr[i], srcAddr[i + 2]); 219 std::swap(srcAddr[i], srcAddr[i + 2]);
187 } 220 }
188 } 221 }
189 222
190 static sk_sp<SkImage> flipSkImageVertically(SkImage* input, 223 static sk_sp<SkImage> flipSkImageVertically(
191 AlphaDisposition alphaOp) { 224 SkImage* input,
225 bool enforceAlphaPremultiply = false,
226 const ParsedOptions& options = defaultOptions()) {
192 unsigned width = static_cast<unsigned>(input->width()); 227 unsigned width = static_cast<unsigned>(input->width());
193 unsigned height = static_cast<unsigned>(input->height()); 228 unsigned height = static_cast<unsigned>(input->height());
194 SkImageInfo info = SkImageInfo::MakeN32(input->width(), input->height(), 229 SkAlphaType alphaType = (enforceAlphaPremultiply || options.premultiplyAlpha)
195 (alphaOp == PremultiplyAlpha) 230 ? kPremul_SkAlphaType
196 ? kPremul_SkAlphaType 231 : kUnpremul_SkAlphaType;
197 : kUnpremul_SkAlphaType); 232 SkImageInfo info = SkImageInfo::Make(input->width(), input->height(),
233 options.latestColorType, alphaType,
234 options.latestColorSpace);
235
198 unsigned imageRowBytes = width * info.bytesPerPixel(); 236 unsigned imageRowBytes = width * info.bytesPerPixel();
199 RefPtr<Uint8Array> imagePixels = copySkImageData(input, info); 237 RefPtr<Uint8Array> imagePixels = copySkImageData(input, info);
200 if (!imagePixels) 238 if (!imagePixels)
201 return nullptr; 239 return nullptr;
202 for (unsigned i = 0; i < height / 2; i++) { 240 for (unsigned i = 0; i < height / 2; i++) {
203 unsigned topFirstElement = i * imageRowBytes; 241 unsigned topFirstElement = i * imageRowBytes;
204 unsigned topLastElement = (i + 1) * imageRowBytes; 242 unsigned topLastElement = (i + 1) * imageRowBytes;
205 unsigned bottomFirstElement = (height - 1 - i) * imageRowBytes; 243 unsigned bottomFirstElement = (height - 1 - i) * imageRowBytes;
206 std::swap_ranges(imagePixels->data() + topFirstElement, 244 std::swap_ranges(imagePixels->data() + topFirstElement,
207 imagePixels->data() + topLastElement, 245 imagePixels->data() + topLastElement,
208 imagePixels->data() + bottomFirstElement); 246 imagePixels->data() + bottomFirstElement);
209 } 247 }
210 return newSkImageFromRaster(info, std::move(imagePixels), imageRowBytes); 248 return newSkImageFromRaster(info, std::move(imagePixels), imageRowBytes);
211 } 249 }
212 250
213 static sk_sp<SkImage> premulSkImageToUnPremul(SkImage* input) { 251 static sk_sp<SkImage> premulSkImageToUnPremul(
214 SkImageInfo info = SkImageInfo::Make(input->width(), input->height(), 252 SkImage* input,
215 kN32_SkColorType, kUnpremul_SkAlphaType); 253 const ParsedOptions& options = defaultOptions()) {
254 SkImageInfo info = SkImageInfo::Make(
255 input->width(), input->height(), options.latestColorType,
256 kUnpremul_SkAlphaType, options.latestColorSpace);
257
216 RefPtr<Uint8Array> dstPixels = copySkImageData(input, info); 258 RefPtr<Uint8Array> dstPixels = copySkImageData(input, info);
217 if (!dstPixels) 259 if (!dstPixels)
218 return nullptr; 260 return nullptr;
219 return newSkImageFromRaster( 261 return newSkImageFromRaster(
220 info, std::move(dstPixels), 262 info, std::move(dstPixels),
221 static_cast<unsigned>(input->width()) * info.bytesPerPixel()); 263 static_cast<unsigned>(input->width()) * info.bytesPerPixel());
222 } 264 }
223 265
224 static sk_sp<SkImage> unPremulSkImageToPremul(SkImage* input) { 266 static sk_sp<SkImage> unPremulSkImageToPremul(
225 SkImageInfo info = SkImageInfo::Make(input->width(), input->height(), 267 SkImage* input,
226 kN32_SkColorType, kPremul_SkAlphaType); 268 const ParsedOptions& options = defaultOptions()) {
269 SkImageInfo info = SkImageInfo::Make(
270 input->width(), input->height(), options.latestColorType,
271 kPremul_SkAlphaType, options.latestColorSpace);
272
227 RefPtr<Uint8Array> dstPixels = copySkImageData(input, info); 273 RefPtr<Uint8Array> dstPixels = copySkImageData(input, info);
228 if (!dstPixels) 274 if (!dstPixels)
229 return nullptr; 275 return nullptr;
230 return newSkImageFromRaster( 276 return newSkImageFromRaster(
231 info, std::move(dstPixels), 277 info, std::move(dstPixels),
232 static_cast<unsigned>(input->width()) * info.bytesPerPixel()); 278 static_cast<unsigned>(input->width()) * info.bytesPerPixel());
233 } 279 }
234 280
281 // This code is borrowed from third_party/skia/src/codec/SkCodecPriv.h
282 // If you need to change this, please check SkColorSpaceXform::ColorFormat
283 // and SkColorType for proper coverage.
284 static inline SkColorSpaceXform::ColorFormat getXformFormat(
285 SkColorType colorType) {
286 switch (colorType) {
287 case kRGBA_8888_SkColorType:
288 return SkColorSpaceXform::kRGBA_8888_ColorFormat;
289 case kBGRA_8888_SkColorType:
290 return SkColorSpaceXform::kBGRA_8888_ColorFormat;
291 case kRGBA_F16_SkColorType:
292 return SkColorSpaceXform::kRGBA_F16_ColorFormat;
293 case kIndex_8_SkColorType:
msarett1 2016/11/30 21:32:39 I'm guessing that this case isn't necessary for no
zakerinasab 2016/12/01 19:49:45 Removed.
294 #ifdef SK_PMCOLOR_IS_RGBA
295 return SkColorSpaceXform::kRGBA_8888_ColorFormat;
296 #else
297 return SkColorSpaceXform::kBGRA_8888_ColorFormat;
298 #endif
299 default:
300 SkASSERT(false);
301 return SkColorSpaceXform::kRGBA_8888_ColorFormat;
302 }
303 }
304
305 static inline void updateLatestColorInformation(ParsedOptions& options) {
306 options.latestColorType = options.dstColorType;
307 options.latestColorSpace = options.dstColorSpace;
308 }
309
310 static sk_sp<SkImage> applyColorSpaceConversion(const sk_sp<SkImage> image,
msarett1 2016/11/30 21:32:39 Unless I'm missing something, I think that this fu
zakerinasab 2016/12/01 19:49:46 Proper TODO added.
311 ParsedOptions& options) {
312 if (!options.dstColorSpace)
313 return image;
314 if (SkColorSpace::Equals(options.latestColorSpace.get(),
315 options.dstColorSpace.get()))
316 return image;
317
318 // If we have the color space information of the source image, we can use
319 // SkColorSpaceXform. Otherwise, we need to draw the image on a canvas and
320 // take a snapshot.
321 if (options.latestColorSpace) {
322 SkImageInfo info = SkImageInfo::Make(
323 image->width(), image->height(), options.latestColorType,
324 image->alphaType(), options.latestColorSpace);
325 size_t size = image->width() * image->height() * info.bytesPerPixel();
326 auto srcPixels = makeUnique<uint8_t>(size);
327 if (!image->readPixels(info, &srcPixels,
328 image->width() * info.bytesPerPixel(), 0, 0)) {
329 return image;
330 }
331
332 // For in-place color correction, bytes per pixel must be equal for source
333 // and destination color spaces.
334 std::unique_ptr<uint8_t> dstPixels = nullptr;
335 if (SkColorTypeBytesPerPixel(options.dstColorType) !=
336 SkColorTypeBytesPerPixel(options.latestColorType)) {
337 size = image->width() * image->height() *
338 SkColorTypeBytesPerPixel(options.latestColorType);
339 dstPixels = makeUnique<uint8_t>(size);
340 }
341
342 std::unique_ptr<SkColorSpaceXform> xform = SkColorSpaceXform::New(
343 options.latestColorSpace.get(), options.dstColorSpace.get());
344 xform->apply(getXformFormat(options.dstColorType),
345 dstPixels ? &dstPixels : &srcPixels,
346 getXformFormat(options.latestColorType), &srcPixels,
347 image->width() * image->height(), kUnpremul_SkAlphaType);
348
349 SkImageInfo dstInfo =
350 SkImageInfo::Make(image->width(), image->height(), options.dstColorType,
351 image->alphaType(), options.dstColorSpace);
352 sk_sp<SkData> data(SkData::MakeWithoutCopy(&dstPixels, size));
353 sk_sp<SkImage> coloredImage = SkImage::MakeRasterData(
354 dstInfo, data, image->width() * dstInfo.bytesPerPixel());
355 if (coloredImage) {
356 updateLatestColorInformation(options);
357 return coloredImage;
358 }
359 return image;
360 }
361
362 // Skia does not supports color conversion for unpremultiplied images.
msarett1 2016/11/30 21:32:39 Not sure what this comment means... I would say t
zakerinasab 2016/12/01 19:49:45 Done.
363 sk_sp<SkImage> unPremulImage = nullptr;
364 if (image->alphaType() == kUnpremul_SkAlphaType)
365 unPremulImage = unPremulSkImageToPremul(image.get(), options);
366
367 // If the color space of the source SkImage is null, the following code
368 // does not do any color conversion even thought the new SkImage will be
369 // tagged by the new color space. If this is the case, the following code
370 // will tag a wrong color space to the SkImage. However, this cannot be
371 // addressed here and the code that creates the SkImage must tag the
372 // SkImage with proper color space.
373 SkImageInfo imageInfo = SkImageInfo::Make(
374 image->width(), image->height(), options.dstColorType,
375 unPremulImage ? unPremulImage->alphaType() : image->alphaType(),
376 options.dstColorSpace);
377 sk_sp<SkSurface> surface = SkSurface::MakeRaster(imageInfo);
378 surface->getCanvas()->drawImage(unPremulImage ? unPremulImage : image, 0, 0);
379 sk_sp<SkImage> coloredImage = surface->makeImageSnapshot();
380 updateLatestColorInformation(options);
381 return coloredImage;
382 }
383
235 sk_sp<SkImage> ImageBitmap::getSkImageFromDecoder( 384 sk_sp<SkImage> ImageBitmap::getSkImageFromDecoder(
236 std::unique_ptr<ImageDecoder> decoder) { 385 std::unique_ptr<ImageDecoder> decoder,
386 SkColorType* decodedColorType,
387 sk_sp<SkColorSpace> decodedColorSpace,
388 bool returnColorSpaceInformation) {
237 if (!decoder->frameCount()) 389 if (!decoder->frameCount())
238 return nullptr; 390 return nullptr;
239 ImageFrame* frame = decoder->frameBufferAtIndex(0); 391 ImageFrame* frame = decoder->frameBufferAtIndex(0);
240 if (!frame || frame->getStatus() != ImageFrame::FrameComplete) 392 if (!frame || frame->getStatus() != ImageFrame::FrameComplete)
241 return nullptr; 393 return nullptr;
242 DCHECK(!frame->bitmap().isNull() && !frame->bitmap().empty()); 394 DCHECK(!frame->bitmap().isNull() && !frame->bitmap().empty());
243 return frame->finalizePixelsAndGetImage(); 395 sk_sp<SkImage> image = frame->finalizePixelsAndGetImage();
396 if (returnColorSpaceInformation) {
397 *decodedColorType = frame->bitmap().colorType();
398 decodedColorSpace = sk_sp<SkColorSpace>(frame->bitmap().colorSpace());
399 }
400 return image;
244 } 401 }
245 402
246 bool ImageBitmap::isResizeOptionValid(const ImageBitmapOptions& options, 403 bool ImageBitmap::isResizeOptionValid(const ImageBitmapOptions& options,
247 ExceptionState& exceptionState) { 404 ExceptionState& exceptionState) {
248 if ((options.hasResizeWidth() && options.resizeWidth() == 0) || 405 if ((options.hasResizeWidth() && options.resizeWidth() == 0) ||
249 (options.hasResizeHeight() && options.resizeHeight() == 0)) { 406 (options.hasResizeHeight() && options.resizeHeight() == 0)) {
250 exceptionState.throwDOMException( 407 exceptionState.throwDOMException(
251 InvalidStateError, 408 InvalidStateError,
252 "The resizeWidth or/and resizeHeight is equal to 0."); 409 "The resizeWidth or/and resizeHeight is equal to 0.");
253 return false; 410 return false;
(...skipping 13 matching lines...) Expand all
267 return true; 424 return true;
268 } 425 }
269 426
270 // The parameter imageFormat indicates whether the first parameter "image" is 427 // The parameter imageFormat indicates whether the first parameter "image" is
271 // unpremultiplied or not. imageFormat = PremultiplyAlpha means the image is in 428 // unpremultiplied or not. imageFormat = PremultiplyAlpha means the image is in
272 // premuliplied format For example, if the image is already in unpremultiplied 429 // premuliplied format For example, if the image is already in unpremultiplied
273 // format and we want the created ImageBitmap in the same format, then we don't 430 // format and we want the created ImageBitmap in the same format, then we don't
274 // need to use the ImageDecoder to decode the image. 431 // need to use the ImageDecoder to decode the image.
275 static PassRefPtr<StaticBitmapImage> cropImage( 432 static PassRefPtr<StaticBitmapImage> cropImage(
276 Image* image, 433 Image* image,
277 const ParsedOptions& parsedOptions, 434 ParsedOptions& parsedOptions,
278 AlphaDisposition imageFormat = PremultiplyAlpha, 435 AlphaDisposition imageFormat = PremultiplyAlpha,
279 ImageDecoder::ColorSpaceOption colorSpaceOp = 436 ImageDecoder::ColorSpaceOption colorSpaceOp =
280 ImageDecoder::ColorSpaceApplied) { 437 ImageDecoder::ColorSpaceApplied) {
281 ASSERT(image); 438 ASSERT(image);
282 IntRect imgRect(IntPoint(), IntSize(image->width(), image->height())); 439 IntRect imgRect(IntPoint(), IntSize(image->width(), image->height()));
283 const IntRect srcRect = intersection(imgRect, parsedOptions.cropRect); 440 const IntRect srcRect = intersection(imgRect, parsedOptions.cropRect);
284 441
285 // In the case when cropRect doesn't intersect the source image and it 442 // In the case when cropRect doesn't intersect the source image and it
286 // requires a umpremul image We immediately return a transparent black image 443 // requires a umpremul image We immediately return a transparent black image
287 // with cropRect.size() 444 // with cropRect.size()
(...skipping 20 matching lines...) Expand all
308 !skiaImage) && 465 !skiaImage) &&
309 image->data() && imageFormat == PremultiplyAlpha) || 466 image->data() && imageFormat == PremultiplyAlpha) ||
310 colorSpaceOp == ImageDecoder::ColorSpaceIgnored) { 467 colorSpaceOp == ImageDecoder::ColorSpaceIgnored) {
311 std::unique_ptr<ImageDecoder> decoder(ImageDecoder::create( 468 std::unique_ptr<ImageDecoder> decoder(ImageDecoder::create(
312 image->data(), true, 469 image->data(), true,
313 parsedOptions.premultiplyAlpha ? ImageDecoder::AlphaPremultiplied 470 parsedOptions.premultiplyAlpha ? ImageDecoder::AlphaPremultiplied
314 : ImageDecoder::AlphaNotPremultiplied, 471 : ImageDecoder::AlphaNotPremultiplied,
315 colorSpaceOp)); 472 colorSpaceOp));
316 if (!decoder) 473 if (!decoder)
317 return nullptr; 474 return nullptr;
318 skiaImage = ImageBitmap::getSkImageFromDecoder(std::move(decoder)); 475 skiaImage = ImageBitmap::getSkImageFromDecoder(
476 std::move(decoder), &parsedOptions.latestColorType,
477 parsedOptions.latestColorSpace, true);
319 if (!skiaImage) 478 if (!skiaImage)
320 return nullptr; 479 return nullptr;
321 } 480 }
322 481
323 if (parsedOptions.cropRect == srcRect && !parsedOptions.shouldScaleInput) { 482 if (parsedOptions.cropRect == srcRect && !parsedOptions.shouldScaleInput) {
324 sk_sp<SkImage> croppedSkImage = skiaImage->makeSubset(srcRect); 483 sk_sp<SkImage> croppedSkImage = skiaImage->makeSubset(srcRect);
325 if (parsedOptions.flipY) 484 if (parsedOptions.dstColorSpace) {
326 return StaticBitmapImage::create(flipSkImageVertically( 485 croppedSkImage = applyColorSpaceConversion(croppedSkImage, parsedOptions);
327 croppedSkImage.get(), parsedOptions.premultiplyAlpha 486 }
328 ? PremultiplyAlpha 487 if (parsedOptions.flipY) {
329 : DontPremultiplyAlpha)); 488 return StaticBitmapImage::create(
489 flipSkImageVertically(croppedSkImage.get(), false, parsedOptions));
490 }
330 // Special case: The first parameter image is unpremul but we need to turn 491 // Special case: The first parameter image is unpremul but we need to turn
331 // it into premul. 492 // it into premul.
332 if (parsedOptions.premultiplyAlpha && imageFormat == DontPremultiplyAlpha) 493 if (parsedOptions.premultiplyAlpha && imageFormat == DontPremultiplyAlpha)
333 return StaticBitmapImage::create( 494 return StaticBitmapImage::create(
334 unPremulSkImageToPremul(croppedSkImage.get())); 495 unPremulSkImageToPremul(croppedSkImage.get()));
335 // Call preroll to trigger image decoding. 496 // Call preroll to trigger image decoding.
336 croppedSkImage->preroll(); 497 croppedSkImage->preroll();
337 return StaticBitmapImage::create(std::move(croppedSkImage)); 498 return StaticBitmapImage::create(std::move(croppedSkImage));
338 } 499 }
339 500
(...skipping 21 matching lines...) Expand all
361 SkRect drawDstRect = SkRect::MakeXYWH(0, 0, parsedOptions.resizeWidth, 522 SkRect drawDstRect = SkRect::MakeXYWH(0, 0, parsedOptions.resizeWidth,
362 parsedOptions.resizeHeight); 523 parsedOptions.resizeHeight);
363 SkPaint paint; 524 SkPaint paint;
364 paint.setFilterQuality(parsedOptions.resizeQuality); 525 paint.setFilterQuality(parsedOptions.resizeQuality);
365 surface->getCanvas()->drawImageRect(skiaImage, drawSrcRect, drawDstRect, 526 surface->getCanvas()->drawImageRect(skiaImage, drawSrcRect, drawDstRect,
366 &paint); 527 &paint);
367 } else { 528 } else {
368 surface->getCanvas()->drawImage(skiaImage, dstLeft, dstTop); 529 surface->getCanvas()->drawImage(skiaImage, dstLeft, dstTop);
369 } 530 }
370 skiaImage = surface->makeImageSnapshot(); 531 skiaImage = surface->makeImageSnapshot();
532 if (parsedOptions.dstColorSpace)
533 skiaImage = applyColorSpaceConversion(skiaImage, parsedOptions);
371 534
372 if (parsedOptions.premultiplyAlpha) { 535 if (parsedOptions.premultiplyAlpha) {
373 if (imageFormat == DontPremultiplyAlpha) 536 if (imageFormat == DontPremultiplyAlpha)
374 return StaticBitmapImage::create( 537 return StaticBitmapImage::create(
375 unPremulSkImageToPremul(skiaImage.get())); 538 unPremulSkImageToPremul(skiaImage.get()));
376 return StaticBitmapImage::create(std::move(skiaImage)); 539 return StaticBitmapImage::create(std::move(skiaImage));
377 } 540 }
378 return StaticBitmapImage::create(premulSkImageToUnPremul(skiaImage.get())); 541 return StaticBitmapImage::create(premulSkImageToUnPremul(skiaImage.get()));
379 } 542 }
380 543
381 ImageBitmap::ImageBitmap(HTMLImageElement* image, 544 ImageBitmap::ImageBitmap(HTMLImageElement* image,
382 Optional<IntRect> cropRect, 545 Optional<IntRect> cropRect,
383 Document* document, 546 Document* document,
384 const ImageBitmapOptions& options) { 547 const ImageBitmapOptions& options) {
385 RefPtr<Image> input = image->cachedImage()->getImage(); 548 RefPtr<Image> input = image->cachedImage()->getImage();
386 ParsedOptions parsedOptions = 549 ParsedOptions parsedOptions =
387 parseOptions(options, cropRect, image->bitmapSourceSize()); 550 parseOptions(options, cropRect, image->bitmapSourceSize());
388 if (dstBufferSizeHasOverflow(parsedOptions)) 551 if (dstBufferSizeHasOverflow(parsedOptions))
389 return; 552 return;
390 553
391 if (options.colorSpaceConversion() == "none") { 554 m_image =
392 m_image = cropImage(input.get(), parsedOptions, PremultiplyAlpha, 555 cropImage(input.get(), parsedOptions, PremultiplyAlpha,
393 ImageDecoder::ColorSpaceIgnored); 556 parsedOptions.dstColorSpace ? ImageDecoder::ColorSpaceApplied
394 } else { 557 : ImageDecoder::ColorSpaceIgnored);
395 m_image = cropImage(input.get(), parsedOptions, PremultiplyAlpha,
396 ImageDecoder::ColorSpaceApplied);
397 }
398 if (!m_image) 558 if (!m_image)
399 return; 559 return;
400 // In the case where the source image is lazy-decoded, m_image may not be in 560 // In the case where the source image is lazy-decoded, m_image may not be in
401 // a decoded state, we trigger it here. 561 // a decoded state, we trigger it here.
402 sk_sp<SkImage> skImage = m_image->imageForCurrentFrame(); 562 sk_sp<SkImage> skImage = m_image->imageForCurrentFrame();
403 SkPixmap pixmap; 563 SkPixmap pixmap;
404 if (!skImage->isTextureBacked() && !skImage->peekPixels(&pixmap)) { 564 if (!skImage->isTextureBacked() && !skImage->peekPixels(&pixmap)) {
405 sk_sp<SkSurface> surface = 565 sk_sp<SkSurface> surface =
406 SkSurface::MakeRasterN32Premul(skImage->width(), skImage->height()); 566 SkSurface::MakeRasterN32Premul(skImage->width(), skImage->height());
407 surface->getCanvas()->drawImage(skImage, 0, 0); 567 surface->getCanvas()->drawImage(skImage, 0, 0);
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after
660 std::min(0, -parsedOptions.cropRect.y())); 820 std::min(0, -parsedOptions.cropRect.y()));
661 if (parsedOptions.cropRect.x() < 0) 821 if (parsedOptions.cropRect.x() < 0)
662 dstPoint.setX(-parsedOptions.cropRect.x()); 822 dstPoint.setX(-parsedOptions.cropRect.x());
663 if (parsedOptions.cropRect.y() < 0) 823 if (parsedOptions.cropRect.y() < 0)
664 dstPoint.setY(-parsedOptions.cropRect.y()); 824 dstPoint.setY(-parsedOptions.cropRect.y());
665 buffer->putByteArray(Unmultiplied, data->data()->data(), data->size(), 825 buffer->putByteArray(Unmultiplied, data->data()->data(), data->size(),
666 srcRect, dstPoint); 826 srcRect, dstPoint);
667 sk_sp<SkImage> skImage = 827 sk_sp<SkImage> skImage =
668 buffer->newSkImageSnapshot(PreferNoAcceleration, SnapshotReasonUnknown); 828 buffer->newSkImageSnapshot(PreferNoAcceleration, SnapshotReasonUnknown);
669 if (parsedOptions.flipY) 829 if (parsedOptions.flipY)
670 skImage = flipSkImageVertically(skImage.get(), PremultiplyAlpha); 830 skImage = flipSkImageVertically(skImage.get(), true);
671 if (!skImage) 831 if (!skImage)
672 return; 832 return;
673 if (parsedOptions.shouldScaleInput) { 833 if (parsedOptions.shouldScaleInput) {
674 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul( 834 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(
675 parsedOptions.resizeWidth, parsedOptions.resizeHeight); 835 parsedOptions.resizeWidth, parsedOptions.resizeHeight);
676 if (!surface) 836 if (!surface)
677 return; 837 return;
678 SkPaint paint; 838 SkPaint paint;
679 paint.setFilterQuality(parsedOptions.resizeQuality); 839 paint.setFilterQuality(parsedOptions.resizeQuality);
680 SkRect dstDrawRect = 840 SkRect dstDrawRect =
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
862 void ImageBitmap::adjustDrawRects(FloatRect* srcRect, 1022 void ImageBitmap::adjustDrawRects(FloatRect* srcRect,
863 FloatRect* dstRect) const {} 1023 FloatRect* dstRect) const {}
864 1024
865 FloatSize ImageBitmap::elementSize(const FloatSize&) const { 1025 FloatSize ImageBitmap::elementSize(const FloatSize&) const {
866 return FloatSize(width(), height()); 1026 return FloatSize(width(), height());
867 } 1027 }
868 1028
869 DEFINE_TRACE(ImageBitmap) {} 1029 DEFINE_TRACE(ImageBitmap) {}
870 1030
871 } // namespace blink 1031 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/frame/ImageBitmap.h ('k') | third_party/WebKit/Source/core/frame/ImageBitmapTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698