bool image_compute_is_opaque(const SkImage* image) { if (image->isOpaque()) { return true; } // keep output PDF small at cost of possible resource use. SkBitmap bm; image_get_ro_pixels(image, &bm); return SkBitmap::ComputeIsOpaque(bm); }
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); }