Use SkPicture::ExtractBitmap callback in pdf too, there is no need for a specialized function pointer for pdf only only to pass a rectangle, when we can use subseted bitmaps.

R=scroggo@google.com, reed@google.com, vandebo@chromium.org, bsalomon@google.com

Author: edisonn@google.com

Review URL: https://codereview.chromium.org/25054002

git-svn-id: http://skia.googlecode.com/svn/trunk@11591 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
commit-bot@chromium.org 2013-10-03 19:29:21 +00:00
parent f7f5b7c506
commit 608ea6508a
7 changed files with 85 additions and 70 deletions

View File

@ -193,7 +193,7 @@ static PipeFlagComboData gPipeWritingFlagCombos[] = {
| SkGPipeWriter::kSharedAddressSpace_Flag }
};
static bool encode_to_dct_stream(SkWStream* stream, const SkBitmap& bitmap, const SkIRect& rect);
static SkData* encode_to_dct_data(size_t* pixelRefOffset, const SkBitmap& bitmap);
const static ErrorCombination kDefaultIgnorableErrorTypes = ErrorCombination()
.plus(kMissingExpectations_ErrorType)
@ -633,7 +633,7 @@ public:
SkScalarRoundToInt(content.height()));
dev = new SkPDFDevice(pageSize, contentSize, initialTransform);
}
dev->setDCTEncoder(encode_to_dct_stream);
dev->setDCTEncoder(encode_to_dct_data);
SkAutoUnref aur(dev);
SkCanvas c(dev);
@ -1422,7 +1422,6 @@ DEFINE_string2(writePicturePath, p, "", "Write .skp files into this directory.")
DEFINE_int32(pdfJpegQuality, -1, "Encodes images in JPEG at quality level N, "
"which can be in range 0-100). N = -1 will disable JPEG compression. "
"Default is N = 100, maximum quality.");
// TODO(edisonn): pass a matrix instead of forcePerspectiveMatrix
// Either the 9 numbers defining the matrix
// or probably more readable would be to replace it with a set of a few predicates
@ -1431,32 +1430,33 @@ DEFINE_int32(pdfJpegQuality, -1, "Encodes images in JPEG at quality level N, "
// then we can write something reabable like --rotate centerx centery 90
DEFINE_bool(forcePerspectiveMatrix, false, "Force a perspective matrix.");
static bool encode_to_dct_stream(SkWStream* stream, const SkBitmap& bitmap, const SkIRect& rect) {
static SkData* encode_to_dct_data(size_t* pixelRefOffset, const SkBitmap& bitmap) {
// Filter output of warnings that JPEG is not available for the image.
if (bitmap.width() >= 65500 || bitmap.height() >= 65500) return false;
if (FLAGS_pdfJpegQuality == -1) return false;
SkIRect bitmapBounds;
SkBitmap subset;
const SkBitmap* bitmapToUse = &bitmap;
bitmap.getBounds(&bitmapBounds);
if (rect != bitmapBounds) {
SkAssertResult(bitmap.extractSubset(&subset, rect));
bitmapToUse = ⊂
}
if (bitmap.width() >= 65500 || bitmap.height() >= 65500) return NULL;
if (FLAGS_pdfJpegQuality == -1) return NULL;
SkBitmap bm = bitmap;
#if defined(SK_BUILD_FOR_MAC)
// Workaround bug #1043 where bitmaps with referenced pixels cause
// CGImageDestinationFinalize to crash
SkBitmap copy;
bitmapToUse->deepCopyTo(&copy, bitmapToUse->config());
bitmapToUse = ©
bitmap.deepCopyTo(&copy, bitmap.config());
bm = copy;
#endif
return SkImageEncoder::EncodeStream(stream,
*bitmapToUse,
SkImageEncoder::kJPEG_Type,
FLAGS_pdfJpegQuality);
SkPixelRef* pr = bm.pixelRef();
if (pr != NULL) {
SkData* data = pr->refEncodedData();
if (data != NULL) {
*pixelRefOffset = bm.pixelRefOffset();
return data;
}
}
*pixelRefOffset = 0;
return SkImageEncoder::EncodeData(bm,
SkImageEncoder::kJPEG_Type,
FLAGS_pdfJpegQuality);
}
static int findConfig(const char config[]) {

View File

@ -14,6 +14,7 @@
#include "SkCanvas.h"
#include "SkPaint.h"
#include "SkPath.h"
#include "SkPicture.h"
#include "SkRect.h"
#include "SkRefCnt.h"
#include "SkStream.h"
@ -38,8 +39,6 @@ struct ContentEntry;
struct GraphicStateEntry;
struct NamedDestination;
typedef bool (*EncodeToDCTStream)(SkWStream* stream, const SkBitmap& bitmap, const SkIRect& rect);
/** \class SkPDFDevice
The drawing context for the PDF backend.
@ -140,7 +139,7 @@ public:
* encoding and decoding might not be worth the space savings,
* if any at all.
*/
void setDCTEncoder(EncodeToDCTStream encoder) {
void setDCTEncoder(SkPicture::EncodeBitmap encoder) {
fEncoder = encoder;
}
@ -232,7 +231,7 @@ private:
// Glyph ids used for each font on this device.
SkAutoTDelete<SkPDFGlyphSetMap> fFontGlyphUsage;
EncodeToDCTStream fEncoder;
SkPicture::EncodeBitmap fEncoder;
SkPDFDevice(const SkISize& layerSize, const SkClipStack& existingClipStack,
const SkRegion& existingClipRegion);

View File

@ -339,7 +339,7 @@ static SkPDFArray* make_indexed_color_space(SkColorTable* table) {
// static
SkPDFImage* SkPDFImage::CreateImage(const SkBitmap& bitmap,
const SkIRect& srcRect,
EncodeToDCTStream encoder) {
SkPicture::EncodeBitmap encoder) {
if (bitmap.getConfig() == SkBitmap::kNo_Config) {
return NULL;
}
@ -390,7 +390,7 @@ SkPDFImage::SkPDFImage(SkStream* stream,
const SkBitmap& bitmap,
bool isAlpha,
const SkIRect& srcRect,
EncodeToDCTStream encoder)
SkPicture::EncodeBitmap encoder)
: fIsAlpha(isAlpha),
fSrcRect(srcRect),
fEncoder(encoder) {
@ -482,19 +482,28 @@ bool SkPDFImage::populate(SkPDFCatalog* catalog) {
// Initializing image data for the first time.
SkDynamicMemoryWStream dctCompressedWStream;
if (!skip_compression(catalog) && fEncoder &&
get_uncompressed_size(fBitmap, fSrcRect) > 1 &&
fEncoder(&dctCompressedWStream, fBitmap, fSrcRect) &&
dctCompressedWStream.getOffset() <
get_uncompressed_size(fBitmap, fSrcRect)) {
SkAutoTUnref<SkData> data(dctCompressedWStream.copyToData());
SkAutoTUnref<SkStream> stream(SkNEW_ARGS(SkMemoryStream, (data)));
setData(stream.get());
get_uncompressed_size(fBitmap, fSrcRect) > 1) {
SkBitmap subset;
// Extract subset
if (!fBitmap.extractSubset(&subset, fSrcRect)) {
// TODO(edisonn) It fails only for kA1_Config, if that is a
// major concern we will fix it later, so far it is NYI.
return false;
}
size_t pixelRefOffset = 0;
SkAutoTUnref<SkData> data(fEncoder(&pixelRefOffset, subset));
if (data.get() && data->size() < get_uncompressed_size(fBitmap,
fSrcRect)) {
SkAutoTUnref<SkStream> stream(SkNEW_ARGS(SkMemoryStream,
(data)));
setData(stream.get());
insertName("Filter", "DCTDecode");
insertInt("ColorTransform", kNoColorTransform);
insertInt("Length", getData()->getLength());
setState(kCompressed_State);
return true;
insertName("Filter", "DCTDecode");
insertInt("ColorTransform", kNoColorTransform);
insertInt("Length", getData()->getLength());
setState(kCompressed_State);
return true;
}
}
// Fallback method
if (!fStreamValid) {

View File

@ -10,6 +10,7 @@
#ifndef SkPDFImage_DEFINED
#define SkPDFImage_DEFINED
#include "SkPicture.h"
#include "SkPDFDevice.h"
#include "SkPDFStream.h"
#include "SkPDFTypes.h"
@ -38,7 +39,7 @@ public:
*/
static SkPDFImage* CreateImage(const SkBitmap& bitmap,
const SkIRect& srcRect,
EncodeToDCTStream encoder);
SkPicture::EncodeBitmap encoder);
virtual ~SkPDFImage();
@ -60,7 +61,7 @@ private:
SkBitmap fBitmap;
bool fIsAlpha;
SkIRect fSrcRect;
EncodeToDCTStream fEncoder;
SkPicture::EncodeBitmap fEncoder;
bool fStreamValid;
SkTDArray<SkPDFObject*> fResources;
@ -80,7 +81,7 @@ private:
* May be NULL.
*/
SkPDFImage(SkStream* stream, const SkBitmap& bitmap, bool isAlpha,
const SkIRect& srcRect, EncodeToDCTStream encoder);
const SkIRect& srcRect, SkPicture::EncodeBitmap encoder);
/** Copy constructor, used to generate substitutes.
* @param image The SkPDFImage to copy.

View File

@ -39,9 +39,11 @@ private:
SkTDArray<SkPDFObject*> fResources;
};
static bool encode_to_dct_stream(SkWStream* stream, const SkBitmap& bitmap, const SkIRect& rect) {
stream->writeText("DCT compessed stream.");
return true;
#define DUMMY_TEXT "DCT compessed stream."
static SkData* encode_to_dct_data(size_t* pixelRefOffset, const SkBitmap& bitmap) {
*pixelRefOffset = 0;
return SkData::NewWithProc(DUMMY_TEXT, sizeof(DUMMY_TEXT) - 1, NULL, NULL);
}
static bool stream_equals(const SkDynamicMemoryWStream& stream, size_t offset,
@ -253,7 +255,7 @@ static void TestImage(skiatest::Reporter* reporter, const SkBitmap& bitmap,
SkAutoTUnref<SkPDFDevice> dev(new SkPDFDevice(pageSize, pageSize, SkMatrix::I()));
if (useDCTEncoder) {
dev->setDCTEncoder(encode_to_dct_stream);
dev->setDCTEncoder(encode_to_dct_data);
}
SkCanvas c(dev);

View File

@ -33,7 +33,7 @@ public:
virtual void render() = 0;
virtual void end();
PdfRenderer(EncodeToDCTStream encoder)
PdfRenderer(SkPicture::EncodeBitmap encoder)
: fPicture(NULL)
, fPDFDevice(NULL)
, fEncoder(encoder)
@ -48,7 +48,7 @@ protected:
SkAutoTUnref<SkCanvas> fCanvas;
SkPicture* fPicture;
SkPDFDevice* fPDFDevice;
EncodeToDCTStream fEncoder;
SkPicture::EncodeBitmap fEncoder;
private:
typedef SkRefCnt INHERITED;
@ -56,7 +56,7 @@ private:
class SimplePdfRenderer : public PdfRenderer {
public:
SimplePdfRenderer(EncodeToDCTStream encoder)
SimplePdfRenderer(SkPicture::EncodeBitmap encoder)
: PdfRenderer(encoder) {}
virtual void render() SK_OVERRIDE;

View File

@ -12,6 +12,7 @@
#include "SkImageEncoder.h"
#include "SkOSFile.h"
#include "SkPicture.h"
#include "SkPixelRef.h"
#include "SkStream.h"
#include "SkTArray.h"
#include "PdfRenderer.h"
@ -81,30 +82,33 @@ static bool replace_filename_extension(SkString* path,
}
int gJpegQuality = 100;
static bool encode_to_dct_stream(SkWStream* stream, const SkBitmap& bitmap, const SkIRect& rect) {
if (gJpegQuality == -1) return false;
SkIRect bitmapBounds;
SkBitmap subset;
const SkBitmap* bitmapToUse = &bitmap;
bitmap.getBounds(&bitmapBounds);
if (rect != bitmapBounds) {
SkAssertResult(bitmap.extractSubset(&subset, rect));
bitmapToUse = &subset;
}
static SkData* encode_to_dct_data(size_t* pixelRefOffset, const SkBitmap& bitmap) {
if (gJpegQuality == -1) {
return NULL;
}
SkBitmap bm = bitmap;
#if defined(SK_BUILD_FOR_MAC)
// Workaround bug #1043 where bitmaps with referenced pixels cause
// CGImageDestinationFinalize to crash
SkBitmap copy;
bitmapToUse->deepCopyTo(&copy, bitmapToUse->config());
bitmapToUse = &copy;
// Workaround bug #1043 where bitmaps with referenced pixels cause
// CGImageDestinationFinalize to crash
SkBitmap copy;
bitmap.deepCopyTo(&copy, bitmap.config());
bm = copy;
#endif
return SkImageEncoder::EncodeStream(stream,
*bitmapToUse,
SkImageEncoder::kJPEG_Type,
gJpegQuality);
SkPixelRef* pr = bm.pixelRef();
if (pr != NULL) {
SkData* data = pr->refEncodedData();
if (data != NULL) {
*pixelRefOffset = bm.pixelRefOffset();
return data;
}
}
*pixelRefOffset = 0;
return SkImageEncoder::EncodeData(bm,
SkImageEncoder::kJPEG_Type,
gJpegQuality);
}
/** Builds the output filename. path = dir/name, and it replaces expected
@ -264,7 +268,7 @@ int tool_main_core(int argc, char** argv) {
SkTArray<SkString> inputs;
SkAutoTUnref<sk_tools::PdfRenderer>
renderer(SkNEW_ARGS(sk_tools::SimplePdfRenderer, (encode_to_dct_stream)));
renderer(SkNEW_ARGS(sk_tools::SimplePdfRenderer, (encode_to_dct_data)));
SkASSERT(renderer.get());
SkString outputDir;