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