Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(156)

Side by Side Diff: third_party/WebKit/Source/core/frame/ImageBitmap.cpp

Issue 2035113002: Implement ImageBitmapOptions resize (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: spec is clear, patch is now ready Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698