Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
259 views
in Technique[技术] by (71.8m points)

uiimage - Cropping image with transparency in iPhone

I am working on Jigsaw type of game where i have two images for masking, I have implemented this code for masking

- (UIImage*) maskImage:(UIImage *)image withMaskImage:(UIImage*)maskImage {

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGImageRef maskImageRef = [maskImage CGImage];

    CGContextRef mainViewContentContext = CGBitmapContextCreate (NULL, maskImage.size.width, maskImage.size.height, 8, 0, colorSpace, kCGImageAlphaPremultipliedLast);

    if (mainViewContentContext==NULL)
        return NULL;

    CGFloat ratio = 0;
    ratio = maskImage.size.width/ image.size.width;
    if(ratio * image.size.height < maskImage.size.height) {
        ratio = maskImage.size.height/ image.size.height;
    } 

    CGRect rect1 = {{0, 0}, {maskImage.size.width, maskImage.size.height}};
    CGRect rect2  = {{-((image.size.width*ratio)-maskImage.size.width)/2,-((image.size.height*ratio)-maskImage.size.height)/2},{image.size.width*ratio, image.size.height*ratio}};

    CGContextClipToMask(mainViewContentContext, rect1, maskImageRef);
    CGContextDrawImage(mainViewContentContext, rect2, image.CGImage);

    CGImageRef newImage = CGBitmapContextCreateImage(mainViewContentContext);
    CGContextRelease(mainViewContentContext);

    UIImage *theImage = [UIImage imageWithCGImage:newImage];
    CGImageRelease(newImage);
    return theImage;
}

enter image description here

+

enter image description here

=

This is final result i got after masking.

enter image description here

now i would like to crop image in piece like enter image description here and enter image description here and so on parametrically(crop an image by transparency).

if any one has implemented such code or any idea on this scenario please share.

Thanks.

I am using this line of code for as Guntis Treulands's suggestion

int i=1;
    for (int x=0; x<=212; x+=106) {
        for (int y=0; y<318; y+=106) {
            CGRect rect = CGRectMake(x, y, 106, 106);
            CGRect rect2x = CGRectMake(x*2, y*2, 212, 212);

            UIImage *orgImg = [UIImage imageNamed:@"cat@2x.png"];
            UIImage *frmImg = [UIImage imageNamed:[NSString stringWithFormat:@"%d@2x.png",i]];
            UIImage *cropImg = [self cropImage:orgImg withRect:rect2x];

            UIImageView *tmpImg = [[UIImageView alloc] initWithFrame:rect];
            [tmpImg setUserInteractionEnabled:YES];
            [tmpImg setImage:[self maskImage:cropImg withMaskImage:frmImg]];

            [self.view addSubview:tmpImg];
            i++;
        }
    }

orgImg is original cat image, frmImg frame for holding individual piece, masked in photoshop and cropImg is 106x106 cropped image of original cat@2x.png.

my function for cropping is as following

- (UIImage *) cropImage:(UIImage*)originalImage withRect:(CGRect)rect { 
    return [UIImage imageWithCGImage:CGImageCreateWithImageInRect([originalImage CGImage], rect)]; 
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

UPDATE 2

I became really curious to find a better way to create a Jigsaw puzzle, so I spent two weekends and created a demo project of Jigsaw puzzle.

It contains:

  • provide column/row count and it will generate necessary puzzle pieces with correct width/height. The more columns/rows - the smaller the width/height and outline/inline puzzle form.
  • each time generate randomly sides
  • can randomly position / rotate pieces at the beginning of launch
  • each piece can be rotated by tap, or by two fingers (like a real piece) - but once released, it will snap to 90/180/270/360 degrees
  • each piece can be moved if touched on its “touchable shape” boundary (which is mostly the - same visible puzzle shape, but WITHOUT inline shapes)

Drawbacks:

  • no checking if piece is in its right place
  • if more than 100 pieces - it starts to lag, because, when picking up a piece, it goes through all subviews until it finds correct piece.

UPDATE

Thanks for updated question.

I managed to get this:

enter image description here

As you can see - jigsaw item is cropped correctly, and it is in square imageView (green color is UIImageView backgroundColor).

So - what I did was:

CGRect rect = CGRectMake(105, 0, 170, 170); //~ location on cat image where second Jigsaw item will be.

UIImage *originalCatImage = [UIImage imageNamed:@"cat.png"];//original cat image

UIImage *jigSawItemMask = [UIImage imageNamed:@"JigsawItemNo2.png"];//second jigsaw item mask (visible in my answer) (same width/height as cat image.)

UIImage *fullJigSawItemImage = [jigSawItemMask maskImage:originalCatImage];//masking - so that from full cat image would be visible second jigsaw item

UIImage *croppedJigSawItemImage = [self fullJigSawItemImage withRect:rect];//cropping so that we would get small image with jigsaw item centered in it.

For image masking I am using UIImage category function: (but you can probably use your masking function. But I'll post it anyways.)

- (UIImage*) maskImage:(UIImage *)image  
{     
     CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

     UIImage *maskImage = self;
     CGImageRef maskImageRef = [maskImage CGImage];

     // create a bitmap graphics context the size of the image
     CGContextRef mainViewContentContext = CGBitmapContextCreate (NULL, maskImage.size.width, maskImage.size.height, 8, 0, colorSpace, kCGImageAlphaPremultipliedLast);


     if (mainViewContentContext==NULL)
          return NULL;

     CGFloat ratio = 0;

     ratio = maskImage.size.width/ image.size.width;

     if(ratio * image.size.height < maskImage.size.height) {
          ratio = maskImage.size.height/ image.size.height;
     } 

     CGRect rect1  = {{0, 0}, {maskImage.size.width, maskImage.size.height}};
     CGRect rect2  = {{-((image.size.width*ratio)-maskImage.size.width)/2 , -((image.size.height*ratio)-maskImage.size.height)/2}, {image.size.width*ratio, image.size.height*ratio}};


     CGContextClipToMask(mainViewContentContext, rect1, maskImageRef);
     CGContextDrawImage(mainViewContentContext, rect2, image.CGImage);


     // Create CGImageRef of the main view bitmap content, and then
     // release that bitmap context
     CGImageRef newImage = CGBitmapContextCreateImage(mainViewContentContext);
     CGContextRelease(mainViewContentContext);

     UIImage *theImage = [UIImage imageWithCGImage:newImage];

     CGImageRelease(newImage);

     // return the image
     return theImage;
}

PREVIOUS ANSWER

Can you prepare a mask for each piece?

For example, you have that frame image. Can you cut it in photoshop in 9 separate images, where in each image it would only show corresponding piece. (all the rest - delete).

Example - second piece mask:

enter image description here

Then you use each of these newly created mask images on cat image - each piece will mask all image, but one peace. Thus you will have 9 piece images using 9 different masks.

For larger or different jigsaw frame - again, create separated image masks.

This is a basic solution, but not perfect, as you need to prepare each peace mask separately.

Hope it helps..


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...