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" |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
132 // will never overflow size_t. | 132 // will never overflow size_t. |
133 size_t width = static_cast<size_t>(input->width()); | 133 size_t width = static_cast<size_t>(input->width()); |
134 RefPtr<ArrayBuffer> dstBuffer = ArrayBuffer::createOrNull(width * input->hei
ght(), info.bytesPerPixel()); | 134 RefPtr<ArrayBuffer> dstBuffer = ArrayBuffer::createOrNull(width * input->hei
ght(), info.bytesPerPixel()); |
135 if (!dstBuffer) | 135 if (!dstBuffer) |
136 return nullptr; | 136 return nullptr; |
137 RefPtr<Uint8Array> dstPixels = Uint8Array::create(dstBuffer, 0, dstBuffer->b
yteLength()); | 137 RefPtr<Uint8Array> dstPixels = Uint8Array::create(dstBuffer, 0, dstBuffer->b
yteLength()); |
138 input->readPixels(info, dstPixels->data(), width * info.bytesPerPixel(), 0,
0); | 138 input->readPixels(info, dstPixels->data(), width * info.bytesPerPixel(), 0,
0); |
139 return dstPixels; | 139 return dstPixels; |
140 } | 140 } |
141 | 141 |
142 static PassRefPtr<SkImage> newSkImageFromRaster(const SkImageInfo& info, PassRef
Ptr<Uint8Array> imagePixels, size_t imageRowBytes) | 142 static sk_sp<SkImage> newSkImageFromRaster(const SkImageInfo& info, PassRefPtr<U
int8Array> imagePixels, size_t imageRowBytes) |
143 { | 143 { |
144 SkPixmap pixmap(info, imagePixels->data(), imageRowBytes); | 144 SkPixmap pixmap(info, imagePixels->data(), imageRowBytes); |
145 return fromSkSp(SkImage::MakeFromRaster(pixmap, [](const void*, void* pixels
) | 145 return SkImage::MakeFromRaster(pixmap, [](const void*, void* pixels) |
146 { | 146 { |
147 static_cast<Uint8Array*>(pixels)->deref(); | 147 static_cast<Uint8Array*>(pixels)->deref(); |
148 }, imagePixels.leakRef())); | 148 }, imagePixels.leakRef()); |
149 } | 149 } |
150 | 150 |
151 static void swizzleImageData(unsigned char* srcAddr, size_t height, size_t bytes
PerRow, bool flipY) | 151 static void swizzleImageData(unsigned char* srcAddr, size_t height, size_t bytes
PerRow, bool flipY) |
152 { | 152 { |
153 if (flipY) { | 153 if (flipY) { |
154 for (size_t i = 0; i < height / 2; i++) { | 154 for (size_t i = 0; i < height / 2; i++) { |
155 size_t topRowStartPosition = i * bytesPerRow; | 155 size_t topRowStartPosition = i * bytesPerRow; |
156 size_t bottomRowStartPosition = (height - 1 - i) * bytesPerRow; | 156 size_t bottomRowStartPosition = (height - 1 - i) * bytesPerRow; |
157 if (kN32_SkColorType == kBGRA_8888_SkColorType) { // needs to swizzl
e | 157 if (kN32_SkColorType == kBGRA_8888_SkColorType) { // needs to swizzl
e |
158 for (size_t j = 0; j < bytesPerRow; j += 4) { | 158 for (size_t j = 0; j < bytesPerRow; j += 4) { |
159 std::swap(srcAddr[topRowStartPosition + j], srcAddr[bottomRo
wStartPosition + j + 2]); | 159 std::swap(srcAddr[topRowStartPosition + j], srcAddr[bottomRo
wStartPosition + j + 2]); |
160 std::swap(srcAddr[topRowStartPosition + j + 1], srcAddr[bott
omRowStartPosition + j + 1]); | 160 std::swap(srcAddr[topRowStartPosition + j + 1], srcAddr[bott
omRowStartPosition + j + 1]); |
161 std::swap(srcAddr[topRowStartPosition + j + 2], srcAddr[bott
omRowStartPosition + j]); | 161 std::swap(srcAddr[topRowStartPosition + j + 2], srcAddr[bott
omRowStartPosition + j]); |
162 std::swap(srcAddr[topRowStartPosition + j + 3], srcAddr[bott
omRowStartPosition + j + 3]); | 162 std::swap(srcAddr[topRowStartPosition + j + 3], srcAddr[bott
omRowStartPosition + j + 3]); |
163 } | 163 } |
164 } else { | 164 } else { |
165 std::swap_ranges(srcAddr + topRowStartPosition, srcAddr + topRow
StartPosition + bytesPerRow, srcAddr + bottomRowStartPosition); | 165 std::swap_ranges(srcAddr + topRowStartPosition, srcAddr + topRow
StartPosition + bytesPerRow, srcAddr + bottomRowStartPosition); |
166 } | 166 } |
167 } | 167 } |
168 } else { | 168 } else { |
169 if (kN32_SkColorType == kBGRA_8888_SkColorType) // needs to swizzle | 169 if (kN32_SkColorType == kBGRA_8888_SkColorType) // needs to swizzle |
170 for (size_t i = 0; i < height * bytesPerRow; i += 4) | 170 for (size_t i = 0; i < height * bytesPerRow; i += 4) |
171 std::swap(srcAddr[i], srcAddr[i + 2]); | 171 std::swap(srcAddr[i], srcAddr[i + 2]); |
172 } | 172 } |
173 } | 173 } |
174 | 174 |
175 static PassRefPtr<SkImage> flipSkImageVertically(SkImage* input, AlphaDispositio
n alphaOp) | 175 static sk_sp<SkImage> flipSkImageVertically(SkImage* input, AlphaDisposition alp
haOp) |
176 { | 176 { |
177 size_t width = static_cast<size_t>(input->width()); | 177 size_t width = static_cast<size_t>(input->width()); |
178 size_t height = static_cast<size_t>(input->height()); | 178 size_t height = static_cast<size_t>(input->height()); |
179 SkImageInfo info = SkImageInfo::MakeN32(input->width(), input->height(), (al
phaOp == PremultiplyAlpha) ? kPremul_SkAlphaType : kUnpremul_SkAlphaType); | 179 SkImageInfo info = SkImageInfo::MakeN32(input->width(), input->height(), (al
phaOp == PremultiplyAlpha) ? kPremul_SkAlphaType : kUnpremul_SkAlphaType); |
180 size_t imageRowBytes = width * info.bytesPerPixel(); | 180 size_t imageRowBytes = width * info.bytesPerPixel(); |
181 RefPtr<Uint8Array> imagePixels = copySkImageData(input, info); | 181 RefPtr<Uint8Array> imagePixels = copySkImageData(input, info); |
182 if (!imagePixels) | 182 if (!imagePixels) |
183 return nullptr; | 183 return nullptr; |
184 for (size_t i = 0; i < height / 2; i++) { | 184 for (size_t i = 0; i < height / 2; i++) { |
185 size_t topFirstElement = i * imageRowBytes; | 185 size_t topFirstElement = i * imageRowBytes; |
186 size_t topLastElement = (i + 1) * imageRowBytes; | 186 size_t topLastElement = (i + 1) * imageRowBytes; |
187 size_t bottomFirstElement = (height - 1 - i) * imageRowBytes; | 187 size_t bottomFirstElement = (height - 1 - i) * imageRowBytes; |
188 std::swap_ranges(imagePixels->data() + topFirstElement, imagePixels->dat
a() + topLastElement, imagePixels->data() + bottomFirstElement); | 188 std::swap_ranges(imagePixels->data() + topFirstElement, imagePixels->dat
a() + topLastElement, imagePixels->data() + bottomFirstElement); |
189 } | 189 } |
190 return newSkImageFromRaster(info, std::move(imagePixels), imageRowBytes); | 190 return newSkImageFromRaster(info, std::move(imagePixels), imageRowBytes); |
191 } | 191 } |
192 | 192 |
193 static PassRefPtr<SkImage> premulSkImageToUnPremul(SkImage* input) | 193 static sk_sp<SkImage> premulSkImageToUnPremul(SkImage* input) |
194 { | 194 { |
195 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); |
196 RefPtr<Uint8Array> dstPixels = copySkImageData(input, info); | 196 RefPtr<Uint8Array> dstPixels = copySkImageData(input, info); |
197 if (!dstPixels) | 197 if (!dstPixels) |
198 return nullptr; | 198 return nullptr; |
199 return newSkImageFromRaster(info, std::move(dstPixels), static_cast<size_t>(
input->width()) * info.bytesPerPixel()); | 199 return newSkImageFromRaster(info, std::move(dstPixels), static_cast<size_t>(
input->width()) * info.bytesPerPixel()); |
200 } | 200 } |
201 | 201 |
202 static PassRefPtr<SkImage> unPremulSkImageToPremul(SkImage* input) | 202 static sk_sp<SkImage> unPremulSkImageToPremul(SkImage* input) |
203 { | 203 { |
204 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); |
205 RefPtr<Uint8Array> dstPixels = copySkImageData(input, info); | 205 RefPtr<Uint8Array> dstPixels = copySkImageData(input, info); |
206 if (!dstPixels) | 206 if (!dstPixels) |
207 return nullptr; | 207 return nullptr; |
208 return newSkImageFromRaster(info, std::move(dstPixels), static_cast<size_t>(
input->width()) * info.bytesPerPixel()); | 208 return newSkImageFromRaster(info, std::move(dstPixels), static_cast<size_t>(
input->width()) * info.bytesPerPixel()); |
209 } | 209 } |
210 | 210 |
211 PassRefPtr<SkImage> ImageBitmap::getSkImageFromDecoder(std::unique_ptr<ImageDeco
der> decoder) | 211 sk_sp<SkImage> ImageBitmap::getSkImageFromDecoder(std::unique_ptr<ImageDecoder>
decoder) |
212 { | 212 { |
213 if (!decoder->frameCount()) | 213 if (!decoder->frameCount()) |
214 return nullptr; | 214 return nullptr; |
215 ImageFrame* frame = decoder->frameBufferAtIndex(0); | 215 ImageFrame* frame = decoder->frameBufferAtIndex(0); |
216 if (!frame || frame->getStatus() != ImageFrame::FrameComplete) | 216 if (!frame || frame->getStatus() != ImageFrame::FrameComplete) |
217 return nullptr; | 217 return nullptr; |
218 SkBitmap bitmap = frame->bitmap(); | 218 SkBitmap bitmap = frame->bitmap(); |
219 if (!frameIsValid(bitmap)) | 219 if (!frameIsValid(bitmap)) |
220 return nullptr; | 220 return nullptr; |
221 return fromSkSp(SkImage::MakeFromBitmap(bitmap)); | 221 return SkImage::MakeFromBitmap(bitmap); |
222 } | 222 } |
223 | 223 |
224 bool ImageBitmap::isResizeOptionValid(const ImageBitmapOptions& options, Excepti
onState& exceptionState) | 224 bool ImageBitmap::isResizeOptionValid(const ImageBitmapOptions& options, Excepti
onState& exceptionState) |
225 { | 225 { |
226 if ((options.hasResizeWidth() && options.resizeWidth() == 0) || (options.has
ResizeHeight() && options.resizeHeight() == 0)) { | 226 if ((options.hasResizeWidth() && options.resizeWidth() == 0) || (options.has
ResizeHeight() && options.resizeHeight() == 0)) { |
227 exceptionState.throwDOMException(InvalidStateError, "The resizeWidth or/
and resizeHeight is equal to 0."); | 227 exceptionState.throwDOMException(InvalidStateError, "The resizeWidth or/
and resizeHeight is equal to 0."); |
228 return false; | 228 return false; |
229 } | 229 } |
230 return true; | 230 return true; |
231 } | 231 } |
(...skipping 21 matching lines...) Expand all Loading... |
253 // We immediately return a transparent black image with cropRect.size() | 253 // We immediately return a transparent black image with cropRect.size() |
254 if (srcRect.isEmpty() && !parsedOptions.premultiplyAlpha) { | 254 if (srcRect.isEmpty() && !parsedOptions.premultiplyAlpha) { |
255 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); |
256 RefPtr<ArrayBuffer> dstBuffer = ArrayBuffer::createOrNull(static_cast<si
ze_t>(info.width()) * info.height(), info.bytesPerPixel()); | 256 RefPtr<ArrayBuffer> dstBuffer = ArrayBuffer::createOrNull(static_cast<si
ze_t>(info.width()) * info.height(), info.bytesPerPixel()); |
257 if (!dstBuffer) | 257 if (!dstBuffer) |
258 return nullptr; | 258 return nullptr; |
259 RefPtr<Uint8Array> dstPixels = Uint8Array::create(dstBuffer, 0, dstBuffe
r->byteLength()); | 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())); | 260 return StaticBitmapImage::create(newSkImageFromRaster(info, std::move(ds
tPixels), static_cast<size_t>(info.width()) * info.bytesPerPixel())); |
261 } | 261 } |
262 | 262 |
263 RefPtr<SkImage> skiaImage = image->imageForCurrentFrame(); | 263 sk_sp<SkImage> skiaImage = image->imageForCurrentFrame(); |
264 // 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. |
265 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) { |
266 std::unique_ptr<ImageDecoder> decoder(ImageDecoder::create( | 266 std::unique_ptr<ImageDecoder> decoder(ImageDecoder::create( |
267 image->data(), true, | 267 image->data(), true, |
268 parsedOptions.premultiplyAlpha ? ImageDecoder::AlphaPremultiplied :
ImageDecoder::AlphaNotPremultiplied, | 268 parsedOptions.premultiplyAlpha ? ImageDecoder::AlphaPremultiplied :
ImageDecoder::AlphaNotPremultiplied, |
269 colorSpaceOp)); | 269 colorSpaceOp)); |
270 if (!decoder) | 270 if (!decoder) |
271 return nullptr; | 271 return nullptr; |
272 skiaImage = ImageBitmap::getSkImageFromDecoder(std::move(decoder)); | 272 skiaImage = ImageBitmap::getSkImageFromDecoder(std::move(decoder)); |
273 if (!skiaImage) | 273 if (!skiaImage) |
274 return nullptr; | 274 return nullptr; |
275 } | 275 } |
276 | 276 |
277 if (parsedOptions.cropRect == srcRect && !parsedOptions.shouldScaleInput) { | 277 if (parsedOptions.cropRect == srcRect && !parsedOptions.shouldScaleInput) { |
278 RefPtr<SkImage> croppedSkImage = fromSkSp(skiaImage->makeSubset(srcRect)
); | 278 sk_sp<SkImage> croppedSkImage = skiaImage->makeSubset(srcRect); |
279 if (parsedOptions.flipY) | 279 if (parsedOptions.flipY) |
280 return StaticBitmapImage::create(flipSkImageVertically(croppedSkImag
e.get(), parsedOptions.premultiplyAlpha ? PremultiplyAlpha : DontPremultiplyAlph
a)); | 280 return StaticBitmapImage::create(flipSkImageVertically(croppedSkImag
e.get(), parsedOptions.premultiplyAlpha ? PremultiplyAlpha : DontPremultiplyAlph
a)); |
281 // Special case: The first parameter image is unpremul but we need to tu
rn it into premul. | 281 // Special case: The first parameter image is unpremul but we need to tu
rn it into premul. |
282 if (parsedOptions.premultiplyAlpha && imageFormat == DontPremultiplyAlph
a) | 282 if (parsedOptions.premultiplyAlpha && imageFormat == DontPremultiplyAlph
a) |
283 return StaticBitmapImage::create(unPremulSkImageToPremul(croppedSkIm
age.get())); | 283 return StaticBitmapImage::create(unPremulSkImageToPremul(croppedSkIm
age.get())); |
284 // Call preroll to trigger image decoding. | 284 // Call preroll to trigger image decoding. |
285 croppedSkImage->preroll(); | 285 croppedSkImage->preroll(); |
286 return StaticBitmapImage::create(croppedSkImage.release()); | 286 return StaticBitmapImage::create(std::move(croppedSkImage)); |
287 } | 287 } |
288 | 288 |
289 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(parsedOptions.resi
zeWidth, parsedOptions.resizeHeight); | 289 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(parsedOptions.resi
zeWidth, parsedOptions.resizeHeight); |
290 if (!surface) | 290 if (!surface) |
291 return nullptr; | 291 return nullptr; |
292 if (srcRect.isEmpty()) | 292 if (srcRect.isEmpty()) |
293 return StaticBitmapImage::create(fromSkSp(surface->makeImageSnapshot()))
; | 293 return StaticBitmapImage::create(surface->makeImageSnapshot()); |
294 | 294 |
295 SkScalar dstLeft = std::min(0, -parsedOptions.cropRect.x()); | 295 SkScalar dstLeft = std::min(0, -parsedOptions.cropRect.x()); |
296 SkScalar dstTop = std::min(0, -parsedOptions.cropRect.y()); | 296 SkScalar dstTop = std::min(0, -parsedOptions.cropRect.y()); |
297 if (parsedOptions.cropRect.x() < 0) | 297 if (parsedOptions.cropRect.x() < 0) |
298 dstLeft = -parsedOptions.cropRect.x(); | 298 dstLeft = -parsedOptions.cropRect.x(); |
299 if (parsedOptions.cropRect.y() < 0) | 299 if (parsedOptions.cropRect.y() < 0) |
300 dstTop = -parsedOptions.cropRect.y(); | 300 dstTop = -parsedOptions.cropRect.y(); |
301 if (parsedOptions.flipY) { | 301 if (parsedOptions.flipY) { |
302 surface->getCanvas()->translate(0, surface->height()); | 302 surface->getCanvas()->translate(0, surface->height()); |
303 surface->getCanvas()->scale(1, -1); | 303 surface->getCanvas()->scale(1, -1); |
304 } | 304 } |
305 if (parsedOptions.shouldScaleInput) { | 305 if (parsedOptions.shouldScaleInput) { |
306 SkRect drawSrcRect = SkRect::MakeXYWH(parsedOptions.cropRect.x(), parsed
Options.cropRect.y(), parsedOptions.cropRect.width(), parsedOptions.cropRect.hei
ght()); | 306 SkRect drawSrcRect = SkRect::MakeXYWH(parsedOptions.cropRect.x(), parsed
Options.cropRect.y(), parsedOptions.cropRect.width(), parsedOptions.cropRect.hei
ght()); |
307 SkRect drawDstRect = SkRect::MakeXYWH(0, 0, parsedOptions.resizeWidth, p
arsedOptions.resizeHeight); | 307 SkRect drawDstRect = SkRect::MakeXYWH(0, 0, parsedOptions.resizeWidth, p
arsedOptions.resizeHeight); |
308 SkPaint paint; | 308 SkPaint paint; |
309 paint.setFilterQuality(parsedOptions.resizeQuality); | 309 paint.setFilterQuality(parsedOptions.resizeQuality); |
310 surface->getCanvas()->drawImageRect(skiaImage.get(), drawSrcRect, drawDs
tRect, &paint); | 310 surface->getCanvas()->drawImageRect(skiaImage, drawSrcRect, drawDstRect,
&paint); |
311 } else { | 311 } else { |
312 surface->getCanvas()->drawImage(skiaImage.get(), dstLeft, dstTop); | 312 surface->getCanvas()->drawImage(skiaImage, dstLeft, dstTop); |
313 } | 313 } |
314 skiaImage = fromSkSp(surface->makeImageSnapshot()); | 314 skiaImage = surface->makeImageSnapshot(); |
315 | 315 |
316 if (parsedOptions.premultiplyAlpha) { | 316 if (parsedOptions.premultiplyAlpha) { |
317 if (imageFormat == DontPremultiplyAlpha) | 317 if (imageFormat == DontPremultiplyAlpha) |
318 return StaticBitmapImage::create(unPremulSkImageToPremul(skiaImage.g
et())); | 318 return StaticBitmapImage::create(unPremulSkImageToPremul(skiaImage.g
et())); |
319 return StaticBitmapImage::create(skiaImage.release()); | 319 return StaticBitmapImage::create(std::move(skiaImage)); |
320 } | 320 } |
321 return StaticBitmapImage::create(premulSkImageToUnPremul(skiaImage.get())); | 321 return StaticBitmapImage::create(premulSkImageToUnPremul(skiaImage.get())); |
322 } | 322 } |
323 | 323 |
324 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) |
325 { | 325 { |
326 RefPtr<Image> input = image->cachedImage()->getImage(); | 326 RefPtr<Image> input = image->cachedImage()->getImage(); |
327 ParsedOptions parsedOptions = parseOptions(options, cropRect, image->bitmapS
ourceSize()); | 327 ParsedOptions parsedOptions = parseOptions(options, cropRect, image->bitmapS
ourceSize()); |
328 if (dstBufferSizeHasOverflow(parsedOptions)) | 328 if (dstBufferSizeHasOverflow(parsedOptions)) |
329 return; | 329 return; |
330 | 330 |
331 if (options.colorSpaceConversion() == "none") | 331 if (options.colorSpaceConversion() == "none") |
332 m_image = cropImage(input.get(), parsedOptions, PremultiplyAlpha, ImageD
ecoder::GammaAndColorProfileIgnored); | 332 m_image = cropImage(input.get(), parsedOptions, PremultiplyAlpha, ImageD
ecoder::GammaAndColorProfileIgnored); |
333 else | 333 else |
334 m_image = cropImage(input.get(), parsedOptions, PremultiplyAlpha, ImageD
ecoder::GammaAndColorProfileApplied); | 334 m_image = cropImage(input.get(), parsedOptions, PremultiplyAlpha, ImageD
ecoder::GammaAndColorProfileApplied); |
335 if (!m_image) | 335 if (!m_image) |
336 return; | 336 return; |
337 // 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 |
338 // a decoded state, we trigger it here. | 338 // a decoded state, we trigger it here. |
339 RefPtr<SkImage> skImage = m_image->imageForCurrentFrame(); | 339 sk_sp<SkImage> skImage = m_image->imageForCurrentFrame(); |
340 SkPixmap pixmap; | 340 SkPixmap pixmap; |
341 if (!skImage->isTextureBacked() && !skImage->peekPixels(&pixmap)) { | 341 if (!skImage->isTextureBacked() && !skImage->peekPixels(&pixmap)) { |
342 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(skImage->width
(), skImage->height()); | 342 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(skImage->width
(), skImage->height()); |
343 surface->getCanvas()->drawImage(skImage.get(), 0, 0); | 343 surface->getCanvas()->drawImage(skImage, 0, 0); |
344 m_image = StaticBitmapImage::create(fromSkSp(surface->makeImageSnapshot(
))); | 344 m_image = StaticBitmapImage::create(surface->makeImageSnapshot()); |
345 } | 345 } |
346 if (!m_image) | 346 if (!m_image) |
347 return; | 347 return; |
348 m_image->setOriginClean(!image->wouldTaintOrigin(document->getSecurityOrigin
())); | 348 m_image->setOriginClean(!image->wouldTaintOrigin(document->getSecurityOrigin
())); |
349 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); | 349 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); |
350 } | 350 } |
351 | 351 |
352 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) |
353 { | 353 { |
354 IntSize playerSize; | 354 IntSize playerSize; |
(...skipping 18 matching lines...) Expand all Loading... |
373 SkPaint paint; | 373 SkPaint paint; |
374 if (parsedOptions.shouldScaleInput) { | 374 if (parsedOptions.shouldScaleInput) { |
375 float scaleRatioX = static_cast<float>(parsedOptions.resizeWidth) / pars
edOptions.cropRect.width(); | 375 float scaleRatioX = static_cast<float>(parsedOptions.resizeWidth) / pars
edOptions.cropRect.width(); |
376 float scaleRatioY = static_cast<float>(parsedOptions.resizeHeight) / par
sedOptions.cropRect.height(); | 376 float scaleRatioY = static_cast<float>(parsedOptions.resizeHeight) / par
sedOptions.cropRect.height(); |
377 dstPoint.scale(scaleRatioX, scaleRatioY); | 377 dstPoint.scale(scaleRatioX, scaleRatioY); |
378 paint.setFilterQuality(parsedOptions.resizeQuality); | 378 paint.setFilterQuality(parsedOptions.resizeQuality); |
379 dstSize.scale(scaleRatioX, scaleRatioY); | 379 dstSize.scale(scaleRatioX, scaleRatioY); |
380 } | 380 } |
381 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); |
382 | 382 |
383 RefPtr<SkImage> skiaImage = buffer->newSkImageSnapshot(PreferNoAcceleration,
SnapshotReasonUnknown); | 383 sk_sp<SkImage> skiaImage = buffer->newSkImageSnapshot(PreferNoAcceleration,
SnapshotReasonUnknown); |
384 if (!parsedOptions.premultiplyAlpha) | 384 if (!parsedOptions.premultiplyAlpha) |
385 skiaImage = premulSkImageToUnPremul(skiaImage.get()); | 385 skiaImage = premulSkImageToUnPremul(skiaImage.get()); |
386 if (!skiaImage) | 386 if (!skiaImage) |
387 return; | 387 return; |
388 m_image = StaticBitmapImage::create(skiaImage.release()); | 388 m_image = StaticBitmapImage::create(std::move(skiaImage)); |
389 m_image->setOriginClean(!video->wouldTaintOrigin(document->getSecurityOrigin
())); | 389 m_image->setOriginClean(!video->wouldTaintOrigin(document->getSecurityOrigin
())); |
390 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); | 390 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); |
391 } | 391 } |
392 | 392 |
393 ImageBitmap::ImageBitmap(HTMLCanvasElement* canvas, Optional<IntRect> cropRect,
const ImageBitmapOptions& options) | 393 ImageBitmap::ImageBitmap(HTMLCanvasElement* canvas, Optional<IntRect> cropRect,
const ImageBitmapOptions& options) |
394 { | 394 { |
395 ASSERT(canvas->isPaintable()); | 395 ASSERT(canvas->isPaintable()); |
396 RefPtr<Image> input = canvas->copiedImage(BackBuffer, PreferAcceleration); | 396 RefPtr<Image> input = canvas->copiedImage(BackBuffer, PreferAcceleration); |
397 ParsedOptions parsedOptions = parseOptions(options, cropRect, canvas->bitmap
SourceSize()); | 397 ParsedOptions parsedOptions = parseOptions(options, cropRect, canvas->bitmap
SourceSize()); |
398 if (dstBufferSizeHasOverflow(parsedOptions)) | 398 if (dstBufferSizeHasOverflow(parsedOptions)) |
(...skipping 13 matching lines...) Expand all Loading... |
412 } | 412 } |
413 if (!m_image) | 413 if (!m_image) |
414 return; | 414 return; |
415 m_image->setOriginClean(canvas->originClean()); | 415 m_image->setOriginClean(canvas->originClean()); |
416 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); | 416 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); |
417 } | 417 } |
418 | 418 |
419 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) |
420 { | 420 { |
421 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); |
422 m_image = StaticBitmapImage::create(fromSkSp(SkImage::MakeRasterCopy(SkPixma
p(info, data.get(), info.bytesPerPixel() * width)))); | 422 m_image = StaticBitmapImage::create(SkImage::MakeRasterCopy(SkPixmap(info, d
ata.get(), info.bytesPerPixel() * width))); |
423 if (!m_image) | 423 if (!m_image) |
424 return; | 424 return; |
425 m_image->setPremultiplied(isImageBitmapPremultiplied); | 425 m_image->setPremultiplied(isImageBitmapPremultiplied); |
426 m_image->setOriginClean(isImageBitmapOriginClean); | 426 m_image->setOriginClean(isImageBitmapOriginClean); |
427 } | 427 } |
428 | 428 |
429 static PassRefPtr<SkImage> scaleSkImage(PassRefPtr<SkImage> skImage, unsigned re
sizeWidth, unsigned resizeHeight, SkFilterQuality resizeQuality) | 429 static sk_sp<SkImage> scaleSkImage(sk_sp<SkImage> skImage, unsigned resizeWidth,
unsigned resizeHeight, SkFilterQuality resizeQuality) |
430 { | 430 { |
431 SkImageInfo resizedInfo = SkImageInfo::Make(resizeWidth, resizeHeight, kN32_
SkColorType, kUnpremul_SkAlphaType); | 431 SkImageInfo resizedInfo = SkImageInfo::Make(resizeWidth, resizeHeight, kN32_
SkColorType, kUnpremul_SkAlphaType); |
432 RefPtr<ArrayBuffer> dstBuffer = ArrayBuffer::createOrNull(resizeWidth * resi
zeHeight, resizedInfo.bytesPerPixel()); | 432 RefPtr<ArrayBuffer> dstBuffer = ArrayBuffer::createOrNull(resizeWidth * resi
zeHeight, resizedInfo.bytesPerPixel()); |
433 if (!dstBuffer) | 433 if (!dstBuffer) |
434 return nullptr; | 434 return nullptr; |
435 RefPtr<Uint8Array> resizedPixels = Uint8Array::create(dstBuffer, 0, dstBuffe
r->byteLength()); | 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()); | 436 SkPixmap pixmap(resizedInfo, resizedPixels->data(), static_cast<size_t>(resi
zeWidth) * resizedInfo.bytesPerPixel()); |
437 skImage->scalePixels(pixmap, resizeQuality); | 437 skImage->scalePixels(pixmap, resizeQuality); |
438 return fromSkSp(SkImage::MakeFromRaster(pixmap, [](const void*, void* pixels
) | 438 return SkImage::MakeFromRaster(pixmap, [](const void*, void* pixels) |
439 { | 439 { |
440 static_cast<Uint8Array*>(pixels)->deref(); | 440 static_cast<Uint8Array*>(pixels)->deref(); |
441 }, resizedPixels.release().leakRef())); | 441 }, resizedPixels.release().leakRef()); |
442 } | 442 } |
443 | 443 |
444 ImageBitmap::ImageBitmap(ImageData* data, Optional<IntRect> cropRect, const Imag
eBitmapOptions& options) | 444 ImageBitmap::ImageBitmap(ImageData* data, Optional<IntRect> cropRect, const Imag
eBitmapOptions& options) |
445 { | 445 { |
446 // TODO(xidachen): implement the resize option | 446 // TODO(xidachen): implement the resize option |
447 IntRect dataSrcRect = IntRect(IntPoint(), data->size()); | 447 IntRect dataSrcRect = IntRect(IntPoint(), data->size()); |
448 ParsedOptions parsedOptions = parseOptions(options, cropRect, data->bitmapSo
urceSize()); | 448 ParsedOptions parsedOptions = parseOptions(options, cropRect, data->bitmapSo
urceSize()); |
449 if (dstBufferSizeHasOverflow(parsedOptions)) | 449 if (dstBufferSizeHasOverflow(parsedOptions)) |
450 return; | 450 return; |
451 IntRect srcRect = cropRect ? intersection(parsedOptions.cropRect, dataSrcRec
t) : dataSrcRect; | 451 IntRect srcRect = cropRect ? intersection(parsedOptions.cropRect, dataSrcRec
t) : dataSrcRect; |
452 | 452 |
453 // treat non-premultiplyAlpha as a special case | 453 // treat non-premultiplyAlpha as a special case |
454 if (!parsedOptions.premultiplyAlpha) { | 454 if (!parsedOptions.premultiplyAlpha) { |
455 unsigned char* srcAddr = data->data()->data(); | 455 unsigned char* srcAddr = data->data()->data(); |
456 | 456 |
457 // Using kN32 type, swizzle input if necessary. | 457 // Using kN32 type, swizzle input if necessary. |
458 SkImageInfo info = SkImageInfo::Make(parsedOptions.cropRect.width(), par
sedOptions.cropRect.height(), kN32_SkColorType, kUnpremul_SkAlphaType); | 458 SkImageInfo info = SkImageInfo::Make(parsedOptions.cropRect.width(), par
sedOptions.cropRect.height(), kN32_SkColorType, kUnpremul_SkAlphaType); |
459 size_t bytesPerPixel = static_cast<size_t>(info.bytesPerPixel()); | 459 size_t bytesPerPixel = static_cast<size_t>(info.bytesPerPixel()); |
460 size_t srcPixelBytesPerRow = bytesPerPixel * data->size().width(); | 460 size_t srcPixelBytesPerRow = bytesPerPixel * data->size().width(); |
461 size_t dstPixelBytesPerRow = bytesPerPixel * parsedOptions.cropRect.widt
h(); | 461 size_t dstPixelBytesPerRow = bytesPerPixel * parsedOptions.cropRect.widt
h(); |
462 RefPtr<SkImage> skImage; | 462 sk_sp<SkImage> skImage; |
463 if (parsedOptions.cropRect == IntRect(IntPoint(), data->size())) { | 463 if (parsedOptions.cropRect == IntRect(IntPoint(), data->size())) { |
464 swizzleImageData(srcAddr, data->size().height(), srcPixelBytesPerRow
, parsedOptions.flipY); | 464 swizzleImageData(srcAddr, data->size().height(), srcPixelBytesPerRow
, parsedOptions.flipY); |
465 skImage = fromSkSp(SkImage::MakeRasterCopy(SkPixmap(info, srcAddr, d
stPixelBytesPerRow))); | 465 skImage = SkImage::MakeRasterCopy(SkPixmap(info, srcAddr, dstPixelBy
tesPerRow)); |
466 // restore the original ImageData | 466 // restore the original ImageData |
467 swizzleImageData(srcAddr, data->size().height(), srcPixelBytesPerRow
, parsedOptions.flipY); | 467 swizzleImageData(srcAddr, data->size().height(), srcPixelBytesPerRow
, parsedOptions.flipY); |
468 } else { | 468 } else { |
469 RefPtr<ArrayBuffer> dstBuffer = ArrayBuffer::createOrNull(static_cas
t<size_t>(parsedOptions.cropRect.height()) * parsedOptions.cropRect.width(), byt
esPerPixel); | 469 RefPtr<ArrayBuffer> dstBuffer = ArrayBuffer::createOrNull(static_cas
t<size_t>(parsedOptions.cropRect.height()) * parsedOptions.cropRect.width(), byt
esPerPixel); |
470 if (!dstBuffer) | 470 if (!dstBuffer) |
471 return; | 471 return; |
472 RefPtr<Uint8Array> copiedDataBuffer = Uint8Array::create(dstBuffer,
0, dstBuffer->byteLength()); | 472 RefPtr<Uint8Array> copiedDataBuffer = Uint8Array::create(dstBuffer,
0, dstBuffer->byteLength()); |
473 if (!srcRect.isEmpty()) { | 473 if (!srcRect.isEmpty()) { |
474 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); |
475 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()); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
524 m_image = StaticBitmapImage::create(buffer->newSkImageSnapshot(PreferNoA
cceleration, SnapshotReasonUnknown)); | 524 m_image = StaticBitmapImage::create(buffer->newSkImageSnapshot(PreferNoA
cceleration, SnapshotReasonUnknown)); |
525 return; | 525 return; |
526 } | 526 } |
527 | 527 |
528 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())); |
529 if (parsedOptions.cropRect.x() < 0) | 529 if (parsedOptions.cropRect.x() < 0) |
530 dstPoint.setX(-parsedOptions.cropRect.x()); | 530 dstPoint.setX(-parsedOptions.cropRect.x()); |
531 if (parsedOptions.cropRect.y() < 0) | 531 if (parsedOptions.cropRect.y() < 0) |
532 dstPoint.setY(-parsedOptions.cropRect.y()); | 532 dstPoint.setY(-parsedOptions.cropRect.y()); |
533 buffer->putByteArray(Unmultiplied, data->data()->data(), data->size(), srcRe
ct, dstPoint); | 533 buffer->putByteArray(Unmultiplied, data->data()->data(), data->size(), srcRe
ct, dstPoint); |
534 RefPtr<SkImage> skImage = buffer->newSkImageSnapshot(PreferNoAcceleration, S
napshotReasonUnknown); | 534 sk_sp<SkImage> skImage = buffer->newSkImageSnapshot(PreferNoAcceleration, Sn
apshotReasonUnknown); |
535 if (parsedOptions.flipY) | 535 if (parsedOptions.flipY) |
536 skImage = flipSkImageVertically(skImage.get(), PremultiplyAlpha); | 536 skImage = flipSkImageVertically(skImage.get(), PremultiplyAlpha); |
537 if (!skImage) | 537 if (!skImage) |
538 return; | 538 return; |
539 if (parsedOptions.shouldScaleInput) { | 539 if (parsedOptions.shouldScaleInput) { |
540 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(parsedOptions.
resizeWidth, parsedOptions.resizeHeight); | 540 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(parsedOptions.
resizeWidth, parsedOptions.resizeHeight); |
541 if (!surface) | 541 if (!surface) |
542 return; | 542 return; |
543 SkPaint paint; | 543 SkPaint paint; |
544 paint.setFilterQuality(parsedOptions.resizeQuality); | 544 paint.setFilterQuality(parsedOptions.resizeQuality); |
545 SkRect dstDrawRect = SkRect::MakeWH(parsedOptions.resizeWidth, parsedOpt
ions.resizeHeight); | 545 SkRect dstDrawRect = SkRect::MakeWH(parsedOptions.resizeWidth, parsedOpt
ions.resizeHeight); |
546 surface->getCanvas()->drawImageRect(skImage.get(), dstDrawRect, &paint); | 546 surface->getCanvas()->drawImageRect(skImage, dstDrawRect, &paint); |
547 skImage = fromSkSp(surface->makeImageSnapshot()); | 547 skImage = surface->makeImageSnapshot(); |
548 } | 548 } |
549 m_image = StaticBitmapImage::create(skImage); | 549 m_image = StaticBitmapImage::create(std::move(skImage)); |
550 } | 550 } |
551 | 551 |
552 ImageBitmap::ImageBitmap(ImageBitmap* bitmap, Optional<IntRect> cropRect, const
ImageBitmapOptions& options) | 552 ImageBitmap::ImageBitmap(ImageBitmap* bitmap, Optional<IntRect> cropRect, const
ImageBitmapOptions& options) |
553 { | 553 { |
554 RefPtr<Image> input = bitmap->bitmapImage(); | 554 RefPtr<Image> input = bitmap->bitmapImage(); |
555 if (!input) | 555 if (!input) |
556 return; | 556 return; |
557 ParsedOptions parsedOptions = parseOptions(options, cropRect, input->size())
; | 557 ParsedOptions parsedOptions = parseOptions(options, cropRect, input->size())
; |
558 if (dstBufferSizeHasOverflow(parsedOptions)) | 558 if (dstBufferSizeHasOverflow(parsedOptions)) |
559 return; | 559 return; |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
641 { | 641 { |
642 if (!m_image || m_isNeutered) | 642 if (!m_image || m_isNeutered) |
643 return; | 643 return; |
644 m_image.clear(); | 644 m_image.clear(); |
645 m_isNeutered = true; | 645 m_isNeutered = true; |
646 } | 646 } |
647 | 647 |
648 // static | 648 // static |
649 ImageBitmap* ImageBitmap::take(ScriptPromiseResolver*, sk_sp<SkImage> image) | 649 ImageBitmap* ImageBitmap::take(ScriptPromiseResolver*, sk_sp<SkImage> image) |
650 { | 650 { |
651 return ImageBitmap::create(StaticBitmapImage::create(fromSkSp(image))); | 651 return ImageBitmap::create(StaticBitmapImage::create(std::move(image))); |
652 } | 652 } |
653 | 653 |
654 PassRefPtr<Uint8Array> ImageBitmap::copyBitmapData(AlphaDisposition alphaOp, Dat
aColorFormat format) | 654 PassRefPtr<Uint8Array> ImageBitmap::copyBitmapData(AlphaDisposition alphaOp, Dat
aColorFormat format) |
655 { | 655 { |
656 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); |
657 RefPtr<Uint8Array> dstPixels = copySkImageData(m_image->imageForCurrentFrame
().get(), info); | 657 RefPtr<Uint8Array> dstPixels = copySkImageData(m_image->imageForCurrentFrame
().get(), info); |
658 return dstPixels.release(); | 658 return dstPixels.release(); |
659 } | 659 } |
660 | 660 |
661 unsigned long ImageBitmap::width() const | 661 unsigned long ImageBitmap::width() const |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
710 FloatSize ImageBitmap::elementSize(const FloatSize&) const | 710 FloatSize ImageBitmap::elementSize(const FloatSize&) const |
711 { | 711 { |
712 return FloatSize(width(), height()); | 712 return FloatSize(width(), height()); |
713 } | 713 } |
714 | 714 |
715 DEFINE_TRACE(ImageBitmap) | 715 DEFINE_TRACE(ImageBitmap) |
716 { | 716 { |
717 } | 717 } |
718 | 718 |
719 } // namespace blink | 719 } // namespace blink |
OLD | NEW |