我正在尝试为CGPDFDocument创建缩略图 在Quartz Programming Guide的PDF Document Parsing部分中,有以下代码:
CGPDFDictionaryRef d;
CGPDFStreamRef stream; // represents a sequence of bytes
d = CGPDFPageGetDictionary(page);
// check for thumbnail data
if (CGPDFDictionaryGetStream (d, “Thumb”, &stream)){
// get the data if it exists
data = CGPDFStreamCopyData (stream, &format);
下一步是使用data
来创建图像
Sugar回答了从PDF中提取图像的类似问题:
Extracting images from a PDF
我正在尝试使用其答案中列出的decodeValuesFromImageDictionary()
和getImageRef()
函数创建一个UIImage来表示我的缩略图。
我的问题是我获得的图像有错误的颜色和错误的尺寸,除非我将CGImageCreate()
函数的CGColorSpaceRef参数设置为CGColorSpaceCreateDeviceGray()
,在这种情况下我得到(正确的)灰度缩略图的表示当然不是我想要的。
通过检查缩略图流字典,我知道图像格式是CGPDFDataFormatRaw,而ColorSpace是DeviceRGB。我也知道有两个滤镜(ASCII85Decode和FlateDecode)应用于图像,即使我不确定这是否有意义。
非常感谢任何关于为什么会发生这种情况的建议或见解以及如何解决这个问题!
答案 0 :(得分:0)
您指定的链接提供的代码中的mona m包含注释行:
// cgColorSpace = colorSpaceFromPDFArray(colorSpaceArray);
不是分析colorSpaceArray并获得准确的色彩空间,而是将CGColorSpaceCreateDeviceRGB分配给错误的cgColorSpace变量。
这是一种缺失方法的实现,我在互联网上找到了它。
CGColorSpaceRef colorSpaceFromPDFArray(CGPDFArrayRef colorSpaceArray){
CGColorSpaceRef cgColorSpace = NULL, alternateColorSpace = NULL;
CGPDFStreamRef stream;
const char *colorSpaceName = NULL, *alternateColorSpaceName = NULL;
CGPDFInteger numberOfComponents;
CGPDFDictionaryRef dict;
bool retrieved;
CGFloat *range;
CGPDFArrayRef rangeArray;
if (CGPDFArrayGetName(colorSpaceArray, 0, &colorSpaceName)) {
if (strcmp(colorSpaceName, "ICCBased") == 0) {
if (CGPDFArrayGetStream(colorSpaceArray, 1, &stream)) {
dict = CGPDFStreamGetDictionary(stream);
// First obtain the alternate color space if present
if (CGPDFDictionaryGetName(dict, "Alternate", &alternateColorSpaceName)) {
if (strcmp(alternateColorSpaceName, "DeviceRGB") == 0) {
alternateColorSpace = CGColorSpaceCreateDeviceRGB();
} else if (strcmp(alternateColorSpaceName, "DeviceGray") ==
0) {
alternateColorSpace = CGColorSpaceCreateDeviceGray();
} else if (strcmp(alternateColorSpaceName, "DeviceCMYK") ==
0) {
alternateColorSpace = CGColorSpaceCreateDeviceCMYK();
}
}
// Obtain the preferential color space
CGPDFDataFormat dataFormat;
CFDataRef colorSpaceDataPtr =
CGPDFStreamCopyData(stream, &dataFormat);
if (dataFormat == CGPDFDataFormatRaw) {
CGDataProviderRef profile =
CGDataProviderCreateWithCFData(colorSpaceDataPtr);
retrieved = CGPDFDictionaryGetInteger(dict, "N",
&numberOfComponents);
// Deduce an alternate color space if we don't have one
//already
if (alternateColorSpace == NULL) {
switch (numberOfComponents) {
case 1:
alternateColorSpace = CGColorSpaceCreateDeviceGray();
break;
case 3:
alternateColorSpace = CGColorSpaceCreateDeviceRGB();
break;
case 4:
alternateColorSpace = CGColorSpaceCreateDeviceCMYK();
break;
default:
break;
}
}
range = malloc(numberOfComponents * 2 * sizeof(CGFloat));
if (!CGPDFDictionaryGetArray(dict, "Range", &rangeArray)) {
for (int i = 0; i < numberOfComponents * 2; i += 2) {
range[i] = (i % 2 == 0) ? 0.0 : 1.0;
}
} else {
size_t count = CGPDFArrayGetCount(rangeArray);
for (int i = 0; i < count; i++) {
(void)CGPDFArrayGetNumber(rangeArray, i, &range[i]);
}
}
cgColorSpace = CGColorSpaceCreateICCBased(numberOfComponents, range, profile,
alternateColorSpace);
CGDataProviderRelease(profile);
free(range);
if (cgColorSpace) {
// Since we have a preferential color space, we no
//longer need the hang on to the alternate color space
CGColorSpaceRelease(alternateColorSpace);
} else {
cgColorSpace = alternateColorSpace;
}
} else if (dataFormat == CGPDFDataFormatJPEGEncoded) {
//
} else if (dataFormat == CGPDFDataFormatJPEG2000) {
//
}
}
} else if (strcmp(colorSpaceName, "Indexed") == 0) {
CGColorSpaceRef baseSpace;
CGPDFArrayRef base = NULL;
CGPDFInteger highValue = 0;
CGPDFStreamRef stream = NULL;
CGPDFStringRef string;
const unsigned char *chars;
const char *namedColorSpaceName;
if (CGPDFArrayGetArray(colorSpaceArray, 1, &base)) {
baseSpace = colorSpaceFromPDFArray(base);
} else if (CGPDFArrayGetName(colorSpaceArray, 1,
&namedColorSpaceName)) {
if (strcmp(namedColorSpaceName, "DeviceRGB") == 0) {
baseSpace = CGColorSpaceCreateDeviceRGB();
} else if (strcmp(namedColorSpaceName, "DeviceGray") == 0) {
baseSpace = CGColorSpaceCreateDeviceGray();
} else if (strcmp(namedColorSpaceName, "DeviceCMYK") == 0) {
baseSpace = CGColorSpaceCreateDeviceCMYK();
}
}
retrieved = CGPDFArrayGetInteger(colorSpaceArray, 2, &highValue);
if (CGPDFArrayGetStream(colorSpaceArray, 3, &stream)) {
chars = CFDataGetBytePtr(CGPDFStreamCopyData(stream, NULL));
} else if (CGPDFArrayGetString(colorSpaceArray, 3, &string)) {
chars = CGPDFStringGetBytePtr(string);
} else {
// TODO: Raise some error state?
}
cgColorSpace = CGColorSpaceCreateIndexed(baseSpace, highValue,
chars);
}
}
return (CGColorSpaceRef)CFMakeCollectable(cgColorSpace);
}
但不幸的是,我最终在图像上得到了一些灰点。