Resizing an image with stretchableImageWithLeftCapWidth - iphone

I'm trying to resize an image using stretchableImageWithLeftCapWidth: it works on the simulator, but on the device, vertical green bars appears.
I've tried to use imageNamed, imageWithContentOfFile and imageWithData lo load the image, it doesnt change.
UIImage *bottomImage = [[UIImage imageWithData:
[NSData dataWithContentsOfFile:
[NSString stringWithFormat:#"%#/bottom_part.png",
[[NSBundle mainBundle] resourcePath]]]]
stretchableImageWithLeftCapWidth:27 topCapHeight:9];
UIImageView *bottomView = [[UIImageView alloc] initWithFrame:CGRectMake(10, 200+73, 100, 73)];
[self.view addSubview:bottomView];
UIGraphicsBeginImageContext(CGSizeMake(100, 73));
[bottomImage drawInRect:CGRectMake(0, 0, 100, 73)];
UIImage *bottomResizedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
bottomView.image = bottomResizedImage;
See the result: the green bars shouldn't be there, they dont appear on the simulator.
alt text http://www.quicksnapper.com/files/5161/96232162149F1C14751048_m.png

Did you figure this out?
Seems like it might be a bug with UIGraphicsGetImageFromCurrentImageContext. If I draw an image that has transparency I get red/green artifacts. These only appear on the device (not in the sim). Also, if I remove transparency from the image, the artifacts go away.
Update: Some more weirdness. I was using PNGs before, so I tried using a transparent gif instead. Using a GIF, shows the artifact problem on the sim.
Victory! Found a solution:
Turn off 'Compress PNG Files' in the build settings for your project. Disabling this makes the PNG transparency work without any artifacts.

It seems like you're writing a lot of unnecessary code, but perhaps that's just because it's out of context and there's more to it that I'm missing.
To get the image:
[[UIImage imageName: #"bottom_part.png"] stretchableImageWithLeftCapWidth: 27 topCapHeight: 9];
What part of your code are you displaying this image? i.e. in what method call are you drawing the images above?
Why not just use a UIImageView and put the image in there? Then you don't need to do any of the image context drawing etc.

In my case I had an UIImageView which I stretched horizontally. I found a strange vertical white line in the stretched image.
The solutions above didn't work for me. However, the following did:
Cast the width value to an int value:
myNewViewFrame.size.width = (int)newWidth;
myView.frame = myNewViewFrame;
Hope it works for you guys as well...

I've spent 5 hours debugging this last night, disabling PNG compression in xcode didn't do anything for me.
For anyone else meeting vertical, green, bars/lines/artifacts with stretchableImageWithLeftCapWidth (in UIImage API) - this post is for you.
I have a 21x30 for a custom barbutton background that I want to widen, but got the same green stripes as the OP. I found a PNG created with photoshop and that worked fine - mine are made with Gimp.
Anyway, stripping ALL chunks from the files (except the three essential ones) made no difference. Neither did disabling PNG compression.
What did work for me was this:
Add ONE empty line above my image (which is now 21x31).
Set topCapHeight:0 when creating the scaled image.
When I use my scaled image, I draw into a CGContext, which is later used to make an UIImage. I use this to draw:
[image drawInRect:CGRectMake(0,-2,width,32)];
This makes the problem go away (for me).
I assume that the bug/issue has to do with not scaling vertically when drawing, so I force scaling of the first source image line (into two lines), which are draw outside my composition.
I hope this helps someone save 5 hours.
/Krisb

I stopped using stretchableImageWithLeftCapWidth in favor of UIView's much more well-behaved contentStretch property. I've never seen the green bars you are describing, but in general I would recommend using contentStretch instead of stretchableImageWithLeftCapWidth.

I tried to disable PNG compression like Nate proposed, but this wouldn't work for me (iOS 3.1.3). I then tried using TIFF images instead of PNG, which works.

I have found similar issues with contentStretch (on any UIView that has drawn content) when using a value of (0.5, 0.5, 0, 0). i.e. stretch on the center pixel.
I have found that only the iphone 3G (possibly 2G) exhibits this problem. iphone 4 and 3GS is OK. So, I assume this is a problem with the old graphics HW.
a way i found around the problem was to stretch on a slightly larger center area.
e.g. (0.4, 0.4, 0.1, 0.1)

Related

Merging UIImageViews to save as 1 image - Transparent areas shows previous images

My app lets users choose or take a picture then add other objects or text on top and rotate/resize them.
For saving i'm just taking a screenshot of the iPhone screen because after trying for hours and hours I just couldn't figure out how to save the original image with the added objects being placed at the right spots, with the right rotation/resized/etc... (If anyone knows a good example/tutorial of how to do this it would be incredibly helpful!)
I have a UIView with a size of 320x366. When user chooses an image I load it inside that UIView and it gets sized to fit properly with it's aspect ratio. When the user is done adding/editing objects on his image he can then save it.
-(UIImage *)createMergedImage
{
UIGraphicsBeginImageContextWithOptions(CGSizeMake(contentView.frame.size.width, contentView.frame.size.height), NO, 0.0f);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextClearRect(context, CGRectMake(0, 0, contentView.frame.size.width,contentView.frame.size.height));
//contentView is the 320x366 view with all the images
[contentView.layer renderInContext:context];
UIImage *screenShot = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return screenShot;
}
That's the code i'm using to save the UIView as a picture. Fitting the images with their correct shrunk aspect ratio, there's either transparent border at the top/bottom or left/right.
Now it's saving and works, when I open the image it's exactly what i'd expect. The problem is when i'm looking at the preview image, it shows other images (that i've previously seen on my iPhone) in the transparent part of the picture. As you can see in this following image.
When I go in the Camera Roll the transparent part looks black (like it should) as seen in this second image.
Also when i'm scrolling through my Camera Roll when I get to the image that my app saved, i'll see those extra random images in the transparent area for 0-1 secs before it disappears and becomes black (leaving the correct image the way it should be).
I'm hoping someone has seen something like this before and knows how to fix it.
Thanks!

How to scale only specific parts of image in iPhone app?

I want to scale the image in iPhone app but not entirely. I just want to scale specific parts like the bottom part or the middle part...How do I do it?
Please help.
Thanks
It sounds like you want to do a form of 9-slice scaling or 3-slice scaling. Let's say you have the following image:
and you want to make it look like this:
(the diagonal end pieces do not stretch at all, the top and bottom pieces stretch horizontal, and the left and right pieces stretch vertical)
To do this, use -stretchableImageWithLeftCapWidth:topCapHeight: in iOS 4.x and earlier, or -resizableImageWithCapInsets: starting with iOS 5.
UIImage *myImage = [UIImage imageNamed:#"FancyButton"];
UIImage *myResizableImage = [myImage resizableImageWithCapInsets:UIEdgeInsetsMake(21.0, 13.0, 21.0, 13.0)];
[anImageView setImage:myResizableImage]
To help visualize the scaling, here is an image showing the above cap insets:
I'm not aware of any way to adjust the scale of just a part of a UIImage. I'd approach is slightly differently by creating seperate images from your primary image using CGImageCreateWithImageInRect and then scaling the seperate images with the different rates that you require.
See:
Cropping a UIImage
CGImage Reference
Quartz 2D Programming Guide

image coming blurred and screwed after applying rotation on image view

I am stuck with a strange problem that,
I have a image view which has to shown at some angle approx 5 degree.For that I rotate my UIImageView to 5 degree but the image in UIImageView not coming proper as it was before transformation.
For more understanding see images
You can see the second image is looking like clipped from corners and looks some blur also.
My code for rotation:-
myimageView.transform = CGAffineTransformMakeRotation(radians(5));
Please suggest me how to solve this problem.
Thanks in advance.
Looks like there are several solutions located in this similar SO Q&A:
Any quick and dirty anti-aliasing techniques for a rotated UIImageView?
If it is, in fact, just the edges that are jagged, try adding a 1px transparent border around in image content (this is a suggestion in the above link).
Have you tried using CGContextRotateCTM(context, radians); and [sourceImage drawInRect:rect];?

Captured UIView image has distorted colors (iPhone SDK)

I'm using the UIGraphicsGetImageFromCurrentImageContext() function to capture the screen contents into an UIImage object (previously rendered into an Image context). This works great for both the simulator and a real device, however in the latter the resulting image has a few pixels with distorted colors, as seen here:
http://img300.imageshack.us/img300/2788/screencap.png
Please notice the few fucsia pixels at the top navigation bar, at both sides of the search field and to the right of the button. There are also such pixels at the right of the bottom-left button.
The code I'm using to capture the screen view into an UIImage object is pretty straightforward:
UIGraphicsBeginImageContext(self.view.window.frame.size);
[self.view.window.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *anImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
One thing to note is that all the graphics that get distorted belong to custom PNG files, used to draw the search field background as well as the buttons background.
Does anyone knows what could be possible causing this strange color distortion?
Best regards,
Just checked my own code that is doing the same thing you are. Yours is nearly identical to mine, except that I am asking the view's layer to render instead of the window's, i.e.:
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
I don't know why that would make a difference, but it's worth a try.
Solved it by using the just-approved private function UIGetScreenImage().
For more info, please check http://www.tuaw.com/2009/12/15/apple-relents-and-is-now-allowing-uigetscreenimage-for-app-st/ and https://devforums.apple.com/message/149553
Regards,
This article explains the issue with image corruption (caused by partially transparent pixels) and provides a workaround which corroborates Chris's comment:
http://www.kaoma.net/iphone/?p=9
UIGetScreenImage() is quite annoying when you just want to capture a view.
I found a nice trick, just re-save all your PNG images into TIFF format using Preview.app :)

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.