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 SkPixmap pixmap(info, imagePixels->data(), imageRowBytes); |
115 [](const void* pixels, void*) | 145 return fromSkSp(SkImage::MakeFromRaster(pixmap, [](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 20 matching lines...) Expand all Loading... |
203 return true; | 239 return true; |
204 } | 240 } |
205 | 241 |
206 // The parameter imageFormat indicates whether the first parameter "image" is un
premultiplied or not. | 242 // The parameter imageFormat indicates whether the first parameter "image" is un
premultiplied or not. |
207 // imageFormat = PremultiplyAlpha means the image is in premuliplied format | 243 // imageFormat = PremultiplyAlpha means the image is in premuliplied format |
208 // For example, if the image is already in unpremultiplied format and we want th
e created ImageBitmap | 244 // For example, if the image is already in unpremultiplied format and we want th
e created ImageBitmap |
209 // in the same format, then we don't need to use the ImageDecoder to decode the
image. | 245 // in the same format, then we don't need to use the ImageDecoder to decode the
image. |
210 static PassRefPtr<StaticBitmapImage> cropImage(Image* image, const ParsedOptions
& parsedOptions, AlphaDisposition imageFormat = PremultiplyAlpha, ImageDecoder::
GammaAndColorProfileOption colorSpaceOp = ImageDecoder::GammaAndColorProfileAppl
ied) | 246 static PassRefPtr<StaticBitmapImage> cropImage(Image* image, const ParsedOptions
& parsedOptions, AlphaDisposition imageFormat = PremultiplyAlpha, ImageDecoder::
GammaAndColorProfileOption colorSpaceOp = ImageDecoder::GammaAndColorProfileAppl
ied) |
211 { | 247 { |
212 ASSERT(image); | 248 ASSERT(image); |
213 | |
214 IntRect imgRect(IntPoint(), IntSize(image->width(), image->height())); | 249 IntRect imgRect(IntPoint(), IntSize(image->width(), image->height())); |
215 const IntRect srcRect = intersection(imgRect, parsedOptions.cropRect); | 250 const IntRect srcRect = intersection(imgRect, parsedOptions.cropRect); |
216 | 251 |
217 // In the case when cropRect doesn't intersect the source image and it requi
res a umpremul image | 252 // 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() | 253 // We immediately return a transparent black image with cropRect.size() |
219 if (srcRect.isEmpty() && !parsedOptions.premultiplyAlpha) { | 254 if (srcRect.isEmpty() && !parsedOptions.premultiplyAlpha) { |
220 SkImageInfo info = SkImageInfo::Make(parsedOptions.resizeWidth, parsedOp
tions.resizeHeight, kN32_SkColorType, kUnpremul_SkAlphaType); | 255 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()]()); | 256 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())); | 257 if (!dstBuffer) |
| 258 return nullptr; |
| 259 RefPtr<Uint8Array> dstPixels = Uint8Array::create(dstBuffer, 0, dstBuffe
r->byteLength()); |
| 260 return StaticBitmapImage::create(newSkImageFromRaster(info, std::move(ds
tPixels), static_cast<size_t>(info.width()) * info.bytesPerPixel())); |
223 } | 261 } |
224 | 262 |
225 RefPtr<SkImage> skiaImage = image->imageForCurrentFrame(); | 263 RefPtr<SkImage> skiaImage = image->imageForCurrentFrame(); |
226 // Attempt to get raw unpremultiplied image data, executed only when skiaIma
ge is premultiplied. | 264 // 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) { | 265 if ((((!parsedOptions.premultiplyAlpha && !skiaImage->isOpaque()) || !skiaIm
age) && image->data() && imageFormat == PremultiplyAlpha) || colorSpaceOp == Ima
geDecoder::GammaAndColorProfileIgnored) { |
228 std::unique_ptr<ImageDecoder> decoder(ImageDecoder::create( | 266 std::unique_ptr<ImageDecoder> decoder(ImageDecoder::create( |
229 image->data(), true, | 267 image->data(), true, |
230 parsedOptions.premultiplyAlpha ? ImageDecoder::AlphaPremultiplied :
ImageDecoder::AlphaNotPremultiplied, | 268 parsedOptions.premultiplyAlpha ? ImageDecoder::AlphaPremultiplied :
ImageDecoder::AlphaNotPremultiplied, |
231 colorSpaceOp)); | 269 colorSpaceOp)); |
232 if (!decoder) | 270 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); | 307 SkRect drawDstRect = SkRect::MakeXYWH(0, 0, parsedOptions.resizeWidth, p
arsedOptions.resizeHeight); |
270 SkPaint paint; | 308 SkPaint paint; |
271 paint.setFilterQuality(parsedOptions.resizeQuality); | 309 paint.setFilterQuality(parsedOptions.resizeQuality); |
272 surface->getCanvas()->drawImageRect(skiaImage.get(), drawSrcRect, drawDs
tRect, &paint); | 310 surface->getCanvas()->drawImageRect(skiaImage.get(), drawSrcRect, drawDs
tRect, &paint); |
273 } else { | 311 } else { |
274 surface->getCanvas()->drawImage(skiaImage.get(), dstLeft, dstTop); | 312 surface->getCanvas()->drawImage(skiaImage.get(), dstLeft, dstTop); |
275 } | 313 } |
276 skiaImage = fromSkSp(surface->makeImageSnapshot()); | 314 skiaImage = fromSkSp(surface->makeImageSnapshot()); |
277 | 315 |
278 if (parsedOptions.premultiplyAlpha) { | 316 if (parsedOptions.premultiplyAlpha) { |
279 if (imageFormat == PremultiplyAlpha) | 317 if (imageFormat == DontPremultiplyAlpha) |
280 return StaticBitmapImage::create(unPremulSkImageToPremul(skiaImage.g
et())); | 318 return StaticBitmapImage::create(unPremulSkImageToPremul(skiaImage.g
et())); |
281 return StaticBitmapImage::create(skiaImage.release()); | 319 return StaticBitmapImage::create(skiaImage.release()); |
282 } | 320 } |
283 return StaticBitmapImage::create(premulSkImageToUnPremul(skiaImage.get())); | 321 return StaticBitmapImage::create(premulSkImageToUnPremul(skiaImage.get())); |
284 } | 322 } |
285 | 323 |
286 ImageBitmap::ImageBitmap(HTMLImageElement* image, Optional<IntRect> cropRect, Do
cument* document, const ImageBitmapOptions& options) | 324 ImageBitmap::ImageBitmap(HTMLImageElement* image, Optional<IntRect> cropRect, Do
cument* document, const ImageBitmapOptions& options) |
287 { | 325 { |
288 RefPtr<Image> input = image->cachedImage()->getImage(); | 326 RefPtr<Image> input = image->cachedImage()->getImage(); |
289 ParsedOptions parsedOptions = parseOptions(options, cropRect, image->bitmapS
ourceSize()); | 327 ParsedOptions parsedOptions = parseOptions(options, cropRect, image->bitmapS
ourceSize()); |
| 328 if (dstBufferSizeHasOverflow(parsedOptions)) |
| 329 return; |
290 | 330 |
291 if (options.colorSpaceConversion() == "none") | 331 if (options.colorSpaceConversion() == "none") |
292 m_image = cropImage(input.get(), parsedOptions, PremultiplyAlpha, ImageD
ecoder::GammaAndColorProfileIgnored); | 332 m_image = cropImage(input.get(), parsedOptions, PremultiplyAlpha, ImageD
ecoder::GammaAndColorProfileIgnored); |
293 else | 333 else |
294 m_image = cropImage(input.get(), parsedOptions, PremultiplyAlpha, ImageD
ecoder::GammaAndColorProfileApplied); | 334 m_image = cropImage(input.get(), parsedOptions, PremultiplyAlpha, ImageD
ecoder::GammaAndColorProfileApplied); |
295 if (!m_image) | 335 if (!m_image) |
296 return; | 336 return; |
297 // In the case where the source image is lazy-decoded, m_image may not be in | 337 // In the case where the source image is lazy-decoded, m_image may not be in |
298 // a decoded state, we trigger it here. | 338 // a decoded state, we trigger it here. |
299 RefPtr<SkImage> skImage = m_image->imageForCurrentFrame(); | 339 RefPtr<SkImage> skImage = m_image->imageForCurrentFrame(); |
300 SkPixmap pixmap; | 340 SkPixmap pixmap; |
301 if (!skImage->isTextureBacked() && !skImage->peekPixels(&pixmap)) { | 341 if (!skImage->isTextureBacked() && !skImage->peekPixels(&pixmap)) { |
302 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(skImage->width
(), skImage->height()); | 342 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(skImage->width
(), skImage->height()); |
303 surface->getCanvas()->drawImage(skImage.get(), 0, 0); | 343 surface->getCanvas()->drawImage(skImage.get(), 0, 0); |
304 m_image = StaticBitmapImage::create(fromSkSp(surface->makeImageSnapshot(
))); | 344 m_image = StaticBitmapImage::create(fromSkSp(surface->makeImageSnapshot(
))); |
305 } | 345 } |
| 346 if (!m_image) |
| 347 return; |
306 m_image->setOriginClean(!image->wouldTaintOrigin(document->getSecurityOrigin
())); | 348 m_image->setOriginClean(!image->wouldTaintOrigin(document->getSecurityOrigin
())); |
307 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); | 349 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); |
308 } | 350 } |
309 | 351 |
310 ImageBitmap::ImageBitmap(HTMLVideoElement* video, Optional<IntRect> cropRect, Do
cument* document, const ImageBitmapOptions& options) | 352 ImageBitmap::ImageBitmap(HTMLVideoElement* video, Optional<IntRect> cropRect, Do
cument* document, const ImageBitmapOptions& options) |
311 { | 353 { |
312 IntSize playerSize; | 354 IntSize playerSize; |
313 if (video->webMediaPlayer()) | 355 if (video->webMediaPlayer()) |
314 playerSize = video->webMediaPlayer()->naturalSize(); | 356 playerSize = video->webMediaPlayer()->naturalSize(); |
315 ParsedOptions parsedOptions = parseOptions(options, cropRect, video->bitmapS
ourceSize()); | 357 ParsedOptions parsedOptions = parseOptions(options, cropRect, video->bitmapS
ourceSize()); |
| 358 if (dstBufferSizeHasOverflow(parsedOptions)) |
| 359 return; |
316 | 360 |
317 IntRect videoRect = IntRect(IntPoint(), playerSize); | 361 IntRect videoRect = IntRect(IntPoint(), playerSize); |
318 IntRect srcRect = intersection(parsedOptions.cropRect, videoRect); | 362 IntRect srcRect = intersection(parsedOptions.cropRect, videoRect); |
319 std::unique_ptr<ImageBuffer> buffer = ImageBuffer::create(IntSize(parsedOpti
ons.resizeWidth, parsedOptions.resizeHeight), NonOpaque, DoNotInitializeImagePix
els); | 363 std::unique_ptr<ImageBuffer> buffer = ImageBuffer::create(IntSize(parsedOpti
ons.resizeWidth, parsedOptions.resizeHeight), NonOpaque, DoNotInitializeImagePix
els); |
320 if (!buffer) | 364 if (!buffer) |
321 return; | 365 return; |
322 | 366 |
323 if (parsedOptions.flipY) { | 367 if (parsedOptions.flipY) { |
324 buffer->canvas()->translate(0, buffer->size().height()); | 368 buffer->canvas()->translate(0, buffer->size().height()); |
325 buffer->canvas()->scale(1, -1); | 369 buffer->canvas()->scale(1, -1); |
326 } | 370 } |
327 IntPoint dstPoint = IntPoint(std::max(0, -parsedOptions.cropRect.x()), std::
max(0, -parsedOptions.cropRect.y())); | 371 IntPoint dstPoint = IntPoint(std::max(0, -parsedOptions.cropRect.x()), std::
max(0, -parsedOptions.cropRect.y())); |
328 IntSize dstSize = srcRect.size(); | 372 IntSize dstSize = srcRect.size(); |
329 SkPaint paint; | 373 SkPaint paint; |
330 if (parsedOptions.shouldScaleInput) { | 374 if (parsedOptions.shouldScaleInput) { |
331 float scaleRatioX = static_cast<float>(parsedOptions.resizeWidth) / pars
edOptions.cropRect.width(); | 375 float scaleRatioX = static_cast<float>(parsedOptions.resizeWidth) / pars
edOptions.cropRect.width(); |
332 float scaleRatioY = static_cast<float>(parsedOptions.resizeHeight) / par
sedOptions.cropRect.height(); | 376 float scaleRatioY = static_cast<float>(parsedOptions.resizeHeight) / par
sedOptions.cropRect.height(); |
333 dstPoint.scale(scaleRatioX, scaleRatioY); | 377 dstPoint.scale(scaleRatioX, scaleRatioY); |
334 paint.setFilterQuality(parsedOptions.resizeQuality); | 378 paint.setFilterQuality(parsedOptions.resizeQuality); |
335 dstSize.scale(scaleRatioX, scaleRatioY); | 379 dstSize.scale(scaleRatioX, scaleRatioY); |
336 } | 380 } |
337 video->paintCurrentFrame(buffer->canvas(), IntRect(dstPoint, dstSize), parse
dOptions.shouldScaleInput ? &paint : nullptr); | 381 video->paintCurrentFrame(buffer->canvas(), IntRect(dstPoint, dstSize), parse
dOptions.shouldScaleInput ? &paint : nullptr); |
338 | 382 |
339 RefPtr<SkImage> skiaImage = buffer->newSkImageSnapshot(PreferNoAcceleration,
SnapshotReasonUnknown); | 383 RefPtr<SkImage> skiaImage = buffer->newSkImageSnapshot(PreferNoAcceleration,
SnapshotReasonUnknown); |
340 if (!parsedOptions.premultiplyAlpha) | 384 if (!parsedOptions.premultiplyAlpha) |
341 skiaImage = premulSkImageToUnPremul(skiaImage.get()); | 385 skiaImage = premulSkImageToUnPremul(skiaImage.get()); |
| 386 if (!skiaImage) |
| 387 return; |
342 m_image = StaticBitmapImage::create(skiaImage.release()); | 388 m_image = StaticBitmapImage::create(skiaImage.release()); |
343 m_image->setOriginClean(!video->wouldTaintOrigin(document->getSecurityOrigin
())); | 389 m_image->setOriginClean(!video->wouldTaintOrigin(document->getSecurityOrigin
())); |
344 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); | 390 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); |
345 } | 391 } |
346 | 392 |
347 ImageBitmap::ImageBitmap(HTMLCanvasElement* canvas, Optional<IntRect> cropRect,
const ImageBitmapOptions& options) | 393 ImageBitmap::ImageBitmap(HTMLCanvasElement* canvas, Optional<IntRect> cropRect,
const ImageBitmapOptions& options) |
348 { | 394 { |
349 ASSERT(canvas->isPaintable()); | 395 ASSERT(canvas->isPaintable()); |
350 RefPtr<Image> input = canvas->copiedImage(BackBuffer, PreferAcceleration); | 396 RefPtr<Image> input = canvas->copiedImage(BackBuffer, PreferAcceleration); |
351 ParsedOptions parsedOptions = parseOptions(options, cropRect, canvas->bitmap
SourceSize()); | 397 ParsedOptions parsedOptions = parseOptions(options, cropRect, canvas->bitmap
SourceSize()); |
| 398 if (dstBufferSizeHasOverflow(parsedOptions)) |
| 399 return; |
352 | 400 |
353 bool isPremultiplyAlphaReverted = false; | 401 bool isPremultiplyAlphaReverted = false; |
354 if (!parsedOptions.premultiplyAlpha) { | 402 if (!parsedOptions.premultiplyAlpha) { |
355 parsedOptions.premultiplyAlpha = true; | 403 parsedOptions.premultiplyAlpha = true; |
356 isPremultiplyAlphaReverted = true; | 404 isPremultiplyAlphaReverted = true; |
357 } | 405 } |
358 m_image = cropImage(input.get(), parsedOptions); | 406 m_image = cropImage(input.get(), parsedOptions); |
359 if (!m_image) | 407 if (!m_image) |
360 return; | 408 return; |
361 if (isPremultiplyAlphaReverted) { | 409 if (isPremultiplyAlphaReverted) { |
362 parsedOptions.premultiplyAlpha = false; | 410 parsedOptions.premultiplyAlpha = false; |
363 m_image = StaticBitmapImage::create(premulSkImageToUnPremul(m_image->ima
geForCurrentFrame().get())); | 411 m_image = StaticBitmapImage::create(premulSkImageToUnPremul(m_image->ima
geForCurrentFrame().get())); |
364 } | 412 } |
| 413 if (!m_image) |
| 414 return; |
365 m_image->setOriginClean(canvas->originClean()); | 415 m_image->setOriginClean(canvas->originClean()); |
366 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); | 416 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); |
367 } | 417 } |
368 | 418 |
369 ImageBitmap::ImageBitmap(std::unique_ptr<uint8_t[]> data, uint32_t width, uint32
_t height, bool isImageBitmapPremultiplied, bool isImageBitmapOriginClean) | 419 ImageBitmap::ImageBitmap(std::unique_ptr<uint8_t[]> data, uint32_t width, uint32
_t height, bool isImageBitmapPremultiplied, bool isImageBitmapOriginClean) |
370 { | 420 { |
371 SkImageInfo info = SkImageInfo::MakeN32(width, height, isImageBitmapPremulti
plied ? kPremul_SkAlphaType : kUnpremul_SkAlphaType); | 421 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)))); | 422 m_image = StaticBitmapImage::create(fromSkSp(SkImage::MakeRasterCopy(SkPixma
p(info, data.get(), info.bytesPerPixel() * width)))); |
| 423 if (!m_image) |
| 424 return; |
373 m_image->setPremultiplied(isImageBitmapPremultiplied); | 425 m_image->setPremultiplied(isImageBitmapPremultiplied); |
374 m_image->setOriginClean(isImageBitmapOriginClean); | 426 m_image->setOriginClean(isImageBitmapOriginClean); |
375 } | 427 } |
376 | 428 |
377 static PassRefPtr<SkImage> scaleSkImage(PassRefPtr<SkImage> skImage, unsigned re
sizeWidth, unsigned resizeHeight, SkFilterQuality resizeQuality) | 429 static PassRefPtr<SkImage> scaleSkImage(PassRefPtr<SkImage> skImage, unsigned re
sizeWidth, unsigned resizeHeight, SkFilterQuality resizeQuality) |
378 { | 430 { |
379 SkImageInfo resizedInfo = SkImageInfo::Make(resizeWidth, resizeHeight, kN32_
SkColorType, kUnpremul_SkAlphaType); | 431 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()]); | 432 RefPtr<ArrayBuffer> dstBuffer = ArrayBuffer::createOrNull(resizeWidth * resi
zeHeight, resizedInfo.bytesPerPixel()); |
381 SkPixmap pixmap(resizedInfo, resizedPixels.release(), resizeWidth * resizedI
nfo.bytesPerPixel()); | 433 if (!dstBuffer) |
| 434 return nullptr; |
| 435 RefPtr<Uint8Array> resizedPixels = Uint8Array::create(dstBuffer, 0, dstBuffe
r->byteLength()); |
| 436 SkPixmap pixmap(resizedInfo, resizedPixels->data(), static_cast<size_t>(resi
zeWidth) * resizedInfo.bytesPerPixel()); |
382 skImage->scalePixels(pixmap, resizeQuality); | 437 skImage->scalePixels(pixmap, resizeQuality); |
383 return fromSkSp(SkImage::MakeFromRaster(pixmap, [](const void* pixels, void*
) | 438 return fromSkSp(SkImage::MakeFromRaster(pixmap, [](const void*, void* pixels
) |
384 { | 439 { |
385 delete[] static_cast<const uint8_t*>(pixels); | 440 static_cast<Uint8Array*>(pixels)->deref(); |
386 }, nullptr)); | 441 }, resizedPixels.release().leakRef())); |
387 } | 442 } |
388 | 443 |
389 ImageBitmap::ImageBitmap(ImageData* data, Optional<IntRect> cropRect, const Imag
eBitmapOptions& options) | 444 ImageBitmap::ImageBitmap(ImageData* data, Optional<IntRect> cropRect, const Imag
eBitmapOptions& options) |
390 { | 445 { |
391 // TODO(xidachen): implement the resize option | 446 // TODO(xidachen): implement the resize option |
392 IntRect dataSrcRect = IntRect(IntPoint(), data->size()); | 447 IntRect dataSrcRect = IntRect(IntPoint(), data->size()); |
393 ParsedOptions parsedOptions = parseOptions(options, cropRect, data->bitmapSo
urceSize()); | 448 ParsedOptions parsedOptions = parseOptions(options, cropRect, data->bitmapSo
urceSize()); |
| 449 if (dstBufferSizeHasOverflow(parsedOptions)) |
| 450 return; |
394 IntRect srcRect = cropRect ? intersection(parsedOptions.cropRect, dataSrcRec
t) : dataSrcRect; | 451 IntRect srcRect = cropRect ? intersection(parsedOptions.cropRect, dataSrcRec
t) : dataSrcRect; |
395 | 452 |
396 // treat non-premultiplyAlpha as a special case | 453 // treat non-premultiplyAlpha as a special case |
397 if (!parsedOptions.premultiplyAlpha) { | 454 if (!parsedOptions.premultiplyAlpha) { |
398 unsigned char* srcAddr = data->data()->data(); | 455 unsigned char* srcAddr = data->data()->data(); |
399 int srcHeight = data->size().height(); | |
400 int dstHeight = parsedOptions.cropRect.height(); | |
401 | 456 |
402 // Using kN32 type, swizzle input if necessary. | 457 // Using kN32 type, swizzle input if necessary. |
403 SkImageInfo info = SkImageInfo::Make(parsedOptions.cropRect.width(), dst
Height, kN32_SkColorType, kUnpremul_SkAlphaType); | 458 SkImageInfo info = SkImageInfo::Make(parsedOptions.cropRect.width(), par
sedOptions.cropRect.height(), kN32_SkColorType, kUnpremul_SkAlphaType); |
404 int srcPixelBytesPerRow = info.bytesPerPixel() * data->size().width(); | 459 size_t bytesPerPixel = static_cast<size_t>(info.bytesPerPixel()); |
405 int dstPixelBytesPerRow = info.bytesPerPixel() * parsedOptions.cropRect.
width(); | 460 size_t srcPixelBytesPerRow = bytesPerPixel * data->size().width(); |
| 461 size_t dstPixelBytesPerRow = bytesPerPixel * parsedOptions.cropRect.widt
h(); |
406 RefPtr<SkImage> skImage; | 462 RefPtr<SkImage> skImage; |
407 if (parsedOptions.cropRect == IntRect(IntPoint(), data->size())) { | 463 if (parsedOptions.cropRect == IntRect(IntPoint(), data->size())) { |
408 swizzleImageData(srcAddr, srcHeight, srcPixelBytesPerRow, parsedOpti
ons.flipY); | 464 swizzleImageData(srcAddr, data->size().height(), srcPixelBytesPerRow
, parsedOptions.flipY); |
409 skImage = fromSkSp(SkImage::MakeRasterCopy(SkPixmap(info, srcAddr, d
stPixelBytesPerRow))); | 465 skImage = fromSkSp(SkImage::MakeRasterCopy(SkPixmap(info, srcAddr, d
stPixelBytesPerRow))); |
410 // restore the original ImageData | 466 // restore the original ImageData |
411 swizzleImageData(srcAddr, srcHeight, srcPixelBytesPerRow, parsedOpti
ons.flipY); | 467 swizzleImageData(srcAddr, data->size().height(), srcPixelBytesPerRow
, parsedOptions.flipY); |
412 } else { | 468 } else { |
413 std::unique_ptr<uint8_t[]> copiedDataBuffer = wrapArrayUnique(new ui
nt8_t[dstHeight * dstPixelBytesPerRow]()); | 469 RefPtr<ArrayBuffer> dstBuffer = ArrayBuffer::createOrNull(static_cas
t<size_t>(parsedOptions.cropRect.height()) * parsedOptions.cropRect.width(), byt
esPerPixel); |
| 470 if (!dstBuffer) |
| 471 return; |
| 472 RefPtr<Uint8Array> copiedDataBuffer = Uint8Array::create(dstBuffer,
0, dstBuffer->byteLength()); |
414 if (!srcRect.isEmpty()) { | 473 if (!srcRect.isEmpty()) { |
415 IntPoint srcPoint = IntPoint((parsedOptions.cropRect.x() > 0) ?
parsedOptions.cropRect.x() : 0, (parsedOptions.cropRect.y() > 0) ? parsedOptions
.cropRect.y() : 0); | 474 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()); | 475 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(); | 476 int copyHeight = data->size().height() - srcPoint.y(); |
418 if (parsedOptions.cropRect.height() < copyHeight) | 477 if (parsedOptions.cropRect.height() < copyHeight) |
419 copyHeight = parsedOptions.cropRect.height(); | 478 copyHeight = parsedOptions.cropRect.height(); |
420 int copyWidth = data->size().width() - srcPoint.x(); | 479 int copyWidth = data->size().width() - srcPoint.x(); |
421 if (parsedOptions.cropRect.width() < copyWidth) | 480 if (parsedOptions.cropRect.width() < copyWidth) |
422 copyWidth = parsedOptions.cropRect.width(); | 481 copyWidth = parsedOptions.cropRect.width(); |
423 for (int i = 0; i < copyHeight; i++) { | 482 for (int i = 0; i < copyHeight; i++) { |
424 int srcStartCopyPosition = (i + srcPoint.y()) * srcPixelByte
sPerRow + srcPoint.x() * info.bytesPerPixel(); | 483 size_t srcStartCopyPosition = (i + srcPoint.y()) * srcPixelB
ytesPerRow + srcPoint.x() * bytesPerPixel; |
425 int srcEndCopyPosition = srcStartCopyPosition + copyWidth *
info.bytesPerPixel(); | 484 size_t srcEndCopyPosition = srcStartCopyPosition + copyWidth
* bytesPerPixel; |
426 int dstStartCopyPosition; | 485 size_t dstStartCopyPosition; |
427 if (parsedOptions.flipY) | 486 if (parsedOptions.flipY) |
428 dstStartCopyPosition = (dstHeight -1 - dstPoint.y() - i)
* dstPixelBytesPerRow + dstPoint.x() * info.bytesPerPixel(); | 487 dstStartCopyPosition = (parsedOptions.cropRect.height()
-1 - dstPoint.y() - i) * dstPixelBytesPerRow + dstPoint.x() * bytesPerPixel; |
429 else | 488 else |
430 dstStartCopyPosition = (dstPoint.y() + i) * dstPixelByte
sPerRow + dstPoint.x() * info.bytesPerPixel(); | 489 dstStartCopyPosition = (dstPoint.y() + i) * dstPixelByte
sPerRow + dstPoint.x() * bytesPerPixel; |
431 for (int j = 0; j < srcEndCopyPosition - srcStartCopyPositio
n; j++) { | 490 for (size_t j = 0; j < srcEndCopyPosition - srcStartCopyPosi
tion; j++) { |
432 // swizzle when necessary | 491 // swizzle when necessary |
433 if (kN32_SkColorType == kBGRA_8888_SkColorType) { | 492 if (kN32_SkColorType == kBGRA_8888_SkColorType) { |
434 if (j % 4 == 0) | 493 if (j % 4 == 0) |
435 copiedDataBuffer[dstStartCopyPosition + j] = src
Addr[srcStartCopyPosition + j + 2]; | 494 copiedDataBuffer->data()[dstStartCopyPosition +
j] = srcAddr[srcStartCopyPosition + j + 2]; |
436 else if (j % 4 == 2) | 495 else if (j % 4 == 2) |
437 copiedDataBuffer[dstStartCopyPosition + j] = src
Addr[srcStartCopyPosition + j - 2]; | 496 copiedDataBuffer->data()[dstStartCopyPosition +
j] = srcAddr[srcStartCopyPosition + j - 2]; |
438 else | 497 else |
439 copiedDataBuffer[dstStartCopyPosition + j] = src
Addr[srcStartCopyPosition + j]; | 498 copiedDataBuffer->data()[dstStartCopyPosition +
j] = srcAddr[srcStartCopyPosition + j]; |
440 } else { | 499 } else { |
441 copiedDataBuffer[dstStartCopyPosition + j] = srcAddr
[srcStartCopyPosition + j]; | 500 copiedDataBuffer->data()[dstStartCopyPosition + j] =
srcAddr[srcStartCopyPosition + j]; |
442 } | 501 } |
443 } | 502 } |
444 } | 503 } |
445 } | 504 } |
446 skImage = newSkImageFromRaster(info, std::move(copiedDataBuffer), ds
tPixelBytesPerRow); | 505 skImage = newSkImageFromRaster(info, std::move(copiedDataBuffer), ds
tPixelBytesPerRow); |
447 } | 506 } |
| 507 if (!skImage) |
| 508 return; |
448 if (parsedOptions.shouldScaleInput) | 509 if (parsedOptions.shouldScaleInput) |
449 m_image = StaticBitmapImage::create(scaleSkImage(skImage, parsedOpti
ons.resizeWidth, parsedOptions.resizeHeight, parsedOptions.resizeQuality)); | 510 m_image = StaticBitmapImage::create(scaleSkImage(skImage, parsedOpti
ons.resizeWidth, parsedOptions.resizeHeight, parsedOptions.resizeQuality)); |
450 else | 511 else |
451 m_image = StaticBitmapImage::create(skImage); | 512 m_image = StaticBitmapImage::create(skImage); |
| 513 if (!m_image) |
| 514 return; |
452 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); | 515 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); |
453 return; | 516 return; |
454 } | 517 } |
455 | 518 |
456 std::unique_ptr<ImageBuffer> buffer = ImageBuffer::create(parsedOptions.crop
Rect.size(), NonOpaque, DoNotInitializeImagePixels); | 519 std::unique_ptr<ImageBuffer> buffer = ImageBuffer::create(parsedOptions.crop
Rect.size(), NonOpaque, DoNotInitializeImagePixels); |
457 if (!buffer) | 520 if (!buffer) |
458 return; | 521 return; |
459 | 522 |
460 if (srcRect.isEmpty()) { | 523 if (srcRect.isEmpty()) { |
461 m_image = StaticBitmapImage::create(buffer->newSkImageSnapshot(PreferNoA
cceleration, SnapshotReasonUnknown)); | 524 m_image = StaticBitmapImage::create(buffer->newSkImageSnapshot(PreferNoA
cceleration, SnapshotReasonUnknown)); |
462 return; | 525 return; |
463 } | 526 } |
464 | 527 |
465 IntPoint dstPoint = IntPoint(std::min(0, -parsedOptions.cropRect.x()), std::
min(0, -parsedOptions.cropRect.y())); | 528 IntPoint dstPoint = IntPoint(std::min(0, -parsedOptions.cropRect.x()), std::
min(0, -parsedOptions.cropRect.y())); |
466 if (parsedOptions.cropRect.x() < 0) | 529 if (parsedOptions.cropRect.x() < 0) |
467 dstPoint.setX(-parsedOptions.cropRect.x()); | 530 dstPoint.setX(-parsedOptions.cropRect.x()); |
468 if (parsedOptions.cropRect.y() < 0) | 531 if (parsedOptions.cropRect.y() < 0) |
469 dstPoint.setY(-parsedOptions.cropRect.y()); | 532 dstPoint.setY(-parsedOptions.cropRect.y()); |
470 buffer->putByteArray(Unmultiplied, data->data()->data(), data->size(), srcRe
ct, dstPoint); | 533 buffer->putByteArray(Unmultiplied, data->data()->data(), data->size(), srcRe
ct, dstPoint); |
471 RefPtr<SkImage> skImage = buffer->newSkImageSnapshot(PreferNoAcceleration, S
napshotReasonUnknown); | 534 RefPtr<SkImage> skImage = buffer->newSkImageSnapshot(PreferNoAcceleration, S
napshotReasonUnknown); |
472 if (parsedOptions.flipY) | 535 if (parsedOptions.flipY) |
473 skImage = flipSkImageVertically(skImage.get(), PremultiplyAlpha); | 536 skImage = flipSkImageVertically(skImage.get(), PremultiplyAlpha); |
| 537 if (!skImage) |
| 538 return; |
474 if (parsedOptions.shouldScaleInput) { | 539 if (parsedOptions.shouldScaleInput) { |
475 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(parsedOptions.
resizeWidth, parsedOptions.resizeHeight); | 540 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(parsedOptions.
resizeWidth, parsedOptions.resizeHeight); |
476 if (!surface) | 541 if (!surface) |
477 return; | 542 return; |
478 SkPaint paint; | 543 SkPaint paint; |
479 paint.setFilterQuality(parsedOptions.resizeQuality); | 544 paint.setFilterQuality(parsedOptions.resizeQuality); |
480 SkRect dstDrawRect = SkRect::MakeWH(parsedOptions.resizeWidth, parsedOpt
ions.resizeHeight); | 545 SkRect dstDrawRect = SkRect::MakeWH(parsedOptions.resizeWidth, parsedOpt
ions.resizeHeight); |
481 surface->getCanvas()->drawImageRect(skImage.get(), dstDrawRect, &paint); | 546 surface->getCanvas()->drawImageRect(skImage.get(), dstDrawRect, &paint); |
482 skImage = fromSkSp(surface->makeImageSnapshot()); | 547 skImage = fromSkSp(surface->makeImageSnapshot()); |
483 } | 548 } |
484 m_image = StaticBitmapImage::create(skImage); | 549 m_image = StaticBitmapImage::create(skImage); |
485 } | 550 } |
486 | 551 |
487 ImageBitmap::ImageBitmap(ImageBitmap* bitmap, Optional<IntRect> cropRect, const
ImageBitmapOptions& options) | 552 ImageBitmap::ImageBitmap(ImageBitmap* bitmap, Optional<IntRect> cropRect, const
ImageBitmapOptions& options) |
488 { | 553 { |
489 RefPtr<Image> input = bitmap->bitmapImage(); | 554 RefPtr<Image> input = bitmap->bitmapImage(); |
490 if (!input) | 555 if (!input) |
491 return; | 556 return; |
492 ParsedOptions parsedOptions = parseOptions(options, cropRect, input->size())
; | 557 ParsedOptions parsedOptions = parseOptions(options, cropRect, input->size())
; |
| 558 if (dstBufferSizeHasOverflow(parsedOptions)) |
| 559 return; |
493 | 560 |
494 m_image = cropImage(input.get(), parsedOptions, bitmap->isPremultiplied() ?
PremultiplyAlpha : DontPremultiplyAlpha); | 561 m_image = cropImage(input.get(), parsedOptions, bitmap->isPremultiplied() ?
PremultiplyAlpha : DontPremultiplyAlpha); |
495 if (!m_image) | 562 if (!m_image) |
496 return; | 563 return; |
497 m_image->setOriginClean(bitmap->originClean()); | 564 m_image->setOriginClean(bitmap->originClean()); |
498 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); | 565 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); |
499 } | 566 } |
500 | 567 |
501 ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image, Optional<IntRect>
cropRect, const ImageBitmapOptions& options) | 568 ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image, Optional<IntRect>
cropRect, const ImageBitmapOptions& options) |
502 { | 569 { |
503 bool originClean = image->originClean(); | 570 bool originClean = image->originClean(); |
504 RefPtr<Image> input = image; | 571 RefPtr<Image> input = image; |
505 ParsedOptions parsedOptions = parseOptions(options, cropRect, input->size())
; | 572 ParsedOptions parsedOptions = parseOptions(options, cropRect, input->size())
; |
| 573 if (dstBufferSizeHasOverflow(parsedOptions)) |
| 574 return; |
506 | 575 |
507 m_image = cropImage(input.get(), parsedOptions, DontPremultiplyAlpha); | 576 m_image = cropImage(input.get(), parsedOptions); |
508 if (!m_image) | 577 if (!m_image) |
509 return; | 578 return; |
| 579 |
510 m_image->setOriginClean(originClean); | 580 m_image->setOriginClean(originClean); |
511 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); | 581 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); |
512 } | 582 } |
513 | 583 |
514 ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image) | 584 ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image) |
515 { | 585 { |
516 m_image = image; | 586 m_image = image; |
517 } | 587 } |
518 | 588 |
519 PassRefPtr<StaticBitmapImage> ImageBitmap::transfer() | 589 PassRefPtr<StaticBitmapImage> ImageBitmap::transfer() |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
574 m_image.clear(); | 644 m_image.clear(); |
575 m_isNeutered = true; | 645 m_isNeutered = true; |
576 } | 646 } |
577 | 647 |
578 // static | 648 // static |
579 ImageBitmap* ImageBitmap::take(ScriptPromiseResolver*, sk_sp<SkImage> image) | 649 ImageBitmap* ImageBitmap::take(ScriptPromiseResolver*, sk_sp<SkImage> image) |
580 { | 650 { |
581 return ImageBitmap::create(StaticBitmapImage::create(fromSkSp(image))); | 651 return ImageBitmap::create(StaticBitmapImage::create(fromSkSp(image))); |
582 } | 652 } |
583 | 653 |
584 std::unique_ptr<uint8_t[]> ImageBitmap::copyBitmapData(AlphaDisposition alphaOp,
DataColorFormat format) | 654 PassRefPtr<Uint8Array> ImageBitmap::copyBitmapData(AlphaDisposition alphaOp, Dat
aColorFormat format) |
585 { | 655 { |
586 SkImageInfo info = SkImageInfo::Make(width(), height(), (format == RGBAColor
Type) ? kRGBA_8888_SkColorType : kN32_SkColorType, (alphaOp == PremultiplyAlpha)
? kPremul_SkAlphaType : kUnpremul_SkAlphaType); | 656 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); | 657 RefPtr<Uint8Array> dstPixels = copySkImageData(m_image->imageForCurrentFrame
().get(), info); |
588 return dstPixels; | 658 return dstPixels.release(); |
589 } | 659 } |
590 | 660 |
591 unsigned long ImageBitmap::width() const | 661 unsigned long ImageBitmap::width() const |
592 { | 662 { |
593 if (!m_image) | 663 if (!m_image) |
594 return 0; | 664 return 0; |
595 ASSERT(m_image->width() > 0); | 665 ASSERT(m_image->width() > 0); |
596 return m_image->width(); | 666 return m_image->width(); |
597 } | 667 } |
598 | 668 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
640 FloatSize ImageBitmap::elementSize(const FloatSize&) const | 710 FloatSize ImageBitmap::elementSize(const FloatSize&) const |
641 { | 711 { |
642 return FloatSize(width(), height()); | 712 return FloatSize(width(), height()); |
643 } | 713 } |
644 | 714 |
645 DEFINE_TRACE(ImageBitmap) | 715 DEFINE_TRACE(ImageBitmap) |
646 { | 716 { |
647 } | 717 } |
648 | 718 |
649 } // namespace blink | 719 } // namespace blink |
OLD | NEW |