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" |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 110 SkBitmap bitmap = frame->bitmap(); | 110 SkBitmap bitmap = frame->bitmap(); |
| 111 if (!frameIsValid(bitmap)) | 111 if (!frameIsValid(bitmap)) |
| 112 return nullptr; | 112 return nullptr; |
| 113 return fromSkSp(SkImage::MakeFromBitmap(bitmap)); | 113 return fromSkSp(SkImage::MakeFromBitmap(bitmap)); |
| 114 } | 114 } |
| 115 | 115 |
| 116 // The parameter imageFormat indicates whether the first parameter "image" is un premultiplied or not. | 116 // The parameter imageFormat indicates whether the first parameter "image" is un premultiplied or not. |
| 117 // imageFormat = PremultiplyAlpha means the image is in premuliplied format | 117 // imageFormat = PremultiplyAlpha means the image is in premuliplied format |
| 118 // For example, if the image is already in unpremultiplied format and we want th e created ImageBitmap | 118 // For example, if the image is already in unpremultiplied format and we want th e created ImageBitmap |
| 119 // in the same format, then we don't need to use the ImageDecoder to decode the image. | 119 // in the same format, then we don't need to use the ImageDecoder to decode the image. |
| 120 static PassRefPtr<StaticBitmapImage> cropImage(Image* image, const IntRect& crop Rect, bool flipY, bool premultiplyAlpha, AlphaDisposition imageFormat = Premulti plyAlpha, ImageDecoder::GammaAndColorProfileOption colorSpaceOp = ImageDecoder:: GammaAndColorProfileApplied) | 120 static PassRefPtr<StaticBitmapImage> cropImage(Image* image, IntRect& cropRect, const ParsedOptions& parsedOptions, AlphaDisposition imageFormat = PremultiplyAl pha, ImageDecoder::GammaAndColorProfileOption colorSpaceOp = ImageDecoder::Gamma AndColorProfileApplied) |
|
jbroman
2016/07/07 19:18:00
Can you point me at why cropRect is now an in-out
xidachen
2016/07/07 20:43:29
Changed to pass by value.
| |
| 121 { | 121 { |
| 122 ASSERT(image); | 122 ASSERT(image); |
| 123 // Adjust the cropRect first: in the case where cropRect is not specified in the API call, | |
| 124 // the cropRect is assumed to be the same as the size of the (scaled) image. | |
| 125 if (parsedOptions.shouldScaleInput && cropRect.x() == 0 && cropRect.y() == 0 && cropRect.width() == image->width() && cropRect.height() == image->height()) { | |
|
jbroman
2016/07/07 19:18:00
What if the cropRect _is_ specified in the API cal
xidachen
2016/07/07 20:43:29
This cannot happen. If that is the case, then in t
jbroman
2016/07/07 21:21:45
I don't mean if sw or sh is zero, but if they matc
| |
| 126 cropRect.setWidth(parsedOptions.resizeWidth); | |
| 127 cropRect.setHeight(parsedOptions.resizeHeight); | |
| 128 } | |
| 123 | 129 |
| 124 IntRect imgRect(IntPoint(), IntSize(image->width(), image->height())); | 130 IntRect imgRect(IntPoint(), IntSize(image->width(), image->height())); |
| 125 const IntRect srcRect = intersection(imgRect, cropRect); | 131 const IntRect srcRect = intersection(imgRect, cropRect); |
| 126 | 132 |
| 127 // In the case when cropRect doesn't intersect the source image and it requi res a umpremul image | 133 // In the case when cropRect doesn't intersect the source image and it requi res a umpremul image |
| 128 // We immediately return a transparent black image with cropRect.size() | 134 // We immediately return a transparent black image with cropRect.size() |
| 129 if (srcRect.isEmpty() && !premultiplyAlpha) { | 135 if (srcRect.isEmpty() && !parsedOptions.premultiplyAlpha) { |
| 130 SkImageInfo info = SkImageInfo::Make(cropRect.width(), cropRect.height() , kN32_SkColorType, kUnpremul_SkAlphaType); | 136 SkImageInfo info = SkImageInfo::Make(cropRect.width(), cropRect.height() , kN32_SkColorType, kUnpremul_SkAlphaType); |
| 131 std::unique_ptr<uint8_t[]> dstPixels = wrapArrayUnique(new uint8_t[cropR ect.width() * cropRect.height() * info.bytesPerPixel()]()); | 137 std::unique_ptr<uint8_t[]> dstPixels = wrapArrayUnique(new uint8_t[cropR ect.width() * cropRect.height() * info.bytesPerPixel()]()); |
| 132 return StaticBitmapImage::create(newSkImageFromRaster(info, std::move(ds tPixels), cropRect.width() * info.bytesPerPixel())); | 138 return StaticBitmapImage::create(newSkImageFromRaster(info, std::move(ds tPixels), cropRect.width() * info.bytesPerPixel())); |
| 133 } | 139 } |
| 134 | 140 |
| 135 RefPtr<SkImage> skiaImage = image->imageForCurrentFrame(); | 141 RefPtr<SkImage> skiaImage = image->imageForCurrentFrame(); |
| 136 // Attempt to get raw unpremultiplied image data, executed only when skiaIma ge is premultiplied. | 142 // Attempt to get raw unpremultiplied image data, executed only when skiaIma ge is premultiplied. |
| 137 if ((((!premultiplyAlpha && !skiaImage->isOpaque()) || !skiaImage) && image- >data() && imageFormat == PremultiplyAlpha) || colorSpaceOp == ImageDecoder::Gam maAndColorProfileIgnored) { | 143 if ((((!parsedOptions.premultiplyAlpha && !skiaImage->isOpaque()) || !skiaIm age) && image->data() && imageFormat == PremultiplyAlpha) || colorSpaceOp == Ima geDecoder::GammaAndColorProfileIgnored) { |
| 138 std::unique_ptr<ImageDecoder> decoder(ImageDecoder::create(*(image->data ()), | 144 std::unique_ptr<ImageDecoder> decoder(ImageDecoder::create(*(image->data ()), |
| 139 premultiplyAlpha ? ImageDecoder::AlphaPremultiplied : ImageDecoder:: AlphaNotPremultiplied, | 145 parsedOptions.premultiplyAlpha ? ImageDecoder::AlphaPremultiplied : ImageDecoder::AlphaNotPremultiplied, |
| 140 colorSpaceOp)); | 146 colorSpaceOp)); |
| 141 if (!decoder) | 147 if (!decoder) |
| 142 return nullptr; | 148 return nullptr; |
| 143 decoder->setData(image->data(), true); | 149 decoder->setData(image->data(), true); |
| 144 skiaImage = ImageBitmap::getSkImageFromDecoder(std::move(decoder)); | 150 skiaImage = ImageBitmap::getSkImageFromDecoder(std::move(decoder)); |
| 145 if (!skiaImage) | 151 if (!skiaImage) |
| 146 return nullptr; | 152 return nullptr; |
| 147 } | 153 } |
| 148 | 154 |
| 149 if (cropRect == srcRect) { | 155 if (cropRect == srcRect) { |
| 150 RefPtr<SkImage> croppedSkImage = fromSkSp(skiaImage->makeSubset(srcRect) ); | 156 RefPtr<SkImage> croppedSkImage = fromSkSp(skiaImage->makeSubset(srcRect) ); |
| 151 if (flipY) | 157 if (parsedOptions.flipY) |
| 152 return StaticBitmapImage::create(flipSkImageVertically(croppedSkImag e.get(), premultiplyAlpha ? PremultiplyAlpha : DontPremultiplyAlpha)); | 158 return StaticBitmapImage::create(flipSkImageVertically(croppedSkImag e.get(), parsedOptions.premultiplyAlpha ? PremultiplyAlpha : DontPremultiplyAlph a)); |
| 153 // Special case: The first parameter image is unpremul but we need to tu rn it into premul. | 159 // Special case: The first parameter image is unpremul but we need to tu rn it into premul. |
| 154 if (premultiplyAlpha && imageFormat == DontPremultiplyAlpha) | 160 if (parsedOptions.premultiplyAlpha && imageFormat == DontPremultiplyAlph a) |
| 155 return StaticBitmapImage::create(unPremulSkImageToPremul(croppedSkIm age.get())); | 161 return StaticBitmapImage::create(unPremulSkImageToPremul(croppedSkIm age.get())); |
| 156 // Call preroll to trigger image decoding. | 162 // Call preroll to trigger image decoding. |
| 157 croppedSkImage->preroll(); | 163 croppedSkImage->preroll(); |
| 158 return StaticBitmapImage::create(croppedSkImage.release()); | 164 return StaticBitmapImage::create(croppedSkImage.release()); |
| 159 } | 165 } |
| 160 | 166 |
| 161 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(cropRect.width(), cropRect.height()); | 167 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(cropRect.width(), cropRect.height()); |
| 162 if (!surface) | 168 if (!surface) |
| 163 return nullptr; | 169 return nullptr; |
| 164 if (srcRect.isEmpty()) | 170 if (srcRect.isEmpty()) |
| 165 return StaticBitmapImage::create(fromSkSp(surface->makeImageSnapshot())) ; | 171 return StaticBitmapImage::create(fromSkSp(surface->makeImageSnapshot())) ; |
| 166 | 172 |
| 167 SkScalar dstLeft = std::min(0, -cropRect.x()); | 173 SkScalar dstLeft = std::min(0, -cropRect.x()); |
| 168 SkScalar dstTop = std::min(0, -cropRect.y()); | 174 SkScalar dstTop = std::min(0, -cropRect.y()); |
| 169 if (cropRect.x() < 0) | 175 if (cropRect.x() < 0) |
| 170 dstLeft = -cropRect.x(); | 176 dstLeft = -cropRect.x(); |
| 171 if (cropRect.y() < 0) | 177 if (cropRect.y() < 0) |
| 172 dstTop = -cropRect.y(); | 178 dstTop = -cropRect.y(); |
| 173 surface->getCanvas()->drawImage(skiaImage.get(), dstLeft, dstTop); | 179 if (parsedOptions.shouldScaleInput) { |
| 180 SkRect drawDstRect = SkRect::MakeXYWH(dstLeft, dstTop, parsedOptions.res izeWidth, parsedOptions.resizeHeight); | |
| 181 SkPaint paint; | |
| 182 paint.setFilterQuality(parsedOptions.resizeQuality); | |
| 183 surface->getCanvas()->drawImageRect(skiaImage.get(), drawDstRect, &paint ); | |
| 184 } else { | |
| 185 surface->getCanvas()->drawImage(skiaImage.get(), dstLeft, dstTop); | |
| 186 } | |
| 174 skiaImage = fromSkSp(surface->makeImageSnapshot()); | 187 skiaImage = fromSkSp(surface->makeImageSnapshot()); |
| 175 if (flipY) | 188 if (parsedOptions.flipY) |
| 176 skiaImage = flipSkImageVertically(skiaImage.get(), PremultiplyAlpha); | 189 skiaImage = flipSkImageVertically(skiaImage.get(), PremultiplyAlpha); |
| 177 | 190 |
| 178 if (premultiplyAlpha) { | 191 if (parsedOptions.premultiplyAlpha) { |
| 179 if (imageFormat == PremultiplyAlpha) | 192 if (imageFormat == PremultiplyAlpha) |
| 180 return StaticBitmapImage::create(unPremulSkImageToPremul(skiaImage.g et())); | 193 return StaticBitmapImage::create(unPremulSkImageToPremul(skiaImage.g et())); |
| 181 return StaticBitmapImage::create(skiaImage.release()); | 194 return StaticBitmapImage::create(skiaImage.release()); |
| 182 } | 195 } |
| 183 return StaticBitmapImage::create(premulSkImageToUnPremul(skiaImage.get())); | 196 return StaticBitmapImage::create(premulSkImageToUnPremul(skiaImage.get())); |
| 184 } | 197 } |
| 185 | 198 |
| 186 ImageBitmap::ImageBitmap(HTMLImageElement* image, const IntRect& cropRect, Docum ent* document, const ImageBitmapOptions& options) | 199 ImageBitmap::ImageBitmap(HTMLImageElement* image, IntRect& cropRect, Document* d ocument, const ImageBitmapOptions& options) |
| 187 { | 200 { |
| 188 bool flipY; | 201 RefPtr<Image> input = image->cachedImage()->getImage(); |
| 189 bool premultiplyAlpha; | 202 ParsedOptions parsedOptions = parseOptions(options, input->width(), input->h eight()); |
| 190 parseOptions(options, flipY, premultiplyAlpha); | |
| 191 | 203 |
| 192 if (options.colorSpaceConversion() == "none") | 204 if (options.colorSpaceConversion() == "none") |
| 193 m_image = cropImage(image->cachedImage()->getImage(), cropRect, flipY, p remultiplyAlpha, PremultiplyAlpha, ImageDecoder::GammaAndColorProfileIgnored); | 205 m_image = cropImage(input.get(), cropRect, parsedOptions, PremultiplyAlp ha, ImageDecoder::GammaAndColorProfileIgnored); |
| 194 else | 206 else |
| 195 m_image = cropImage(image->cachedImage()->getImage(), cropRect, flipY, p remultiplyAlpha, PremultiplyAlpha, ImageDecoder::GammaAndColorProfileApplied); | 207 m_image = cropImage(input.get(), cropRect, parsedOptions, PremultiplyAlp ha, ImageDecoder::GammaAndColorProfileApplied); |
| 196 if (!m_image) | 208 if (!m_image) |
| 197 return; | 209 return; |
| 198 // In the case where the source image is lazy-decoded, m_image may not be in | 210 // In the case where the source image is lazy-decoded, m_image may not be in |
| 199 // a decoded state, we trigger it here. | 211 // a decoded state, we trigger it here. |
| 200 RefPtr<SkImage> skImage = m_image->imageForCurrentFrame(); | 212 RefPtr<SkImage> skImage = m_image->imageForCurrentFrame(); |
| 201 SkPixmap pixmap; | 213 SkPixmap pixmap; |
| 202 if (!skImage->isTextureBacked() && !skImage->peekPixels(&pixmap)) { | 214 if (!skImage->isTextureBacked() && !skImage->peekPixels(&pixmap)) { |
| 203 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(skImage->width (), skImage->height()); | 215 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(skImage->width (), skImage->height()); |
| 204 surface->getCanvas()->drawImage(skImage.get(), 0, 0); | 216 surface->getCanvas()->drawImage(skImage.get(), 0, 0); |
| 205 m_image = StaticBitmapImage::create(fromSkSp(surface->makeImageSnapshot( ))); | 217 m_image = StaticBitmapImage::create(fromSkSp(surface->makeImageSnapshot( ))); |
| 206 } | 218 } |
| 207 m_image->setOriginClean(!image->wouldTaintOrigin(document->getSecurityOrigin ())); | 219 m_image->setOriginClean(!image->wouldTaintOrigin(document->getSecurityOrigin ())); |
| 208 m_image->setPremultiplied(premultiplyAlpha); | 220 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); |
| 209 } | 221 } |
| 210 | 222 |
| 211 ImageBitmap::ImageBitmap(HTMLVideoElement* video, const IntRect& cropRect, Docum ent* document, const ImageBitmapOptions& options) | 223 ImageBitmap::ImageBitmap(HTMLVideoElement* video, IntRect& cropRect, Document* d ocument, const ImageBitmapOptions& options) |
| 212 { | 224 { |
| 213 IntSize playerSize; | 225 IntSize playerSize; |
| 214 if (video->webMediaPlayer()) | 226 if (video->webMediaPlayer()) |
| 215 playerSize = video->webMediaPlayer()->naturalSize(); | 227 playerSize = video->webMediaPlayer()->naturalSize(); |
| 216 | 228 |
| 217 IntRect videoRect = IntRect(IntPoint(), playerSize); | 229 IntRect videoRect = IntRect(IntPoint(), playerSize); |
| 218 IntRect srcRect = intersection(cropRect, videoRect); | 230 IntRect srcRect = intersection(cropRect, videoRect); |
| 219 std::unique_ptr<ImageBuffer> buffer = ImageBuffer::create(cropRect.size(), N onOpaque, DoNotInitializeImagePixels); | 231 std::unique_ptr<ImageBuffer> buffer = ImageBuffer::create(cropRect.size(), N onOpaque, DoNotInitializeImagePixels); |
| 220 if (!buffer) | 232 if (!buffer) |
| 221 return; | 233 return; |
| 222 | 234 |
| 223 IntPoint dstPoint = IntPoint(std::max(0, -cropRect.x()), std::max(0, -cropRe ct.y())); | 235 IntPoint dstPoint = IntPoint(std::max(0, -cropRect.x()), std::max(0, -cropRe ct.y())); |
| 224 video->paintCurrentFrame(buffer->canvas(), IntRect(dstPoint, srcRect.size()) , nullptr); | 236 video->paintCurrentFrame(buffer->canvas(), IntRect(dstPoint, srcRect.size()) , nullptr); |
| 225 | 237 |
| 226 bool flipY; | 238 // TODO(xidachen); implement the resize option. |
| 227 bool premultiplyAlpha; | 239 ParsedOptions parsedOptions = parseOptions(options, playerSize.width(), play erSize.height()); |
| 228 parseOptions(options, flipY, premultiplyAlpha); | |
| 229 | 240 |
| 230 if (flipY || !premultiplyAlpha) { | 241 if (parsedOptions.flipY || !parsedOptions.premultiplyAlpha) { |
| 231 RefPtr<SkImage> skiaImage = buffer->newSkImageSnapshot(PreferNoAccelerat ion, SnapshotReasonUnknown); | 242 RefPtr<SkImage> skiaImage = buffer->newSkImageSnapshot(PreferNoAccelerat ion, SnapshotReasonUnknown); |
| 232 if (flipY) | 243 if (parsedOptions.flipY) |
| 233 skiaImage = flipSkImageVertically(skiaImage.get(), PremultiplyAlpha) ; | 244 skiaImage = flipSkImageVertically(skiaImage.get(), PremultiplyAlpha) ; |
| 234 if (!premultiplyAlpha) | 245 if (!parsedOptions.premultiplyAlpha) |
| 235 skiaImage = premulSkImageToUnPremul(skiaImage.get()); | 246 skiaImage = premulSkImageToUnPremul(skiaImage.get()); |
| 236 m_image = StaticBitmapImage::create(skiaImage.release()); | 247 m_image = StaticBitmapImage::create(skiaImage.release()); |
| 237 } else { | 248 } else { |
| 238 m_image = StaticBitmapImage::create(buffer->newSkImageSnapshot(PreferNoA cceleration, SnapshotReasonUnknown)); | 249 m_image = StaticBitmapImage::create(buffer->newSkImageSnapshot(PreferNoA cceleration, SnapshotReasonUnknown)); |
| 239 } | 250 } |
| 240 m_image->setOriginClean(!video->wouldTaintOrigin(document->getSecurityOrigin ())); | 251 m_image->setOriginClean(!video->wouldTaintOrigin(document->getSecurityOrigin ())); |
| 241 m_image->setPremultiplied(premultiplyAlpha); | 252 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); |
| 242 } | 253 } |
| 243 | 254 |
| 244 ImageBitmap::ImageBitmap(HTMLCanvasElement* canvas, const IntRect& cropRect, con st ImageBitmapOptions& options) | 255 ImageBitmap::ImageBitmap(HTMLCanvasElement* canvas, IntRect& cropRect, const Ima geBitmapOptions& options) |
| 245 { | 256 { |
| 246 ASSERT(canvas->isPaintable()); | 257 ASSERT(canvas->isPaintable()); |
| 247 bool flipY; | 258 RefPtr<Image> input = canvas->copiedImage(BackBuffer, PreferAcceleration); |
| 248 bool premultiplyAlpha; | 259 ParsedOptions parsedOptions = parseOptions(options, input->width(), input->h eight()); |
| 249 parseOptions(options, flipY, premultiplyAlpha); | |
| 250 | 260 |
| 251 // canvas is always premultiplied, so set the last parameter to true and con vert to un-premul later | 261 bool isPremultiplyAlphaReverted = false; |
| 252 m_image = cropImage(canvas->copiedImage(BackBuffer, PreferAcceleration).get( ), cropRect, flipY, true); | 262 if (!parsedOptions.premultiplyAlpha) { |
| 263 parsedOptions.premultiplyAlpha = true; | |
| 264 isPremultiplyAlphaReverted = true; | |
| 265 } | |
| 266 m_image = cropImage(input.get(), cropRect, parsedOptions); | |
| 253 if (!m_image) | 267 if (!m_image) |
| 254 return; | 268 return; |
| 255 if (!premultiplyAlpha) | 269 if (isPremultiplyAlphaReverted) { |
| 270 parsedOptions.premultiplyAlpha = false; | |
| 256 m_image = StaticBitmapImage::create(premulSkImageToUnPremul(m_image->ima geForCurrentFrame().get())); | 271 m_image = StaticBitmapImage::create(premulSkImageToUnPremul(m_image->ima geForCurrentFrame().get())); |
| 272 } | |
| 257 m_image->setOriginClean(canvas->originClean()); | 273 m_image->setOriginClean(canvas->originClean()); |
| 258 m_image->setPremultiplied(premultiplyAlpha); | 274 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); |
| 259 } | 275 } |
| 260 | 276 |
| 261 ImageBitmap::ImageBitmap(std::unique_ptr<uint8_t[]> data, uint32_t width, uint32 _t height, bool isImageBitmapPremultiplied, bool isImageBitmapOriginClean) | 277 ImageBitmap::ImageBitmap(std::unique_ptr<uint8_t[]> data, uint32_t width, uint32 _t height, bool isImageBitmapPremultiplied, bool isImageBitmapOriginClean) |
| 262 { | 278 { |
| 263 SkImageInfo info = SkImageInfo::MakeN32(width, height, isImageBitmapPremulti plied ? kPremul_SkAlphaType : kUnpremul_SkAlphaType); | 279 SkImageInfo info = SkImageInfo::MakeN32(width, height, isImageBitmapPremulti plied ? kPremul_SkAlphaType : kUnpremul_SkAlphaType); |
| 264 m_image = StaticBitmapImage::create(fromSkSp(SkImage::MakeRasterCopy(SkPixma p(info, data.get(), info.bytesPerPixel() * width)))); | 280 m_image = StaticBitmapImage::create(fromSkSp(SkImage::MakeRasterCopy(SkPixma p(info, data.get(), info.bytesPerPixel() * width)))); |
| 265 m_image->setPremultiplied(isImageBitmapPremultiplied); | 281 m_image->setPremultiplied(isImageBitmapPremultiplied); |
| 266 m_image->setOriginClean(isImageBitmapOriginClean); | 282 m_image->setOriginClean(isImageBitmapOriginClean); |
| 267 } | 283 } |
| 268 | 284 |
| 269 ImageBitmap::ImageBitmap(ImageData* data, const IntRect& cropRect, const ImageBi tmapOptions& options) | 285 ImageBitmap::ImageBitmap(ImageData* data, IntRect& cropRect, const ImageBitmapOp tions& options) |
| 270 { | 286 { |
| 271 bool flipY; | 287 // TODO(xidachen): implement the resize option |
| 272 bool premultiplyAlpha; | 288 ParsedOptions parsedOptions = parseOptions(options, data->width(), data->hei ght()); |
| 273 parseOptions(options, flipY, premultiplyAlpha); | |
| 274 IntRect srcRect = intersection(cropRect, IntRect(IntPoint(), data->size())); | 289 IntRect srcRect = intersection(cropRect, IntRect(IntPoint(), data->size())); |
| 275 | 290 |
| 276 // treat non-premultiplyAlpha as a special case | 291 // treat non-premultiplyAlpha as a special case |
| 277 if (!premultiplyAlpha) { | 292 if (!parsedOptions.premultiplyAlpha) { |
| 278 unsigned char* srcAddr = data->data()->data(); | 293 unsigned char* srcAddr = data->data()->data(); |
| 279 int srcHeight = data->size().height(); | 294 int srcHeight = data->size().height(); |
| 280 int dstHeight = cropRect.height(); | 295 int dstHeight = cropRect.height(); |
| 281 // TODO (xidachen): skia doesn't support SkImage::NewRasterCopy from a k RGBA color type. | 296 // TODO (xidachen): skia doesn't support SkImage::NewRasterCopy from a k RGBA color type. |
| 282 // For now, we swap R and B channel and uses kBGRA color type. | 297 // For now, we swap R and B channel and uses kBGRA color type. |
| 283 SkImageInfo info = SkImageInfo::Make(cropRect.width(), dstHeight, kBGRA_ 8888_SkColorType, kUnpremul_SkAlphaType); | 298 SkImageInfo info = SkImageInfo::Make(cropRect.width(), dstHeight, kBGRA_ 8888_SkColorType, kUnpremul_SkAlphaType); |
| 284 int srcPixelBytesPerRow = info.bytesPerPixel() * data->size().width(); | 299 int srcPixelBytesPerRow = info.bytesPerPixel() * data->size().width(); |
| 285 int dstPixelBytesPerRow = info.bytesPerPixel() * cropRect.width(); | 300 int dstPixelBytesPerRow = info.bytesPerPixel() * cropRect.width(); |
| 286 if (cropRect == IntRect(IntPoint(), data->size())) { | 301 if (cropRect == IntRect(IntPoint(), data->size())) { |
| 287 swizzleImageData(srcAddr, srcHeight, srcPixelBytesPerRow, flipY); | 302 swizzleImageData(srcAddr, srcHeight, srcPixelBytesPerRow, parsedOpti ons.flipY); |
| 288 m_image = StaticBitmapImage::create(fromSkSp(SkImage::MakeRasterCopy (SkPixmap(info, srcAddr, dstPixelBytesPerRow)))); | 303 m_image = StaticBitmapImage::create(fromSkSp(SkImage::MakeRasterCopy (SkPixmap(info, srcAddr, dstPixelBytesPerRow)))); |
| 289 // restore the original ImageData | 304 // restore the original ImageData |
| 290 swizzleImageData(srcAddr, srcHeight, srcPixelBytesPerRow, flipY); | 305 swizzleImageData(srcAddr, srcHeight, srcPixelBytesPerRow, parsedOpti ons.flipY); |
| 291 } else { | 306 } else { |
| 292 std::unique_ptr<uint8_t[]> copiedDataBuffer = wrapArrayUnique(new ui nt8_t[dstHeight * dstPixelBytesPerRow]()); | 307 std::unique_ptr<uint8_t[]> copiedDataBuffer = wrapArrayUnique(new ui nt8_t[dstHeight * dstPixelBytesPerRow]()); |
| 293 if (!srcRect.isEmpty()) { | 308 if (!srcRect.isEmpty()) { |
| 294 IntPoint srcPoint = IntPoint((cropRect.x() > 0) ? cropRect.x() : 0, (cropRect.y() > 0) ? cropRect.y() : 0); | 309 IntPoint srcPoint = IntPoint((cropRect.x() > 0) ? cropRect.x() : 0, (cropRect.y() > 0) ? cropRect.y() : 0); |
| 295 IntPoint dstPoint = IntPoint((cropRect.x() >= 0) ? 0 : -cropRect .x(), (cropRect.y() >= 0) ? 0 : -cropRect.y()); | 310 IntPoint dstPoint = IntPoint((cropRect.x() >= 0) ? 0 : -cropRect .x(), (cropRect.y() >= 0) ? 0 : -cropRect.y()); |
| 296 int copyHeight = srcHeight - srcPoint.y(); | 311 int copyHeight = srcHeight - srcPoint.y(); |
| 297 if (cropRect.height() < copyHeight) | 312 if (cropRect.height() < copyHeight) |
| 298 copyHeight = cropRect.height(); | 313 copyHeight = cropRect.height(); |
| 299 int copyWidth = data->size().width() - srcPoint.x(); | 314 int copyWidth = data->size().width() - srcPoint.x(); |
| 300 if (cropRect.width() < copyWidth) | 315 if (cropRect.width() < copyWidth) |
| 301 copyWidth = cropRect.width(); | 316 copyWidth = cropRect.width(); |
| 302 for (int i = 0; i < copyHeight; i++) { | 317 for (int i = 0; i < copyHeight; i++) { |
| 303 int srcStartCopyPosition = (i + srcPoint.y()) * srcPixelByte sPerRow + srcPoint.x() * info.bytesPerPixel(); | 318 int srcStartCopyPosition = (i + srcPoint.y()) * srcPixelByte sPerRow + srcPoint.x() * info.bytesPerPixel(); |
| 304 int srcEndCopyPosition = srcStartCopyPosition + copyWidth * info.bytesPerPixel(); | 319 int srcEndCopyPosition = srcStartCopyPosition + copyWidth * info.bytesPerPixel(); |
| 305 int dstStartCopyPosition; | 320 int dstStartCopyPosition; |
| 306 if (flipY) | 321 if (parsedOptions.flipY) |
| 307 dstStartCopyPosition = (dstHeight -1 - dstPoint.y() - i) * dstPixelBytesPerRow + dstPoint.x() * info.bytesPerPixel(); | 322 dstStartCopyPosition = (dstHeight -1 - dstPoint.y() - i) * dstPixelBytesPerRow + dstPoint.x() * info.bytesPerPixel(); |
| 308 else | 323 else |
| 309 dstStartCopyPosition = (dstPoint.y() + i) * dstPixelByte sPerRow + dstPoint.x() * info.bytesPerPixel(); | 324 dstStartCopyPosition = (dstPoint.y() + i) * dstPixelByte sPerRow + dstPoint.x() * info.bytesPerPixel(); |
| 310 for (int j = 0; j < srcEndCopyPosition - srcStartCopyPositio n; j++) { | 325 for (int j = 0; j < srcEndCopyPosition - srcStartCopyPositio n; j++) { |
| 311 if (j % 4 == 0) | 326 if (j % 4 == 0) |
| 312 copiedDataBuffer[dstStartCopyPosition + j] = srcAddr [srcStartCopyPosition + j + 2]; | 327 copiedDataBuffer[dstStartCopyPosition + j] = srcAddr [srcStartCopyPosition + j + 2]; |
| 313 else if (j % 4 == 2) | 328 else if (j % 4 == 2) |
| 314 copiedDataBuffer[dstStartCopyPosition + j] = srcAddr [srcStartCopyPosition + j - 2]; | 329 copiedDataBuffer[dstStartCopyPosition + j] = srcAddr [srcStartCopyPosition + j - 2]; |
| 315 else | 330 else |
| 316 copiedDataBuffer[dstStartCopyPosition + j] = srcAddr [srcStartCopyPosition + j]; | 331 copiedDataBuffer[dstStartCopyPosition + j] = srcAddr [srcStartCopyPosition + j]; |
| 317 } | 332 } |
| 318 } | 333 } |
| 319 } | 334 } |
| 320 m_image = StaticBitmapImage::create(newSkImageFromRaster(info, std:: move(copiedDataBuffer), dstPixelBytesPerRow)); | 335 m_image = StaticBitmapImage::create(newSkImageFromRaster(info, std:: move(copiedDataBuffer), dstPixelBytesPerRow)); |
| 321 } | 336 } |
| 322 m_image->setPremultiplied(premultiplyAlpha); | 337 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); |
| 323 return; | 338 return; |
| 324 } | 339 } |
| 325 | 340 |
| 326 std::unique_ptr<ImageBuffer> buffer = ImageBuffer::create(cropRect.size(), N onOpaque, DoNotInitializeImagePixels); | 341 std::unique_ptr<ImageBuffer> buffer = ImageBuffer::create(cropRect.size(), N onOpaque, DoNotInitializeImagePixels); |
| 327 if (!buffer) | 342 if (!buffer) |
| 328 return; | 343 return; |
| 329 | 344 |
| 330 if (srcRect.isEmpty()) { | 345 if (srcRect.isEmpty()) { |
| 331 m_image = StaticBitmapImage::create(buffer->newSkImageSnapshot(PreferNoA cceleration, SnapshotReasonUnknown)); | 346 m_image = StaticBitmapImage::create(buffer->newSkImageSnapshot(PreferNoA cceleration, SnapshotReasonUnknown)); |
| 332 return; | 347 return; |
| 333 } | 348 } |
| 334 | 349 |
| 335 IntPoint dstPoint = IntPoint(std::min(0, -cropRect.x()), std::min(0, -cropRe ct.y())); | 350 IntPoint dstPoint = IntPoint(std::min(0, -cropRect.x()), std::min(0, -cropRe ct.y())); |
| 336 if (cropRect.x() < 0) | 351 if (cropRect.x() < 0) |
| 337 dstPoint.setX(-cropRect.x()); | 352 dstPoint.setX(-cropRect.x()); |
| 338 if (cropRect.y() < 0) | 353 if (cropRect.y() < 0) |
| 339 dstPoint.setY(-cropRect.y()); | 354 dstPoint.setY(-cropRect.y()); |
| 340 buffer->putByteArray(Unmultiplied, data->data()->data(), data->size(), srcRe ct, dstPoint); | 355 buffer->putByteArray(Unmultiplied, data->data()->data(), data->size(), srcRe ct, dstPoint); |
| 341 if (flipY) | 356 if (parsedOptions.flipY) |
| 342 m_image = StaticBitmapImage::create(flipSkImageVertically(buffer->newSkI mageSnapshot(PreferNoAcceleration, SnapshotReasonUnknown).get(), PremultiplyAlph a)); | 357 m_image = StaticBitmapImage::create(flipSkImageVertically(buffer->newSkI mageSnapshot(PreferNoAcceleration, SnapshotReasonUnknown).get(), PremultiplyAlph a)); |
| 343 else | 358 else |
| 344 m_image = StaticBitmapImage::create(buffer->newSkImageSnapshot(PreferNoA cceleration, SnapshotReasonUnknown)); | 359 m_image = StaticBitmapImage::create(buffer->newSkImageSnapshot(PreferNoA cceleration, SnapshotReasonUnknown)); |
| 345 } | 360 } |
| 346 | 361 |
| 347 ImageBitmap::ImageBitmap(ImageBitmap* bitmap, const IntRect& cropRect, const Ima geBitmapOptions& options) | 362 ImageBitmap::ImageBitmap(ImageBitmap* bitmap, IntRect& cropRect, const ImageBitm apOptions& options) |
| 348 { | 363 { |
| 349 bool flipY; | 364 RefPtr<Image> input = bitmap->bitmapImage(); |
| 350 bool premultiplyAlpha; | 365 ParsedOptions parsedOptions = parseOptions(options, input->width(), input->h eight()); |
| 351 parseOptions(options, flipY, premultiplyAlpha); | 366 |
| 352 m_image = cropImage(bitmap->bitmapImage(), cropRect, flipY, premultiplyAlpha , bitmap->isPremultiplied() ? PremultiplyAlpha : DontPremultiplyAlpha); | 367 m_image = cropImage(input.get(), cropRect, parsedOptions, bitmap->isPremulti plied() ? PremultiplyAlpha : DontPremultiplyAlpha); |
| 353 if (!m_image) | 368 if (!m_image) |
| 354 return; | 369 return; |
| 355 m_image->setOriginClean(bitmap->originClean()); | 370 m_image->setOriginClean(bitmap->originClean()); |
| 356 m_image->setPremultiplied(premultiplyAlpha); | 371 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); |
| 357 } | 372 } |
| 358 | 373 |
| 359 ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image, const IntRect& cro pRect, const ImageBitmapOptions& options) | 374 ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image, IntRect& cropRect, const ImageBitmapOptions& options) |
| 360 { | 375 { |
| 361 bool flipY; | 376 bool originClean = image->originClean(); |
| 362 bool premultiplyAlpha; | 377 RefPtr<Image> input = image; |
| 363 parseOptions(options, flipY, premultiplyAlpha); | 378 ParsedOptions parsedOptions = parseOptions(options, input->width(), input->h eight()); |
| 364 m_image = cropImage(image.get(), cropRect, flipY, premultiplyAlpha, DontPrem ultiplyAlpha); | 379 |
| 380 m_image = cropImage(input.get(), cropRect, parsedOptions, DontPremultiplyAlp ha); | |
| 365 if (!m_image) | 381 if (!m_image) |
| 366 return; | 382 return; |
| 367 m_image->setOriginClean(image->originClean()); | 383 m_image->setOriginClean(originClean); |
| 368 m_image->setPremultiplied(premultiplyAlpha); | 384 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); |
| 369 } | 385 } |
| 370 | 386 |
| 371 ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image) | 387 ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image) |
| 372 { | 388 { |
| 373 m_image = image; | 389 m_image = image; |
| 374 } | 390 } |
| 375 | 391 |
| 376 ImageBitmap::ImageBitmap(WebExternalTextureMailbox& mailbox) | 392 ImageBitmap::ImageBitmap(WebExternalTextureMailbox& mailbox) |
| 377 { | 393 { |
| 378 m_image = StaticBitmapImage::create(mailbox); | 394 m_image = StaticBitmapImage::create(mailbox); |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 489 ASSERT(m_image->width() > 0 && m_image->height() > 0); | 505 ASSERT(m_image->width() > 0 && m_image->height() > 0); |
| 490 return IntSize(m_image->width(), m_image->height()); | 506 return IntSize(m_image->width(), m_image->height()); |
| 491 } | 507 } |
| 492 | 508 |
| 493 ScriptPromise ImageBitmap::createImageBitmap(ScriptState* scriptState, EventTarg et& eventTarget, int sx, int sy, int sw, int sh, const ImageBitmapOptions& optio ns, ExceptionState& exceptionState) | 509 ScriptPromise ImageBitmap::createImageBitmap(ScriptState* scriptState, EventTarg et& eventTarget, int sx, int sy, int sw, int sh, const ImageBitmapOptions& optio ns, ExceptionState& exceptionState) |
| 494 { | 510 { |
| 495 if (!sw || !sh) { | 511 if (!sw || !sh) { |
| 496 exceptionState.throwDOMException(IndexSizeError, String::format("The sou rce %s provided is 0.", sw ? "height" : "width")); | 512 exceptionState.throwDOMException(IndexSizeError, String::format("The sou rce %s provided is 0.", sw ? "height" : "width")); |
| 497 return ScriptPromise(); | 513 return ScriptPromise(); |
| 498 } | 514 } |
| 515 if ((options.hasResizeWidth() && options.resizeWidth() <= 0) || (options.has ResizeHeight() && options.resizeHeight() <= 0)) { | |
| 516 exceptionState.throwDOMException(InvalidStateError, "The resizeWidth or/ and resizeHeight is less than or equals to 0."); | |
| 517 return ScriptPromise(); | |
| 518 } | |
| 499 return ImageBitmapSource::fulfillImageBitmap(scriptState, create(this, IntRe ct(sx, sy, sw, sh), options)); | 519 return ImageBitmapSource::fulfillImageBitmap(scriptState, create(this, IntRe ct(sx, sy, sw, sh), options)); |
| 500 } | 520 } |
| 501 | 521 |
| 502 void ImageBitmap::parseOptions(const ImageBitmapOptions& options, bool& flipY, b ool& premultiplyAlpha) | 522 ParsedOptions ImageBitmap::parseOptions(const ImageBitmapOptions& options, const int width, const int height) |
|
jbroman
2016/07/07 19:18:00
width and height of what?
Suggest something like
xidachen
2016/07/07 20:43:29
Done.
| |
| 503 { | 523 { |
| 524 ParsedOptions parsedOptions; | |
| 504 if (options.imageOrientation() == imageOrientationFlipY) { | 525 if (options.imageOrientation() == imageOrientationFlipY) { |
| 505 flipY = true; | 526 parsedOptions.flipY = true; |
| 506 } else { | 527 } else { |
| 507 flipY = false; | 528 parsedOptions.flipY = false; |
| 508 ASSERT(options.imageOrientation() == imageBitmapOptionNone); | 529 ASSERT(options.imageOrientation() == imageBitmapOptionNone); |
| 509 } | 530 } |
| 510 if (options.premultiplyAlpha() == imageBitmapOptionNone) { | 531 if (options.premultiplyAlpha() == imageBitmapOptionNone) { |
| 511 premultiplyAlpha = false; | 532 parsedOptions.premultiplyAlpha = false; |
| 512 } else { | 533 } else { |
| 513 premultiplyAlpha = true; | 534 parsedOptions.premultiplyAlpha = true; |
| 514 ASSERT(options.premultiplyAlpha() == "default" || options.premultiplyAlp ha() == "premultiply"); | 535 ASSERT(options.premultiplyAlpha() == "default" || options.premultiplyAlp ha() == "premultiply"); |
| 515 } | 536 } |
| 537 | |
| 538 parsedOptions.shouldScaleInput = false; | |
| 539 if (!options.hasResizeWidth() && !options.hasResizeHeight()) | |
| 540 return parsedOptions; | |
| 541 if (options.hasResizeWidth() && options.hasResizeHeight()) { | |
| 542 parsedOptions.resizeWidth = options.resizeWidth(); | |
| 543 parsedOptions.resizeHeight = options.resizeHeight(); | |
| 544 } else if (options.hasResizeWidth() && !options.hasResizeHeight()) { | |
| 545 parsedOptions.resizeWidth = options.resizeWidth(); | |
| 546 parsedOptions.resizeHeight = ceil(static_cast<float>(options.resizeWidth ()) / width * height); | |
| 547 } else { | |
| 548 parsedOptions.resizeHeight = options.resizeHeight(); | |
| 549 parsedOptions.resizeWidth = ceil(static_cast<float>(options.resizeHeight ()) / height * width); | |
| 550 } | |
| 551 if (static_cast<int>(parsedOptions.resizeWidth) != width || static_cast<int> (parsedOptions.resizeHeight) != height) | |
| 552 parsedOptions.shouldScaleInput = true; | |
| 553 else | |
| 554 return parsedOptions; | |
| 555 | |
| 556 if (options.resizeQuality() == "high") | |
| 557 parsedOptions.resizeQuality = kHigh_SkFilterQuality; | |
| 558 else if (options.resizeQuality() == "medium") | |
| 559 parsedOptions.resizeQuality = kMedium_SkFilterQuality; | |
| 560 else if (options.resizeQuality() == "pixelated") | |
| 561 parsedOptions.resizeQuality = kNone_SkFilterQuality; | |
| 562 else | |
| 563 parsedOptions.resizeQuality = kLow_SkFilterQuality; | |
| 564 return parsedOptions; | |
| 516 } | 565 } |
| 517 | 566 |
| 518 PassRefPtr<Image> ImageBitmap::getSourceImageForCanvas(SourceImageStatus* status , AccelerationHint, SnapshotReason, const FloatSize&) const | 567 PassRefPtr<Image> ImageBitmap::getSourceImageForCanvas(SourceImageStatus* status , AccelerationHint, SnapshotReason, const FloatSize&) const |
| 519 { | 568 { |
| 520 *status = NormalSourceImageStatus; | 569 *status = NormalSourceImageStatus; |
| 521 return m_image ? m_image : nullptr; | 570 return m_image ? m_image : nullptr; |
| 522 } | 571 } |
| 523 | 572 |
| 524 void ImageBitmap::adjustDrawRects(FloatRect* srcRect, FloatRect* dstRect) const | 573 void ImageBitmap::adjustDrawRects(FloatRect* srcRect, FloatRect* dstRect) const |
| 525 { | 574 { |
| 526 } | 575 } |
| 527 | 576 |
| 528 FloatSize ImageBitmap::elementSize(const FloatSize&) const | 577 FloatSize ImageBitmap::elementSize(const FloatSize&) const |
| 529 { | 578 { |
| 530 return FloatSize(width(), height()); | 579 return FloatSize(width(), height()); |
| 531 } | 580 } |
| 532 | 581 |
| 533 DEFINE_TRACE(ImageBitmap) | 582 DEFINE_TRACE(ImageBitmap) |
| 534 { | 583 { |
| 535 } | 584 } |
| 536 | 585 |
| 537 } // namespace blink | 586 } // namespace blink |
| OLD | NEW |