Add drop shadow to PNG using Cocoa - iphone

I have some PNGs with transparent backgrounds that I would like to add shadows to programatically. I've seen examples of adding shadows to square objects, but haven't seen any with complex shapes.
So the two steps I think I'd have to do would be:
Isolate the PNG shape
Draw a shape behind the PNG that is blurred, faded, and offset.
I don't have much experience with drawing within Cocoa, so any insight on where to begin would be much appreciated!
Screenshot:
(source: iworkinprogress.com)

Simplest way is to call CGContextSetShadow in your drawRect: before you draw the images.
- (void)drawRect:(CGRect)invalidRect
{
CGContextRef c = UIGraphicsGetCurrentContext();
CGContextSetShadow(c, CGSizeMake(5.0f, 5.0f), 5.0f);
[myImage drawAtPoint:CGPointMake(50.0f, 50.0f)];
}

I found this category to be very useful: UIImage+Shadow.m
https://gist.github.com/kompozer/387210

I am not really a graphics person, but what about this: if you have a mask for these images, or if you can create one programatically, then you can probably use a blur function to add a shadow like effect.
Experiment in Photoshop/Acorn/Pixelmator?

Since you want shadows like they all have the same light source... it seems like you might actually be better off with an OpenGL view, that casts a light from above and the images would sit slightly above a flat plane to cast a shadow on. I'd look for 3D OpenGL frameworks that would let you add things pretty easily...

Related

iPhone OpenGL - How to gradient fade out a texture?

I want to customize the reflection from the FlowCover (Cover Flow remake) sample code. Now, the reflection (a texture) is only transparent but I want it to have a gradient so that the texture fades to be completely transparent.
How would you achieve this effect with OpenGL? This is the code that handles the textures.
glPushMatrix();
glBindTexture(GL_TEXTURE_2D,fcr.texture);
glTranslatef(trans, 0, 0);
glScalef(sc,sc,1.0);
glMultMatrixf(m);
glDrawArrays(GL_TRIANGLE_STRIP,0,4);
// reflect
glTranslatef(0,-2,0);
glScalef(1,-1,1);
glColor4f(0.5,0.5,0.5,0.5);
glDrawArrays(GL_TRIANGLE_STRIP,0,4);
glColor4f(1,1,1,1);
glPopMatrix();
Any hints or key words are welcome.
Thanks a lot.
My solution to this problem was to remove openGL reflection and to path image with reflection and gradient to FlowCower. Here is a nice example on creating image reflection.
It's a good idea to draw reflection with gradient way. ^_^
I think you can put a light source, and change the normal vector of project view. The lighting source will make some gradient effect.
You might want to look into multitexturing. You can combine the base texture with a gradient texture in a way that uses the color of the first and the alpha values of the second. Take a look at the glTexEnvi command.

Eraser in OpenGL ES iphone

i have two images which are overlapping 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 am new to OpenGL ES development.
kindly help me out or give me any suggestion to complete this functionality.
Thanks in advance
You're going to need render-to-texture using Framebuffer Objects (FBOs). Render to the desired texture, but only to the alpha channel, which is done using glColorMask (With it you can mask all color channels except alpha), and then draw the pattern into the alpha channel, setting alpha to 0.0, then display the textures as normal.
I just did something similar, and I found a solution in GLBlending:
if (eraseMode) {
glBlendFunc(1.0,0.0);
}
else {
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
Some cosmetics are needed around this, but it's a simple solution that fits basic needs.

The antialias of rotated CGImage/CGlayer seems jaggy, UIImageView's is not

I need to mask a "texture" image with a rotated greyscale image.
I found out, that I have to do it with CGImages or CGlayers (if there is a simplier way using UIImageViews only, please let me know about it).
My problem is simple:
The antialias of any
rotation-transformed CG stuff is quiet
jaggy...
... but the antialias of a rotation-transformed UIImageView is kinda perfect. How can I produce that beautiful antialiased rotations?
I've uploaded a "proof" involving actual iPhone Simulator screenshots, to see what am I talkin' about: http://gotoandplay.freeblog.hu/files/Proof.png
I've tried to use CGImages, CGLayers, UIImageViews "captured" with renderInContext, I've tried to CGContextSetInterpolationQuality to high, and also tried to set CGContextSetAllowsAntialiasing - CGContextSetShouldAntialias, but every case returned the same jaggy result.
I'm planning to learn using OpenGL next year, but this development should released using CoreGraphics only. Please let me know how to get a perfectly rendered rotated image, I just can't accept it's impossible.
To add 1px transparent border to your image use this
CGRect imageRect = CGRectMake(0, 0, image.size.width, image.size.height);
UIGraphicsBeginImageContext( imageRect.size );
[image drawInRect:CGRectMake(1,1,image.size.width-2,image.size.height-2)];
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Have you tried adding a clear, 1 pixel border around your image? I've heard of that recommended as a trick to avoid aliasing, by giving CoreGraphics some room to work with when blending the edges.
I am having a similar problem, looks like I'm going to move it over to OpenGL ES as well. I can't nail down an effective solution that doesn't hurt performance.
For reference of future CoreGraphics explorers, putting a 1-pixel transparent border did make for a noticeable improvement in my experiments, but it appears that as Eonil mentioned, you end up with multiple stages of antialiasing/smoothing/interpolation working against each other. IE: CGLayer does some interpolation for it's rotation, then context it's being drawn to will do some interpolation/antialiasing, so on so forth until it ends up looking pretty rough.
I actually ended up with better results by disabling interpolation and antialiasing on the destination context, though it was still obviously jaggy (less artifacts overall though). I was able to achieve the best overall appearance by enabling interpolation and antialiasing when constructing the CGLayer, and disabling it for the destination context when re-drawing it. This approach, obviously, is fraught with other problems.

"Beveled" Shapes in Quartz 2D

I'm familiar with some of the basics of Quartz 2D drawing, like drawing basic shapes and gradients and so on, but I'm not sure how to draw a shape with a "beveled" look, like this:
beveled circle http://www.shaggyfrog.com/junk/beveled-circle.jpg
Essentially we've got a shine on one corner, and maybe some shading in the opposite corner. I think -- I didn't make this image, although I'd like to be able to approximate it.
Any ideas? This is on the iPhone, and I'd like to use built-in frameworks and avoid any external libraries if at all possible.
There are really only a few useful approaches you can take to this problem.
Use your basic shape drawing techniques and combine them with a one or more gradient curves. (Implicit object construction) with curves/fills.
Custom build a UIView and build the object up per-pixel in a drawRect.
Pre-render your beveled/shadowed shapes and load them into an image and blit them into a UIImageView.

iPhone Animation: how to anti-alias?

I was looking at some animations in my iPhone app and felt like it was kind of ugly. And then I undertsood it: it just doesn't animate through subpixel states.
So, in case I use usual +beginAnimations/+commitAnimations, moving some stuff just a few pixels look "jumpy". How can I avoid it? Are there any flags to make it animate through float coords or whatever?
Just to give you an idea of what I have and what I'm looking for, please refer to the picture:
alt text http://www.ptoing.net/subpixel_aa.gif
Thanks in advance,
Anton
That's funny, but I found that UIImageView animate its content using aniti-aliasing, while edges of the view are not anti-aliased (hard). It seems to be because UIView itself should maintain the same bounds, while subpixel rendering might add to the bound a bit.
So, I ended up just putting an image with some transparent space around the picture, and it all went smooth.
Just don't let UIView cut its contents for you :)
You can try deriving the item you're animating from a custom UIView that overrides its drawRect method and sets anti-aliasing on for it then lets the parent draw into it. Something along the lines of:
- (void) drawRect:(CGRect)area
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGContextSetShouldAntialias(context, true);
CGContextSetAllowsAntialiasing(context, true);
[super drawRect:area];
// We have to turn it back off since it's not saved in graphic state.
CGContextSetAllowsAntialiasing(context, false);
CGContextRestoreGState(context);
}
On the other hand, it might be too late in the rendering pipeline by the time you get here, so you may have to end up rolling your own animation scheme that lets you have full control over pixel-positioning.
Per Jeeva's comment above, you can make UIView edges render with Anti-aliasing by settings the following option in the info.plist to YES.
Renders with edge antialiasing
Here is the link Jeeva pointed to:
http://www.techpaa.com/2012/06/avoiding-view-edge-antialiasing.html