我正在尝试使用CoreGraphics&的C接口。 CoreFoundation将32位RGBA数据缓冲区(作为void *)保存到PNG文件中。当我尝试完成CGImageDestinationRef
的初始化时,会在控制台上显示以下错误消息:
libpng error: No IDATs written into file
据我所知,CGImageRef
我添加到CGImageDestinationRef
是有效的。
相关代码:
void saveImage(const char* szImage, void* data, size_t dataSize, size_t width, size_t height)
{
CFStringRef name = CFStringCreateWithCString(NULL, szImage, kCFStringEncodingASCII);
CFURLRef texture_url = CFURLCreateWithFileSystemPath(
NULL,
name,
kCFURLPOSIXPathStyle,
false);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, data, dataSize, NULL);
CGImageRef image = CGImageCreate(width, height, 8, 32, 32 * width, colorSpace,
kCGImageAlphaLast | kCGBitmapByteOrderDefault, dataProvider,
NULL, FALSE, kCGRenderingIntentDefault);
// From Image I/O Programming Guide, "Working with Image Destinations"
float compression = 1.0; // Lossless compression if available.
int orientation = 4; // Origin is at bottom, left.
CFStringRef myKeys[3];
CFTypeRef myValues[3];
CFDictionaryRef myOptions = NULL;
myKeys[0] = kCGImagePropertyOrientation;
myValues[0] = CFNumberCreate(NULL, kCFNumberIntType, &orientation);
myKeys[1] = kCGImagePropertyHasAlpha;
myValues[1] = kCFBooleanTrue;
myKeys[2] = kCGImageDestinationLossyCompressionQuality;
myValues[2] = CFNumberCreate(NULL, kCFNumberFloatType, &compression);
myOptions = CFDictionaryCreate( NULL, (const void **)myKeys, (const void **)myValues, 3,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFStringRef type = CFStringCreateWithCString(NULL, "public.png", kCFStringEncodingASCII);
CGImageDestinationRef dest = CGImageDestinationCreateWithURL(texture_url, type, 1, myOptions);
CGImageDestinationAddImage(dest, image, NULL);
if (!CGImageDestinationFinalize(dest))
{
// ERROR!
}
CFRelease(image);
CFRelease(colorSpace);
CFRelease(dataProvider);
CFRelease(dest);
CFRelease(texture_url);
}
这篇文章很相似,只是我没有使用Objective C界面:Saving a 32 bit RGBA buffer into a .png file (Cocoa OSX)
答案 0 :(得分:0)
您的代码存在许多问题。
这里重写了我将如何做到这一点:
void saveImage(const char* szImage, void* data, size_t dataSize, size_t width, size_t height)
{
CFStringRef name = CFStringCreateWithCString(NULL, szImage, kCFStringEncodingUTF8);
CFURLRef texture_url = CFURLCreateWithFileSystemPath(
NULL,
name,
kCFURLPOSIXPathStyle,
false);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, data,
dataSize, NULL);
CGImageRef image = CGImageCreate(width, height, 8, 32, 32 * width, colorSpace,
kCGImageAlphaLast | kCGBitmapByteOrderDefault,
dataProvider, NULL, FALSE, kCGRenderingIntentDefault);
// From Image I/O Programming Guide, "Working with Image Destinations"
float compression = 1.0; // Lossless compression if available.
int orientation = 4; // Origin is at bottom, left.
CFStringRef myKeys[3];
CFTypeRef myValues[3];
CFDictionaryRef myOptions = NULL;
myKeys[0] = kCGImagePropertyOrientation;
myValues[0] = CFNumberCreate(NULL, kCFNumberIntType, &orientation);
myKeys[1] = kCGImagePropertyHasAlpha;
myValues[1] = kCFBooleanTrue;
myKeys[2] = kCGImageDestinationLossyCompressionQuality;
myValues[2] = CFNumberCreate(NULL, kCFNumberFloatType, &compression);
myOptions = CFDictionaryCreate(NULL, (const void **)myKeys,
(const void **)myValues, 3, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
CGImageDestinationRef dest =
CGImageDestinationCreateWithURL(texture_url, kUTTypePNG, 1, NULL);
CGImageDestinationAddImage(dest, image, NULL);
CGImageDestinationSetProperties(dest, myOptions);
if (!CGImageDestinationFinalize(dest))
{
// ERROR!
}
}
首先,在处理文件系统路径时不要使用ASCII,请使用UTF8。其次,您构建了一个用于设置图像属性的字典,但是您使用了错误的函数。 CGImageDestinationCreateWithURL()
的文档说明如下:
<强> CGImageDestinationCreateWithURL 强>
创建一个写入目标位置的图像目标 URL。
CGImageDestinationRef CGImageDestinationCreateWithURL ( CFURLRef url, CFStringRef type, size_t count, CFDictionaryRef options );
<强>参数强> options - 保留供将来使用。通过
NULL
。
当您应该通过NULL
时,您试图传递属性字典。 (另外,您可以简单地使用kUTTypePNG
统一类型标识符字符串常量而不是重新创建它)。首先调用CGImageDestinationCreateWithURL()
,然后调用CGImageDestinationAddImage()
添加图片,然后调用CGImageDestinationSetProperties()
并传入您创建的属性字典。
[更新]:如果在完成这些更改后仍然遇到libpng error: No IDATs written into file
个问题,请尝试以下操作:首先,确保dataProvider
不是NULL
- 换句话说,确保CGDataProviderCreateWithData()
功能成功。其次,如果dataProvider
有效,可以尝试将选项从kCGImageAlphaLast | kCGBitmapByteOrderDefault
更改为简单kCGImageAlphaPremultipliedLast
,看看是否成功。
答案 1 :(得分:0)
回答我自己的问题:
除了NSGod指出的问题之外,IDAT问题是CGImageCreate()的无效参数:参数5是bytesPerRow,而不是bitsPerRow。所以32 * width
是不正确的; 4 * width
是正确的。
尽管有this page官方文档列表,但UTCoreTypes.h位于MacOSX的CoreServices.framework
,而不是MobileCoreServices.framework
。