OLD | NEW |
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/SkSurface.h" | 13 #include "third_party/skia/include/core/SkSurface.h" |
| 14 #include "wtf/CheckedNumeric.h" |
14 #include "wtf/PtrUtil.h" | 15 #include "wtf/PtrUtil.h" |
15 #include "wtf/RefPtr.h" | 16 #include "wtf/RefPtr.h" |
16 #include <memory> | 17 #include <memory> |
17 | 18 |
18 namespace blink { | 19 namespace blink { |
19 | 20 |
20 static const char* imageOrientationFlipY = "flipY"; | 21 static const char* imageOrientationFlipY = "flipY"; |
21 static const char* imageBitmapOptionNone = "none"; | 22 static const char* imageBitmapOptionNone = "none"; |
22 | 23 |
23 namespace { | 24 namespace { |
24 | 25 |
25 struct ParsedOptions { | 26 struct ParsedOptions { |
26 bool flipY = false; | 27 bool flipY = false; |
27 bool premultiplyAlpha = true; | 28 bool premultiplyAlpha = true; |
28 bool shouldScaleInput = false; | 29 bool shouldScaleInput = false; |
29 unsigned resizeWidth = 0; | 30 unsigned resizeWidth = 0; |
30 unsigned resizeHeight = 0; | 31 unsigned resizeHeight = 0; |
31 IntRect cropRect; | 32 IntRect cropRect; |
32 SkFilterQuality resizeQuality = kLow_SkFilterQuality; | 33 SkFilterQuality resizeQuality = kLow_SkFilterQuality; |
| 34 // This value should be changed in the future when we support createImageBit
map with higher |
| 35 // bit depth, in the parseOptions() function. For now, it is always 4. |
| 36 int bytesPerPixel = 4; |
33 }; | 37 }; |
34 | 38 |
35 // The following two functions are helpers used in cropImage | 39 // The following two functions are helpers used in cropImage |
36 static inline IntRect normalizeRect(const IntRect& rect) | 40 static inline IntRect normalizeRect(const IntRect& rect) |
37 { | 41 { |
38 return IntRect(std::min(rect.x(), rect.maxX()), | 42 return IntRect(std::min(rect.x(), rect.maxX()), |
39 std::min(rect.y(), rect.maxY()), | 43 std::min(rect.y(), rect.maxY()), |
40 std::max(rect.width(), -rect.width()), | 44 std::max(rect.width(), -rect.width()), |
41 std::max(rect.height(), -rect.height())); | 45 std::max(rect.height(), -rect.height())); |
42 } | 46 } |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 parsedOptions.resizeQuality = kHigh_SkFilterQuality; | 97 parsedOptions.resizeQuality = kHigh_SkFilterQuality; |
94 else if (options.resizeQuality() == "medium") | 98 else if (options.resizeQuality() == "medium") |
95 parsedOptions.resizeQuality = kMedium_SkFilterQuality; | 99 parsedOptions.resizeQuality = kMedium_SkFilterQuality; |
96 else if (options.resizeQuality() == "pixelated") | 100 else if (options.resizeQuality() == "pixelated") |
97 parsedOptions.resizeQuality = kNone_SkFilterQuality; | 101 parsedOptions.resizeQuality = kNone_SkFilterQuality; |
98 else | 102 else |
99 parsedOptions.resizeQuality = kLow_SkFilterQuality; | 103 parsedOptions.resizeQuality = kLow_SkFilterQuality; |
100 return parsedOptions; | 104 return parsedOptions; |
101 } | 105 } |
102 | 106 |
| 107 bool dstBufferSizeHasOverflow(ParsedOptions options) |
| 108 { |
| 109 CheckedNumeric<size_t> totalBytes = options.cropRect.width(); |
| 110 totalBytes *= options.cropRect.height(); |
| 111 totalBytes *= options.bytesPerPixel; |
| 112 if (!totalBytes.IsValid()) |
| 113 return true; |
| 114 |
| 115 if (!options.shouldScaleInput) |
| 116 return false; |
| 117 totalBytes = options.resizeWidth; |
| 118 totalBytes *= options.resizeHeight; |
| 119 totalBytes *= options.bytesPerPixel; |
| 120 if (!totalBytes.IsValid()) |
| 121 return true; |
| 122 |
| 123 return false; |
| 124 } |
| 125 |
103 } // namespace | 126 } // namespace |
104 | 127 |
105 static std::unique_ptr<uint8_t[]> copySkImageData(SkImage* input, const SkImageI
nfo& info) | 128 static PassRefPtr<Uint8Array> copySkImageData(SkImage* input, const SkImageInfo&
info) |
106 { | 129 { |
107 std::unique_ptr<uint8_t[]> dstPixels = wrapArrayUnique(new uint8_t[input->wi
dth() * input->height() * info.bytesPerPixel()]); | 130 // The function dstBufferSizeHasOverflow() is being called at the beginning
of each |
108 input->readPixels(info, dstPixels.get(), input->width() * info.bytesPerPixel
(), 0, 0); | 131 // ImageBitmap() constructor, which makes sure that doing width * height * b
ytesPerPixel |
| 132 // will never overflow size_t. |
| 133 size_t width = static_cast<size_t>(input->width()); |
| 134 RefPtr<ArrayBuffer> dstBuffer = ArrayBuffer::createOrNull(width * input->hei
ght(), info.bytesPerPixel()); |
| 135 if (!dstBuffer) |
| 136 return nullptr; |
| 137 RefPtr<Uint8Array> dstPixels = Uint8Array::create(dstBuffer, 0, dstBuffer->b
yteLength()); |
| 138 input->readPixels(info, dstPixels->data(), width * info.bytesPerPixel(), 0,
0); |
109 return dstPixels; | 139 return dstPixels; |
110 } | 140 } |
111 | 141 |
112 static PassRefPtr<SkImage> newSkImageFromRaster(const SkImageInfo& info, std::un
ique_ptr<uint8_t[]> imagePixels, int imageRowBytes) | 142 static PassRefPtr<SkImage> newSkImageFromRaster(const SkImageInfo& info, PassRef
Ptr<Uint8Array> imagePixels, size_t imageRowBytes) |
113 { | 143 { |
114 return fromSkSp(SkImage::MakeFromRaster(SkPixmap(info, imagePixels.release()
, imageRowBytes), | 144 return fromSkSp(SkImage::MakeFromRaster(SkPixmap(info, imagePixels->data(),
imageRowBytes), |
115 [](const void* pixels, void*) | 145 [](const void*, void* pixels) |
116 { | 146 { |
117 delete[] static_cast<const uint8_t*>(pixels); | 147 static_cast<Uint8Array*>(pixels)->deref(); |
118 }, nullptr)); | 148 }, imagePixels.leakRef())); |
119 } | 149 } |
120 | 150 |
121 static void swizzleImageData(unsigned char* srcAddr, int height, int bytesPerRow
, bool flipY) | 151 static void swizzleImageData(unsigned char* srcAddr, size_t height, size_t bytes
PerRow, bool flipY) |
122 { | 152 { |
123 if (flipY) { | 153 if (flipY) { |
124 for (int i = 0; i < height / 2; i++) { | 154 for (size_t i = 0; i < height / 2; i++) { |
125 int topRowStartPosition = i * bytesPerRow; | 155 size_t topRowStartPosition = i * bytesPerRow; |
126 int bottomRowStartPosition = (height - 1 - i) * bytesPerRow; | 156 size_t bottomRowStartPosition = (height - 1 - i) * bytesPerRow; |
127 if (kN32_SkColorType == kBGRA_8888_SkColorType) { // needs to swizzl
e | 157 if (kN32_SkColorType == kBGRA_8888_SkColorType) { // needs to swizzl
e |
128 for (int j = 0; j < bytesPerRow; j += 4) { | 158 for (size_t j = 0; j < bytesPerRow; j += 4) { |
129 std::swap(srcAddr[topRowStartPosition + j], srcAddr[bottomRo
wStartPosition + j + 2]); | 159 std::swap(srcAddr[topRowStartPosition + j], srcAddr[bottomRo
wStartPosition + j + 2]); |
130 std::swap(srcAddr[topRowStartPosition + j + 1], srcAddr[bott
omRowStartPosition + j + 1]); | 160 std::swap(srcAddr[topRowStartPosition + j + 1], srcAddr[bott
omRowStartPosition + j + 1]); |
131 std::swap(srcAddr[topRowStartPosition + j + 2], srcAddr[bott
omRowStartPosition + j]); | 161 std::swap(srcAddr[topRowStartPosition + j + 2], srcAddr[bott
omRowStartPosition + j]); |
132 std::swap(srcAddr[topRowStartPosition + j + 3], srcAddr[bott
omRowStartPosition + j + 3]); | 162 std::swap(srcAddr[topRowStartPosition + j + 3], srcAddr[bott
omRowStartPosition + j + 3]); |
133 } | 163 } |
134 } else { | 164 } else { |
135 std::swap_ranges(srcAddr + topRowStartPosition, srcAddr + topRow
StartPosition + bytesPerRow, srcAddr + bottomRowStartPosition); | 165 std::swap_ranges(srcAddr + topRowStartPosition, srcAddr + topRow
StartPosition + bytesPerRow, srcAddr + bottomRowStartPosition); |
136 } | 166 } |
137 } | 167 } |
138 } else { | 168 } else { |
139 if (kN32_SkColorType == kBGRA_8888_SkColorType) // needs to swizzle | 169 if (kN32_SkColorType == kBGRA_8888_SkColorType) // needs to swizzle |
140 for (int i = 0; i < height * bytesPerRow; i += 4) | 170 for (size_t i = 0; i < height * bytesPerRow; i += 4) |
141 std::swap(srcAddr[i], srcAddr[i + 2]); | 171 std::swap(srcAddr[i], srcAddr[i + 2]); |
142 } | 172 } |
143 } | 173 } |
144 | 174 |
145 static PassRefPtr<SkImage> flipSkImageVertically(SkImage* input, AlphaDispositio
n alphaOp) | 175 static PassRefPtr<SkImage> flipSkImageVertically(SkImage* input, AlphaDispositio
n alphaOp) |
146 { | 176 { |
147 int width = input->width(); | 177 size_t width = static_cast<size_t>(input->width()); |
148 int height = input->height(); | 178 size_t height = static_cast<size_t>(input->height()); |
149 SkImageInfo info = SkImageInfo::MakeN32(width, height, (alphaOp == Premultip
lyAlpha) ? kPremul_SkAlphaType : kUnpremul_SkAlphaType); | 179 SkImageInfo info = SkImageInfo::MakeN32(input->width(), input->height(), (al
phaOp == PremultiplyAlpha) ? kPremul_SkAlphaType : kUnpremul_SkAlphaType); |
150 int imageRowBytes = width * info.bytesPerPixel(); | 180 size_t imageRowBytes = width * info.bytesPerPixel(); |
151 std::unique_ptr<uint8_t[]> imagePixels = copySkImageData(input, info); | 181 RefPtr<Uint8Array> imagePixels = copySkImageData(input, info); |
152 for (int i = 0; i < height / 2; i++) { | 182 if (!imagePixels) |
153 int topFirstElement = i * imageRowBytes; | 183 return nullptr; |
154 int topLastElement = (i + 1) * imageRowBytes; | 184 for (size_t i = 0; i < height / 2; i++) { |
155 int bottomFirstElement = (height - 1 - i) * imageRowBytes; | 185 size_t topFirstElement = i * imageRowBytes; |
156 std::swap_ranges(imagePixels.get() + topFirstElement, imagePixels.get()
+ topLastElement, imagePixels.get() + bottomFirstElement); | 186 size_t topLastElement = (i + 1) * imageRowBytes; |
| 187 size_t bottomFirstElement = (height - 1 - i) * imageRowBytes; |
| 188 std::swap_ranges(imagePixels->data() + topFirstElement, imagePixels->dat
a() + topLastElement, imagePixels->data() + bottomFirstElement); |
157 } | 189 } |
158 return newSkImageFromRaster(info, std::move(imagePixels), imageRowBytes); | 190 return newSkImageFromRaster(info, std::move(imagePixels), imageRowBytes); |
159 } | 191 } |
160 | 192 |
161 static PassRefPtr<SkImage> premulSkImageToUnPremul(SkImage* input) | 193 static PassRefPtr<SkImage> premulSkImageToUnPremul(SkImage* input) |
162 { | 194 { |
163 SkImageInfo info = SkImageInfo::Make(input->width(), input->height(), kN32_S
kColorType, kUnpremul_SkAlphaType); | 195 SkImageInfo info = SkImageInfo::Make(input->width(), input->height(), kN32_S
kColorType, kUnpremul_SkAlphaType); |
164 std::unique_ptr<uint8_t[]> dstPixels = copySkImageData(input, info); | 196 RefPtr<Uint8Array> dstPixels = copySkImageData(input, info); |
165 return newSkImageFromRaster(info, std::move(dstPixels), input->width() * inf
o.bytesPerPixel()); | 197 if (!dstPixels) |
| 198 return nullptr; |
| 199 return newSkImageFromRaster(info, std::move(dstPixels), static_cast<size_t>(
input->width()) * info.bytesPerPixel()); |
166 } | 200 } |
167 | 201 |
168 static PassRefPtr<SkImage> unPremulSkImageToPremul(SkImage* input) | 202 static PassRefPtr<SkImage> unPremulSkImageToPremul(SkImage* input) |
169 { | 203 { |
170 SkImageInfo info = SkImageInfo::Make(input->width(), input->height(), kN32_S
kColorType, kPremul_SkAlphaType); | 204 SkImageInfo info = SkImageInfo::Make(input->width(), input->height(), kN32_S
kColorType, kPremul_SkAlphaType); |
171 std::unique_ptr<uint8_t[]> dstPixels = copySkImageData(input, info); | 205 RefPtr<Uint8Array> dstPixels = copySkImageData(input, info); |
172 return newSkImageFromRaster(info, std::move(dstPixels), input->width() * inf
o.bytesPerPixel()); | 206 if (!dstPixels) |
| 207 return nullptr; |
| 208 return newSkImageFromRaster(info, std::move(dstPixels), static_cast<size_t>(
input->width()) * info.bytesPerPixel()); |
173 } | 209 } |
174 | 210 |
175 PassRefPtr<SkImage> ImageBitmap::getSkImageFromDecoder(std::unique_ptr<ImageDeco
der> decoder) | 211 PassRefPtr<SkImage> ImageBitmap::getSkImageFromDecoder(std::unique_ptr<ImageDeco
der> decoder) |
176 { | 212 { |
177 if (!decoder->frameCount()) | 213 if (!decoder->frameCount()) |
178 return nullptr; | 214 return nullptr; |
179 ImageFrame* frame = decoder->frameBufferAtIndex(0); | 215 ImageFrame* frame = decoder->frameBufferAtIndex(0); |
180 if (!frame || frame->getStatus() != ImageFrame::FrameComplete) | 216 if (!frame || frame->getStatus() != ImageFrame::FrameComplete) |
181 return nullptr; | 217 return nullptr; |
182 SkBitmap bitmap = frame->bitmap(); | 218 SkBitmap bitmap = frame->bitmap(); |
(...skipping 28 matching lines...) Expand all Loading... |
211 { | 247 { |
212 ASSERT(image); | 248 ASSERT(image); |
213 | 249 |
214 IntRect imgRect(IntPoint(), IntSize(image->width(), image->height())); | 250 IntRect imgRect(IntPoint(), IntSize(image->width(), image->height())); |
215 const IntRect srcRect = intersection(imgRect, parsedOptions.cropRect); | 251 const IntRect srcRect = intersection(imgRect, parsedOptions.cropRect); |
216 | 252 |
217 // In the case when cropRect doesn't intersect the source image and it requi
res a umpremul image | 253 // In the case when cropRect doesn't intersect the source image and it requi
res a umpremul image |
218 // We immediately return a transparent black image with cropRect.size() | 254 // We immediately return a transparent black image with cropRect.size() |
219 if (srcRect.isEmpty() && !parsedOptions.premultiplyAlpha) { | 255 if (srcRect.isEmpty() && !parsedOptions.premultiplyAlpha) { |
220 SkImageInfo info = SkImageInfo::Make(parsedOptions.resizeWidth, parsedOp
tions.resizeHeight, kN32_SkColorType, kUnpremul_SkAlphaType); | 256 SkImageInfo info = SkImageInfo::Make(parsedOptions.resizeWidth, parsedOp
tions.resizeHeight, kN32_SkColorType, kUnpremul_SkAlphaType); |
221 std::unique_ptr<uint8_t[]> dstPixels = wrapArrayUnique(new uint8_t[info.
width() * info.height() * info.bytesPerPixel()]()); | 257 RefPtr<ArrayBuffer> dstBuffer = ArrayBuffer::createOrNull(static_cast<si
ze_t>(info.width()) * info.height(), info.bytesPerPixel()); |
222 return StaticBitmapImage::create(newSkImageFromRaster(info, std::move(ds
tPixels), info.width() * info.bytesPerPixel())); | 258 if (!dstBuffer) |
| 259 return nullptr; |
| 260 RefPtr<Uint8Array> dstPixels = Uint8Array::create(dstBuffer, 0, dstBuffe
r->byteLength()); |
| 261 return StaticBitmapImage::create(newSkImageFromRaster(info, std::move(ds
tPixels), static_cast<size_t>(info.width()) * info.bytesPerPixel())); |
223 } | 262 } |
224 | 263 |
225 RefPtr<SkImage> skiaImage = image->imageForCurrentFrame(); | 264 RefPtr<SkImage> skiaImage = image->imageForCurrentFrame(); |
226 // Attempt to get raw unpremultiplied image data, executed only when skiaIma
ge is premultiplied. | 265 // Attempt to get raw unpremultiplied image data, executed only when skiaIma
ge is premultiplied. |
227 if ((((!parsedOptions.premultiplyAlpha && !skiaImage->isOpaque()) || !skiaIm
age) && image->data() && imageFormat == PremultiplyAlpha) || colorSpaceOp == Ima
geDecoder::GammaAndColorProfileIgnored) { | 266 if ((((!parsedOptions.premultiplyAlpha && !skiaImage->isOpaque()) || !skiaIm
age) && image->data() && imageFormat == PremultiplyAlpha) || colorSpaceOp == Ima
geDecoder::GammaAndColorProfileIgnored) { |
228 std::unique_ptr<ImageDecoder> decoder(ImageDecoder::create( | 267 std::unique_ptr<ImageDecoder> decoder(ImageDecoder::create( |
229 image->data(), true, | 268 image->data(), true, |
230 parsedOptions.premultiplyAlpha ? ImageDecoder::AlphaPremultiplied :
ImageDecoder::AlphaNotPremultiplied, | 269 parsedOptions.premultiplyAlpha ? ImageDecoder::AlphaPremultiplied :
ImageDecoder::AlphaNotPremultiplied, |
231 colorSpaceOp)); | 270 colorSpaceOp)); |
232 if (!decoder) | 271 if (!decoder) |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
269 SkRect drawDstRect = SkRect::MakeXYWH(0, 0, parsedOptions.resizeWidth, p
arsedOptions.resizeHeight); | 308 SkRect drawDstRect = SkRect::MakeXYWH(0, 0, parsedOptions.resizeWidth, p
arsedOptions.resizeHeight); |
270 SkPaint paint; | 309 SkPaint paint; |
271 paint.setFilterQuality(parsedOptions.resizeQuality); | 310 paint.setFilterQuality(parsedOptions.resizeQuality); |
272 surface->getCanvas()->drawImageRect(skiaImage.get(), drawSrcRect, drawDs
tRect, &paint); | 311 surface->getCanvas()->drawImageRect(skiaImage.get(), drawSrcRect, drawDs
tRect, &paint); |
273 } else { | 312 } else { |
274 surface->getCanvas()->drawImage(skiaImage.get(), dstLeft, dstTop); | 313 surface->getCanvas()->drawImage(skiaImage.get(), dstLeft, dstTop); |
275 } | 314 } |
276 skiaImage = fromSkSp(surface->makeImageSnapshot()); | 315 skiaImage = fromSkSp(surface->makeImageSnapshot()); |
277 | 316 |
278 if (parsedOptions.premultiplyAlpha) { | 317 if (parsedOptions.premultiplyAlpha) { |
279 if (imageFormat == PremultiplyAlpha) | 318 if (imageFormat == DontPremultiplyAlpha) |
280 return StaticBitmapImage::create(unPremulSkImageToPremul(skiaImage.g
et())); | 319 return StaticBitmapImage::create(unPremulSkImageToPremul(skiaImage.g
et())); |
281 return StaticBitmapImage::create(skiaImage.release()); | 320 return StaticBitmapImage::create(skiaImage.release()); |
282 } | 321 } |
283 return StaticBitmapImage::create(premulSkImageToUnPremul(skiaImage.get())); | 322 return StaticBitmapImage::create(premulSkImageToUnPremul(skiaImage.get())); |
284 } | 323 } |
285 | 324 |
286 ImageBitmap::ImageBitmap(HTMLImageElement* image, Optional<IntRect> cropRect, Do
cument* document, const ImageBitmapOptions& options) | 325 ImageBitmap::ImageBitmap(HTMLImageElement* image, Optional<IntRect> cropRect, Do
cument* document, const ImageBitmapOptions& options) |
287 { | 326 { |
288 RefPtr<Image> input = image->cachedImage()->getImage(); | 327 RefPtr<Image> input = image->cachedImage()->getImage(); |
289 ParsedOptions parsedOptions = parseOptions(options, cropRect, image->bitmapS
ourceSize()); | 328 ParsedOptions parsedOptions = parseOptions(options, cropRect, image->bitmapS
ourceSize()); |
| 329 if (dstBufferSizeHasOverflow(parsedOptions)) |
| 330 return; |
290 | 331 |
291 if (options.colorSpaceConversion() == "none") | 332 if (options.colorSpaceConversion() == "none") |
292 m_image = cropImage(input.get(), parsedOptions, PremultiplyAlpha, ImageD
ecoder::GammaAndColorProfileIgnored); | 333 m_image = cropImage(input.get(), parsedOptions, PremultiplyAlpha, ImageD
ecoder::GammaAndColorProfileIgnored); |
293 else | 334 else |
294 m_image = cropImage(input.get(), parsedOptions, PremultiplyAlpha, ImageD
ecoder::GammaAndColorProfileApplied); | 335 m_image = cropImage(input.get(), parsedOptions, PremultiplyAlpha, ImageD
ecoder::GammaAndColorProfileApplied); |
295 if (!m_image) | 336 if (!m_image) |
296 return; | 337 return; |
297 // In the case where the source image is lazy-decoded, m_image may not be in | 338 // In the case where the source image is lazy-decoded, m_image may not be in |
298 // a decoded state, we trigger it here. | 339 // a decoded state, we trigger it here. |
299 RefPtr<SkImage> skImage = m_image->imageForCurrentFrame(); | 340 RefPtr<SkImage> skImage = m_image->imageForCurrentFrame(); |
300 SkPixmap pixmap; | 341 SkPixmap pixmap; |
301 if (!skImage->isTextureBacked() && !skImage->peekPixels(&pixmap)) { | 342 if (!skImage->isTextureBacked() && !skImage->peekPixels(&pixmap)) { |
302 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(skImage->width
(), skImage->height()); | 343 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(skImage->width
(), skImage->height()); |
303 surface->getCanvas()->drawImage(skImage.get(), 0, 0); | 344 surface->getCanvas()->drawImage(skImage.get(), 0, 0); |
304 m_image = StaticBitmapImage::create(fromSkSp(surface->makeImageSnapshot(
))); | 345 m_image = StaticBitmapImage::create(fromSkSp(surface->makeImageSnapshot(
))); |
305 } | 346 } |
| 347 if (!m_image) |
| 348 return; |
306 m_image->setOriginClean(!image->wouldTaintOrigin(document->getSecurityOrigin
())); | 349 m_image->setOriginClean(!image->wouldTaintOrigin(document->getSecurityOrigin
())); |
307 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); | 350 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); |
308 } | 351 } |
309 | 352 |
310 ImageBitmap::ImageBitmap(HTMLVideoElement* video, Optional<IntRect> cropRect, Do
cument* document, const ImageBitmapOptions& options) | 353 ImageBitmap::ImageBitmap(HTMLVideoElement* video, Optional<IntRect> cropRect, Do
cument* document, const ImageBitmapOptions& options) |
311 { | 354 { |
312 IntSize playerSize; | 355 IntSize playerSize; |
313 if (video->webMediaPlayer()) | 356 if (video->webMediaPlayer()) |
314 playerSize = video->webMediaPlayer()->naturalSize(); | 357 playerSize = video->webMediaPlayer()->naturalSize(); |
315 ParsedOptions parsedOptions = parseOptions(options, cropRect, video->bitmapS
ourceSize()); | 358 ParsedOptions parsedOptions = parseOptions(options, cropRect, video->bitmapS
ourceSize()); |
| 359 if (dstBufferSizeHasOverflow(parsedOptions)) |
| 360 return; |
316 | 361 |
317 IntRect videoRect = IntRect(IntPoint(), playerSize); | 362 IntRect videoRect = IntRect(IntPoint(), playerSize); |
318 IntRect srcRect = intersection(parsedOptions.cropRect, videoRect); | 363 IntRect srcRect = intersection(parsedOptions.cropRect, videoRect); |
319 std::unique_ptr<ImageBuffer> buffer = ImageBuffer::create(IntSize(parsedOpti
ons.resizeWidth, parsedOptions.resizeHeight), NonOpaque, DoNotInitializeImagePix
els); | 364 std::unique_ptr<ImageBuffer> buffer = ImageBuffer::create(IntSize(parsedOpti
ons.resizeWidth, parsedOptions.resizeHeight), NonOpaque, DoNotInitializeImagePix
els); |
320 if (!buffer) | 365 if (!buffer) |
321 return; | 366 return; |
322 | 367 |
323 if (parsedOptions.flipY) { | 368 if (parsedOptions.flipY) { |
324 buffer->canvas()->translate(0, buffer->size().height()); | 369 buffer->canvas()->translate(0, buffer->size().height()); |
325 buffer->canvas()->scale(1, -1); | 370 buffer->canvas()->scale(1, -1); |
326 } | 371 } |
327 IntPoint dstPoint = IntPoint(std::max(0, -parsedOptions.cropRect.x()), std::
max(0, -parsedOptions.cropRect.y())); | 372 IntPoint dstPoint = IntPoint(std::max(0, -parsedOptions.cropRect.x()), std::
max(0, -parsedOptions.cropRect.y())); |
328 IntSize dstSize = srcRect.size(); | 373 IntSize dstSize = srcRect.size(); |
329 SkPaint paint; | 374 SkPaint paint; |
330 if (parsedOptions.shouldScaleInput) { | 375 if (parsedOptions.shouldScaleInput) { |
331 float scaleRatioX = static_cast<float>(parsedOptions.resizeWidth) / pars
edOptions.cropRect.width(); | 376 float scaleRatioX = static_cast<float>(parsedOptions.resizeWidth) / pars
edOptions.cropRect.width(); |
332 float scaleRatioY = static_cast<float>(parsedOptions.resizeHeight) / par
sedOptions.cropRect.height(); | 377 float scaleRatioY = static_cast<float>(parsedOptions.resizeHeight) / par
sedOptions.cropRect.height(); |
333 dstPoint.scale(scaleRatioX, scaleRatioY); | 378 dstPoint.scale(scaleRatioX, scaleRatioY); |
334 paint.setFilterQuality(parsedOptions.resizeQuality); | 379 paint.setFilterQuality(parsedOptions.resizeQuality); |
335 dstSize.scale(scaleRatioX, scaleRatioY); | 380 dstSize.scale(scaleRatioX, scaleRatioY); |
336 } | 381 } |
337 video->paintCurrentFrame(buffer->canvas(), IntRect(dstPoint, dstSize), parse
dOptions.shouldScaleInput ? &paint : nullptr); | 382 video->paintCurrentFrame(buffer->canvas(), IntRect(dstPoint, dstSize), parse
dOptions.shouldScaleInput ? &paint : nullptr); |
338 | 383 |
339 RefPtr<SkImage> skiaImage = buffer->newSkImageSnapshot(PreferNoAcceleration,
SnapshotReasonUnknown); | 384 RefPtr<SkImage> skiaImage = buffer->newSkImageSnapshot(PreferNoAcceleration,
SnapshotReasonUnknown); |
340 if (!parsedOptions.premultiplyAlpha) | 385 if (!parsedOptions.premultiplyAlpha) |
341 skiaImage = premulSkImageToUnPremul(skiaImage.get()); | 386 skiaImage = premulSkImageToUnPremul(skiaImage.get()); |
| 387 if (!skiaImage) |
| 388 return; |
342 m_image = StaticBitmapImage::create(skiaImage.release()); | 389 m_image = StaticBitmapImage::create(skiaImage.release()); |
343 m_image->setOriginClean(!video->wouldTaintOrigin(document->getSecurityOrigin
())); | 390 m_image->setOriginClean(!video->wouldTaintOrigin(document->getSecurityOrigin
())); |
344 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); | 391 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); |
345 } | 392 } |
346 | 393 |
347 ImageBitmap::ImageBitmap(HTMLCanvasElement* canvas, Optional<IntRect> cropRect,
const ImageBitmapOptions& options) | 394 ImageBitmap::ImageBitmap(HTMLCanvasElement* canvas, Optional<IntRect> cropRect,
const ImageBitmapOptions& options) |
348 { | 395 { |
349 ASSERT(canvas->isPaintable()); | 396 ASSERT(canvas->isPaintable()); |
350 RefPtr<Image> input = canvas->copiedImage(BackBuffer, PreferAcceleration); | 397 RefPtr<Image> input = canvas->copiedImage(BackBuffer, PreferAcceleration); |
351 ParsedOptions parsedOptions = parseOptions(options, cropRect, canvas->bitmap
SourceSize()); | 398 ParsedOptions parsedOptions = parseOptions(options, cropRect, canvas->bitmap
SourceSize()); |
| 399 if (dstBufferSizeHasOverflow(parsedOptions)) |
| 400 return; |
352 | 401 |
353 bool isPremultiplyAlphaReverted = false; | 402 bool isPremultiplyAlphaReverted = false; |
354 if (!parsedOptions.premultiplyAlpha) { | 403 if (!parsedOptions.premultiplyAlpha) { |
355 parsedOptions.premultiplyAlpha = true; | 404 parsedOptions.premultiplyAlpha = true; |
356 isPremultiplyAlphaReverted = true; | 405 isPremultiplyAlphaReverted = true; |
357 } | 406 } |
358 m_image = cropImage(input.get(), parsedOptions); | 407 m_image = cropImage(input.get(), parsedOptions); |
359 if (!m_image) | 408 if (!m_image) |
360 return; | 409 return; |
361 if (isPremultiplyAlphaReverted) { | 410 if (isPremultiplyAlphaReverted) { |
362 parsedOptions.premultiplyAlpha = false; | 411 parsedOptions.premultiplyAlpha = false; |
363 m_image = StaticBitmapImage::create(premulSkImageToUnPremul(m_image->ima
geForCurrentFrame().get())); | 412 m_image = StaticBitmapImage::create(premulSkImageToUnPremul(m_image->ima
geForCurrentFrame().get())); |
364 } | 413 } |
| 414 if (!m_image) |
| 415 return; |
365 m_image->setOriginClean(canvas->originClean()); | 416 m_image->setOriginClean(canvas->originClean()); |
366 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); | 417 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); |
367 } | 418 } |
368 | 419 |
369 ImageBitmap::ImageBitmap(std::unique_ptr<uint8_t[]> data, uint32_t width, uint32
_t height, bool isImageBitmapPremultiplied, bool isImageBitmapOriginClean) | 420 ImageBitmap::ImageBitmap(std::unique_ptr<uint8_t[]> data, uint32_t width, uint32
_t height, bool isImageBitmapPremultiplied, bool isImageBitmapOriginClean) |
370 { | 421 { |
371 SkImageInfo info = SkImageInfo::MakeN32(width, height, isImageBitmapPremulti
plied ? kPremul_SkAlphaType : kUnpremul_SkAlphaType); | 422 SkImageInfo info = SkImageInfo::MakeN32(width, height, isImageBitmapPremulti
plied ? kPremul_SkAlphaType : kUnpremul_SkAlphaType); |
372 m_image = StaticBitmapImage::create(fromSkSp(SkImage::MakeRasterCopy(SkPixma
p(info, data.get(), info.bytesPerPixel() * width)))); | 423 m_image = StaticBitmapImage::create(fromSkSp(SkImage::MakeRasterCopy(SkPixma
p(info, data.get(), info.bytesPerPixel() * width)))); |
| 424 if (!m_image) |
| 425 return; |
373 m_image->setPremultiplied(isImageBitmapPremultiplied); | 426 m_image->setPremultiplied(isImageBitmapPremultiplied); |
374 m_image->setOriginClean(isImageBitmapOriginClean); | 427 m_image->setOriginClean(isImageBitmapOriginClean); |
375 } | 428 } |
376 | 429 |
377 static PassRefPtr<SkImage> scaleSkImage(PassRefPtr<SkImage> skImage, unsigned re
sizeWidth, unsigned resizeHeight, SkFilterQuality resizeQuality) | 430 static PassRefPtr<SkImage> scaleSkImage(PassRefPtr<SkImage> skImage, unsigned re
sizeWidth, unsigned resizeHeight, SkFilterQuality resizeQuality) |
378 { | 431 { |
379 SkImageInfo resizedInfo = SkImageInfo::Make(resizeWidth, resizeHeight, kN32_
SkColorType, kUnpremul_SkAlphaType); | 432 SkImageInfo resizedInfo = SkImageInfo::Make(resizeWidth, resizeHeight, kN32_
SkColorType, kUnpremul_SkAlphaType); |
380 std::unique_ptr<uint8_t[]> resizedPixels = wrapArrayUnique(new uint8_t[resiz
eWidth * resizeHeight * resizedInfo.bytesPerPixel()]); | 433 RefPtr<ArrayBuffer> dstBuffer = ArrayBuffer::createOrNull(resizeWidth * resi
zeHeight, resizedInfo.bytesPerPixel()); |
381 SkPixmap pixmap(resizedInfo, resizedPixels.release(), resizeWidth * resizedI
nfo.bytesPerPixel()); | 434 if (!dstBuffer) |
| 435 return nullptr; |
| 436 RefPtr<Uint8Array> resizedPixels = Uint8Array::create(dstBuffer, 0, dstBuffe
r->byteLength()); |
| 437 SkPixmap pixmap(resizedInfo, resizedPixels->data(), static_cast<size_t>(resi
zeWidth) * resizedInfo.bytesPerPixel()); |
382 skImage->scalePixels(pixmap, resizeQuality); | 438 skImage->scalePixels(pixmap, resizeQuality); |
383 return fromSkSp(SkImage::MakeFromRaster(pixmap, [](const void* pixels, void*
) | 439 return fromSkSp(SkImage::MakeFromRaster(pixmap, [](const void*, void* pixels
) |
384 { | 440 { |
385 delete[] static_cast<const uint8_t*>(pixels); | 441 static_cast<Uint8Array*>(pixels)->deref(); |
386 }, nullptr)); | 442 }, resizedPixels.release().leakRef())); |
387 } | 443 } |
388 | 444 |
389 ImageBitmap::ImageBitmap(ImageData* data, Optional<IntRect> cropRect, const Imag
eBitmapOptions& options) | 445 ImageBitmap::ImageBitmap(ImageData* data, Optional<IntRect> cropRect, const Imag
eBitmapOptions& options) |
390 { | 446 { |
391 // TODO(xidachen): implement the resize option | 447 // TODO(xidachen): implement the resize option |
392 IntRect dataSrcRect = IntRect(IntPoint(), data->size()); | 448 IntRect dataSrcRect = IntRect(IntPoint(), data->size()); |
393 ParsedOptions parsedOptions = parseOptions(options, cropRect, data->bitmapSo
urceSize()); | 449 ParsedOptions parsedOptions = parseOptions(options, cropRect, data->bitmapSo
urceSize()); |
| 450 if (dstBufferSizeHasOverflow(parsedOptions)) |
| 451 return; |
394 IntRect srcRect = cropRect ? intersection(parsedOptions.cropRect, dataSrcRec
t) : dataSrcRect; | 452 IntRect srcRect = cropRect ? intersection(parsedOptions.cropRect, dataSrcRec
t) : dataSrcRect; |
395 | 453 |
396 // treat non-premultiplyAlpha as a special case | 454 // treat non-premultiplyAlpha as a special case |
397 if (!parsedOptions.premultiplyAlpha) { | 455 if (!parsedOptions.premultiplyAlpha) { |
398 unsigned char* srcAddr = data->data()->data(); | 456 unsigned char* srcAddr = data->data()->data(); |
399 int srcHeight = data->size().height(); | |
400 int dstHeight = parsedOptions.cropRect.height(); | |
401 | 457 |
402 // Using kN32 type, swizzle input if necessary. | 458 // Using kN32 type, swizzle input if necessary. |
403 SkImageInfo info = SkImageInfo::Make(parsedOptions.cropRect.width(), dst
Height, kN32_SkColorType, kUnpremul_SkAlphaType); | 459 SkImageInfo info = SkImageInfo::Make(parsedOptions.cropRect.width(), par
sedOptions.cropRect.height(), kN32_SkColorType, kUnpremul_SkAlphaType); |
404 int srcPixelBytesPerRow = info.bytesPerPixel() * data->size().width(); | 460 size_t bytesPerPixel = static_cast<size_t>(info.bytesPerPixel()); |
405 int dstPixelBytesPerRow = info.bytesPerPixel() * parsedOptions.cropRect.
width(); | 461 size_t srcPixelBytesPerRow = bytesPerPixel * data->size().width(); |
| 462 size_t dstPixelBytesPerRow = bytesPerPixel * parsedOptions.cropRect.widt
h(); |
406 RefPtr<SkImage> skImage; | 463 RefPtr<SkImage> skImage; |
407 if (parsedOptions.cropRect == IntRect(IntPoint(), data->size())) { | 464 if (parsedOptions.cropRect == IntRect(IntPoint(), data->size())) { |
408 swizzleImageData(srcAddr, srcHeight, srcPixelBytesPerRow, parsedOpti
ons.flipY); | 465 swizzleImageData(srcAddr, data->size().height(), srcPixelBytesPerRow
, parsedOptions.flipY); |
409 skImage = fromSkSp(SkImage::MakeRasterCopy(SkPixmap(info, srcAddr, d
stPixelBytesPerRow))); | 466 skImage = fromSkSp(SkImage::MakeRasterCopy(SkPixmap(info, srcAddr, d
stPixelBytesPerRow))); |
410 // restore the original ImageData | 467 // restore the original ImageData |
411 swizzleImageData(srcAddr, srcHeight, srcPixelBytesPerRow, parsedOpti
ons.flipY); | 468 swizzleImageData(srcAddr, data->size().height(), srcPixelBytesPerRow
, parsedOptions.flipY); |
412 } else { | 469 } else { |
413 std::unique_ptr<uint8_t[]> copiedDataBuffer = wrapArrayUnique(new ui
nt8_t[dstHeight * dstPixelBytesPerRow]()); | 470 RefPtr<ArrayBuffer> dstBuffer = ArrayBuffer::createOrNull(static_cas
t<size_t>(parsedOptions.cropRect.height()) * parsedOptions.cropRect.width(), byt
esPerPixel); |
| 471 if (!dstBuffer) |
| 472 return; |
| 473 RefPtr<Uint8Array> copiedDataBuffer = Uint8Array::create(dstBuffer,
0, dstBuffer->byteLength()); |
414 if (!srcRect.isEmpty()) { | 474 if (!srcRect.isEmpty()) { |
415 IntPoint srcPoint = IntPoint((parsedOptions.cropRect.x() > 0) ?
parsedOptions.cropRect.x() : 0, (parsedOptions.cropRect.y() > 0) ? parsedOptions
.cropRect.y() : 0); | 475 IntPoint srcPoint = IntPoint((parsedOptions.cropRect.x() > 0) ?
parsedOptions.cropRect.x() : 0, (parsedOptions.cropRect.y() > 0) ? parsedOptions
.cropRect.y() : 0); |
416 IntPoint dstPoint = IntPoint((parsedOptions.cropRect.x() >= 0) ?
0 : -parsedOptions.cropRect.x(), (parsedOptions.cropRect.y() >= 0) ? 0 : -parse
dOptions.cropRect.y()); | 476 IntPoint dstPoint = IntPoint((parsedOptions.cropRect.x() >= 0) ?
0 : -parsedOptions.cropRect.x(), (parsedOptions.cropRect.y() >= 0) ? 0 : -parse
dOptions.cropRect.y()); |
417 int copyHeight = srcHeight - srcPoint.y(); | 477 int copyHeight = data->size().height() - srcPoint.y(); |
418 if (parsedOptions.cropRect.height() < copyHeight) | 478 if (parsedOptions.cropRect.height() < copyHeight) |
419 copyHeight = parsedOptions.cropRect.height(); | 479 copyHeight = parsedOptions.cropRect.height(); |
420 int copyWidth = data->size().width() - srcPoint.x(); | 480 int copyWidth = data->size().width() - srcPoint.x(); |
421 if (parsedOptions.cropRect.width() < copyWidth) | 481 if (parsedOptions.cropRect.width() < copyWidth) |
422 copyWidth = parsedOptions.cropRect.width(); | 482 copyWidth = parsedOptions.cropRect.width(); |
423 for (int i = 0; i < copyHeight; i++) { | 483 for (int i = 0; i < copyHeight; i++) { |
424 int srcStartCopyPosition = (i + srcPoint.y()) * srcPixelByte
sPerRow + srcPoint.x() * info.bytesPerPixel(); | 484 size_t srcStartCopyPosition = (i + srcPoint.y()) * srcPixelB
ytesPerRow + srcPoint.x() * bytesPerPixel; |
425 int srcEndCopyPosition = srcStartCopyPosition + copyWidth *
info.bytesPerPixel(); | 485 size_t srcEndCopyPosition = srcStartCopyPosition + copyWidth
* bytesPerPixel; |
426 int dstStartCopyPosition; | 486 size_t dstStartCopyPosition; |
427 if (parsedOptions.flipY) | 487 if (parsedOptions.flipY) |
428 dstStartCopyPosition = (dstHeight -1 - dstPoint.y() - i)
* dstPixelBytesPerRow + dstPoint.x() * info.bytesPerPixel(); | 488 dstStartCopyPosition = (parsedOptions.cropRect.height()
-1 - dstPoint.y() - i) * dstPixelBytesPerRow + dstPoint.x() * bytesPerPixel; |
429 else | 489 else |
430 dstStartCopyPosition = (dstPoint.y() + i) * dstPixelByte
sPerRow + dstPoint.x() * info.bytesPerPixel(); | 490 dstStartCopyPosition = (dstPoint.y() + i) * dstPixelByte
sPerRow + dstPoint.x() * bytesPerPixel; |
431 for (int j = 0; j < srcEndCopyPosition - srcStartCopyPositio
n; j++) { | 491 for (size_t j = 0; j < srcEndCopyPosition - srcStartCopyPosi
tion; j++) { |
432 // swizzle when necessary | 492 // swizzle when necessary |
433 if (kN32_SkColorType == kBGRA_8888_SkColorType) { | 493 if (kN32_SkColorType == kBGRA_8888_SkColorType) { |
434 if (j % 4 == 0) | 494 if (j % 4 == 0) |
435 copiedDataBuffer[dstStartCopyPosition + j] = src
Addr[srcStartCopyPosition + j + 2]; | 495 copiedDataBuffer->data()[dstStartCopyPosition +
j] = srcAddr[srcStartCopyPosition + j + 2]; |
436 else if (j % 4 == 2) | 496 else if (j % 4 == 2) |
437 copiedDataBuffer[dstStartCopyPosition + j] = src
Addr[srcStartCopyPosition + j - 2]; | 497 copiedDataBuffer->data()[dstStartCopyPosition +
j] = srcAddr[srcStartCopyPosition + j - 2]; |
438 else | 498 else |
439 copiedDataBuffer[dstStartCopyPosition + j] = src
Addr[srcStartCopyPosition + j]; | 499 copiedDataBuffer->data()[dstStartCopyPosition +
j] = srcAddr[srcStartCopyPosition + j]; |
440 } else { | 500 } else { |
441 copiedDataBuffer[dstStartCopyPosition + j] = srcAddr
[srcStartCopyPosition + j]; | 501 copiedDataBuffer->data()[dstStartCopyPosition + j] =
srcAddr[srcStartCopyPosition + j]; |
442 } | 502 } |
443 } | 503 } |
444 } | 504 } |
445 } | 505 } |
446 skImage = newSkImageFromRaster(info, std::move(copiedDataBuffer), ds
tPixelBytesPerRow); | 506 skImage = newSkImageFromRaster(info, std::move(copiedDataBuffer), ds
tPixelBytesPerRow); |
447 } | 507 } |
| 508 if (!skImage) |
| 509 return; |
448 if (parsedOptions.shouldScaleInput) | 510 if (parsedOptions.shouldScaleInput) |
449 m_image = StaticBitmapImage::create(scaleSkImage(skImage, parsedOpti
ons.resizeWidth, parsedOptions.resizeHeight, parsedOptions.resizeQuality)); | 511 m_image = StaticBitmapImage::create(scaleSkImage(skImage, parsedOpti
ons.resizeWidth, parsedOptions.resizeHeight, parsedOptions.resizeQuality)); |
450 else | 512 else |
451 m_image = StaticBitmapImage::create(skImage); | 513 m_image = StaticBitmapImage::create(skImage); |
| 514 if (!m_image) |
| 515 return; |
452 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); | 516 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); |
453 return; | 517 return; |
454 } | 518 } |
455 | 519 |
456 std::unique_ptr<ImageBuffer> buffer = ImageBuffer::create(parsedOptions.crop
Rect.size(), NonOpaque, DoNotInitializeImagePixels); | 520 std::unique_ptr<ImageBuffer> buffer = ImageBuffer::create(parsedOptions.crop
Rect.size(), NonOpaque, DoNotInitializeImagePixels); |
457 if (!buffer) | 521 if (!buffer) |
458 return; | 522 return; |
459 | 523 |
460 if (srcRect.isEmpty()) { | 524 if (srcRect.isEmpty()) { |
461 m_image = StaticBitmapImage::create(buffer->newSkImageSnapshot(PreferNoA
cceleration, SnapshotReasonUnknown)); | 525 m_image = StaticBitmapImage::create(buffer->newSkImageSnapshot(PreferNoA
cceleration, SnapshotReasonUnknown)); |
462 return; | 526 return; |
463 } | 527 } |
464 | 528 |
465 IntPoint dstPoint = IntPoint(std::min(0, -parsedOptions.cropRect.x()), std::
min(0, -parsedOptions.cropRect.y())); | 529 IntPoint dstPoint = IntPoint(std::min(0, -parsedOptions.cropRect.x()), std::
min(0, -parsedOptions.cropRect.y())); |
466 if (parsedOptions.cropRect.x() < 0) | 530 if (parsedOptions.cropRect.x() < 0) |
467 dstPoint.setX(-parsedOptions.cropRect.x()); | 531 dstPoint.setX(-parsedOptions.cropRect.x()); |
468 if (parsedOptions.cropRect.y() < 0) | 532 if (parsedOptions.cropRect.y() < 0) |
469 dstPoint.setY(-parsedOptions.cropRect.y()); | 533 dstPoint.setY(-parsedOptions.cropRect.y()); |
470 buffer->putByteArray(Unmultiplied, data->data()->data(), data->size(), srcRe
ct, dstPoint); | 534 buffer->putByteArray(Unmultiplied, data->data()->data(), data->size(), srcRe
ct, dstPoint); |
471 RefPtr<SkImage> skImage = buffer->newSkImageSnapshot(PreferNoAcceleration, S
napshotReasonUnknown); | 535 RefPtr<SkImage> skImage = buffer->newSkImageSnapshot(PreferNoAcceleration, S
napshotReasonUnknown); |
472 if (parsedOptions.flipY) | 536 if (parsedOptions.flipY) |
473 skImage = flipSkImageVertically(skImage.get(), PremultiplyAlpha); | 537 skImage = flipSkImageVertically(skImage.get(), PremultiplyAlpha); |
| 538 if (!skImage) |
| 539 return; |
474 if (parsedOptions.shouldScaleInput) { | 540 if (parsedOptions.shouldScaleInput) { |
475 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(parsedOptions.
resizeWidth, parsedOptions.resizeHeight); | 541 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(parsedOptions.
resizeWidth, parsedOptions.resizeHeight); |
476 if (!surface) | 542 if (!surface) |
477 return; | 543 return; |
478 SkPaint paint; | 544 SkPaint paint; |
479 paint.setFilterQuality(parsedOptions.resizeQuality); | 545 paint.setFilterQuality(parsedOptions.resizeQuality); |
480 SkRect dstDrawRect = SkRect::MakeWH(parsedOptions.resizeWidth, parsedOpt
ions.resizeHeight); | 546 SkRect dstDrawRect = SkRect::MakeWH(parsedOptions.resizeWidth, parsedOpt
ions.resizeHeight); |
481 surface->getCanvas()->drawImageRect(skImage.get(), dstDrawRect, &paint); | 547 surface->getCanvas()->drawImageRect(skImage.get(), dstDrawRect, &paint); |
482 skImage = fromSkSp(surface->makeImageSnapshot()); | 548 skImage = fromSkSp(surface->makeImageSnapshot()); |
483 } | 549 } |
484 m_image = StaticBitmapImage::create(skImage); | 550 m_image = StaticBitmapImage::create(skImage); |
485 } | 551 } |
486 | 552 |
487 ImageBitmap::ImageBitmap(ImageBitmap* bitmap, Optional<IntRect> cropRect, const
ImageBitmapOptions& options) | 553 ImageBitmap::ImageBitmap(ImageBitmap* bitmap, Optional<IntRect> cropRect, const
ImageBitmapOptions& options) |
488 { | 554 { |
489 RefPtr<Image> input = bitmap->bitmapImage(); | 555 RefPtr<Image> input = bitmap->bitmapImage(); |
490 if (!input) | 556 if (!input) |
491 return; | 557 return; |
492 ParsedOptions parsedOptions = parseOptions(options, cropRect, input->size())
; | 558 ParsedOptions parsedOptions = parseOptions(options, cropRect, input->size())
; |
| 559 if (dstBufferSizeHasOverflow(parsedOptions)) |
| 560 return; |
493 | 561 |
494 m_image = cropImage(input.get(), parsedOptions, bitmap->isPremultiplied() ?
PremultiplyAlpha : DontPremultiplyAlpha); | 562 m_image = cropImage(input.get(), parsedOptions, bitmap->isPremultiplied() ?
PremultiplyAlpha : DontPremultiplyAlpha); |
495 if (!m_image) | 563 if (!m_image) |
496 return; | 564 return; |
497 m_image->setOriginClean(bitmap->originClean()); | 565 m_image->setOriginClean(bitmap->originClean()); |
498 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); | 566 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); |
499 } | 567 } |
500 | 568 |
501 ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image, Optional<IntRect>
cropRect, const ImageBitmapOptions& options) | 569 ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image, Optional<IntRect>
cropRect, const ImageBitmapOptions& options) |
502 { | 570 { |
| 571 fprintf(stderr, "ImageBItmap constructor with StaticBitmapImage and cropRect
and options\n"); |
503 bool originClean = image->originClean(); | 572 bool originClean = image->originClean(); |
504 RefPtr<Image> input = image; | 573 RefPtr<Image> input = image; |
505 ParsedOptions parsedOptions = parseOptions(options, cropRect, input->size())
; | 574 ParsedOptions parsedOptions = parseOptions(options, cropRect, input->size())
; |
506 | 575 if (dstBufferSizeHasOverflow(parsedOptions)) |
| 576 return; |
| 577 fprintf(stderr, "done parsedOptions and check overflow\n"); |
507 m_image = cropImage(input.get(), parsedOptions, DontPremultiplyAlpha); | 578 m_image = cropImage(input.get(), parsedOptions, DontPremultiplyAlpha); |
508 if (!m_image) | 579 if (!m_image) |
509 return; | 580 return; |
| 581 fprintf(stderr, "done calling cropImage and m_image is not null\n"); |
510 m_image->setOriginClean(originClean); | 582 m_image->setOriginClean(originClean); |
511 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); | 583 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); |
| 584 fprintf(stderr, "ImageBitmap constructor is done\n"); |
512 } | 585 } |
513 | 586 |
514 ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image) | 587 ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image) |
515 { | 588 { |
516 m_image = image; | 589 m_image = image; |
517 } | 590 } |
518 | 591 |
519 PassRefPtr<StaticBitmapImage> ImageBitmap::transfer() | 592 PassRefPtr<StaticBitmapImage> ImageBitmap::transfer() |
520 { | 593 { |
521 ASSERT(!isNeutered()); | 594 ASSERT(!isNeutered()); |
(...skipping 25 matching lines...) Expand all Loading... |
547 return new ImageBitmap(data, cropRect, options); | 620 return new ImageBitmap(data, cropRect, options); |
548 } | 621 } |
549 | 622 |
550 ImageBitmap* ImageBitmap::create(ImageBitmap* bitmap, Optional<IntRect> cropRect
, const ImageBitmapOptions& options) | 623 ImageBitmap* ImageBitmap::create(ImageBitmap* bitmap, Optional<IntRect> cropRect
, const ImageBitmapOptions& options) |
551 { | 624 { |
552 return new ImageBitmap(bitmap, cropRect, options); | 625 return new ImageBitmap(bitmap, cropRect, options); |
553 } | 626 } |
554 | 627 |
555 ImageBitmap* ImageBitmap::create(PassRefPtr<StaticBitmapImage> image, Optional<I
ntRect> cropRect, const ImageBitmapOptions& options) | 628 ImageBitmap* ImageBitmap::create(PassRefPtr<StaticBitmapImage> image, Optional<I
ntRect> cropRect, const ImageBitmapOptions& options) |
556 { | 629 { |
| 630 fprintf(stderr, "calling ImageBitmap::create from StaticBitmapImage with cro
p and options\n"); |
557 return new ImageBitmap(image, cropRect, options); | 631 return new ImageBitmap(image, cropRect, options); |
558 } | 632 } |
559 | 633 |
560 ImageBitmap* ImageBitmap::create(PassRefPtr<StaticBitmapImage> image) | 634 ImageBitmap* ImageBitmap::create(PassRefPtr<StaticBitmapImage> image) |
561 { | 635 { |
562 return new ImageBitmap(image); | 636 return new ImageBitmap(image); |
563 } | 637 } |
564 | 638 |
565 ImageBitmap* ImageBitmap::create(std::unique_ptr<uint8_t[]> data, uint32_t width
, uint32_t height, bool isImageBitmapPremultiplied, bool isImageBitmapOriginClea
n) | 639 ImageBitmap* ImageBitmap::create(std::unique_ptr<uint8_t[]> data, uint32_t width
, uint32_t height, bool isImageBitmapPremultiplied, bool isImageBitmapOriginClea
n) |
566 { | 640 { |
567 return new ImageBitmap(std::move(data), width, height, isImageBitmapPremulti
plied, isImageBitmapOriginClean); | 641 return new ImageBitmap(std::move(data), width, height, isImageBitmapPremulti
plied, isImageBitmapOriginClean); |
568 } | 642 } |
569 | 643 |
570 void ImageBitmap::close() | 644 void ImageBitmap::close() |
571 { | 645 { |
572 if (!m_image || m_isNeutered) | 646 if (!m_image || m_isNeutered) |
573 return; | 647 return; |
574 m_image.clear(); | 648 m_image.clear(); |
575 m_isNeutered = true; | 649 m_isNeutered = true; |
576 } | 650 } |
577 | 651 |
578 // static | 652 // static |
579 ImageBitmap* ImageBitmap::take(ScriptPromiseResolver*, sk_sp<SkImage> image) | 653 ImageBitmap* ImageBitmap::take(ScriptPromiseResolver*, sk_sp<SkImage> image) |
580 { | 654 { |
581 return ImageBitmap::create(StaticBitmapImage::create(fromSkSp(image))); | 655 return ImageBitmap::create(StaticBitmapImage::create(fromSkSp(image))); |
582 } | 656 } |
583 | 657 |
584 std::unique_ptr<uint8_t[]> ImageBitmap::copyBitmapData(AlphaDisposition alphaOp,
DataColorFormat format) | 658 PassRefPtr<Uint8Array> ImageBitmap::copyBitmapData(AlphaDisposition alphaOp, Dat
aColorFormat format) |
585 { | 659 { |
586 SkImageInfo info = SkImageInfo::Make(width(), height(), (format == RGBAColor
Type) ? kRGBA_8888_SkColorType : kN32_SkColorType, (alphaOp == PremultiplyAlpha)
? kPremul_SkAlphaType : kUnpremul_SkAlphaType); | 660 SkImageInfo info = SkImageInfo::Make(width(), height(), (format == RGBAColor
Type) ? kRGBA_8888_SkColorType : kN32_SkColorType, (alphaOp == PremultiplyAlpha)
? kPremul_SkAlphaType : kUnpremul_SkAlphaType); |
587 std::unique_ptr<uint8_t[]> dstPixels = copySkImageData(m_image->imageForCurr
entFrame().get(), info); | 661 RefPtr<Uint8Array> dstPixels = copySkImageData(m_image->imageForCurrentFrame
().get(), info); |
588 return dstPixels; | 662 return dstPixels; |
589 } | 663 } |
590 | 664 |
591 unsigned long ImageBitmap::width() const | 665 unsigned long ImageBitmap::width() const |
592 { | 666 { |
593 if (!m_image) | 667 if (!m_image) |
594 return 0; | 668 return 0; |
595 ASSERT(m_image->width() > 0); | 669 ASSERT(m_image->width() > 0); |
596 return m_image->width(); | 670 return m_image->width(); |
597 } | 671 } |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
640 FloatSize ImageBitmap::elementSize(const FloatSize&) const | 714 FloatSize ImageBitmap::elementSize(const FloatSize&) const |
641 { | 715 { |
642 return FloatSize(width(), height()); | 716 return FloatSize(width(), height()); |
643 } | 717 } |
644 | 718 |
645 DEFINE_TRACE(ImageBitmap) | 719 DEFINE_TRACE(ImageBitmap) |
646 { | 720 { |
647 } | 721 } |
648 | 722 |
649 } // namespace blink | 723 } // namespace blink |
OLD | NEW |