| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "modules/shapedetection/ShapeDetector.h" | 5 #include "modules/shapedetection/ShapeDetector.h" |
| 6 | 6 |
| 7 #include "core/dom/DOMException.h" | 7 #include "core/dom/DOMException.h" |
| 8 #include "core/dom/Document.h" | 8 #include "core/dom/Document.h" |
| 9 #include "core/dom/ExecutionContext.h" | 9 #include "core/dom/ExecutionContext.h" |
| 10 #include "core/frame/ImageBitmap.h" | 10 #include "core/frame/ImageBitmap.h" |
| 11 #include "core/frame/LocalFrame.h" | 11 #include "core/frame/LocalFrame.h" |
| 12 #include "core/geometry/DOMRect.h" | 12 #include "core/geometry/DOMRect.h" |
| 13 #include "core/html/HTMLImageElement.h" | 13 #include "core/html/HTMLImageElement.h" |
| 14 #include "core/html/HTMLVideoElement.h" | 14 #include "core/html/HTMLVideoElement.h" |
| 15 #include "core/html/ImageData.h" | 15 #include "core/html/ImageData.h" |
| 16 #include "core/loader/resource/ImageResourceContent.h" | 16 #include "core/loader/resource/ImageResourceContent.h" |
| 17 #include "platform/graphics/Image.h" | 17 #include "platform/graphics/Image.h" |
| 18 #include "platform/wtf/CheckedNumeric.h" | 18 #include "platform/wtf/CheckedNumeric.h" |
| 19 #include "third_party/skia/include/core/SkImage.h" | 19 #include "third_party/skia/include/core/SkImage.h" |
| 20 #include "third_party/skia/include/core/SkImageInfo.h" | 20 #include "third_party/skia/include/core/SkImageInfo.h" |
| 21 | 21 |
| 22 namespace blink { | 22 namespace blink { |
| 23 | 23 |
| 24 namespace { | 24 namespace { |
| 25 | 25 |
| 26 mojo::ScopedSharedBufferHandle GetSharedBufferOnData( | 26 skia::mojom::blink::BitmapPtr createBitmapFromData(int width, |
| 27 ScriptPromiseResolver* resolver, | 27 int height, |
| 28 uint8_t* data, | 28 Vector<uint8_t> bitmapData) { |
| 29 int size) { | 29 skia::mojom::blink::BitmapPtr bitmap = skia::mojom::blink::Bitmap::New(); |
| 30 DCHECK(data); | |
| 31 DCHECK(size); | |
| 32 ScriptPromise promise = resolver->Promise(); | |
| 33 | 30 |
| 34 mojo::ScopedSharedBufferHandle shared_buffer_handle = | 31 bitmap->color_type = (kN32_SkColorType == kRGBA_8888_SkColorType) |
| 35 mojo::SharedBufferHandle::Create(size); | 32 ? skia::mojom::blink::ColorType::RGBA_8888 |
| 36 if (!shared_buffer_handle->is_valid()) { | 33 : skia::mojom::blink::ColorType::BGRA_8888; |
| 37 resolver->Reject( | 34 bitmap->alpha_type = skia::mojom::blink::AlphaType::ALPHA_TYPE_OPAQUE; |
| 38 DOMException::Create(kInvalidStateError, "Internal allocation error")); | 35 bitmap->profile_type = skia::mojom::blink::ColorProfileType::LINEAR; |
| 39 return shared_buffer_handle; | 36 bitmap->width = width; |
| 40 } | 37 bitmap->height = height; |
| 38 bitmap->row_bytes = width * 4 /* bytes per pixel */; |
| 39 bitmap->pixel_data = std::move(bitmapData); |
| 41 | 40 |
| 42 const mojo::ScopedSharedBufferMapping mapped_buffer = | 41 return bitmap; |
| 43 shared_buffer_handle->Map(size); | |
| 44 DCHECK(mapped_buffer.get()); | |
| 45 memcpy(mapped_buffer.get(), data, size); | |
| 46 | |
| 47 return shared_buffer_handle; | |
| 48 } | 42 } |
| 49 | 43 |
| 50 } // anonymous namespace | 44 } // anonymous namespace |
| 51 | 45 |
| 52 ScriptPromise ShapeDetector::detect( | 46 ScriptPromise ShapeDetector::detect( |
| 53 ScriptState* script_state, | 47 ScriptState* script_state, |
| 54 const ImageBitmapSourceUnion& image_source) { | 48 const ImageBitmapSourceUnion& image_source) { |
| 55 ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); | 49 ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); |
| 56 ScriptPromise promise = resolver->Promise(); | 50 ScriptPromise promise = resolver->Promise(); |
| 57 | 51 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 124 pixel_data_ptr = static_cast<uint8_t*>(pixmap.writable_addr()); | 118 pixel_data_ptr = static_cast<uint8_t*>(pixmap.writable_addr()); |
| 125 allocation_size = pixmap.getSafeSize(); | 119 allocation_size = pixmap.getSafeSize(); |
| 126 } else { | 120 } else { |
| 127 // TODO(mcasas): retrieve the pixels from elsewhere. | 121 // TODO(mcasas): retrieve the pixels from elsewhere. |
| 128 NOTREACHED(); | 122 NOTREACHED(); |
| 129 resolver->Reject(DOMException::Create( | 123 resolver->Reject(DOMException::Create( |
| 130 kInvalidStateError, "Failed to get pixels for current frame.")); | 124 kInvalidStateError, "Failed to get pixels for current frame.")); |
| 131 return promise; | 125 return promise; |
| 132 } | 126 } |
| 133 | 127 |
| 134 mojo::ScopedSharedBufferHandle shared_buffer_handle = GetSharedBufferOnData( | 128 WTF::Vector<uint8_t> bitmap_data; |
| 135 resolver, pixel_data_ptr, allocation_size.ValueOrDefault(0)); | 129 bitmap_data.Append(pixel_data_ptr, |
| 136 if (!shared_buffer_handle->is_valid()) | 130 static_cast<int>(allocation_size.ValueOrDefault(0))); |
| 137 return promise; | |
| 138 | 131 |
| 139 return DoDetect(resolver, std::move(shared_buffer_handle), image->width(), | 132 return DoDetect(resolver, |
| 140 image->height()); | 133 createBitmapFromData(image->width(), image->height(), |
| 134 std::move(bitmap_data))); |
| 141 } | 135 } |
| 142 | 136 |
| 143 ScriptPromise ShapeDetector::DetectShapesOnImageData( | 137 ScriptPromise ShapeDetector::DetectShapesOnImageData( |
| 144 ScriptPromiseResolver* resolver, | 138 ScriptPromiseResolver* resolver, |
| 145 ImageData* image_data) { | 139 ImageData* image_data) { |
| 146 ScriptPromise promise = resolver->Promise(); | 140 ScriptPromise promise = resolver->Promise(); |
| 147 | 141 |
| 148 if (image_data->Size().IsZero()) { | 142 if (image_data->Size().IsZero()) { |
| 149 resolver->Resolve(HeapVector<Member<DOMRect>>()); | 143 resolver->Resolve(HeapVector<Member<DOMRect>>()); |
| 150 return promise; | 144 return promise; |
| 151 } | 145 } |
| 152 | 146 |
| 153 uint8_t* const data = image_data->data()->Data(); | 147 uint8_t* const data = image_data->data()->Data(); |
| 154 WTF::CheckedNumeric<int> allocation_size = image_data->Size().Area() * 4; | 148 WTF::CheckedNumeric<int> allocation_size = image_data->Size().Area() * 4; |
| 155 | 149 |
| 156 mojo::ScopedSharedBufferHandle shared_buffer_handle = | 150 WTF::Vector<uint8_t> bitmap_data; |
| 157 GetSharedBufferOnData(resolver, data, allocation_size.ValueOrDefault(0)); | 151 bitmap_data.Append(data, static_cast<int>(allocation_size.ValueOrDefault(0))); |
| 158 if (!shared_buffer_handle->is_valid()) | |
| 159 return promise; | |
| 160 | 152 |
| 161 return DoDetect(resolver, std::move(shared_buffer_handle), | 153 return DoDetect( |
| 162 image_data->width(), image_data->height()); | 154 resolver, createBitmapFromData(image_data->width(), image_data->height(), |
| 155 std::move(bitmap_data))); |
| 163 } | 156 } |
| 164 | 157 |
| 165 ScriptPromise ShapeDetector::DetectShapesOnImageElement( | 158 ScriptPromise ShapeDetector::DetectShapesOnImageElement( |
| 166 ScriptPromiseResolver* resolver, | 159 ScriptPromiseResolver* resolver, |
| 167 const HTMLImageElement* img) { | 160 const HTMLImageElement* img) { |
| 168 ScriptPromise promise = resolver->Promise(); | 161 ScriptPromise promise = resolver->Promise(); |
| 169 | 162 |
| 170 if (img->BitmapSourceSize().IsZero()) { | 163 if (img->BitmapSourceSize().IsZero()) { |
| 171 resolver->Resolve(HeapVector<Member<DOMRect>>()); | 164 resolver->Resolve(HeapVector<Member<DOMRect>>()); |
| 172 return promise; | 165 return promise; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 191 DCHECK_EQ(img->naturalHeight(), static_cast<unsigned>(image->height())); | 184 DCHECK_EQ(img->naturalHeight(), static_cast<unsigned>(image->height())); |
| 192 | 185 |
| 193 if (!image) { | 186 if (!image) { |
| 194 resolver->Reject(DOMException::Create( | 187 resolver->Reject(DOMException::Create( |
| 195 kInvalidStateError, "Failed to get image from current frame.")); | 188 kInvalidStateError, "Failed to get image from current frame.")); |
| 196 return promise; | 189 return promise; |
| 197 } | 190 } |
| 198 | 191 |
| 199 const SkImageInfo skia_info = | 192 const SkImageInfo skia_info = |
| 200 SkImageInfo::MakeN32(image->width(), image->height(), image->alphaType()); | 193 SkImageInfo::MakeN32(image->width(), image->height(), image->alphaType()); |
| 194 size_t rowBytes = skia_info.minRowBytes(); |
| 201 | 195 |
| 202 const uint32_t allocation_size = | 196 Vector<uint8_t> bitmap_data(skia_info.getSafeSize(rowBytes)); |
| 203 skia_info.getSafeSize(skia_info.minRowBytes()); | 197 const SkPixmap pixmap(skia_info, bitmap_data.data(), rowBytes); |
| 204 | 198 |
| 205 mojo::ScopedSharedBufferHandle shared_buffer_handle = | |
| 206 mojo::SharedBufferHandle::Create(allocation_size); | |
| 207 if (!shared_buffer_handle.is_valid()) { | |
| 208 DLOG(ERROR) << "Requested allocation : " << allocation_size | |
| 209 << "B, larger than |mojo::edk::kMaxSharedBufferSize| == 16MB "; | |
| 210 // TODO(xianglu): For now we reject the promise if the image is too large. | |
| 211 // But consider resizing the image to remove restriction on the user side. | |
| 212 // Also, add LayoutTests for this case later. | |
| 213 resolver->Reject( | |
| 214 DOMException::Create(kInvalidStateError, "Image exceeds size limit.")); | |
| 215 return promise; | |
| 216 } | |
| 217 | |
| 218 const mojo::ScopedSharedBufferMapping mapped_buffer = | |
| 219 shared_buffer_handle->Map(allocation_size); | |
| 220 | |
| 221 const SkPixmap pixmap(skia_info, mapped_buffer.get(), | |
| 222 skia_info.minRowBytes()); | |
| 223 if (!image->readPixels(pixmap, 0, 0)) { | 199 if (!image->readPixels(pixmap, 0, 0)) { |
| 224 resolver->Reject(DOMException::Create( | 200 resolver->Reject(DOMException::Create( |
| 225 kInvalidStateError, | 201 kInvalidStateError, |
| 226 "Failed to read pixels: Unable to decompress or unsupported format.")); | 202 "Failed to read pixels: Unable to decompress or unsupported format.")); |
| 227 return promise; | 203 return promise; |
| 228 } | 204 } |
| 229 | 205 |
| 230 return DoDetect(resolver, std::move(shared_buffer_handle), | 206 return DoDetect( |
| 231 img->naturalWidth(), img->naturalHeight()); | 207 resolver, createBitmapFromData(img->naturalWidth(), img->naturalHeight(), |
| 208 std::move(bitmap_data))); |
| 232 } | 209 } |
| 233 | 210 |
| 234 } // namespace blink | 211 } // namespace blink |
| OLD | NEW |