PNG 压缩 - ImageIO(在 Mac OS 上使用 C/C++)

问题描述 投票:0回答:1

我正在尝试通过应用 PNG 过滤器(例如(Sub、Up、Average、Paeth))来压缩 PNG 图像,我正在使用属性 kCGImagePropertyPNGCompressionFilter 应用文件管理器,但在尝试任何过滤器后,结果图像中没有看到任何变化。这里有什么问题有人可以帮我解决这个问题吗? 应用滤镜后是否压缩图像数据?如果是的话该怎么做?

这是我的源代码

    CGImageDestinationRef   outImageDestRef = NULL;
        long                    keyCounter = kzero;
        CFStringRef             dstImageFormatStrRef = NULL;
        CFMutableDataRef        destDataRef = CFDataCreateMutable(kCFAllocatorDefault,0);
        Handle srcHndl = //source image handle;
        ImageTypes srcImageType = //'JPEG', 'PNGf, etct;
        CGImageRef inImageRef = CreateCGImageFromHandle(srcHndl,srcImageType);
        
        if(inImageRef)
        {
            CFTypeRef keys[4] = {nil};
            CFTypeRef values[4] = {nil};

            dstImageFormatStrRef = CFSTR("public.png");
            long png_filter = IMAGEIO_PNG_FILTER_SUB; //IMAGEIO_PNG_FILTER_SUB, IMAGEIO_PNG_FILTER_UP, IMAGEIO_PNG_FILTER_AVG, IMAGEIO_PNG_FILTER_PAETH .. it is one of this at a time
            keys[keyCounter] = kCGImagePropertyPNGCompressionFilter;
            values[keyCounter] = CFNumberCreate(NULL,kCFNumberLongType,&png_filter);
            keyCounter++;

            outImageDestRef = CGImageDestinationCreateWithData(destDataRef, dstImageFormatStrRef, 1, NULL);
            
            if(outImageDestRef)
            {
//                keys[keyCounter] = kCGImagePropertyDPIWidth;
//                values[keyCounter] = CFNumberCreate(NULL,kCFNumberLongType,&Resolution);
//                keyCounter++;
//
//                keys[keyCounter] = kCGImagePropertyDPIHeight;
//                values[keyCounter] = CFNumberCreate(NULL,kCFNumberLongType,&Resolution);
//                keyCounter++;
                
                CFDictionaryRef options = CFDictionaryCreate(NULL,keys,values,keyCounter,&kCFTypeDictionaryKeyCallBacks,&kCFTypeDictionaryValueCallBacks);
                CGImageDestinationAddImage(outImageDestRef,inImageRef, options);
                CFRelease(options);
                status = CGImageDestinationFinalize(outImageDestRef);
                if(status == true)
                {
                    UInt8 *destImagePtr = CFDataGetMutableBytePtr(destDataRef);
                    destSize = CFDataGetLength(destDataRef);
                    //using destImagePtr after this ...
                }

                CFRelease(outImageDestRef);
            }
            
            for(long cnt = kzero; cnt < keyCounter; cnt++)
                if(values[cnt])
                    CFRelease(values[cnt]);

            if(inImageRef)
                CGImageRelease(inImageRef);
        }
image png core-graphics image-compression
1个回答
0
投票

我向苹果开发团队寻求帮助并从他们那里得到了解决方案。我正在分享他们分享的示例代码,该代码按预期工作。

{ // 在此处插入代码来初始化您的应用程序

    CFStringRef dstImageFormatStrRef = NULL;

    /* load the source image */
    NSDictionary * myOptions = @{
        (id)kCGImageSourceShouldAllowFloat : @YES,
        (id)kCGImageSourceShouldCache : @YES,
    };
    NSURL *input_file = [[NSBundle mainBundle] URLForResource:@"dogcow2021b" withExtension:@"png"];
    CGImageSourceRef myImageSource = CGImageSourceCreateWithURL((CFURLRef)input_file, (CFDictionaryRef)myOptions);

    CGImageRef inImageRef = CGImageSourceCreateImageAtIndex(myImageSource, 0, NULL);

    if(inImageRef)
    {
        dstImageFormatStrRef = CFSTR("public.png");
        long png_filters[] = {IMAGEIO_PNG_FILTER_SUB, IMAGEIO_PNG_FILTER_UP, IMAGEIO_PNG_FILTER_AVG, IMAGEIO_PNG_FILTER_PAETH};
        NSMutableData * result_file_data[5];
        
        NSMutableDictionary * options = [NSMutableDictionary dictionary];
        NSMutableDictionary * png_options = [NSMutableDictionary dictionary];
        options[(id)kCGImagePropertyPNGDictionary] = png_options;

        for (int i = 0; i < sizeof(png_filters)/sizeof(long); i++ ) {
            
            result_file_data[i] = [NSMutableData data];

            long png_filter = 0;
            //for (int loop = 0; loop <= i; loop++)
                png_filter = png_filters[i];
            png_options[(id)kCGImagePropertyPNGCompressionFilter] = @(png_filter);

            NSLog(@"#%3d trying png filter %ld", i, png_filter);
            
            CGImageDestinationRef outImageDestRef = CGImageDestinationCreateWithData((CFMutableDataRef)result_file_data[i], dstImageFormatStrRef, 1, NULL);
                        
            CGImageDestinationAddImage(outImageDestRef,inImageRef, (CFDictionaryRef)options);

            int status = CGImageDestinationFinalize(outImageDestRef);
            if(status == true)
            {
                CFIndex aSize = result_file_data[i].length;
                NSLog(@"     created an image of size '%ld'", aSize);
                if (i > 0) {
                    CFIndex bSize = result_file_data[i-1].length;
                    if ( aSize == bSize ) {
                        // if the size is the same, do a byte by byte comparison.
                        const uint8_t *B = [result_file_data[i-1] bytes];
                        const uint8_t *A = [result_file_data[i] bytes];
                        CFIndex sameBytes = 0;
                        CFIndex differentBytes = 0;
                        
                        for (CFIndex k = 0; k < aSize; k++ ) { // memcmp but counting different bytes
                            if ( A[k] == B[k] ) {
                                sameBytes++;
                            } else {
                                differentBytes++;
                            }
                        }
                        NSLog(@"(%ld bytes identical to previous, %ld bytes different than previous)", sameBytes, differentBytes);
                    } else {
                        NSLog(@"(images have different sizes '%ld' vs '%ld')", aSize, bSize);
                    }
                }
            }
            
            CFRelease(outImageDestRef);
            
        }
        
        CGImageRelease(inImageRef);
    }
}

 
© www.soinside.com 2019 - 2024. All rights reserved.