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

Side by Side Diff: src/pdf/SkPDFBitmap.cpp

Issue 1133443003: SkPDF: detect YUV-JPEG without relying on ImageGenerator (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years, 7 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 | « src/pdf/SkJpegInfo.cpp ('k') | tests/PDFJpegEmbedTest.cpp » ('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 "SkColorPriv.h" 8 #include "SkColorPriv.h"
9 #include "SkData.h" 9 #include "SkData.h"
10 #include "SkFlate.h" 10 #include "SkFlate.h"
11 #include "SkImageGenerator.h" 11 #include "SkImageGenerator.h"
12 #include "SkJpegInfo.h"
12 #include "SkPDFBitmap.h" 13 #include "SkPDFBitmap.h"
13 #include "SkPDFCanon.h" 14 #include "SkPDFCanon.h"
14 #include "SkPixelRef.h" 15 #include "SkPixelRef.h"
15 #include "SkStream.h" 16 #include "SkStream.h"
16 #include "SkUnPreMultiply.h" 17 #include "SkUnPreMultiply.h"
17 18
18 //////////////////////////////////////////////////////////////////////////////// 19 ////////////////////////////////////////////////////////////////////////////////
19 20
20 static void pdf_stream_begin(SkWStream* stream) { 21 static void pdf_stream_begin(SkWStream* stream) {
21 static const char streamBegin[] = " stream\n"; 22 static const char streamBegin[] = " stream\n";
(...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 } 395 }
395 396
396 namespace { 397 namespace {
397 /** 398 /**
398 * This PDFObject assumes that its constructor was handed YUV JFIF 399 * This PDFObject assumes that its constructor was handed YUV JFIF
399 * Jpeg-encoded data that can be directly embedded into a PDF. 400 * Jpeg-encoded data that can be directly embedded into a PDF.
400 */ 401 */
401 class PDFJpegBitmap : public SkPDFBitmap { 402 class PDFJpegBitmap : public SkPDFBitmap {
402 public: 403 public:
403 SkAutoTUnref<SkData> fData; 404 SkAutoTUnref<SkData> fData;
404 PDFJpegBitmap(const SkBitmap& bm, SkData* data) 405 bool fIsYUV;
405 : SkPDFBitmap(bm), fData(SkRef(data)) {} 406 PDFJpegBitmap(const SkBitmap& bm, SkData* data, bool isYUV)
407 : SkPDFBitmap(bm), fData(SkRef(data)), fIsYUV(isYUV) {}
406 void emitObject(SkWStream*, 408 void emitObject(SkWStream*,
407 const SkPDFObjNumMap&, 409 const SkPDFObjNumMap&,
408 const SkPDFSubstituteMap&) override; 410 const SkPDFSubstituteMap&) override;
409 }; 411 };
410 412
411 void PDFJpegBitmap::emitObject(SkWStream* stream, 413 void PDFJpegBitmap::emitObject(SkWStream* stream,
412 const SkPDFObjNumMap& objNumMap, 414 const SkPDFObjNumMap& objNumMap,
413 const SkPDFSubstituteMap& substituteMap) { 415 const SkPDFSubstituteMap& substituteMap) {
414 SkPDFDict pdfDict("XObject"); 416 SkPDFDict pdfDict("XObject");
415 pdfDict.insertName("Subtype", "Image"); 417 pdfDict.insertName("Subtype", "Image");
416 pdfDict.insertInt("Width", fBitmap.width()); 418 pdfDict.insertInt("Width", fBitmap.width());
417 pdfDict.insertInt("Height", fBitmap.height()); 419 pdfDict.insertInt("Height", fBitmap.height());
418 pdfDict.insertName("ColorSpace", "DeviceRGB"); 420 if (fIsYUV) {
421 pdfDict.insertName("ColorSpace", "DeviceRGB");
422 } else {
423 pdfDict.insertName("ColorSpace", "DeviceGray");
424 }
419 pdfDict.insertInt("BitsPerComponent", 8); 425 pdfDict.insertInt("BitsPerComponent", 8);
420 pdfDict.insertName("Filter", "DCTDecode"); 426 pdfDict.insertName("Filter", "DCTDecode");
421 pdfDict.insertInt("ColorTransform", 0); 427 pdfDict.insertInt("ColorTransform", 0);
422 pdfDict.insertInt("Length", SkToInt(fData->size())); 428 pdfDict.insertInt("Length", SkToInt(fData->size()));
423 pdfDict.emitObject(stream, objNumMap, substituteMap); 429 pdfDict.emitObject(stream, objNumMap, substituteMap);
424 pdf_stream_begin(stream); 430 pdf_stream_begin(stream);
425 stream->write(fData->data(), fData->size()); 431 stream->write(fData->data(), fData->size());
426 pdf_stream_end(stream); 432 pdf_stream_end(stream);
427 } 433 }
428 } // namespace 434 } // namespace
429 435
430 //////////////////////////////////////////////////////////////////////////////// 436 ////////////////////////////////////////////////////////////////////////////////
431 437
432 static bool is_jfif_yuv_jpeg(SkData* data) {
433 const uint8_t bytesZeroToThree[] = {0xFF, 0xD8, 0xFF, 0xE0};
434 const uint8_t bytesSixToTen[] = {'J', 'F', 'I', 'F', 0};
435 // 0 1 2 3 4 5 6 7 8 9 10
436 // FF D8 FF E0 ?? ?? 'J' 'F' 'I' 'F' 00 ...
437 if (data->size() < 11 ||
438 0 != memcmp(data->bytes(), bytesZeroToThree,
439 sizeof(bytesZeroToThree)) ||
440 0 != memcmp(data->bytes() + 6, bytesSixToTen, sizeof(bytesSixToTen))) {
441 return false;
442 }
443 SkAutoTDelete<SkImageGenerator> gen(SkImageGenerator::NewFromData(data));
444 SkISize sizes[3];
445 // Only YUV JPEG allows access to YUV planes.
446 return gen && gen->getYUV8Planes(sizes, NULL, NULL, NULL);
447 }
448
449 SkPDFBitmap* SkPDFBitmap::Create(SkPDFCanon* canon, const SkBitmap& bitmap) { 438 SkPDFBitmap* SkPDFBitmap::Create(SkPDFCanon* canon, const SkBitmap& bitmap) {
450 SkASSERT(canon); 439 SkASSERT(canon);
451 if (!SkColorTypeIsValid(bitmap.colorType()) || 440 if (!SkColorTypeIsValid(bitmap.colorType()) ||
452 kUnknown_SkColorType == bitmap.colorType()) { 441 kUnknown_SkColorType == bitmap.colorType()) {
453 return NULL; 442 return NULL;
454 } 443 }
455 SkBitmap copy; 444 SkBitmap copy;
456 const SkBitmap& bm = immutable_bitmap(bitmap, &copy); 445 const SkBitmap& bm = immutable_bitmap(bitmap, &copy);
457 if (bm.drawsNothing()) { 446 if (bm.drawsNothing()) {
458 return NULL; 447 return NULL;
459 } 448 }
460 if (SkPDFBitmap* canonBitmap = canon->findBitmap(bm)) { 449 if (SkPDFBitmap* canonBitmap = canon->findBitmap(bm)) {
461 return SkRef(canonBitmap); 450 return SkRef(canonBitmap);
462 } 451 }
463 452
464 if (bm.pixelRef() && bm.pixelRefOrigin().isZero() && 453 if (bm.pixelRef() && bm.pixelRefOrigin().isZero() &&
465 bm.dimensions() == bm.pixelRef()->info().dimensions()) { 454 bm.dimensions() == bm.pixelRef()->info().dimensions()) {
466 // Requires the bitmap to be backed by lazy pixels. 455 // Requires the bitmap to be backed by lazy pixels.
467 SkAutoTUnref<SkData> data(bm.pixelRef()->refEncodedData()); 456 SkAutoTUnref<SkData> data(bm.pixelRef()->refEncodedData());
468 if (data && is_jfif_yuv_jpeg(data)) { 457 SkJFIFInfo info;
469 SkPDFBitmap* pdfBitmap = SkNEW_ARGS(PDFJpegBitmap, (bm, data)); 458 if (data && SkIsJFIF(data, &info)) {
459 bool yuv = info.fType == SkJFIFInfo::kYCbCr;
460 SkPDFBitmap* pdfBitmap = SkNEW_ARGS(PDFJpegBitmap, (bm, data, yuv));
470 canon->addBitmap(pdfBitmap); 461 canon->addBitmap(pdfBitmap);
471 return pdfBitmap; 462 return pdfBitmap;
472 } 463 }
473 } 464 }
474 465
475 SkPDFObject* smask = NULL; 466 SkPDFObject* smask = NULL;
476 if (!bm.isOpaque() && !SkBitmap::ComputeIsOpaque(bm)) { 467 if (!bm.isOpaque() && !SkBitmap::ComputeIsOpaque(bm)) {
477 smask = SkNEW_ARGS(PDFAlphaBitmap, (bm)); 468 smask = SkNEW_ARGS(PDFAlphaBitmap, (bm));
478 } 469 }
479 SkPDFBitmap* pdfBitmap = SkNEW_ARGS(PDFDefaultBitmap, (bm, smask)); 470 SkPDFBitmap* pdfBitmap = SkNEW_ARGS(PDFDefaultBitmap, (bm, smask));
480 canon->addBitmap(pdfBitmap); 471 canon->addBitmap(pdfBitmap);
481 return pdfBitmap; 472 return pdfBitmap;
482 } 473 }
OLDNEW
« no previous file with comments | « src/pdf/SkJpegInfo.cpp ('k') | tests/PDFJpegEmbedTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698