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/DOMRect.h" | 8 #include "core/dom/DOMRect.h" |
9 #include "core/dom/Document.h" | 9 #include "core/dom/Document.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/html/HTMLImageElement.h" | 12 #include "core/html/HTMLImageElement.h" |
13 #include "core/html/HTMLVideoElement.h" | 13 #include "core/html/HTMLVideoElement.h" |
14 #include "core/html/ImageData.h" | 14 #include "core/html/ImageData.h" |
15 #include "core/loader/resource/ImageResourceContent.h" | 15 #include "core/loader/resource/ImageResourceContent.h" |
16 #include "platform/graphics/Image.h" | 16 #include "platform/graphics/Image.h" |
17 #include "third_party/skia/include/core/SkImage.h" | 17 #include "third_party/skia/include/core/SkImage.h" |
18 #include "third_party/skia/include/core/SkImageInfo.h" | 18 #include "third_party/skia/include/core/SkImageInfo.h" |
19 #include "wtf/CheckedNumeric.h" | 19 #include "wtf/CheckedNumeric.h" |
20 | 20 |
21 namespace blink { | 21 namespace blink { |
22 | 22 |
23 namespace { | |
24 | |
25 mojo::ScopedSharedBufferHandle getSharedBufferOnData( | |
26 ScriptPromiseResolver* resolver, | |
27 uint8_t* data, | |
28 int size) { | |
29 DCHECK(data); | |
30 DCHECK(size); | |
31 ScriptPromise promise = resolver->promise(); | |
32 | |
33 mojo::ScopedSharedBufferHandle sharedBufferHandle = | |
34 mojo::SharedBufferHandle::Create(size); | |
35 if (!sharedBufferHandle->is_valid()) { | |
36 resolver->reject( | |
37 DOMException::create(InvalidStateError, "Internal allocation error")); | |
38 return sharedBufferHandle; | |
39 } | |
40 | |
41 const mojo::ScopedSharedBufferMapping mappedBuffer = | |
42 sharedBufferHandle->Map(size); | |
43 DCHECK(mappedBuffer.get()); | |
44 memcpy(mappedBuffer.get(), data, size); | |
45 | |
46 return sharedBufferHandle; | |
47 } | |
48 | |
49 } // anonymous namespace | |
50 | |
51 ShapeDetector::ShapeDetector(LocalFrame& frame) { | 23 ShapeDetector::ShapeDetector(LocalFrame& frame) { |
52 DCHECK(frame.interfaceProvider()); | 24 DCHECK(frame.interfaceProvider()); |
53 } | 25 } |
54 | 26 |
55 ScriptPromise ShapeDetector::detect(ScriptState* scriptState, | 27 ScriptPromise ShapeDetector::detect(ScriptState* scriptState, |
56 const ImageBitmapSourceUnion& imageSource) { | 28 const ImageBitmapSourceUnion& imageSource) { |
57 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); | 29 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); |
58 ScriptPromise promise = resolver->promise(); | 30 ScriptPromise promise = resolver->promise(); |
59 | 31 |
60 // ImageDatas cannot be tainted by definition. | 32 // ImageDatas cannot be tainted by definition. |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
133 pixelDataPtr = pixelData->data(); | 105 pixelDataPtr = pixelData->data(); |
134 allocationSize = imageBitmap->size().area() * 4 /* bytes per pixel */; | 106 allocationSize = imageBitmap->size().area() * 4 /* bytes per pixel */; |
135 } else { | 107 } else { |
136 // TODO(mcasas): retrieve the pixels from elsewhere. | 108 // TODO(mcasas): retrieve the pixels from elsewhere. |
137 NOTREACHED(); | 109 NOTREACHED(); |
138 resolver->reject(DOMException::create( | 110 resolver->reject(DOMException::create( |
139 InvalidStateError, "Failed to get pixels for current frame.")); | 111 InvalidStateError, "Failed to get pixels for current frame.")); |
140 return promise; | 112 return promise; |
141 } | 113 } |
142 | 114 |
143 mojo::ScopedSharedBufferHandle sharedBufferHandle = getSharedBufferOnData( | 115 skia::mojom::blink::BitmapPtr bitmap = skia::mojom::blink::Bitmap::New(); |
144 resolver, pixelDataPtr, allocationSize.ValueOrDefault(0)); | 116 WTF::Vector<uint8_t> data; |
xianglu
2017/01/18 21:08:37
nit: Maybe we can call it something like "bitmapDa
| |
145 if (!sharedBufferHandle->is_valid()) | 117 data.append(pixelDataPtr, static_cast<int>(allocationSize.ValueOrDefault(0))); |
146 return promise; | 118 bitmap->width = image->width(); |
119 bitmap->height = image->height(); | |
120 bitmap->pixel_data = std::move(data); | |
147 | 121 |
148 return doDetect(resolver, std::move(sharedBufferHandle), image->width(), | 122 return doDetect(resolver, std::move(bitmap)); |
149 image->height()); | |
150 } | 123 } |
151 | 124 |
152 ScriptPromise ShapeDetector::detectShapesOnImageData( | 125 ScriptPromise ShapeDetector::detectShapesOnImageData( |
153 ScriptPromiseResolver* resolver, | 126 ScriptPromiseResolver* resolver, |
154 ImageData* imageData) { | 127 ImageData* imageData) { |
155 ScriptPromise promise = resolver->promise(); | 128 ScriptPromise promise = resolver->promise(); |
156 | 129 |
157 if (imageData->size().isZero()) { | 130 if (imageData->size().isZero()) { |
158 resolver->resolve(HeapVector<Member<DOMRect>>()); | 131 resolver->resolve(HeapVector<Member<DOMRect>>()); |
159 return promise; | 132 return promise; |
160 } | 133 } |
161 | 134 |
162 uint8_t* const data = imageData->data()->data(); | 135 uint8_t* const data = imageData->data()->data(); |
163 WTF::CheckedNumeric<int> allocationSize = imageData->size().area() * 4; | 136 WTF::CheckedNumeric<int> allocationSize = imageData->size().area() * 4; |
137 skia::mojom::blink::BitmapPtr bitmap = skia::mojom::blink::Bitmap::New(); | |
138 WTF::Vector<uint8_t> datas; | |
139 datas.append(data, static_cast<int>(allocationSize.ValueOrDefault(0))); | |
140 bitmap->width = imageData->width(); | |
141 bitmap->height = imageData->height(); | |
142 bitmap->pixel_data = std::move(datas); | |
164 | 143 |
165 mojo::ScopedSharedBufferHandle sharedBufferHandle = | 144 return doDetect(resolver, std::move(bitmap)); |
166 getSharedBufferOnData(resolver, data, allocationSize.ValueOrDefault(0)); | |
167 if (!sharedBufferHandle->is_valid()) | |
168 return promise; | |
169 | |
170 return doDetect(resolver, std::move(sharedBufferHandle), imageData->width(), | |
171 imageData->height()); | |
172 } | 145 } |
173 | 146 |
174 ScriptPromise ShapeDetector::detectShapesOnImageElement( | 147 ScriptPromise ShapeDetector::detectShapesOnImageElement( |
175 ScriptPromiseResolver* resolver, | 148 ScriptPromiseResolver* resolver, |
176 const HTMLImageElement* img) { | 149 const HTMLImageElement* img) { |
177 ScriptPromise promise = resolver->promise(); | 150 ScriptPromise promise = resolver->promise(); |
178 | 151 |
179 if (img->bitmapSourceSize().isZero()) { | 152 if (img->bitmapSourceSize().isZero()) { |
180 resolver->resolve(HeapVector<Member<DOMRect>>()); | 153 resolver->resolve(HeapVector<Member<DOMRect>>()); |
181 return promise; | 154 return promise; |
(...skipping 20 matching lines...) Expand all Loading... | |
202 DCHECK_EQ(img->naturalHeight(), static_cast<unsigned>(image->height())); | 175 DCHECK_EQ(img->naturalHeight(), static_cast<unsigned>(image->height())); |
203 | 176 |
204 if (!image) { | 177 if (!image) { |
205 resolver->reject(DOMException::create( | 178 resolver->reject(DOMException::create( |
206 InvalidStateError, "Failed to get image from current frame.")); | 179 InvalidStateError, "Failed to get image from current frame.")); |
207 return promise; | 180 return promise; |
208 } | 181 } |
209 | 182 |
210 const SkImageInfo skiaInfo = | 183 const SkImageInfo skiaInfo = |
211 SkImageInfo::MakeN32(image->width(), image->height(), image->alphaType()); | 184 SkImageInfo::MakeN32(image->width(), image->height(), image->alphaType()); |
185 size_t rowBytes = skiaInfo.minRowBytes(); | |
212 | 186 |
213 const uint32_t allocationSize = skiaInfo.getSafeSize(skiaInfo.minRowBytes()); | 187 Vector<uint8_t> datas(skiaInfo.getSafeSize(rowBytes)); |
214 | 188 const SkPixmap pixmap(skiaInfo, datas.data(), rowBytes); |
215 mojo::ScopedSharedBufferHandle sharedBufferHandle = | |
216 mojo::SharedBufferHandle::Create(allocationSize); | |
217 if (!sharedBufferHandle.is_valid()) { | |
218 DLOG(ERROR) << "Requested allocation : " << allocationSize | |
219 << "B, larger than |mojo::edk::kMaxSharedBufferSize| == 16MB "; | |
220 // TODO(xianglu): For now we reject the promise if the image is too large. | |
221 // But consider resizing the image to remove restriction on the user side. | |
222 // Also, add LayoutTests for this case later. | |
223 resolver->reject( | |
224 DOMException::create(InvalidStateError, "Image exceeds size limit.")); | |
225 return promise; | |
226 } | |
227 | |
228 const mojo::ScopedSharedBufferMapping mappedBuffer = | |
229 sharedBufferHandle->Map(allocationSize); | |
230 | |
231 const SkPixmap pixmap(skiaInfo, mappedBuffer.get(), skiaInfo.minRowBytes()); | |
232 if (!image->readPixels(pixmap, 0, 0)) { | 189 if (!image->readPixels(pixmap, 0, 0)) { |
233 resolver->reject(DOMException::create( | 190 resolver->reject(DOMException::create( |
234 InvalidStateError, | 191 InvalidStateError, |
235 "Failed to read pixels: Unable to decompress or unsupported format.")); | 192 "Failed to read pixels: Unable to decompress or unsupported format.")); |
236 return promise; | 193 return promise; |
237 } | 194 } |
238 | 195 |
239 return doDetect(resolver, std::move(sharedBufferHandle), img->naturalWidth(), | 196 skia::mojom::blink::BitmapPtr bitmap = skia::mojom::blink::Bitmap::New(); |
240 img->naturalHeight()); | 197 bitmap->width = img->naturalWidth(); |
198 bitmap->height = img->naturalHeight(); | |
199 bitmap->pixel_data = std::move(datas); | |
200 | |
201 return doDetect(resolver, std::move(bitmap)); | |
241 } | 202 } |
242 | 203 |
243 } // namespace blink | 204 } // namespace blink |
OLD | NEW |