2

If I have a UIImage and I convert is to NSData I can see how many bytes it is.

If I have a variable requiredSize and I want to set that UIImage to a certain length and width so that when it is rendered as a PNG-file NSData UIImagePNGRepresentation(); it is a certain byte-size (requiredSize). How do I go about doing this.


I know how to get the current byte size [NSData length];


And I know how to downscale a UIImage (If there's a better way please tell me)

    //UIImage *tempImage = whateverTheImagePointerIs;

    int tempWidth = tempImage.size.width/2;//50% width of original
    int tempHeight = tempImage.size.height/2;//50% height of original
    UIImageView *tempImageRender = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, tempWidth, tempHeight)];

    tempImageRender.image = tempImage;


    UIGraphicsBeginImageContextWithOptions(tempImageRender.bounds.size, tempImageRender.opaque, 1.0);
    [tempImageRender.layer renderInContext:UIGraphicsGetCurrentContext()];

    UIImage *tempFinalImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

But when I scale it by 50% on width and 50% on height (25% net-total) the final bytes of the new rendered scaled image (when converted to PNG using UIImagePNGRepresentation();) is not 25% of the original bytes... it seems to just be random (I'm sure this is happening because PNG compression algorithms change with image quality/size.)


Is there no way to resize an image to a given byte size?

Albert Renshaw
  • 17,282
  • 18
  • 107
  • 195
  • @rmaddy What you posted uses a recursive formula that resizes then renders an image with a while-loop until it is beneath a certain size. For one this is incredibly slow, for two this also doesn't answer my question.. this could get me a .4mB file when I need a .6mB file. I want to set a file size, not recursively compress until I've gone below a "maximum". – Albert Renshaw Apr 28 '14 at 22:27
  • There is no direct way to get what you want. There is no method that says "scale the image so the resulting PNG data will be X bytes". – rmaddy Apr 28 '14 at 22:28
  • @AlbertRenshaw Since PNG compression doesn't scale with image size, there's no way to do it that isn't iterative. – David Berry Apr 28 '14 at 22:29
  • @David Do either of you know an image format that doesn't compress (unlike PNG) that I can render in Objective-C as NSData that way I don't have to deal with this? Thanks! – Albert Renshaw Apr 28 '14 at 22:30
  • 1
    @AlbertRenshaw If you're limited to how many bytes you can upload, why would you want to use a non-compressing storage format? – David Berry Apr 28 '14 at 22:32
  • @David I'm not limited to how many bytes I can use... I need to have the file size an exact number of bytes (or very close at least) – Albert Renshaw Apr 28 '14 at 22:41
  • If your goal is to generate an image file with the most consistent/predictable size, try something like BMP or just raw image data. Unfortunately, neither of those can be directly generated by iOS. – David Berry Apr 28 '14 at 22:45

1 Answers1

-1

See this answer for how to scale an image fairly effectively:

As you've discovered, there really isn't a direct correlation between image size and data size when compressed, you'll just have to do it iteratively:

-(NSData*)pngRepresentationWithMaxSize:(NSInteger)maxSize
{
    UIImage*    image = self;

    while(1)
    {
        NSData* data = UIImagePNGRepresentation(image);
        if(data.length < maxSize)
            return data;
        CGSize  size = image.size;

        image = [UIImage imageScaledToSize:CGSizeMake(image.size.width / 2., image.size.height / 2.)];
    }

    return nil;
}

Note that I assume you change the referenced scaling code to be a category method on UIImage and put the method above into a UIImage category as well.

Community
  • 1
  • 1
David Berry
  • 40,941
  • 12
  • 84
  • 95