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

Side by Side Diff: src/codec/SkJpegCodec.cpp

Issue 1411193006: Revert of Use SkSwizzler to convert from CMYK (Closed) Base URL: https://skia.googlesource.com/skia.git@NewFromData
Patch Set: Created 5 years, 2 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
« no previous file with comments | « no previous file | src/codec/SkSwizzler.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2015 Google Inc. 2 * Copyright 2015 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkCodec.h" 8 #include "SkCodec.h"
9 #include "SkJpegCodec.h" 9 #include "SkJpegCodec.h"
10 #include "SkJpegDecoderMgr.h" 10 #include "SkJpegDecoderMgr.h"
11 #include "SkJpegUtility_codec.h" 11 #include "SkJpegUtility_codec.h"
12 #include "SkCodecPriv.h" 12 #include "SkCodecPriv.h"
13 #include "SkColorPriv.h" 13 #include "SkColorPriv.h"
14 #include "SkStream.h" 14 #include "SkStream.h"
15 #include "SkTemplates.h" 15 #include "SkTemplates.h"
16 #include "SkTypes.h" 16 #include "SkTypes.h"
17 17
18 // stdio is needed for libjpeg-turbo 18 // stdio is needed for libjpeg-turbo
19 #include <stdio.h> 19 #include <stdio.h>
20 20
21 extern "C" { 21 extern "C" {
22 #include "jerror.h" 22 #include "jerror.h"
23 #include "jpeglib.h" 23 #include "jpeglib.h"
24 } 24 }
25 25
26 /*
27 * Convert a row of CMYK samples to RGBA in place.
28 * Note that this method moves the row pointer.
29 * @param width the number of pixels in the row that is being converted
30 * CMYK is stored as four bytes per pixel
31 */
32 static void convert_CMYK_to_RGBA(uint8_t* row, uint32_t width) {
33 // We will implement a crude conversion from CMYK -> RGB using formulas
34 // from easyrgb.com.
35 //
36 // CMYK -> CMY
37 // C = C * (1 - K) + K
38 // M = M * (1 - K) + K
39 // Y = Y * (1 - K) + K
40 //
41 // libjpeg actually gives us inverted CMYK, so we must subtract the
42 // original terms from 1.
43 // CMYK -> CMY
44 // C = (1 - C) * (1 - (1 - K)) + (1 - K)
45 // M = (1 - M) * (1 - (1 - K)) + (1 - K)
46 // Y = (1 - Y) * (1 - (1 - K)) + (1 - K)
47 //
48 // Simplifying the above expression.
49 // CMYK -> CMY
50 // C = 1 - CK
51 // M = 1 - MK
52 // Y = 1 - YK
53 //
54 // CMY -> RGB
55 // R = (1 - C) * 255
56 // G = (1 - M) * 255
57 // B = (1 - Y) * 255
58 //
59 // Therefore the full conversion is below. This can be verified at
60 // www.rapidtables.com (assuming inverted CMYK).
61 // CMYK -> RGB
62 // R = C * K * 255
63 // G = M * K * 255
64 // B = Y * K * 255
65 //
66 // As a final note, we have treated the CMYK values as if they were on
67 // a scale from 0-1, when in fact they are 8-bit ints scaling from 0-255.
68 // We must divide each CMYK component by 255 to obtain the true conversion
69 // we should perform.
70 // CMYK -> RGB
71 // R = C * K / 255
72 // G = M * K / 255
73 // B = Y * K / 255
74 for (uint32_t x = 0; x < width; x++, row += 4) {
75 #if defined(SK_PMCOLOR_IS_RGBA)
76 row[0] = SkMulDiv255Round(row[0], row[3]);
77 row[1] = SkMulDiv255Round(row[1], row[3]);
78 row[2] = SkMulDiv255Round(row[2], row[3]);
79 #else
80 uint8_t tmp = row[0];
81 row[0] = SkMulDiv255Round(row[2], row[3]);
82 row[1] = SkMulDiv255Round(row[1], row[3]);
83 row[2] = SkMulDiv255Round(tmp, row[3]);
84 #endif
85 row[3] = 0xFF;
86 }
87 }
88
26 bool SkJpegCodec::IsJpeg(SkStream* stream) { 89 bool SkJpegCodec::IsJpeg(SkStream* stream) {
27 static const uint8_t jpegSig[] = { 0xFF, 0xD8, 0xFF }; 90 static const uint8_t jpegSig[] = { 0xFF, 0xD8, 0xFF };
28 char buffer[sizeof(jpegSig)]; 91 char buffer[sizeof(jpegSig)];
29 return stream->read(buffer, sizeof(jpegSig)) == sizeof(jpegSig) && 92 return stream->read(buffer, sizeof(jpegSig)) == sizeof(jpegSig) &&
30 !memcmp(buffer, jpegSig, sizeof(jpegSig)); 93 !memcmp(buffer, jpegSig, sizeof(jpegSig));
31 } 94 }
32 95
33 bool SkJpegCodec::ReadHeader(SkStream* stream, SkCodec** codecOut, 96 bool SkJpegCodec::ReadHeader(SkStream* stream, SkCodec** codecOut,
34 JpegDecoderMgr** decoderMgrOut) { 97 JpegDecoderMgr** decoderMgrOut) {
35 98
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 #if defined(SK_PMCOLOR_IS_RGBA) 256 #if defined(SK_PMCOLOR_IS_RGBA)
194 fDecoderMgr->dinfo()->out_color_space = JCS_EXT_RGBA; 257 fDecoderMgr->dinfo()->out_color_space = JCS_EXT_RGBA;
195 #else 258 #else
196 fDecoderMgr->dinfo()->out_color_space = JCS_EXT_BGRA; 259 fDecoderMgr->dinfo()->out_color_space = JCS_EXT_BGRA;
197 #endif 260 #endif
198 #endif 261 #endif
199 } 262 }
200 return true; 263 return true;
201 case kRGB_565_SkColorType: 264 case kRGB_565_SkColorType:
202 if (isCMYK) { 265 if (isCMYK) {
203 fDecoderMgr->dinfo()->out_color_space = JCS_CMYK; 266 // FIXME (msarett): We need to support 565 here. It's not hard to do, considering
267 // we already convert CMYK to RGBA, I just need to do it. I thi nk it might be
268 // best to do this in SkSwizzler and also move convert_CMYK_to_R GBA into SkSwizzler.
269 return false;
204 } else { 270 } else {
205 #if defined(GOOGLE3) 271 #if defined(GOOGLE3)
206 return false; 272 return false;
207 #else 273 #else
208 fDecoderMgr->dinfo()->dither_mode = JDITHER_NONE; 274 fDecoderMgr->dinfo()->dither_mode = JDITHER_NONE;
209 fDecoderMgr->dinfo()->out_color_space = JCS_RGB565; 275 fDecoderMgr->dinfo()->out_color_space = JCS_RGB565;
210 #endif 276 #endif
211 } 277 }
212 return true; 278 return true;
213 case kGray_8_SkColorType: 279 case kGray_8_SkColorType:
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
292 358
293 // Now, given valid output dimensions, we can start the decompress 359 // Now, given valid output dimensions, we can start the decompress
294 if (!jpeg_start_decompress(dinfo)) { 360 if (!jpeg_start_decompress(dinfo)) {
295 return fDecoderMgr->returnFailure("startDecompress", kInvalidInput); 361 return fDecoderMgr->returnFailure("startDecompress", kInvalidInput);
296 } 362 }
297 363
298 // The recommended output buffer height should always be 1 in high quality m odes. 364 // The recommended output buffer height should always be 1 in high quality m odes.
299 // If it's not, we want to know because it means our strategy is not optimal . 365 // If it's not, we want to know because it means our strategy is not optimal .
300 SkASSERT(1 == dinfo->rec_outbuf_height); 366 SkASSERT(1 == dinfo->rec_outbuf_height);
301 367
302 if (JCS_CMYK == dinfo->out_color_space) {
303 this->initializeSwizzler(dstInfo, options);
304 }
305
306 // Perform the decode a single row at a time 368 // Perform the decode a single row at a time
307 uint32_t dstHeight = dstInfo.height(); 369 uint32_t dstHeight = dstInfo.height();
308 370 JSAMPLE* dstRow = (JSAMPLE*) dst;
309 JSAMPLE* dstRow;
310 if (fSwizzler) {
311 // write data to storage row, then sample using swizzler
312 dstRow = fSrcRow;
313 } else {
314 // write data directly to dst
315 dstRow = (JSAMPLE*) dst;
316 }
317
318 for (uint32_t y = 0; y < dstHeight; y++) { 371 for (uint32_t y = 0; y < dstHeight; y++) {
319 // Read rows of the image 372 // Read rows of the image
320 uint32_t lines = jpeg_read_scanlines(dinfo, &dstRow, 1); 373 uint32_t lines = jpeg_read_scanlines(dinfo, &dstRow, 1);
321 374
322 // If we cannot read enough rows, assume the input is incomplete 375 // If we cannot read enough rows, assume the input is incomplete
323 if (lines != 1) { 376 if (lines != 1) {
324 *rowsDecoded = y; 377 *rowsDecoded = y;
325 378
326 return fDecoderMgr->returnFailure("Incomplete image data", kIncomple teInput); 379 return fDecoderMgr->returnFailure("Incomplete image data", kIncomple teInput);
327 } 380 }
328 381
329 if (fSwizzler) { 382 // Convert to RGBA if necessary
330 // use swizzler to sample row 383 if (JCS_CMYK == dinfo->out_color_space) {
331 fSwizzler->swizzle(dst, dstRow); 384 convert_CMYK_to_RGBA(dstRow, dstInfo.width());
332 dst = SkTAddOffset<JSAMPLE>(dst, dstRowBytes);
333 } else {
334 dstRow = SkTAddOffset<JSAMPLE>(dstRow, dstRowBytes);
335 } 385 }
386
387 // Move to the next row
388 dstRow = SkTAddOffset<JSAMPLE>(dstRow, dstRowBytes);
336 } 389 }
337 390
338 return kSuccess; 391 return kSuccess;
339 } 392 }
340 393
341 void SkJpegCodec::initializeSwizzler(const SkImageInfo& dstInfo, const Options& options) { 394 void SkJpegCodec::initializeSwizzler(const SkImageInfo& dstInfo, const Options& options) {
342 SkSwizzler::SrcConfig srcConfig = SkSwizzler::kUnknown; 395 SkSwizzler::SrcConfig srcConfig = SkSwizzler::kUnknown;
343 if (JCS_CMYK == fDecoderMgr->dinfo()->out_color_space) { 396 switch (dstInfo.colorType()) {
344 srcConfig = SkSwizzler::kCMYK; 397 case kGray_8_SkColorType:
345 } else { 398 srcConfig = SkSwizzler::kGray;
346 switch (dstInfo.colorType()) { 399 break;
347 case kGray_8_SkColorType: 400 case kRGBA_8888_SkColorType:
348 srcConfig = SkSwizzler::kGray; 401 srcConfig = SkSwizzler::kRGBX;
349 break; 402 break;
350 case kRGBA_8888_SkColorType: 403 case kBGRA_8888_SkColorType:
351 srcConfig = SkSwizzler::kRGBX; 404 srcConfig = SkSwizzler::kBGRX;
352 break; 405 break;
353 case kBGRA_8888_SkColorType: 406 case kRGB_565_SkColorType:
354 srcConfig = SkSwizzler::kBGRX; 407 srcConfig = SkSwizzler::kRGB_565;
355 break; 408 break;
356 case kRGB_565_SkColorType: 409 default:
357 srcConfig = SkSwizzler::kRGB_565; 410 // This function should only be called if the colorType is supported by jpeg
358 break;
359 default:
360 // This function should only be called if the colorType is suppo rted by jpeg
361 #if defined(GOOGLE3) 411 #if defined(GOOGLE3)
362 SK_CRASH(); 412 SK_CRASH();
363 #else 413 #else
364 SkASSERT(false); 414 SkASSERT(false);
365 #endif 415 #endif
366 }
367 } 416 }
368 417
369 fSwizzler.reset(SkSwizzler::CreateSwizzler(srcConfig, nullptr, dstInfo, opti ons)); 418 fSwizzler.reset(SkSwizzler::CreateSwizzler(srcConfig, nullptr, dstInfo, opti ons));
370 fStorage.reset(get_row_bytes(fDecoderMgr->dinfo())); 419 fStorage.reset(get_row_bytes(fDecoderMgr->dinfo()));
371 fSrcRow = static_cast<uint8_t*>(fStorage.get()); 420 fSrcRow = static_cast<uint8_t*>(fStorage.get());
372 } 421 }
373 422
374 SkSampler* SkJpegCodec::getSampler(bool createIfNecessary) { 423 SkSampler* SkJpegCodec::getSampler(bool createIfNecessary) {
375 if (!createIfNecessary || fSwizzler) { 424 if (!createIfNecessary || fSwizzler) {
376 SkASSERT(!fSwizzler || (fSrcRow && static_cast<uint8_t*>(fStorage.get()) == fSrcRow)); 425 SkASSERT(!fSwizzler || (fSrcRow && static_cast<uint8_t*>(fStorage.get()) == fSrcRow));
(...skipping 21 matching lines...) Expand all
398 fSwizzler.reset(nullptr); 447 fSwizzler.reset(nullptr);
399 fSrcRow = nullptr; 448 fSrcRow = nullptr;
400 fStorage.free(); 449 fStorage.free();
401 450
402 // Now, given valid output dimensions, we can start the decompress 451 // Now, given valid output dimensions, we can start the decompress
403 if (!jpeg_start_decompress(fDecoderMgr->dinfo())) { 452 if (!jpeg_start_decompress(fDecoderMgr->dinfo())) {
404 SkCodecPrintf("start decompress failed\n"); 453 SkCodecPrintf("start decompress failed\n");
405 return kInvalidInput; 454 return kInvalidInput;
406 } 455 }
407 456
408 // We will need a swizzler if we are performing a subset decode or 457 // We will need a swizzler if we are performing a subset decode
409 // converting from CMYK. 458 if (options.fSubset) {
410 if (options.fSubset || JCS_CMYK == fDecoderMgr->dinfo()->out_color_space) {
411 this->initializeSwizzler(dstInfo, options); 459 this->initializeSwizzler(dstInfo, options);
412 } 460 }
413 461
414 return kSuccess; 462 return kSuccess;
415 } 463 }
416 464
417 int SkJpegCodec::onGetScanlines(void* dst, int count, size_t rowBytes) { 465 int SkJpegCodec::onGetScanlines(void* dst, int count, size_t rowBytes) {
418 // Set the jump location for libjpeg errors 466 // Set the jump location for libjpeg errors
419 if (setjmp(fDecoderMgr->getJmpBuf())) { 467 if (setjmp(fDecoderMgr->getJmpBuf())) {
420 return fDecoderMgr->returnFailure("setjmp", kInvalidInput); 468 return fDecoderMgr->returnFailure("setjmp", kInvalidInput);
421 } 469 }
422 // Read rows one at a time 470 // Read rows one at a time
423 JSAMPLE* dstRow; 471 JSAMPLE* dstRow;
424 if (fSwizzler) { 472 if (fSwizzler) {
425 // write data to storage row, then sample using swizzler 473 // write data to storage row, then sample using swizzler
426 dstRow = fSrcRow; 474 dstRow = fSrcRow;
427 } else { 475 } else {
428 // write data directly to dst 476 // write data directly to dst
429 dstRow = (JSAMPLE*) dst; 477 dstRow = (JSAMPLE*) dst;
430 } 478 }
431 479
432 for (int y = 0; y < count; y++) { 480 for (int y = 0; y < count; y++) {
433 // Read row of the image 481 // Read row of the image
434 uint32_t rowsDecoded = jpeg_read_scanlines(fDecoderMgr->dinfo(), &dstRow , 1); 482 uint32_t rowsDecoded = jpeg_read_scanlines(fDecoderMgr->dinfo(), &dstRow , 1);
435 if (rowsDecoded != 1) { 483 if (rowsDecoded != 1) {
436 fDecoderMgr->dinfo()->output_scanline = this->dstInfo().height(); 484 fDecoderMgr->dinfo()->output_scanline = this->dstInfo().height();
437 return y; 485 return y;
438 } 486 }
439 487
440 if (fSwizzler) { 488 // Convert to RGBA if necessary
489 if (JCS_CMYK == fDecoderMgr->dinfo()->out_color_space) {
490 convert_CMYK_to_RGBA(dstRow, fDecoderMgr->dinfo()->output_width);
491 }
492
493 if(fSwizzler) {
441 // use swizzler to sample row 494 // use swizzler to sample row
442 fSwizzler->swizzle(dst, dstRow); 495 fSwizzler->swizzle(dst, dstRow);
443 dst = SkTAddOffset<JSAMPLE>(dst, rowBytes); 496 dst = SkTAddOffset<JSAMPLE>(dst, rowBytes);
444 } else { 497 } else {
445 dstRow = SkTAddOffset<JSAMPLE>(dstRow, rowBytes); 498 dstRow = SkTAddOffset<JSAMPLE>(dstRow, rowBytes);
446 } 499 }
447 } 500 }
448 return count; 501 return count;
449 } 502 }
450 503
(...skipping 12 matching lines...) Expand all
463 #endif 516 #endif
464 517
465 bool SkJpegCodec::onSkipScanlines(int count) { 518 bool SkJpegCodec::onSkipScanlines(int count) {
466 // Set the jump location for libjpeg errors 519 // Set the jump location for libjpeg errors
467 if (setjmp(fDecoderMgr->getJmpBuf())) { 520 if (setjmp(fDecoderMgr->getJmpBuf())) {
468 return fDecoderMgr->returnFalse("setjmp"); 521 return fDecoderMgr->returnFalse("setjmp");
469 } 522 }
470 523
471 return (uint32_t) count == jpeg_skip_scanlines(fDecoderMgr->dinfo(), count); 524 return (uint32_t) count == jpeg_skip_scanlines(fDecoderMgr->dinfo(), count);
472 } 525 }
OLDNEW
« no previous file with comments | « no previous file | src/codec/SkSwizzler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698