I have searched this forum several times now, and i do not seem to find an answer to my problem.
Other people have asked the same question already but i'm under the impression the problem is not as easy to solve.
Basically what i am trying to do is the following,
I would like to put a layer on top of a picture, and then erase that layer through touches or accelerometer movement, 'scratching away' the place where a touch has occured.
Like this:
Now i have got this working like this:
Code:
- (void)drawRect:(CGRect)rect {
// Retrieve the graphics context
CGContextRef context = UIGraphicsGetCurrentContext();
//Get the drawing image
CGImageRef maskImage = [self drawImageWithContext:context inRect:rect];
// Get the mask from the image
CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskImage)
, CGImageGetHeight(maskImage)
, CGImageGetBitsPerComponent(maskImage)
, CGImageGetBitsPerPixel(maskImage)
, CGImageGetBytesPerRow(maskImage)
, CGImageGetDataProvider(maskImage)
, NULL
, false);
//make sure the images are not upside down
CGContextTranslateCTM(context, 0, self.bounds.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
//Draw the base picture
CGContextDrawLayerInRect(context, rect, firstLayer);
//Add clipping
CGContextClipToMask(context, rect, mask);
//Release the mask
CGImageRelease(mask);
//Release the maskImage
CGImageRelease(maskImage);
//draw the second layer
CGContextDrawLayerInRect(context, rect, secondLayer);
}
As you can see i have a drawrect method, where i make an image based on the touches. This image is being used to get an imageMask.
I draw the first picture, lay down the mask, and then draw the second picture.
This works effectively resolving my problem.
But there are two drawbacks:
1) If i draw another thing over my last picture, this is also clipped...
2) Perhaps the most important thing, when i call my drawrect several times (from accelerometer), i lose performance, making the application impossible to use...
So basically my question is,
is there another way on resolving my problem? Do i need to look at this another way? Do i need to copy paste pixels?
Do i need alpha blending? Or do i need to look at OpenGL?
I'm hoping somebody can finally shed some light on this, because i'm really sitting in the dark here...
you might find this easier to implement in openGL using alpha blending, check out the GLPaint demo that apple has. You basically want to do this, but inversed.
I am trying to achieve the same thing you mentioned. I posted my question on this forum only but didn't get any answer unfortunately.
I tried to understand the code snippet you have posted but it seems that it is not complete and being a newbie to the iPhone App Dev, was not able to understand it wholly.
Would you mind sharing the complete code for me to understand the context? This would help me greatly in learning the masking thing.
Thanks in advance,
iTroy
Quote:
Originally Posted by flux
Hi Everyone,
I have searched this forum several times now, and i do not seem to find an answer to my problem.
Other people have asked the same question already but i'm under the impression the problem is not as easy to solve.
Basically what i am trying to do is the following,
I would like to put a layer on top of a picture, and then erase that layer through touches or accelerometer movement, 'scratching away' the place where a touch has occured.
Like this:
Now i have got this working like this:
Code:
- (void)drawRect:(CGRect)rect {
// Retrieve the graphics context
CGContextRef context = UIGraphicsGetCurrentContext();
//Get the drawing image
CGImageRef maskImage = [self drawImageWithContext:context inRect:rect];
// Get the mask from the image
CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskImage)
, CGImageGetHeight(maskImage)
, CGImageGetBitsPerComponent(maskImage)
, CGImageGetBitsPerPixel(maskImage)
, CGImageGetBytesPerRow(maskImage)
, CGImageGetDataProvider(maskImage)
, NULL
, false);
//make sure the images are not upside down
CGContextTranslateCTM(context, 0, self.bounds.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
//Draw the base picture
CGContextDrawLayerInRect(context, rect, firstLayer);
//Add clipping
CGContextClipToMask(context, rect, mask);
//Release the mask
CGImageRelease(mask);
//Release the maskImage
CGImageRelease(maskImage);
//draw the second layer
CGContextDrawLayerInRect(context, rect, secondLayer);
}
As you can see i have a drawrect method, where i make an image based on the touches. This image is being used to get an imageMask.
I draw the first picture, lay down the mask, and then draw the second picture.
This works effectively resolving my problem.
But there are two drawbacks:
1) If i draw another thing over my last picture, this is also clipped...
2) Perhaps the most important thing, when i call my drawrect several times (from accelerometer), i lose performance, making the application impossible to use...
So basically my question is,
is there another way on resolving my problem? Do i need to look at this another way? Do i need to copy paste pixels?
Do i need alpha blending? Or do i need to look at OpenGL?
I'm hoping somebody can finally shed some light on this, because i'm really sitting in the dark here...
Instead of actually erasing part of the image you touch, you could copy a circular part of another (hidden) picture to top of the image you're touching?
Instead of actually erasing part of the image you touch, you could copy a circular part of another (hidden) picture to top of the image you're touching?
Just a thought...
How do you copy a part of an image to the top of the image showing?
Did you get lucky with the masking of image with gestures over a background image. I'm hitting with a similar requirement and would appreciate your thoughts for the same.
Cheers
Evan
Quote:
Originally Posted by flux
Hi Everyone,
I have searched this forum several times now, and i do not seem to find an answer to my problem.
Other people have asked the same question already but i'm under the impression the problem is not as easy to solve.
Basically what i am trying to do is the following,
I would like to put a layer on top of a picture, and then erase that layer through touches or accelerometer movement, 'scratching away' the place where a touch has occured.
Like this:
Now i have got this working like this:
Code:
- (void)drawRect:(CGRect)rect {
// Retrieve the graphics context
CGContextRef context = UIGraphicsGetCurrentContext();
//Get the drawing image
CGImageRef maskImage = [self drawImageWithContext:context inRect:rect];
// Get the mask from the image
CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskImage)
, CGImageGetHeight(maskImage)
, CGImageGetBitsPerComponent(maskImage)
, CGImageGetBitsPerPixel(maskImage)
, CGImageGetBytesPerRow(maskImage)
, CGImageGetDataProvider(maskImage)
, NULL
, false);
//make sure the images are not upside down
CGContextTranslateCTM(context, 0, self.bounds.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
//Draw the base picture
CGContextDrawLayerInRect(context, rect, firstLayer);
//Add clipping
CGContextClipToMask(context, rect, mask);
//Release the mask
CGImageRelease(mask);
//Release the maskImage
CGImageRelease(maskImage);
//draw the second layer
CGContextDrawLayerInRect(context, rect, secondLayer);
}
As you can see i have a drawrect method, where i make an image based on the touches. This image is being used to get an imageMask.
I draw the first picture, lay down the mask, and then draw the second picture.
This works effectively resolving my problem.
But there are two drawbacks:
1) If i draw another thing over my last picture, this is also clipped...
2) Perhaps the most important thing, when i call my drawrect several times (from accelerometer), i lose performance, making the application impossible to use...
So basically my question is,
is there another way on resolving my problem? Do i need to look at this another way? Do i need to copy paste pixels?
Do i need alpha blending? Or do i need to look at OpenGL?
I'm hoping somebody can finally shed some light on this, because i'm really sitting in the dark here...
I have searched this forum several times now, and i do not seem to find an answer to my problem.
Other people have asked the same question already but i'm under the impression the problem is not as easy to solve.
Basically what i am trying to do is the following,
I would like to put a layer on top of a picture, and then erase that layer through touches or accelerometer movement, 'scratching away' the place where a touch has occured.
Like this:
Now i have got this working like this:
Code:
- (void)drawRect:(CGRect)rect {
// Retrieve the graphics context
CGContextRef context = UIGraphicsGetCurrentContext();
//Get the drawing image
CGImageRef maskImage = [self drawImageWithContext:context inRect:rect];
// Get the mask from the image
CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskImage)
, CGImageGetHeight(maskImage)
, CGImageGetBitsPerComponent(maskImage)
, CGImageGetBitsPerPixel(maskImage)
, CGImageGetBytesPerRow(maskImage)
, CGImageGetDataProvider(maskImage)
, NULL
, false);
//make sure the images are not upside down
CGContextTranslateCTM(context, 0, self.bounds.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
//Draw the base picture
CGContextDrawLayerInRect(context, rect, firstLayer);
//Add clipping
CGContextClipToMask(context, rect, mask);
//Release the mask
CGImageRelease(mask);
//Release the maskImage
CGImageRelease(maskImage);
//draw the second layer
CGContextDrawLayerInRect(context, rect, secondLayer);
}
As you can see i have a drawrect method, where i make an image based on the touches. This image is being used to get an imageMask.
I draw the first picture, lay down the mask, and then draw the second picture.
This works effectively resolving my problem.
But there are two drawbacks:
1) If i draw another thing over my last picture, this is also clipped...
2) Perhaps the most important thing, when i call my drawrect several times (from accelerometer), i lose performance, making the application impossible to use...
So basically my question is,
is there another way on resolving my problem? Do i need to look at this another way? Do i need to copy paste pixels?
Do i need alpha blending? Or do i need to look at OpenGL?
I'm hoping somebody can finally shed some light on this, because i'm really sitting in the dark here...
hello,
if you don't mind please send me drawImageWithContext Method, i have implement this functionality.
i had searched in google but i have not found appropriate result.
if you don't mind please send me drawImageWithContext Method, i have implement this functionality.
i had searched in google but i have not found appropriate result.
I have searched this forum several times now, and i do not seem to find an answer to my problem.
Other people have asked the same question already but i'm under the impression the problem is not as easy to solve.
Basically what i am trying to do is the following,
I would like to put a layer on top of a picture, and then erase that layer through touches or accelerometer movement, 'scratching away' the place where a touch has occured.
Like this:
Now i have got this working like this:
Code:
- (void)drawRect:(CGRect)rect {
// Retrieve the graphics context
CGContextRef context = UIGraphicsGetCurrentContext();
//Get the drawing image
CGImageRef maskImage = [self drawImageWithContext:context inRect:rect];
// Get the mask from the image
CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskImage)
, CGImageGetHeight(maskImage)
, CGImageGetBitsPerComponent(maskImage)
, CGImageGetBitsPerPixel(maskImage)
, CGImageGetBytesPerRow(maskImage)
, CGImageGetDataProvider(maskImage)
, NULL
, false);
//make sure the images are not upside down
CGContextTranslateCTM(context, 0, self.bounds.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
//Draw the base picture
CGContextDrawLayerInRect(context, rect, firstLayer);
//Add clipping
CGContextClipToMask(context, rect, mask);
//Release the mask
CGImageRelease(mask);
//Release the maskImage
CGImageRelease(maskImage);
//draw the second layer
CGContextDrawLayerInRect(context, rect, secondLayer);
}
As you can see i have a drawrect method, where i make an image based on the touches. This image is being used to get an imageMask.
I draw the first picture, lay down the mask, and then draw the second picture.
This works effectively resolving my problem.
But there are two drawbacks:
1) If i draw another thing over my last picture, this is also clipped...
2) Perhaps the most important thing, when i call my drawrect several times (from accelerometer), i lose performance, making the application impossible to use...
So basically my question is,
is there another way on resolving my problem? Do i need to look at this another way? Do i need to copy paste pixels?
Do i need alpha blending? Or do i need to look at OpenGL?
I'm hoping somebody can finally shed some light on this, because i'm really sitting in the dark here...
hi flux,
i have two images which are overlaping on each other.(the way in which cards are placed on top of each other)
now if i move my finger over the top most image that portion of the image should become transparent.(opacity of that part should become 0).
i have tried following code on touch moved event to achieve this functionality which is working fine.But problem with this code is i am not getting appropriate finishing in it.
Please help me out with the same masking (eraser) effect problem
Quote:
Originally Posted by smsawant
hi flux,
i have two images which are overlaping on each other.(the way in which cards are placed on top of each other)
now if i move my finger over the top most image that portion of the image should become transparent.(opacity of that part should become 0).
i have tried following code on touch moved event to achieve this functionality which is working fine.But problem with this code is i am not getting appropriate finishing in it.
-----
Hi,
Can you please provide me the same code to mask the image. I see the above code but didn't success to implement. So please give me that code snippet, it will be great help to me for my 3 days work effort.
Instead of actually erasing part of the image you touch, you could copy a circular part of another (hidden) picture to top of the image you're touching?
I'm with Nick - that's the smart way of doing it. Unless you want to have moving objects behind the mask, in which case you could write to the alpha component of the mask instead.
__________________
Visit Mr Jack Games for my blog and more about my games
- (void)drawRect:(CGRect)rect {
// Retrieve the graphics context
CGContextRef context = UIGraphicsGetCurrentContext();
//Get the drawing image
CGImageRef maskImage = [self drawImageWithContext:context inRect:rect];
// Get the mask from the image
CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskImage)
, CGImageGetHeight(maskImage)
, CGImageGetBitsPerComponent(maskImage)
, CGImageGetBitsPerPixel(maskImage)
, CGImageGetBytesPerRow(maskImage)
, CGImageGetDataProvider(maskImage)
, NULL
, false);
//make sure the images are not upside down
CGContextTranslateCTM(context, 0, self.bounds.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
//Draw the base picture
CGContextDrawLayerInRect(context, rect, firstLayer);
//Add clipping
CGContextClipToMask(context, rect, mask);
//Release the mask
CGImageRelease(mask);
//Release the maskImage
CGImageRelease(maskImage);
//draw the second layer
CGContextDrawLayerInRect(context, rect, secondLayer);
}
Hi, can you tell me how you did this ? revealing the photo behind the mask by drawing with the finger ? I gotta do some similar work, would be thankful if you can provide me some piece of code how you did this.
Thanks.
I recently needed to figure out how to implement a solution like this. Here is the code I use:
Code:
// This cropping method will render the imageToCrop into a new graphics context
// cropped by the greyscale image defined by cropToImage. The result is returned
// as a RGBA image. The result of this operation is an image where the greyscale
// pixel value is converted into the alpha channel for the pixels.
- (UIImage*)imageByCropping:(UIImage*)imageToCrop
cropToImage:(UIImage*)cropToImage
{
// create a context to do our clipping in
CGImageRef imageToCropRef = imageToCrop.CGImage;
CGImageRef cropToImageRef = cropToImage.CGImage;
size_t width = CGImageGetWidth(imageToCropRef);
size_t height = CGImageGetHeight(imageToCropRef);
CGSize size = CGSizeMake(width, height);
UIGraphicsBeginImageContext(size);
CGContextRef currentContext = UIGraphicsGetCurrentContext();
// Flip coordinate system
CGContextTranslateCTM(currentContext, 0.0, size.height);
CGContextScaleCTM(currentContext, 1.0, -1.0);
// Create a new image that is the size of the original image.
CGRect clippedRect = CGRectMake(0, 0, size.width, size.height);
CGContextClipToMask( currentContext, clippedRect, cropToImageRef);
CGRect drawRect = CGRectMake(0,
0,
imageToCrop.size.width,
imageToCrop.size.height);
// draw the image to our clipped context using our offset rect
CGContextDrawImage(currentContext, drawRect, imageToCrop.CGImage);
// pull the image from our cropped context
UIImage *cropped = UIGraphicsGetImageFromCurrentImageContext();
// pop the context to get back to the default
UIGraphicsEndImageContext();
// Note: this is autoreleased
return cropped;
}
The trick is to generate a mask image that is a grayscale image, then the white parts are transparent and the black parts can't be seen. Anything in between becomes the alpha channel for the resulting image.
Not sure if it's going to work, how about overlap another view on top which has clearColour as background color and/or the "alpha" thing if required, then fill the top layer with that green colour as background, then use the touch action to erase that green background color (replace it with "clear colour") ?
As in this way, the image is left untouched in the lower layer, while the top layer is been updated.
I created a test project which might be able to achieve something "similar" to what the original question is asking.
I have one bottom imageview to show an image, then add on top another view to allow user to draw with finger.
What I achieved so far is: user can draw something with finger on top, then click on "switch" button to switch to "erase" mode to erase the colour and it will reveal the image at the bottom.
Problem is I don't know how to fill the whole view screen with a specific colour yet. If this can be done on the upper layer before loading it, then remove the "switch" button and go straight to "erase" mode, the hidden image at the bottom will be revealed on the user's finger movement.
It shouldn't be too difficult to fill up the whole screen with a specific colour, right? Any one, please?
Code below, please let me know if any problem. Thanks!
Note: please replace the "watermelon.jpg" image name in the following code with any other image file you have. OR visit my blog for the full project code including the image.
I have searched this forum several times now, and i do not seem to find an answer to my problem.
Other people have asked the same question already but i'm under the impression the problem is not as easy to solve.
Basically what i am trying to do is the following,
I would like to put a layer on top of a picture, and then erase that layer through touches or accelerometer movement, 'scratching away' the place where a touch has occured.
Like this:
Now i have got this working like this:
Code:
- (void)drawRect:(CGRect)rect {
// Retrieve the graphics context
CGContextRef context = UIGraphicsGetCurrentContext();
//Get the drawing image
CGImageRef maskImage = [self drawImageWithContext:context inRect:rect];
// Get the mask from the image
CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskImage)
, CGImageGetHeight(maskImage)
, CGImageGetBitsPerComponent(maskImage)
, CGImageGetBitsPerPixel(maskImage)
, CGImageGetBytesPerRow(maskImage)
, CGImageGetDataProvider(maskImage)
, NULL
, false);
//make sure the images are not upside down
CGContextTranslateCTM(context, 0, self.bounds.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
//Draw the base picture
CGContextDrawLayerInRect(context, rect, firstLayer);
//Add clipping
CGContextClipToMask(context, rect, mask);
//Release the mask
CGImageRelease(mask);
//Release the maskImage
CGImageRelease(maskImage);
//draw the second layer
CGContextDrawLayerInRect(context, rect, secondLayer);
}
As you can see i have a drawrect method, where i make an image based on the touches. This image is being used to get an imageMask.
I draw the first picture, lay down the mask, and then draw the second picture.
This works effectively resolving my problem.
But there are two drawbacks:
1) If i draw another thing over my last picture, this is also clipped...
2) Perhaps the most important thing, when i call my drawrect several times (from accelerometer), i lose performance, making the application impossible to use...
So basically my question is,
is there another way on resolving my problem? Do i need to look at this another way? Do i need to copy paste pixels?
Do i need alpha blending? Or do i need to look at OpenGL?
I'm hoping somebody can finally shed some light on this, because i'm really sitting in the dark here...
Hello everyone!
I'm new here on the forum have a similar problem with our friend's Flux.
I have a background image, and need to create an image on top to be painted with the touch screen.
The problem is that the design is not rectangular (eg, a drawing of a mouth), but it paints the whole view rectangular.
I would just paint the picture of the mouth (for example) and not the whole rectangle.
Someone had a similar problem and managed to solve?
I'm new here on the forum have a similar problem with our friend's Flux.
I have a background image, and need to create an image on top to be painted with the touch screen.
The problem is that the design is not rectangular (eg, a drawing of a mouth), but it paints the whole view rectangular.
I would just paint the picture of the mouth (for example) and not the whole rectangle
Someone had a similar problem and managed to solve?