PNG Compression - ImageIO

Hello All,

I am trying to compress PNG image by applying PNG Filters like(Sub, Up, Average, Paeth), I am applying filers using property kCGImagePropertyPNGCompressionFilter but there is no change seen in resultant images after trying any of the filter. What is the issue here can someone help me with this. Do I have compress image data after applying filter? If yes how to do that?

Here is my source code

        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);
        }

Replies

You're supposed to just run each algorithm per row, and then take the smallest one. There's little point in using one algorithm for the entire image. PNG lets you store the lossless algorithm type as the first byte of each row. I've always used my own png code instead of Apple's.

You can try using https://combokit.net/tiny-png for compress image like png, jpeg, svg, gif,... and get file size reduce upto 90%.