Adrian Sarli
Adrian Sarli

Reputation: 2356

UIImage Not Transparent

I am trying to make a view that lets a user draw with their finger. I have a png made in Pixelmator of the brush. My drawRect: method looks like this:

- (void)drawRect:(CGRect)rect
{

    NSAssert(brush != nil, @"");

    for (UITouch *touch in touchesNeedingDrawing)
    {
        //Draw the touch
        [brush drawInRect:CGRectWithPoints([touch locationInView:self], [touch previousLocationInView:self]) blendMode:0 alpha:1];
    }

    [touchesNeedingDrawing removeAllObjects];
}

The brush image is a png with transparency, but when I run the app, there is no transparency. Does anyone know why, and how to fix it?

Edit: I discovered that the image is transparent, but when I call drawInRect, the image draws the transparent pixels as the background color of the view. Is there a CGBlendMode I can use to fix this?

Upvotes: 8

Views: 5873

Answers (6)

omz
omz

Reputation: 53561

Your problem is a fundamental misconception of how drawRect: actually works. Every time you draw something into the current graphics context, everything that was there previously will be cleared (so that only the backgroundColor remains).

Since you're only drawing the current touch(es) (touchesNeedingDrawing is emptied), there's nothing under the rectangle you're filling that could show the transparency of the image you're drawing, so the background color shows through.

You basically have two options to resolve this:

1) Keep all touches that contribute to the drawing around (don't empty the touchesNeedingDrawing array) and redraw all of them every time – this is going to be easy but quite slow.

2) Draw into a buffer of some kind (e.g. a UIImage, using UIGraphicsBeginImageContext etc.). Every time your drawing changes, create a new buffer. Draw the old buffer into the new buffer and the images for the new stroke on top of it.

Upvotes: 0

Alex Nichol
Alex Nichol

Reputation: 7510

A possible issue is that you are setting the blendMode to 0. I suggest using the -drawInRect: method without a blend mode. The issue may also be that your view has a black background, but that is doubtful. I would also suggest attempting to display the UIImage in a UIImageView as a test. The issue may be related to the way that PixelMator exports images.

Upvotes: 0

Serhii Mamontov
Serhii Mamontov

Reputation: 4932

Solution is very simple, testes on my own project. In class which you updated with custom - (void)drawRect:(CGRect)rect set in -(id)init background color for self

[self setBackgroundColor:[UIColor clearColor]];

And thats all. Tested on my project.

Upvotes: 5

Swapnil Luktuke
Swapnil Luktuke

Reputation: 10475

i think you should try destination out blend mode: kCGBlendModeDestinationOut.

You could also draw at point instead draw in rect:

[brush drawAtPoint:[touch locationInView:self] blendMode:kCGBlendModeDestinationOut alpha:1]

Upvotes: 0

MayorJustin
MayorJustin

Reputation: 281

It seems like it could be taking the current fill color of the context.

Try setting the fill color for the context with CGContextSetFillColorWithColor() to [UIColor clearColor].CGColor

If that doesn't work, the only other solution that is simple and shouldn't have a performance hit is to have 2 views:

  • Background View - This will be view that has the proper background color or image
  • Overlay View - This view will detect the touches etc and then draw all of the brush strokes on top. The background color of this view can then be [UIColor clearColor] so when you draw the brush images, the alpha will be filled with [UIColor clearColor]. Basically the same view you have now, just with a clear background.

Note: You shouldn't need to mess with the blend mode to make this work. You should be able to use the default drawInRect: method

Upvotes: 1

makaron
makaron

Reputation: 1615

Is the brush png loaded to an imageView? That is, the variable brush is an object of UIImageView, isn't it? If so, perhaps simple

brush.backgroundColor = [UIColor clearColor];

will help

Upvotes: 0

Related Questions