C4 saving part of an image

2019-02-27 17:39发布

Hei, I went through the example for saving images and afterwards I wanted to save only a part of the screen. I managed to save the part starting at the upper left corner of the image but I actually want to save the center of my screen. The magic to save only a part of an image is setting up the Graphics Context with a certain size, like this:

 UIGraphicsBeginImageContextWithOptions(CGSizeMake(300, 300), YES, 5.0f);

I thought there might be a way to use a CGRect instead of the size, but that gives me an error. any other attempts or thoughts? Do I have to go through the pixels of my screenshot, grab those needed and make a new image out of that (that would be the kind of complicated way I can think of but maybe there is an easier one)?

3条回答
我欲成王,谁敢阻挡
2楼-- · 2019-02-27 18:04

To do this with C4Image objects, you can modify incmiko's answer to look like the following:

#import "C4Workspace.h"

@implementation C4WorkSpace{
    C4Image *image;
    C4Image *croppedImage;
}

-(void)setup {
    image=[C4Image imageNamed:@"C4Sky.png"];
    image.origin=CGPointMake(0, 20);

    croppedImage = [self cropImage:image toArea:CGRectMake(150,50,100,100)];
    croppedImage.origin = CGPointMake(20, 360);
    [self.canvas addObjects:@[image,croppedImage]];
}

-(C4Image *)cropImage:(C4Image *)originalImage toArea:(CGRect)rect{
    //grab the image scale
    CGFloat scale = originalImage.UIImage.scale;

    //begin an image context
    UIGraphicsBeginImageContextWithOptions(rect.size, NO, scale);

    //create a new context ref
    CGContextRef c = UIGraphicsGetCurrentContext();

    //shift BACKWARDS in both directions because this moves the image
    //the area to crop shifts INTO: (0, 0, rect.size.width, rect.size.height)
    CGContextTranslateCTM(c, -rect.origin.x, -rect.origin.y);

    //render the original image into the context
    [originalImage renderInContext:c];

    //grab a UIImage from the context
    UIImage *newUIImage = UIGraphicsGetImageFromCurrentImageContext();

    //end the image context
    UIGraphicsEndImageContext();

    //create a new C4Image
    C4Image *newImage = [C4Image imageWithUIImage:newUIImage];

    //return the new image
    return newImage;
}
@end

Aside from the comments in the code there are a couple other things to be aware of:

  1. The "area" you're cropping will always be in reference to the "image" that you're cropping. So, if you want to crop {150,50} from the image, and the image's origin is at {20,20} then it will LOOK like you are cropping {170,70} from the CANVAS.

  2. The C4Image object actually has a renderInContext: method, so you don't have to do this from the image's layer.

  3. C4Image objects wrap UIImage objects, which is why we build a new one using the UIImage that we get from the current context

查看更多
祖国的老花朵
3楼-- · 2019-02-27 18:13

a little modification to Travis' answer makes it independent from the image but dependent on the canvas origin:

-(C4Image *)cropImage:(C4Image *)originalImage withOrigin:(CGPoint)origin toArea:(CGRect)rect{
    //grab the image scale
    CGFloat scale = originalImage.UIImage.scale;

    //begin an image context
    UIGraphicsBeginImageContextWithOptions(rect.size, NO, scale);

    //create a new context ref
    CGContextRef c = UIGraphicsGetCurrentContext();

    //shift BACKWARDS in both directions because this moves the image
    //the area to crop shifts INTO: (0, 0, rect.size.width, rect.size.height)
    CGContextTranslateCTM(c, origin.x-rect.origin.x, origin.y-rect.origin.y);

    //render the original image into the context
    [originalImage renderInContext:c];

    //grab a UIImage from the context
    UIImage *newUIImage = UIGraphicsGetImageFromCurrentImageContext();

    //end the image context
    UIGraphicsEndImageContext();

    //create a new C4Image
    C4Image *newImage = [C4Image imageWithUIImage:newUIImage];

    //return the new image
    return newImage;
}
查看更多
爷、活的狠高调
4楼-- · 2019-02-27 18:26

This method what I wrote for this is works perfectly:

+ (UIImage*) getTheArea:(CGRect)area inView:(UIView*)view{

    if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)])
        UIGraphicsBeginImageContextWithOptions(CGSizeMake(area.size.width, area.size.height), NO, [UIScreen mainScreen].scale);
    else
        UIGraphicsBeginImageContext(view.bounds.size);

    CGContextRef c = UIGraphicsGetCurrentContext();
    CGContextTranslateCTM(c, -area.origin.x, -area.origin.y);    // <-- shift everything up by 40px when drawing.
    [view.layer renderInContext:c];
    UIImage* thePrintScreen = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return thePrintScreen;
}

for example, if you want to make a printscreen of your main view, in (100,50,100,100)

UIImage* image = [self getTheArea:CGRectMake(100,50,100,100) inView:view];
查看更多
登录 后发表回答