Search code examples
xcodeimageresizetilecgimageref

How do I use CGImageRef to loop over parts of an image that has been resized without increasing pixelation?


I am trying to create an effect that looks as if 2 images are woven into each other. So I scaled the first image to be the background and I am looping over the second image using several UIIMageViews on top of the background to give my desired look. This works when I use images that don't need to be scaled to fit and are the size of my display but when I am using UIGraphics to resize the image I am getting a problem where the image loses quality. Any suggestions would be greatly appreciated.

Image 1.jpg is 2112 × 2816

Image 2.jpg is 2000 × 3008

UIImage *bgImage = [UIImage imageNamed:@"1.jpg"];
UIImageView *bgView = [[UIImageView alloc] initWithImage:bgImage];
bgView.contentMode = UIViewContentModeScaleToFill;
bgView.frame = CGRectMake(0,0,CGRectGetWidth(self.view.frame), (CGRectGetWidth(self.view.frame) / bgImage.size.width) * bgImage.size.height);

bgView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
[self.view addSubview:bgView];

UIImage *frontImage = [UIImage imageNamed:@"2.jpg"];
CGSize newSize = CGSizeMake(CGRectGetWidth(self.view.frame), (CGRectGetWidth(self.view.frame)/frontImage.size.width) * frontImage.size.height);
UIGraphicsBeginImageContextWithOptions(newSize, YES, 0.0);
[frontImage drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

int count = 0;
int varX = 10;
int varY = 10;

CGFloat width = self.view.frame.size.width;
CGFloat height = self.view.frame.size.height;
CGFloat tileWidth = width / varX;
CGFloat tileHeight = height / varY;

for (int x = 0; x < varX; x++) {
    for (int y = 0; y < varY; y++) {

        NSLog(@"%f, %f, %f, %f",x*tileWidth, y*tileHeight, tileWidth, tileHeight);

        CGImageRef scaledRef = CGImageCreateWithImageInRect(scaledImage.CGImage, CGRectMake(x*tileWidth, y*tileHeight, tileWidth, tileHeight));
        UIImage *image = [UIImage imageWithCGImage:scaledRef scale:scaledImage.scale orientation:scaledImage.imageOrientation];
        UIImageView *bgx = [[UIImageView alloc] initWithImage:image];
        CGImageRelease(scaledRef);

        bgx.frame = CGRectMake((x*tileWidth), (y*tileHeight), tileWidth, tileHeight);
        bgx.backgroundColor = [UIColor yellowColor];
        bgx.contentMode = UIViewContentModeTopLeft;

        if(count%2==0){
            [self.view addSubview:bgx];
        }
        count++;
    }
    count++;
}

Solution

  • I was able to fix my issue by changing the second line in my loop to:

     CGImageRef scaledRef = CGImageCreateWithImageInRect(scaledImage.CGImage, CGRectMake(x*(tileWidth*2), y*(tileHeight*2), tileWidth*2, tileHeight*2));
    

    My previous output was off by a factor of 2 but I don't know why that was the case to start off with.

    Any insight is appreciated.