small medium large xlarge

Img_0048b_pragsmall
11 Nov 2008, 21:52
Bryan Wills (10 posts)

I am trying to create an app that allows the user to reveal a photo by rubbing off a masked photo layer with their finger (similar to the rub-off tickets you get in a gas station). I want to stack 2 images on top of each other with the top one completely hidden (masked) at start. Here is a basic diagram of what I am trying to accomplish:

http://dev.oneinchpunch.com/dynamicMask.jpg

I have been wading thru the GLPaint example code for the drawing portion, just not sure how to make the drawing view become a mask for an image below it.

Any suggestions?

Looking forward to the iPhone class in Denver in Jan. Thanks in advance for your help!

Biopic_100x100_pragsmall
11 Nov 2008, 22:38
Bill Dudney (917 posts)

Hi Bryan,

I have working code to do this in the Core Animation screencast.

http://www.pragprog.com/screencasts/v-bdcora/creating-a-compelling-user-interface-with-core-animation

Episode 6 is where I talk about it.

Specifically the reflectionMask method in the MyView.m file.

Good luck! And please let me know what you are able to get going.

Img_0048b_pragsmall
12 Nov 2008, 17:09
Bryan Wills (10 posts)

Thanks Bill! Let me start by waving my Noobie flag high, so I apologize in advance if this is way off, but here is what i have (not-working) so far:

  • (void)viewDidLoad { [super viewDidLoad];

    // add background image (that will be revealed when user “rubs off mask”) UIImage* revealImage = [UIImage imageNamed:@”myRevealImage.png”]; theReveal = [[UIImageView alloc] initWithImage:revealImage]; [self.view addSubview:theReveal];

    // create “drawing area” (code based on GLPaint sample) CGRect rect = [[UIScreen mainScreen] applicationFrame]; drawingView = [[FlipsideView alloc] initWithFrame:CGRectMake(rect.origin.x, rect.origin.y-10.0, rect.size.width, rect.size.height)];

    // mask reveal image with drawing area? CALayer *maskedLayer = [CALayer layer]; maskedLayer.contents = (id)[self maskedImage:(CGImageRef)theReveal.contents];

}

  • (CGImageRef)maskedImage:(CGImageRef*)image { return CGImageCreateWithMask(image, self.drawingView); }

Still trying to get my head around this view/layer/image/mask thing. Am I headed in the right direction? The drawing thing works by itself, and the image works by itself, but the peanut butter and chocolate don’t go so great together yet! lol - Thanks for you help and patience! -B

Biopic_100x100_pragsmall
13 Nov 2008, 02:43
Bill Dudney (917 posts)

Hi Bryan,

Welcome, noobies are always great to hear from!

So in the above code, what is drawingView? Keep in mind that the second argument must be a CGImageRef that was created as a mask.

What what I could see (looking at the above code) it appears that drawingView is a UIView subclass, that won’t work as a mask. You have to use the CG function call to create a mask.

Hope this helps, and good luck!

Img_0048b_pragsmall
13 Nov 2008, 03:34
Bryan Wills (10 posts)

Hmmm… so drawingView is basically the same thing as the GLPaint sample code from the Apple Developer site (rub your finger on the screen and it draws). I think that is where my confusion is coming in. I understand the concept of masking one image with another image, but I wanted to mask one image with a “live” drawing layer that masked (or really unmasked) the image below it as the user “draws” with their finger. Not sure if I am articulating what I am trying to do clearly.

I am also wondering if I am over-thinking this and perhaps have a simpler approach: Is it possible (and by “possible” I mean “fairly simple”) to load an image and then make the pixels of that image that the user touches become transparent? (alpha=0.0) This would give basically the same effect that I am looking for by revealing another image below it.

Thanks again for your help. -B

Img_0048b_pragsmall
18 Nov 2008, 19:12
Bryan Wills (10 posts)

Bill,

I am trying to understand your MyView.m file in your example. You have an “imageLayer” and a “reflectionLayer” inside a “containerLayer” right? How does “holderLayer” fit in the mix?

In trying to translate what you are doing over to what I am trying to do, is is possible to “draw” inside a layer (your reflection layer essentially)?

Thanks for your help and patience. This Obj-C syntax is very confusing to me, trying to remain calm. lol

Biopic_100x100_pragsmall
18 Nov 2008, 19:47
Bill Dudney (917 posts)

Hey Bryan,

No problem! Its fun to help, and remind you to take deep breaths :)

The holder layer is the layer that holds the 2 other layers. It is also the layer that is transformed with the rotation (sublayersTransform).

On the live masking thing, you would have to updated the mask with each touchesMoved: method (or in some way coalesce them) and re-apply the mask by redrawing the image. The Quartz book (Gelphman, Laden) has a great write up of applying masks with Quartz.

Generic-user-small
04 Jun 2009, 22:15
Gregory Brown (2 posts)

Bryan, Bill, I was wondering if either of you had made any headway with what your talking about here. I stumpled onto this post while googling around trying to accomplish something very similar to what Bryan is talking about. Been trying to do this on the iphone with opengl though and am realizing its probably best to go with core animation. After watching Bill’s screencast and looking at the sample code I’m trying to set up… -a function that fills an array of points in a line between every touchesMoved -something similar to reflectionMask which will iterate through this array and draw circles around all points -as a bonus I want to try and make each of these circles slowly fade away as if your dragging your finger across a heat sensitive screen(believe this can be achieved by going through the array and whitening each by a shade of grey until they are perfectly white which is when I’ll remove them)

Right now I’m hung up on translating the reflectionMask to iphone because I guess uikit doesn’t like anything I’m doing to make a new graphics context. Also I am a little worried about whether or not the phone is going to be able to handle this processing. Any help would be great!

Biopic_100x100_pragsmall
05 Jun 2009, 10:40
Bill Dudney (917 posts)

Hi Gregory,

As to the iPhone being able to handle, its very capable but if you are going to have 100’s of circles on the screen all at once and all of them animating it might be a bit much to expect it to be able to dynamically generate the image for each circle on each frame. However I’d set up a simple test to see if you can accomplish what you are looking for without building the whole app.

As for drawing, you have to create an image context, draw to that, then get the CGImageRef from the context in order to draw at arbitrary times on the phone. Unlike the mac world you can’t just arbitrarily lock focus and start drawing. You have to wait for the phone to tell you that it has locked (via drawRect: method calls).

Good luck, and can’t wait to see your app. It sounds cool!

Generic-user-small
06 Jun 2009, 15:59
Gregory Brown (2 posts)

Bill, Thanks for your help. I’ve made alot of process so far, I currently have a spotlight effect I’m able to control over images. For the heat sensitive effect I was talking about I have two roads I’m thinking of going down. I could either do what I was talking about before with keeping track of every circle and reducing them to white or I could get the old context and draw a white rect over the whole screen with a slight alpha over it which will keep the white colors white and fade the black circles over time till they are white also. This approach would reduce the amount of circles I have to draw but I’m not totally sure if the implementation would work/is actually better. Any opinions? This is my first foray into core animation so I’m deeply appreciative of your help.

Biopic_100x100_pragsmall
07 Jun 2009, 11:17
Bill Dudney (917 posts)

Hi Gregory,

I’m not sure which approach would work better without playing with it. I’d suggest setting up both in as simple an app as possible then running Instruments or Shark against it to see which one does better.

Good luck!

You must be logged in to comment