2

So here's the gist I've got a program that has a large image composed of many little images and it takes this image and separates it into many smaller images (like frames for a film) that the user can then go and scrub through.

I currently use this method

- (NSMutableArray *)createArrayFromImage: (NSData *)largerImageData
{
    UIImage *largerImage = [UIImage imageWithData: largerImageData];
    int arraySize = (int)largerImage.size.height/largerImage.size.width; //Find out how many images there are
    NSMutableArray *imageArray = [[NSMutableArray alloc] init];
    for (int i = 0; i < arraySize; i++) {

        CGRect cropRect = CGRectMake(0, largerImage.size.width * i, largerImage.size.width, largerImage.size.width);
        CGImageRef imageRef = CGImageCreateWithImageInRect([largerImage CGImage], cropRect);
        UIImage *image = [UIImage imageWithCGImage: imageRef];
        CGImageRelease(imageRef);

        [imageArray addObject: UIImageJPEGRepresentation(image, 1.0)];
        NSLog(@"Added image %d", i);
    }

    NSLog(@"Final size %d", (int)[imageArray count]);
    return imageArray;
}

However this is extremely slow due to UIImageJPEGRepresentation being called and is much faster if I just add the UIImage directly into the array however when I do this when the user scrubs through the images from the array it starts allocating huge amounts of memory forcing the app to eventually crash. It calls [UIImageView setImage:]; if that helps. Any assistance with this would be extremely appreciated.

ED|T: CGImageCreateWithImageInRect might keep the "largerImage" which causes it to take up so much memory

What what
  • 527
  • 4
  • 15
  • Is the posted code the working-but-slow version? – nhgrif Jul 13 '14 at 22:53
  • Also, there's not a `setImage:` method on `UIImage`, so I can only assume you're talking about a `UIImageView`. – nhgrif Jul 13 '14 at 23:02
  • Yes and yes to both questions – What what Jul 13 '14 at 23:05
  • The code is slow because of the UIImageJPEGRepresentation being called – What what Jul 13 '14 at 23:06
  • `int arraySize = (int)largerImage.size.height/largerImage.size.width; //Find out how many images there are` How can that be right? If the larger image is 1000x1000 there is only one image (1000/1000) but if it is 1x5 there are five images (5/1)? – matt Jul 14 '14 at 11:56
  • Ahh... It's a vertical strip of images that all have a 1:1 ratio so that part works fine, it's irrelevant to the memory problem – What what Jul 14 '14 at 12:03

2 Answers2

1

Essentially, your goal seems to show specific portions of an image to users randomly.

You don't have to create smaller images if what you want to do is just showing the smaller portion of an image. Especially if the large image is loadable into memory at once. Instead try view clipping to adjust visible portion of the image.

For example, you can try this.

  1. Set large image to an UIImageView and sizeToFit.
  2. Put the image-view inside of a UIView.
  3. Set frame of UIView to a small image size.
  4. clipsToBounds of outer UIView to YES.
  5. Adjust transform of inner UIImageView to control visible portion.

This is essentially same with what you do with UIScrollView except automatic scroll by user interaction.

Here's a code example.

- (void)viewDidLoad {
    [super viewDidLoad];

    UIImageView*    v1  =   [[UIImageView alloc] init];
    [v1 setImage:[UIImage imageWithContentsOfFile:@"large-image.png"]];
    [v1 sizeToFit];

    UIView* v2  =   [[UIView alloc] init];
    [v2 setFrame:CGRectMake(0, 0, 100, 100)];
    [v2 addSubview:v1];
    [v2 setClipsToBounds:YES];

    // Set transform later to adjust visible portion.
    v1.transform    =   CGAffineTransformMakeTranslation(-100, -100);

    [self.view addSubview:v2];
}
eonil
  • 83,476
  • 81
  • 317
  • 516
0

Instead to use in memory small images try to save this images to DB if they are small size. But I don't understand why you need to crop a big image to a small images? You can ZOOM and Preview small part of image with CATiledLayer and you need only the CGRect of that part.

Voda Ion
  • 3,426
  • 2
  • 16
  • 18