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 |