简体   繁体   中英

Change NSData Size of a UIImage - Compress And Resize UIImage With a Maximum Megabyte Mb limit

I have a UIImage that the user has uploaded.

If the image data is more than 10Mb how can I resize it to a maximum of 10 Mb? So far the closest thing I've found for data resizing is this:

NSData *imageData = UIImageJPEGRepresentation(theUploadedImage.image, 0.5f);

But I don't seem to have control over the Mb of file size... just over the second parameter in the JPG representation (image quality float)

Had to create my own function that compresses an image as small as it can get, and if it's still over my "max size" then it resizes, reserves and begins the compression iteration again. This does a fairly good job of getting the image as close as possible to target "max image file size" if it's over the file size. Also includes a failsafe after 1024 iterations. (Which should never last longer than a minute (but that's a scenario that would never occour... who uses images that are gigabytes on an iPhone? Haha))...

-(void)shrinkImage {


    //IMPORTANT!!! THIS CODE WAS CREATED WITH "ARC" IN MIND... DO NOT USE WITHOUT ARC UNLESS YOU ALTER THIS CODE TO MANAGE MEMORY


    float compressionVal = 1.0;
    float maxVal = 9.7;//MB

    UIImage *compressedImage = theUploadedImage.image; //get UIImage from imageView

    int iterations = 0;
    int totalIterations = 0;

    float initialCompressionVal = 0.00000000f;

    while (((((float)(UIImageJPEGRepresentation(compressedImage, compressionVal).length))/(1048576.000000000f)) > maxVal) && (totalIterations < 1024)) {

        NSLog(@"Image is %f MB", (float)(((float)(UIImageJPEGRepresentation(compressedImage, compressionVal)).length)/(1048576.000000f)));//converts bytes to MB

        compressionVal = (((compressionVal)+((compressionVal)*((float)(((float)maxVal)/((float)(((float)(UIImageJPEGRepresentation(compressedImage, compressionVal).length))/(1048576.000000000f)))))))/(2));
        compressionVal *= 0.97;//subtracts 3% of it's current value just incase above algorithm limits at just above MaxVal and while loop becomes infinite.

        if (initialCompressionVal == 0.00000000f) {
            initialCompressionVal = compressionVal;
        }

        iterations ++;

        if ((iterations >= 3) || (compressionVal < 0.1)) {
            iterations = 0;
            NSLog(@"%f", compressionVal);

            compressionVal = 1.0f;


            compressedImage = [UIImage imageWithData:UIImageJPEGRepresentation(compressedImage, compressionVal)];



            float resizeAmount = 1.0f;
            resizeAmount = (resizeAmount+initialCompressionVal)/(2);//percentage
            resizeAmount *= 0.97;//3% boost just incase image compression algorithm reaches a limit.
            resizeAmount = 1/(resizeAmount);//value
            initialCompressionVal = 0.00000000f;


            UIView *imageHolder = [[UIView alloc] initWithFrame:CGRectMake(0,0,(int)floorf((float)(compressedImage.size.width/(resizeAmount))), (int)floorf((float)(compressedImage.size.height/(resizeAmount))))];//round down to ensure frame isnt larger than image itself

            UIImageView *theResizedImage = [[UIImageView alloc] initWithFrame:CGRectMake(0,0,(int)ceilf((float)(compressedImage.size.width/(resizeAmount))), (int)ceilf((float)(compressedImage.size.height/(resizeAmount))))];//round up to ensure image fits
            theResizedImage.image = compressedImage;


            [imageHolder addSubview:theResizedImage];


            UIGraphicsBeginImageContextWithOptions(CGSizeMake(imageHolder.frame.size.width, imageHolder.frame.size.height), YES, 1.0f);
            CGContextRef resize_context = UIGraphicsGetCurrentContext();
            [imageHolder.layer renderInContext:resize_context];
            compressedImage = UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();


            //after 3 compressions, if we still haven't shrunk down to maxVal size, apply the maximum compression we can, then resize the image (90%?), then re-start the process, this time compressing the compressed version of the image we were checking.

            NSLog(@"resize");
        }

        totalIterations ++;

    }

    if (totalIterations >= 1024) {
        NSLog(@"Image was too big, gave up on trying to re-size");//too many iterations failsafe. Gave up on trying to resize.
    } else {

        NSData *imageData = UIImageJPEGRepresentation(compressedImage, compressionVal);
        NSLog(@"FINAL Image is %f MB ... iterations: %i", (float)(((float)imageData.length)/(1048576.000000f)), totalIterations);//converts bytes to MB

        theUploadedImage.image = [UIImage imageWithData:imageData];//save new image to UIImageView.

    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM