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

Side by Side Diff: third_party/WebKit/Source/core/html/ImageData.cpp

Issue 2771813003: Prepare ImageData for color managed BaseRenderingContext2D::create/put/get-ImageData (Closed)
Patch Set: Unit test added Created 3 years, 8 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 /* 1 /*
2 * Copyright (C) 2008 Apple Inc. All rights reserved. 2 * Copyright (C) 2008 Apple Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 17 matching lines...) Expand all
28 28
29 #include "core/html/ImageData.h" 29 #include "core/html/ImageData.h"
30 30
31 #include "bindings/core/v8/ExceptionState.h" 31 #include "bindings/core/v8/ExceptionState.h"
32 #include "bindings/core/v8/V8Uint8ClampedArray.h" 32 #include "bindings/core/v8/V8Uint8ClampedArray.h"
33 #include "core/dom/ExceptionCode.h" 33 #include "core/dom/ExceptionCode.h"
34 #include "core/frame/ImageBitmap.h" 34 #include "core/frame/ImageBitmap.h"
35 #include "core/imagebitmap/ImageBitmapOptions.h" 35 #include "core/imagebitmap/ImageBitmapOptions.h"
36 #include "platform/RuntimeEnabledFeatures.h" 36 #include "platform/RuntimeEnabledFeatures.h"
37 #include "platform/graphics/ColorBehavior.h" 37 #include "platform/graphics/ColorBehavior.h"
38 #include "third_party/skia/include/core/SkColorSpaceXform.h"
38 39
39 namespace blink { 40 namespace blink {
40 41
41 bool RaiseDOMExceptionAndReturnFalse(ExceptionState* exceptionState, 42 bool RaiseDOMExceptionAndReturnFalse(ExceptionState* exceptionState,
42 ExceptionCode exceptionCode, 43 ExceptionCode exceptionCode,
43 const char* message) { 44 const char* message) {
44 if (exceptionState) 45 if (exceptionState)
45 exceptionState->throwDOMException(exceptionCode, message); 46 exceptionState->throwDOMException(exceptionCode, message);
46 return false; 47 return false;
47 } 48 }
48 49
49 bool ImageData::validateConstructorArguments(const unsigned& paramFlags, 50 bool ImageData::validateConstructorArguments(
50 const IntSize* size, 51 const unsigned& paramFlags,
51 const unsigned& width, 52 const IntSize* size,
52 const unsigned& height, 53 const unsigned& width,
53 const DOMArrayBufferView* data, 54 const unsigned& height,
54 ExceptionState* exceptionState) { 55 const DOMArrayBufferView* data,
56 const ImageDataColorSettings* colorSettings,
57 ExceptionState* exceptionState) {
55 // We accept all the combinations of colorSpace and storageFormat in an 58 // We accept all the combinations of colorSpace and storageFormat in an
56 // ImageDataColorSettings to be stored in an ImageData. Therefore, we don't 59 // ImageDataColorSettings to be stored in an ImageData. Therefore, we don't
57 // check the color settings in this function. 60 // check the color settings in this function.
58 61
59 if ((paramFlags & kParamWidth) && !width) { 62 if ((paramFlags & kParamWidth) && !width) {
60 return RaiseDOMExceptionAndReturnFalse( 63 return RaiseDOMExceptionAndReturnFalse(
61 exceptionState, IndexSizeError, 64 exceptionState, IndexSizeError,
62 "The source width is zero or not a number."); 65 "The source width is zero or not a number.");
63 } 66 }
64 67
65 if ((paramFlags & kParamHeight) && !height) { 68 if ((paramFlags & kParamHeight) && !height) {
66 return RaiseDOMExceptionAndReturnFalse( 69 return RaiseDOMExceptionAndReturnFalse(
67 exceptionState, IndexSizeError, 70 exceptionState, IndexSizeError,
68 "The source height is zero or not a number."); 71 "The source height is zero or not a number.");
69 } 72 }
70 73
71 if (paramFlags & (kParamWidth | kParamHeight)) { 74 if (paramFlags & (kParamWidth | kParamHeight)) {
72 CheckedNumeric<unsigned> dataSize = 4; 75 CheckedNumeric<unsigned> dataSize = 4;
76 if (colorSettings) {
77 dataSize *=
78 ImageData::getStorageFormatDataSize(colorSettings->storageFormat());
79 }
73 dataSize *= width; 80 dataSize *= width;
74 dataSize *= height; 81 dataSize *= height;
75 if (!dataSize.IsValid()) 82 if (!dataSize.IsValid())
76 return RaiseDOMExceptionAndReturnFalse( 83 return RaiseDOMExceptionAndReturnFalse(
77 exceptionState, IndexSizeError, 84 exceptionState, IndexSizeError,
78 "The requested image size exceeds the supported range."); 85 "The requested image size exceeds the supported range.");
79 } 86 }
80 87
81 unsigned dataLength = 0; 88 unsigned dataLength = 0;
82 if (paramFlags & kParamData) { 89 if (paramFlags & kParamData) {
83 DCHECK(data); 90 DCHECK(data);
84 switch (data->type()) { 91 if (data->type() != DOMArrayBufferView::ViewType::TypeUint8Clamped &&
85 case DOMArrayBufferView::ViewType::TypeUint8Clamped: 92 data->type() != DOMArrayBufferView::ViewType::TypeUint16 &&
86 dataLength = data->view()->byteLength(); 93 data->type() != DOMArrayBufferView::ViewType::TypeFloat32) {
87 break; 94 return RaiseDOMExceptionAndReturnFalse(
88 case DOMArrayBufferView::ViewType::TypeUint16: 95 exceptionState, NotSupportedError,
89 dataLength = data->view()->byteLength() / 2; 96 "The input data type is not supported.");
90 break;
91 case DOMArrayBufferView::ViewType::TypeFloat32:
92 dataLength = data->view()->byteLength() / 4;
93 break;
94 default:
95 return RaiseDOMExceptionAndReturnFalse(
96 exceptionState, NotSupportedError,
97 "The input data type is not supported.");
98 } 97 }
99 98
100 if (!dataLength) { 99 if (!data->byteLength()) {
101 return RaiseDOMExceptionAndReturnFalse( 100 return RaiseDOMExceptionAndReturnFalse(
102 exceptionState, IndexSizeError, "The input data has zero elements."); 101 exceptionState, IndexSizeError, "The input data has zero elements.");
103 } 102 }
104 103
104 dataLength = data->byteLength() / data->typeSize();
105 if (dataLength % 4) { 105 if (dataLength % 4) {
106 return RaiseDOMExceptionAndReturnFalse( 106 return RaiseDOMExceptionAndReturnFalse(
107 exceptionState, IndexSizeError, 107 exceptionState, IndexSizeError,
108 "The input data length is not a multiple of 4."); 108 "The input data length is not a multiple of 4.");
109 } 109 }
110 110
111 if ((paramFlags & kParamWidth) && (dataLength / 4) % width) { 111 if ((paramFlags & kParamWidth) && (dataLength / 4) % width) {
112 return RaiseDOMExceptionAndReturnFalse( 112 return RaiseDOMExceptionAndReturnFalse(
113 exceptionState, IndexSizeError, 113 exceptionState, IndexSizeError,
114 "The input data length is not a multiple of (4 * width)."); 114 "The input data length is not a multiple of (4 * width).");
(...skipping 24 matching lines...) Expand all
139 } 139 }
140 140
141 DOMArrayBufferView* ImageData::allocateAndValidateDataArray( 141 DOMArrayBufferView* ImageData::allocateAndValidateDataArray(
142 const unsigned& length, 142 const unsigned& length,
143 ImageDataStorageFormat storageFormat, 143 ImageDataStorageFormat storageFormat,
144 ExceptionState* exceptionState) { 144 ExceptionState* exceptionState) {
145 if (!length) 145 if (!length)
146 return nullptr; 146 return nullptr;
147 147
148 DOMArrayBufferView* dataArray = nullptr; 148 DOMArrayBufferView* dataArray = nullptr;
149 unsigned dataLength = 0;
150 unsigned dataItemLength = 1;
151 switch (storageFormat) { 149 switch (storageFormat) {
152 case kUint8ClampedArrayStorageFormat: 150 case kUint8ClampedArrayStorageFormat:
153 dataArray = DOMUint8ClampedArray::createOrNull(length); 151 dataArray = DOMUint8ClampedArray::createOrNull(length);
154 break; 152 break;
155 case kUint16ArrayStorageFormat: 153 case kUint16ArrayStorageFormat:
156 dataArray = DOMUint16Array::createOrNull(length); 154 dataArray = DOMUint16Array::createOrNull(length);
157 dataItemLength = 2;
158 break; 155 break;
159 case kFloat32ArrayStorageFormat: 156 case kFloat32ArrayStorageFormat:
160 dataArray = DOMFloat32Array::createOrNull(length); 157 dataArray = DOMFloat32Array::createOrNull(length);
161 dataItemLength = 4;
162 break; 158 break;
163 default: 159 default:
164 NOTREACHED(); 160 NOTREACHED();
165 } 161 }
166 162
167 if (dataArray) 163 if (!dataArray || length != dataArray->byteLength() / dataArray->typeSize()) {
168 dataLength = dataArray->view()->byteLength() / dataItemLength;
169
170 if (!dataArray || length != dataLength) {
171 if (exceptionState) 164 if (exceptionState)
172 exceptionState->throwDOMException(V8RangeError, 165 exceptionState->throwDOMException(V8RangeError,
173 "Out of memory at ImageData creation"); 166 "Out of memory at ImageData creation");
174 return nullptr; 167 return nullptr;
175 } 168 }
176 169
177 return dataArray; 170 return dataArray;
178 } 171 }
179 172
180 ImageData* ImageData::create(const IntSize& size) { 173 DOMUint8ClampedArray* ImageData::allocateAndValidateUint8ClampedArray(
181 if (!ImageData::validateConstructorArguments(kParamSize, &size)) 174 const unsigned& length,
175 ExceptionState* exceptionState) {
176 DOMArrayBufferView* bufferView = allocateAndValidateDataArray(
177 length, kUint8ClampedArrayStorageFormat, exceptionState);
178 if (!bufferView)
182 return nullptr; 179 return nullptr;
183 DOMArrayBufferView* byteArray = 180 DOMUint8ClampedArray* u8Array = const_cast<DOMUint8ClampedArray*>(
181 static_cast<const DOMUint8ClampedArray*>(bufferView));
182 DCHECK(u8Array);
183 return u8Array;
184 }
185
186 DOMUint16Array* ImageData::allocateAndValidateUint16Array(
187 const unsigned& length,
188 ExceptionState* exceptionState) {
189 DOMArrayBufferView* bufferView = allocateAndValidateDataArray(
190 length, kUint16ArrayStorageFormat, exceptionState);
191 if (!bufferView)
192 return nullptr;
193 DOMUint16Array* u16Array = const_cast<DOMUint16Array*>(
194 static_cast<const DOMUint16Array*>(bufferView));
195 DCHECK(u16Array);
196 return u16Array;
197 }
198
199 DOMFloat32Array* ImageData::allocateAndValidateFloat32Array(
200 const unsigned& length,
201 ExceptionState* exceptionState) {
202 DOMArrayBufferView* bufferView = allocateAndValidateDataArray(
203 length, kFloat32ArrayStorageFormat, exceptionState);
204 if (!bufferView)
205 return nullptr;
206 DOMFloat32Array* f32Array = const_cast<DOMFloat32Array*>(
207 static_cast<const DOMFloat32Array*>(bufferView));
208 DCHECK(f32Array);
209 return f32Array;
210 }
211
212 ImageData* ImageData::create(const IntSize& size,
213 const ImageDataColorSettings* colorSettings) {
214 if (!ImageData::validateConstructorArguments(kParamSize, &size, 0, 0, nullptr,
215 colorSettings))
216 return nullptr;
217 ImageDataStorageFormat storageFormat = kUint8ClampedArrayStorageFormat;
218 if (colorSettings) {
219 storageFormat =
220 ImageData::getImageDataStorageFormat(colorSettings->storageFormat());
221 }
222 DOMArrayBufferView* dataArray =
184 allocateAndValidateDataArray(4 * static_cast<unsigned>(size.width()) * 223 allocateAndValidateDataArray(4 * static_cast<unsigned>(size.width()) *
185 static_cast<unsigned>(size.height()), 224 static_cast<unsigned>(size.height()),
186 kUint8ClampedArrayStorageFormat); 225 kUint8ClampedArrayStorageFormat);
187 return byteArray ? new ImageData(size, byteArray) : nullptr; 226 return dataArray ? new ImageData(size, dataArray) : nullptr;
188 } 227 }
189 228
190 // This function accepts size (0, 0) and always returns the ImageData in 229 // This function accepts size (0, 0) and always returns the ImageData in
191 // "srgb" color space and "uint8" storage format. 230 // "srgb" color space and "uint8" storage format.
192 ImageData* ImageData::createForTest(const IntSize& size) { 231 ImageData* ImageData::createForTest(const IntSize& size) {
193 CheckedNumeric<unsigned> dataSize = 4; 232 CheckedNumeric<unsigned> dataSize = 4;
194 dataSize *= size.width(); 233 dataSize *= size.width();
195 dataSize *= size.height(); 234 dataSize *= size.height();
196 if (!dataSize.IsValid()) 235 if (!dataSize.IsValid())
197 return nullptr; 236 return nullptr;
198 237
199 DOMUint8ClampedArray* byteArray = 238 DOMUint8ClampedArray* byteArray =
200 DOMUint8ClampedArray::createOrNull(dataSize.ValueOrDie()); 239 DOMUint8ClampedArray::createOrNull(dataSize.ValueOrDie());
201 if (!byteArray) 240 if (!byteArray)
202 return nullptr; 241 return nullptr;
203 242
204 return new ImageData(size, byteArray); 243 return new ImageData(size, byteArray);
205 } 244 }
206 245
207 ImageData* ImageData::create(const IntSize& size, 246 ImageData* ImageData::create(const IntSize& size,
208 DOMUint8ClampedArray* byteArray) { 247 DOMArrayBufferView* dataArray,
248 const ImageDataColorSettings* colorSettings) {
249 LOG(ERROR) << "HERE";
209 if (!ImageData::validateConstructorArguments(kParamSize | kParamData, &size, 250 if (!ImageData::validateConstructorArguments(kParamSize | kParamData, &size,
210 0, 0, byteArray)) 251 0, 0, dataArray, colorSettings))
211 return nullptr; 252 return nullptr;
212 253
213 return new ImageData(size, byteArray); 254 LOG(ERROR) << "HERE";
255 return new ImageData(size, dataArray, colorSettings);
214 } 256 }
215 257
216 ImageData* ImageData::create(unsigned width, 258 ImageData* ImageData::create(unsigned width,
217 unsigned height, 259 unsigned height,
218 ExceptionState& exceptionState) { 260 ExceptionState& exceptionState) {
219 if (!ImageData::validateConstructorArguments(kParamWidth | kParamHeight, 261 if (!ImageData::validateConstructorArguments(kParamWidth | kParamHeight,
220 nullptr, width, height, nullptr, 262 nullptr, width, height, nullptr,
221 &exceptionState)) 263 nullptr, &exceptionState))
222 return nullptr; 264 return nullptr;
223 265
224 DOMArrayBufferView* byteArray = allocateAndValidateDataArray( 266 DOMArrayBufferView* byteArray = allocateAndValidateDataArray(
225 4 * width * height, kUint8ClampedArrayStorageFormat, &exceptionState); 267 4 * width * height, kUint8ClampedArrayStorageFormat, &exceptionState);
226 return byteArray ? new ImageData(IntSize(width, height), byteArray) : nullptr; 268 return byteArray ? new ImageData(IntSize(width, height), byteArray) : nullptr;
227 } 269 }
228 270
229 ImageData* ImageData::create(DOMUint8ClampedArray* data, 271 ImageData* ImageData::create(DOMUint8ClampedArray* data,
230 unsigned width, 272 unsigned width,
231 ExceptionState& exceptionState) { 273 ExceptionState& exceptionState) {
232 if (!ImageData::validateConstructorArguments( 274 if (!ImageData::validateConstructorArguments(kParamData | kParamWidth,
233 kParamData | kParamWidth, nullptr, width, 0, data, &exceptionState)) 275 nullptr, width, 0, data, nullptr,
276 &exceptionState))
234 return nullptr; 277 return nullptr;
235 278
236 unsigned height = data->length() / (width * 4); 279 unsigned height = data->length() / (width * 4);
237 return new ImageData(IntSize(width, height), data); 280 return new ImageData(IntSize(width, height), data);
238 } 281 }
239 282
240 ImageData* ImageData::create(DOMUint8ClampedArray* data, 283 ImageData* ImageData::create(DOMUint8ClampedArray* data,
241 unsigned width, 284 unsigned width,
242 unsigned height, 285 unsigned height,
243 ExceptionState& exceptionState) { 286 ExceptionState& exceptionState) {
244 if (!ImageData::validateConstructorArguments( 287 if (!ImageData::validateConstructorArguments(
245 kParamData | kParamWidth | kParamHeight, nullptr, width, height, data, 288 kParamData | kParamWidth | kParamHeight, nullptr, width, height, data,
246 &exceptionState)) 289 nullptr, &exceptionState))
247 return nullptr; 290 return nullptr;
248 291
249 return new ImageData(IntSize(width, height), data); 292 return new ImageData(IntSize(width, height), data);
250 } 293 }
251 294
252 ImageData* ImageData::createImageData( 295 ImageData* ImageData::createImageData(
253 unsigned width, 296 unsigned width,
254 unsigned height, 297 unsigned height,
255 const ImageDataColorSettings& colorSettings, 298 const ImageDataColorSettings& colorSettings,
256 ExceptionState& exceptionState) { 299 ExceptionState& exceptionState) {
257 if (!ImageData::validateConstructorArguments(kParamWidth | kParamHeight, 300 if (!ImageData::validateConstructorArguments(kParamWidth | kParamHeight,
258 nullptr, width, height, nullptr, 301 nullptr, width, height, nullptr,
259 &exceptionState)) 302 &colorSettings, &exceptionState))
260 return nullptr; 303 return nullptr;
261 304
262 ImageDataStorageFormat storageFormat = 305 ImageDataStorageFormat storageFormat =
263 ImageData::getImageDataStorageFormat(colorSettings.storageFormat()); 306 ImageData::getImageDataStorageFormat(colorSettings.storageFormat());
264 DOMArrayBufferView* bufferView = allocateAndValidateDataArray( 307 DOMArrayBufferView* bufferView = allocateAndValidateDataArray(
265 4 * width * height, storageFormat, &exceptionState); 308 4 * width * height, storageFormat, &exceptionState);
266 309
267 if (!bufferView) 310 if (!bufferView)
268 return nullptr; 311 return nullptr;
269 312
(...skipping 11 matching lines...) Expand all
281 bufferView = data.getAsUint8ClampedArray(); 324 bufferView = data.getAsUint8ClampedArray();
282 else if (data.isUint16Array()) 325 else if (data.isUint16Array())
283 bufferView = data.getAsUint16Array(); 326 bufferView = data.getAsUint16Array();
284 else if (data.isFloat32Array()) 327 else if (data.isFloat32Array())
285 bufferView = data.getAsFloat32Array(); 328 bufferView = data.getAsFloat32Array();
286 else 329 else
287 NOTREACHED(); 330 NOTREACHED();
288 331
289 if (!ImageData::validateConstructorArguments( 332 if (!ImageData::validateConstructorArguments(
290 kParamData | kParamWidth | kParamHeight, nullptr, width, height, 333 kParamData | kParamWidth | kParamHeight, nullptr, width, height,
291 bufferView, &exceptionState)) 334 bufferView, &colorSettings, &exceptionState))
292 return nullptr; 335 return nullptr;
293 336
294 return new ImageData(IntSize(width, height), bufferView, &colorSettings, 337 return new ImageData(IntSize(width, height), bufferView, &colorSettings,
295 kStorageFormatFromBufferType); 338 kStorageFormatFromBufferType);
296 } 339 }
297 340
298 ScriptPromise ImageData::createImageBitmap(ScriptState* scriptState, 341 ScriptPromise ImageData::createImageBitmap(ScriptState* scriptState,
299 EventTarget& eventTarget, 342 EventTarget& eventTarget,
300 Optional<IntRect> cropRect, 343 Optional<IntRect> cropRect,
301 const ImageBitmapOptions& options, 344 const ImageBitmapOptions& options,
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
344 return m_data.get(); 387 return m_data.get();
345 return nullptr; 388 return nullptr;
346 } 389 }
347 390
348 DOMUint8ClampedArray* ImageData::data() { 391 DOMUint8ClampedArray* ImageData::data() {
349 if (m_colorSettings.storageFormat() == kUint8ClampedArrayStorageFormatName) 392 if (m_colorSettings.storageFormat() == kUint8ClampedArrayStorageFormatName)
350 return m_data.get(); 393 return m_data.get();
351 return nullptr; 394 return nullptr;
352 } 395 }
353 396
397 CanvasColorSpace ImageData::getCanvasColorSpace(const String& colorSpaceName) {
Justin Novosad 2017/03/27 19:43:48 In blink, don't use the "get" prefix in method nam
zakerinasab 2017/03/30 17:56:11 Done.
398 if (colorSpaceName == kLegacyCanvasColorSpaceName)
399 return kLegacyCanvasColorSpace;
400 if (colorSpaceName == kSRGBCanvasColorSpaceName)
401 return kSRGBCanvasColorSpace;
402 if (colorSpaceName == kRec2020CanvasColorSpaceName)
403 return kRec2020CanvasColorSpace;
404 if (colorSpaceName == kP3CanvasColorSpaceName)
405 return kP3CanvasColorSpace;
406 NOTREACHED();
407 return kSRGBCanvasColorSpace;
408 }
409
354 ImageDataStorageFormat ImageData::getImageDataStorageFormat( 410 ImageDataStorageFormat ImageData::getImageDataStorageFormat(
355 const String& storageFormatName) { 411 const String& storageFormatName) {
356 if (storageFormatName == kUint8ClampedArrayStorageFormatName) 412 if (storageFormatName == kUint8ClampedArrayStorageFormatName)
357 return kUint8ClampedArrayStorageFormat; 413 return kUint8ClampedArrayStorageFormat;
358 if (storageFormatName == kUint16ArrayStorageFormatName) 414 if (storageFormatName == kUint16ArrayStorageFormatName)
359 return kUint16ArrayStorageFormat; 415 return kUint16ArrayStorageFormat;
360 if (storageFormatName == kFloat32ArrayStorageFormatName) 416 if (storageFormatName == kFloat32ArrayStorageFormatName)
361 return kFloat32ArrayStorageFormat; 417 return kFloat32ArrayStorageFormat;
362 NOTREACHED(); 418 NOTREACHED();
363 return kUint8ClampedArrayStorageFormat; 419 return kUint8ClampedArrayStorageFormat;
364 } 420 }
365 421
422 unsigned ImageData::getStorageFormatDataSize(const String& storageFormatName) {
Justin Novosad 2017/03/27 19:43:48 same here.
zakerinasab 2017/03/30 17:56:11 Done.
423 if (storageFormatName == kUint8ClampedArrayStorageFormatName)
424 return 1;
425 if (storageFormatName == kUint16ArrayStorageFormatName)
426 return 2;
427 if (storageFormatName == kFloat32ArrayStorageFormatName)
428 return 4;
429 NOTREACHED();
430 return 1;
431 }
432
433 DOMFloat32Array* ImageData::convertFloat16ArrayToFloat32Array(
434 const uint16_t* f16Array,
435 unsigned arrayLength) {
436 if (!f16Array || arrayLength <= 0)
437 return nullptr;
438
439 DOMFloat32Array* f32Array = allocateAndValidateFloat32Array(arrayLength);
440 if (!f32Array)
441 return nullptr;
442
443 std::unique_ptr<SkColorSpaceXform> xform =
444 SkColorSpaceXform::New(SkColorSpace::MakeSRGBLinear().get(),
445 SkColorSpace::MakeSRGBLinear().get());
446 xform->apply(SkColorSpaceXform::ColorFormat::kRGBA_F32_ColorFormat,
447 f32Array->data(),
448 SkColorSpaceXform::ColorFormat::kRGBA_F16_ColorFormat, f16Array,
449 arrayLength, SkAlphaType::kUnpremul_SkAlphaType);
450 return f32Array;
451 }
452
453 DOMArrayBufferView*
454 ImageData::convertPixelsFromCanvasPixelFormatToImageDataStorageFormat(
455 WTF::ArrayBufferContents& content,
456 CanvasPixelFormat pixelFormat,
457 ImageDataStorageFormat storageFormat) {
458 if (!content.sizeInBytes())
459 return nullptr;
460
461 // Uint16 is not supported as the storage format for ImageData created from a
462 // canvas
463 if (storageFormat == kUint16ArrayStorageFormat)
464 return nullptr;
465
466 unsigned numPixels = 0;
467 uint8_t* dataU8 = nullptr;
468 DOMArrayBuffer* arrayBuffer = nullptr;
469 DOMUint8ClampedArray* u8Array = nullptr;
470 DOMFloat32Array* f32Array = nullptr;
471
472 SkColorSpaceXform::ColorFormat srcColorFormat =
473 SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat;
474 SkColorSpaceXform::ColorFormat dstColorFormat =
475 SkColorSpaceXform::ColorFormat::kRGBA_F32_ColorFormat;
476 std::unique_ptr<SkColorSpaceXform> xform =
477 SkColorSpaceXform::New(SkColorSpace::MakeSRGBLinear().get(),
478 SkColorSpace::MakeSRGBLinear().get());
479
480 // To speed up the conversion process, we use SkColorSpaceXform::apply()
481 // wherever appropriate.
482 switch (pixelFormat) {
483 case kRGBA8CanvasPixelFormat:
484 numPixels = content.sizeInBytes();
485 dataU8 = static_cast<uint8_t*>(content.data());
486 DCHECK(dataU8);
487 switch (storageFormat) {
488 case kUint8ClampedArrayStorageFormat:
489 arrayBuffer = DOMArrayBuffer::create(content);
490 return DOMUint8ClampedArray::create(arrayBuffer, 0,
491 arrayBuffer->byteLength());
492 break;
493 case kFloat32ArrayStorageFormat:
494 f32Array = allocateAndValidateFloat32Array(numPixels);
495 if (!f32Array)
496 return nullptr;
497 xform->apply(dstColorFormat, f32Array->data(), srcColorFormat,
498 content.data(), numPixels,
499 SkAlphaType::kUnpremul_SkAlphaType);
500 return f32Array;
501 break;
502 default:
503 NOTREACHED();
504 }
505 break;
506
507 case kF16CanvasPixelFormat:
508 numPixels = content.sizeInBytes() / 2;
509 srcColorFormat = SkColorSpaceXform::ColorFormat::kRGBA_F16_ColorFormat;
510
511 switch (storageFormat) {
512 case kUint8ClampedArrayStorageFormat:
513 u8Array = allocateAndValidateUint8ClampedArray(numPixels);
514 if (!u8Array)
515 return nullptr;
516 dstColorFormat =
517 SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat;
518 xform->apply(dstColorFormat, u8Array->data(), srcColorFormat,
519 content.data(), numPixels,
520 SkAlphaType::kUnpremul_SkAlphaType);
521 return u8Array;
522 break;
523 case kFloat32ArrayStorageFormat:
524 f32Array = allocateAndValidateFloat32Array(numPixels);
525 if (!f32Array)
526 return nullptr;
527 dstColorFormat =
528 SkColorSpaceXform::ColorFormat::kRGBA_F32_ColorFormat;
529 xform->apply(dstColorFormat, f32Array->data(), srcColorFormat,
530 content.data(), numPixels,
531 SkAlphaType::kUnpremul_SkAlphaType);
532 return f32Array;
533 break;
534 default:
535 NOTREACHED();
536 }
537 break;
538
539 default:
540 NOTREACHED();
541 }
542 return nullptr;
543 }
544
366 // For ImageData, the color space is only specified by color settings. 545 // For ImageData, the color space is only specified by color settings.
367 // It cannot have a SkColorSpace. This doesn't mean anything. Fix this. 546 // It cannot have a SkColorSpace. This doesn't mean anything. Fix this.
368 sk_sp<SkColorSpace> ImageData::getSkColorSpace() { 547 sk_sp<SkColorSpace> ImageData::getSkColorSpace() {
369 if (!RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled() || 548 if (!RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled() ||
370 !RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) 549 !RuntimeEnabledFeatures::colorCorrectRenderingEnabled())
371 return nullptr; 550 return nullptr;
372 551
373 return SkColorSpace::MakeSRGB(); 552 return SkColorSpace::MakeSRGB();
374 } 553 }
375 554
555 sk_sp<SkColorSpace> ImageData::getSkColorSpace(
556 const CanvasColorSpace& colorSpace,
557 const CanvasPixelFormat& pixelFormat) {
558 switch (colorSpace) {
559 case kLegacyCanvasColorSpace:
560 return (gfx::ColorSpace::CreateSRGB()).ToSkColorSpace();
561 case kSRGBCanvasColorSpace:
562 if (pixelFormat == kF16CanvasPixelFormat)
563 return (gfx::ColorSpace::CreateSCRGBLinear()).ToSkColorSpace();
564 return (gfx::ColorSpace::CreateSRGB()).ToSkColorSpace();
565 case kRec2020CanvasColorSpace:
566 return (gfx::ColorSpace(gfx::ColorSpace::PrimaryID::BT2020,
567 gfx::ColorSpace::TransferID::IEC61966_2_1))
568 .ToSkColorSpace();
569 case kP3CanvasColorSpace:
570 return (gfx::ColorSpace(gfx::ColorSpace::PrimaryID::SMPTEST432_1,
571 gfx::ColorSpace::TransferID::IEC61966_2_1))
572 .ToSkColorSpace();
573 }
574 NOTREACHED();
575 return nullptr;
576 }
577
578 unsigned char* ImageData::getImageDataInCanvasColorSettings(
579 const CanvasColorSpace& canvasColorSpace,
580 const CanvasPixelFormat& canvasPixelFormat) {
581 if (!m_data && !m_dataU16 && !m_dataF32)
582 return nullptr;
583
584 // If canvas and image data are both in the same color space and pixel format
585 // is 8-8-8-8, just return the embedded data.
586 CanvasColorSpace imageDataColorSpace =
587 ImageData::getCanvasColorSpace(m_colorSettings.colorSpace());
588 if (canvasPixelFormat == kRGBA8CanvasPixelFormat &&
589 m_colorSettings.storageFormat() == kUint8ClampedArrayStorageFormatName) {
590 if ((canvasColorSpace == kLegacyCanvasColorSpace ||
591 canvasColorSpace == kSRGBCanvasColorSpace) &&
592 (imageDataColorSpace == kLegacyCanvasColorSpace ||
593 imageDataColorSpace == kSRGBCanvasColorSpace)) {
594 return m_data->data();
595 }
596 }
597
598 // Otherwise, color convert the pixels.
599 sk_sp<SkColorSpace> srcColorSpace =
600 ImageData::getSkColorSpace(imageDataColorSpace, canvasPixelFormat);
601
602 unsigned dataLength = 0;
603 void* srcData = nullptr;
604 SkColorSpaceXform::ColorFormat srcColorFormat =
605 SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat;
606 if (m_data) {
607 dataLength = m_data->length();
608 srcData = static_cast<void*>(m_data->data());
609 DCHECK(srcData);
610 } else if (m_dataU16) {
611 dataLength = m_dataU16->length();
612 srcData = static_cast<void*>(m_dataU16->data());
613 DCHECK(srcData);
614 srcColorFormat = SkColorSpaceXform::ColorFormat::kRGBA_U16_BE_ColorFormat;
615 } else if (m_dataF32) {
616 dataLength = m_dataF32->length();
617 srcData = static_cast<void*>(m_dataF32->data());
618 DCHECK(srcData);
619 srcColorFormat = SkColorSpaceXform::ColorFormat::kRGBA_F32_ColorFormat;
620 }
621
622 sk_sp<SkColorSpace> dstColorSpace =
623 ImageData::getSkColorSpace(canvasColorSpace, canvasPixelFormat);
624
625 void* dstData = nullptr;
626 SkColorSpaceXform::ColorFormat dstColorFormat =
627 SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat;
628 if (canvasPixelFormat == kRGBA8CanvasPixelFormat) {
629 dstData = new unsigned char[dataLength];
630 } else {
631 dstData = new unsigned char[dataLength * 2];
632 dstColorFormat = SkColorSpaceXform::ColorFormat::kRGBA_F16_ColorFormat;
633 }
634 if (!dstData)
635 return nullptr;
636
637 if (SkColorSpace::Equals(srcColorSpace.get(), dstColorSpace.get()) &&
638 srcColorFormat == dstColorFormat)
639 return static_cast<unsigned char*>(srcData);
640
641 std::unique_ptr<SkColorSpaceXform> xform =
642 SkColorSpaceXform::New(srcColorSpace.get(), dstColorSpace.get());
643 xform->apply(dstColorFormat, dstData, srcColorFormat, srcData, dataLength,
644 SkAlphaType::kUnpremul_SkAlphaType);
645
646 return static_cast<unsigned char*>(dstData);
647 }
648
376 void ImageData::trace(Visitor* visitor) { 649 void ImageData::trace(Visitor* visitor) {
377 visitor->trace(m_data); 650 visitor->trace(m_data);
378 visitor->trace(m_dataU16); 651 visitor->trace(m_dataU16);
379 visitor->trace(m_dataF32); 652 visitor->trace(m_dataF32);
380 visitor->trace(m_dataUnion); 653 visitor->trace(m_dataUnion);
381 } 654 }
382 655
383 ImageData::ImageData(const IntSize& size, 656 ImageData::ImageData(const IntSize& size,
384 DOMArrayBufferView* data, 657 DOMArrayBufferView* data,
385 const ImageDataColorSettings* colorSettings, 658 const ImageDataColorSettings* colorSettings,
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
448 SECURITY_CHECK(static_cast<unsigned>(size.width() * size.height() * 4) <= 721 SECURITY_CHECK(static_cast<unsigned>(size.width() * size.height() * 4) <=
449 m_dataF32->length()); 722 m_dataF32->length());
450 break; 723 break;
451 724
452 default: 725 default:
453 NOTREACHED(); 726 NOTREACHED();
454 } 727 }
455 } 728 }
456 729
457 } // namespace blink 730 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698