static void emit_image_xobject(SkWStream* stream, const SkImage* image, bool alpha, const sk_sp<SkPDFObject>& smask, const SkPDFObjNumMap& objNumMap, const SkPDFSubstituteMap& substitutes) { SkBitmap bitmap; image_get_ro_pixels(image, &bitmap); // TODO(halcanary): test SkAutoLockPixels autoLockPixels(bitmap); // with malformed images. // Write to a temporary buffer to get the compressed length. SkDynamicMemoryWStream buffer; SkDeflateWStream deflateWStream(&buffer); if (alpha) { bitmap_alpha_to_a8(bitmap, &deflateWStream); } else { bitmap_to_pdf_pixels(bitmap, &deflateWStream); } deflateWStream.finalize(); // call before detachAsStream(). std::unique_ptr<SkStreamAsset> asset(buffer.detachAsStream()); SkPDFDict pdfDict("XObject"); pdfDict.insertName("Subtype", "Image"); pdfDict.insertInt("Width", bitmap.width()); pdfDict.insertInt("Height", bitmap.height()); if (alpha) { pdfDict.insertName("ColorSpace", "DeviceGray"); } else if (bitmap.colorType() == kIndex_8_SkColorType) { SkASSERT(1 == pdf_color_component_count(bitmap.colorType())); pdfDict.insertObject("ColorSpace", make_indexed_color_space(bitmap.getColorTable(), bitmap.alphaType())); } else if (1 == pdf_color_component_count(bitmap.colorType())) { pdfDict.insertName("ColorSpace", "DeviceGray"); } else { pdfDict.insertName("ColorSpace", "DeviceRGB"); } if (smask) { pdfDict.insertObjRef("SMask", smask); } pdfDict.insertInt("BitsPerComponent", 8); pdfDict.insertName("Filter", "FlateDecode"); pdfDict.insertInt("Length", asset->getLength()); pdfDict.emitObject(stream, objNumMap, substitutes); pdf_stream_begin(stream); stream->writeStream(asset.get(), asset->getLength()); pdf_stream_end(stream); }
void PDFDefaultBitmap::emitObject(SkWStream* stream, const SkPDFObjNumMap& objNumMap, const SkPDFSubstituteMap& substitutes) const { SkAutoLockPixels autoLockPixels(fBitmap); SkASSERT(fBitmap.colorType() != kIndex_8_SkColorType || fBitmap.getColorTable()); // Write to a temporary buffer to get the compressed length. SkDynamicMemoryWStream buffer; SkDeflateWStream deflateWStream(&buffer); bitmap_to_pdf_pixels(fBitmap, &deflateWStream); deflateWStream.finalize(); // call before detachAsStream(). SkAutoTDelete<SkStreamAsset> asset(buffer.detachAsStream()); SkPDFDict pdfDict("XObject"); pdfDict.insertName("Subtype", "Image"); pdfDict.insertInt("Width", fBitmap.width()); pdfDict.insertInt("Height", fBitmap.height()); if (fBitmap.colorType() == kIndex_8_SkColorType) { SkASSERT(1 == pdf_color_component_count(fBitmap.colorType())); pdfDict.insertObject("ColorSpace", make_indexed_color_space(fBitmap.getColorTable())); } else if (1 == pdf_color_component_count(fBitmap.colorType())) { pdfDict.insertName("ColorSpace", "DeviceGray"); } else { pdfDict.insertName("ColorSpace", "DeviceRGB"); } pdfDict.insertInt("BitsPerComponent", 8); if (fSMask) { pdfDict.insertObjRef("SMask", SkRef(fSMask.get())); } pdfDict.insertName("Filter", "FlateDecode"); pdfDict.insertInt("Length", asset->getLength()); pdfDict.emitObject(stream, objNumMap, substitutes); pdf_stream_begin(stream); stream->writeStream(asset.get(), asset->getLength()); pdf_stream_end(stream); }
static void bitmap_to_pdf_pixels(const SkBitmap& bitmap, SkWStream* out) { if (!bitmap.getPixels()) { size_t size = pixel_count(bitmap) * pdf_color_component_count(bitmap.colorType()); fill_stream(out, '\x00', size); return; } SkBitmap copy; const SkBitmap& bm = not4444(bitmap, ©); SkAutoLockPixels autoLockPixels(bm); SkColorType colorType = bm.colorType(); switch (colorType) { case kRGBA_8888_SkColorType: case kBGRA_8888_SkColorType: { SkASSERT(3 == pdf_color_component_count(colorType)); SkAutoTMalloc<uint8_t> scanline(3 * bm.width()); for (int y = 0; y < bm.height(); ++y) { const uint32_t* src = bm.getAddr32(0, y); uint8_t* dst = scanline.get(); for (int x = 0; x < bm.width(); ++x) { uint32_t color = *src++; U8CPU alpha = SkGetA32Component(color, colorType); if (alpha != SK_AlphaTRANSPARENT) { pmcolor_to_rgb24(color, dst, colorType); } else { get_neighbor_avg_color(bm, x, y, dst, colorType); } dst += 3; } out->write(scanline.get(), 3 * bm.width()); } return; } case kRGB_565_SkColorType: { SkASSERT(3 == pdf_color_component_count(colorType)); SkAutoTMalloc<uint8_t> scanline(3 * bm.width()); for (int y = 0; y < bm.height(); ++y) { const uint16_t* src = bm.getAddr16(0, y); uint8_t* dst = scanline.get(); for (int x = 0; x < bm.width(); ++x) { U16CPU color565 = *src++; *dst++ = SkPacked16ToR32(color565); *dst++ = SkPacked16ToG32(color565); *dst++ = SkPacked16ToB32(color565); } out->write(scanline.get(), 3 * bm.width()); } return; } case kAlpha_8_SkColorType: SkASSERT(1 == pdf_color_component_count(colorType)); fill_stream(out, '\x00', pixel_count(bm)); return; case kGray_8_SkColorType: case kIndex_8_SkColorType: SkASSERT(1 == pdf_color_component_count(colorType)); // these two formats need no transformation to serialize. for (int y = 0; y < bm.height(); ++y) { out->write(bm.getAddr8(0, y), bm.width()); } return; case kUnknown_SkColorType: case kARGB_4444_SkColorType: default: SkDEBUGFAIL("unexpected color type"); } }