ALAsset thumbnail without inward black translucent border - iphone

I have find that for most photos in the gallery, [ALAsset thumbnail] will return the thumbnail with an inward black translucent border.
My question is, how can I obtain the thumbnail without this border?

You have a lot of options. If you just need to display it on screen you could simply fake it so that 1 pixel of the thumbnail isn't visible. You can put a UIImageView inside a UIView that clips to bounds.
UIView* view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
view.backgroundColor = [UIColor clearColor];
view.clipsToBounds = YES;
UIImageView* imgView = [[UIImageView alloc] initWithFrame:CGRectMake(-1, -1, 202, 202)];
imgView.image = [asset thumbnail];
[view addSubview:imgView];
Or better yet, make a UIView subclass and override drawRect.
-(void)drawRect:(CGRect)rect
{
UIImage* thumb = [asset thumbnail];
[thumb drawInRect:CGRectMake(rect.origin.x-1, rect.origin.y-1, rect.size.width+2, rect.size.height+2)];
}
Or you can use the aspectRatioThumbnail instead and make it squared yourself.
UIImageView* imgView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
imgView.image = [asset aspectRatioThumbnail];
imgView.contentMode = UIViewContentModeScaleAspectFill;
Or if you actually need to crop the UIImage itself for some reason you can do this.
UIImage* thumb = [asset thumbnail];
CGRect cropRect = CGRectMake(1, 1, thumb.size.width-2, thumb.size.height-2);
cropRect = CGRectMake(cropRect.origin.x*thumb.scale, cropRect.origin.y*thumb.scale, cropRect.size.height*cropRect.scale);
CGImageRef imageRef = CGImageCreateWithImageInRect([thumb CGImage], cropRect);
UIImage* result = [UIImage imageWithCGImage:imageRef scale:thumb.scale orientation:thumb.imageOrientation];
CGImageRelease(imageRef);

There are no methods to get thumbnail without 1 pixel black border.
You can use also
[asset aspectRatioThumbnail]; // but it is not rounded.
So i think you should resize the image yourself using:
asset.defaultRepresentation.fullScreenImage or
asset.defaultRepresentation.fullResolutionImage

Related

How can i write text on image and send it on mail?

I am creating an app that send photo on email,i have created gallery,now i want my app can write text on that photo and send it on email. Any suggestions? tutorials are acceptable.
Simplest but tricky, Add a UIView inside a UIImageView and a UILabel, update with yourimage and text. Now take an UIImage by capture screenshot here. and attach it with your email.
You can create UIImageView with image then place UILabel with clear background on image view, and finally make a UIImage using Core Graphics.
Something like this:
UIImage *bcg = [UIImage imageNamed:#"image.png"];
UIImageView *imgView = [[UIImageView alloc] initWithImage:bcg];
imgView.frame = CGRectZero;//Some frame
[self addSubview:imgView];
[imgView release];
UILabel *text = [[UILabel alloc] initWithFrame:CGRectMake(0, imgView.frame.size.height - 20, imgView.frame.size.width, 20)];
text.backgroundColor = [UIColor clearColor];
text.text = #"Some text";
[imgView addSubview:text];
UIImage *resultImage = nil;
UIGraphicsBeginImageContext(CGSizeMake(self.bounds.size.width,
self.bounds.size.height));
[self.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CGSize imageSize = CGSizeMake(self.bounds.size.width,
self.bounds.size.height);
UIGraphicsBeginImageContext(imageSize);
[viewImage drawInRect:CGRectMake(0,
0,
imageSize.width,
imageSize.height)
blendMode:kCGBlendModeNormal alpha:1];
resultImage = UIGraphicsGetImageFromCurrentImageContext();
This method easier to debug than draw image and text in context.

How to stretch Image to fill the Label Width set in Background in UILabel?

I have simple View based application. I had taken only UILabel on it.
Following is my code in viewDidLoad:
lblBack.textColor = [UIColor blueColor];
UIImage *img = [UIImage imageNamed:#"cn3.png"];
lblBack.backgroundColor = [UIColor colorWithPatternImage:img];
lblBack.text = #"Hello World!!!...";
// UIImageView *imgView = [[UIImageView alloc] initWithImage:img];
//
// CGRect rect = CGRectMake(0, 0, lblBack.frame.size.width, lblBack.frame.size.height);
// [imgView setFrame:rect];
// NSLog(#"Rect : %#",NSStringFromCGRect(rect));
// [img drawInRect:rect];
// imgView.contentMode = UIViewContentModeScaleAspectFill;
// imgView.contentMode = UIViewContentModeScaleAspectFit;
// imgView.contentMode = UIViewContentModeScaleToFill;
// [lblBack addSubview:imgView];
Comments shows some of the things that i have tried. I am getting following output:
In this one image is repeated 3 times. But I want that image should be stretched to fill the Label width.
I have referred some of the previous links that shows me to add Image in background and use clearColor for UILabel. Also seen example of Adding custom view in Background. But all this I dont want to use unless I dont have other solutions...
I just want to perform all things on UILabel only.... no other control except UIImage or UIImageView i want to use..
Dhiren try this code :
UIImage *img = [UIImage imageNamed:#"cab.png"];
CGSize imgSize = testLabel.frame.size;
UIGraphicsBeginImageContext( imgSize );
[img drawInRect:CGRectMake(0,0,imgSize.width,imgSize.height)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
testLabel.backgroundColor = [UIColor colorWithPatternImage:newImage];
I have tested this code.
Porting over Maulik's answer to Swift 2.2, you get the following code:
var img: UIImage = UIImage(named: "cabImage")!
var imgSize: CGSize = testLabel.frame.size
UIGraphicsBeginImageContext(imgSize)
img.drawInRect(CGRectMake(0, 0, imgSize.width, imgSize.height))
var newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext();
testLabel.backgroundColor = UIColor(patternImage: newImage)
Personally tested to be working!

How can I resize my UIImage?

Here is the code I am using to resize my UIImage, but unfortunately it isn't working:
UIImage *cellImage = [UIImage imageNamed:#"warning.png"];
CGRect cropRect = CGRectMake(0.0, 0.0, 12.0, 12.0);
CGImageRef croppedImage = CGImageCreateWithImageInRect([cellImage CGImage], cropRect);
UIImageView *myImageView = [[UIImageView alloc] initWithFrame:cropRect];
[myImageView setImage:[UIImage imageWithCGImage:croppedImage]];
CGImageRelease(croppedImage);
Why does this code not work?
Thanks
HI try this:-
UIGraphicsBeginImageContext(CGSizeMake(50,50));
[[UIImage imageNamed:#"warning.png"] drawInRect: CGRectMake(0, 0,50,50)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Are you forgetting to add myImageView as a subview of your main view or another visible view? E.g.
[cell.contentView addSubview:myImageView];
This would explain why nothing appears.
However, CGImageCreateWithImageInRect() crops the image within the rect if your rect is smaller than the image. To resize the UIImage itself, see: The simplest way to resize an UIImage?
However, it's easiest if you just let the UIImageView handle the resizing if you don't actually need the UIImage itself resized.
UIImage *cellImage = [UIImage imageNamed:#"warning.png"];
CGRect cropRect = CGRectMake(0.0, 0.0, 12.0, 12.0);
CGImageRef croppedImage = CGImageCreateWithImageInRect([cellImage CGImage], CGRectMake(0.0f,0.0f,cellImage.size.width,cellImage.size.height));
UIImageView *myImageView = [[UIImageView alloc] initWithFrame:cropRect];
[myImageView setImage:[UIImage imageWithCGImage:croppedImage]];
CGImageRelease(croppedImage);
[cell.contentView addSubview:myImageView];
See:
UITableViewCell Class Reference: contentView
I don't know why that doesn't work but try using UIGraphicsBeginImageContext and UIGraphicsEndImageContext instead, UIGraphicsBeginImageContext takes a size.

UIImageView round corner has white background

The rounded corner has white background.
I followed other SO answers but don't know why i'm getting this whites
Bellow is the code.
UIView* testView = [[[UIView alloc] initWithFrame: self.animationView.bounds] autorelease];
UIImageView* testImageView = [[[UIImageView alloc] initWithImage:backImage] autorelease];
[testView addSubview: testImageView];
testImageView.backgroundColor = [UIColor clearColor];
CALayer* layer = [testView layer];
bool prev = layer.masksToBounds;
layer.masksToBounds = YES;
layer.cornerRadius = 30;
testView.clipsToBounds = YES;
UIImage* image = [UIImage captureView: testView];
//this image has the white regions in the four corners.
// when seen on iphone photo album
+ (UIImage*)captureView:(UIView*)view
{
CGSize size = view.bounds.size;
CGContextRef context = CreateARGBBitmapContext(size);
CGContextTranslateCTM(context, 0, size.height);
CGContextScaleCTM(context, 1.0, -1.0);
[view.layer renderInContext: context];
CGImageRef imageRef = CGBitmapContextCreateImage(context);
UIImage* img = [UIImage imageWithCGImage: imageRef];
CGImageRelease(imageRef);
CGContextRelease(context);
return img;
}
Add [testImageView setClipsToBounds:YES].
It might be that you have to set testImageView.opaque = NO.

How to make something like iPhone Folders?

I'm wanting to know if there's a way I can transform my view to look something like iPhone folders. In other words, I want my view to split somewhere in the middle and reveal a view underneath it. Is this possible?
EDIT:
Per the suggestion below, I could take a screenshot of my application by doing this:
UIGraphicsBeginImageContext(self.view.bounds.size);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Not sure what to do with this, however.
EDIT:2
I've figured out how to add some shadows to my view, and here's what I've achieved (cropped to show relevant part):
EDIT:3
http://github.com/jwilling/JWFolders
the basic thought will be to take a picture of your current state and split it somewhere. Then animate both parts by setting a new frame. I don't know how to take a screenshot programmatically so I can't provide sample codeā€¦
EDIT: hey hey it's not looking great but it works ^^
// wouldn't be sharp on retina displays, instead use "withOptions" and set scale to 0.0
// UIGraphicsBeginImageContext(self.view.bounds.size);
UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, 0.0);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *f = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CGRect fstRect = CGRectMake(0, 0, 320, 200);
CGRect sndRect = CGRectMake(0, 200, 320, 260); // was 0,200,320,280
CGImageRef fImageRef = CGImageCreateWithImageInRect([f CGImage], fstRect);
UIImage *fCroppedImage = [UIImage imageWithCGImage:fImageRef];
CGImageRelease(fImageRef);
CGImageRef sImageRef = CGImageCreateWithImageInRect([f CGImage], sndRect);
UIImage *sCroppedImage = [UIImage imageWithCGImage:sImageRef];
CGImageRelease(sImageRef);
UIImageView *first = [[UIImageView alloc]initWithFrame:fstRect];
first.image = fCroppedImage;
//first.contentMode = UIViewContentModeTop;
UIImageView *second = [[UIImageView alloc]initWithFrame:sndRect];
second.image = sCroppedImage;
//second.contentMode = UIViewContentModeBottom;
UIView *blank = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 320, 460)];
blank.backgroundColor = [UIColor darkGrayColor];
[self.view addSubview:blank];
[self.view addSubview:first];
[self.view addSubview:second];
[UIView animateWithDuration:2.0 animations:^{
second.center = CGPointMake(second.center.x, second.center.y+75);
}];
You can uncomment the two .contentMode lines and the quality will improve but in my case the subview has an offset of 10px or so (you can see it by setting a background color to both subviews)
//EDIT 2: ok found that bug. Had used the whole 320x480 screen, but had to cut off the status bar so it should be 320x460 and all is working great ;)
Instead of taking a snapshot of the view, you could use a separate view for each row of icons. You'll have to do a bit more work with repositioning stuff, but the rows won't be static when the folder is open (in other words, they'll keep redrawing as necessary).
I took relikd's code as a base and made it a bit more dynamic.
You can specify split position and direction when calling the function and I added a boarder to the split images.
#define splitAnimationTime 0.5
- (void)split:(SplitDirection)splitDirection
atYPostition:(int)splitYPosition
withRevealedViewHeight:(int)revealedViewHeight{
// wouldn't be sharp on retina displays, instead use "withOptions" and set scale to 0.0
// UIGraphicsBeginImageContext(self.view.bounds.size);
UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, 0.0);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *f = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CGRect fullScreenRect = [self getScreenFrameForCurrentOrientation];
CGRect upperSplitRect = CGRectMake(0, 0,fullScreenRect.size.width, splitYPosition);
CGRect lowerSplitRect = CGRectMake(0, splitYPosition, fullScreenRect.size.width, fullScreenRect.size.height-splitYPosition);
CGImageRef upperImageRef = CGImageCreateWithImageInRect([f CGImage], upperSplitRect);
UIImage *upperCroppedImage = [UIImage imageWithCGImage:upperImageRef];
CGImageRelease(upperImageRef);
CGImageRef lowerImageRef = CGImageCreateWithImageInRect([f CGImage], lowerSplitRect);
UIImage *lowerCroppedImage = [UIImage imageWithCGImage:lowerImageRef];
CGImageRelease(lowerImageRef);
UIImageView *upperImage = [[UIImageView alloc]initWithFrame:upperSplitRect];
upperImage.image = upperCroppedImage;
//first.contentMode = UIViewContentModeTop;
UIView *upperBoarder = [[UIView alloc]initWithFrame:CGRectMake(0, splitYPosition, fullScreenRect.size.width, 1)];
upperBoarder.backgroundColor = [UIColor whiteColor];
[upperImage addSubview:upperBoarder];
UIImageView *lowerImage = [[UIImageView alloc]initWithFrame:lowerSplitRect];
lowerImage.image = lowerCroppedImage;
//second.contentMode = UIViewContentModeBottom;
UIView *lowerBoarder = [[UIView alloc]initWithFrame:CGRectMake(0, 0, fullScreenRect.size.width, 1)];
lowerBoarder.backgroundColor = [UIColor whiteColor];
[lowerImage addSubview:lowerBoarder];
int reveledViewYPosition = splitYPosition;
if(splitDirection==SplitDirectionUp){
reveledViewYPosition = splitYPosition - revealedViewHeight;
}
UIView *revealedView = [[UIView alloc]initWithFrame:CGRectMake(0, reveledViewYPosition, fullScreenRect.size.width, revealedViewHeight)];
revealedView.backgroundColor = [UIColor scrollViewTexturedBackgroundColor];
[self.view addSubview:revealedView];
[self.view addSubview:upperImage];
[self.view addSubview:lowerImage];
[UIView animateWithDuration:splitAnimationTime animations:^{
if(splitDirection==SplitDirectionUp){
upperImage.center = CGPointMake(upperImage.center.x, upperImage.center.y-revealedViewHeight);
} else { //assume down
lowerImage.center = CGPointMake(lowerImage.center.x, lowerImage.center.y+revealedViewHeight);
}
}];
}
This means I can call it like this:
[self split:SplitDirectionUp atYPostition:500 withRevealedViewHeight:200];
I used these conveniance functions in the updated split function:
- (CGRect)getScreenFrameForCurrentOrientation {
return [self getScreenFrameForOrientation:[UIApplication sharedApplication].statusBarOrientation];
}
- (CGRect)getScreenFrameForOrientation:(UIInterfaceOrientation)orientation {
UIScreen *screen = [UIScreen mainScreen];
CGRect fullScreenRect = screen.bounds;
BOOL statusBarHidden = [UIApplication sharedApplication].statusBarHidden;
//implicitly in Portrait orientation.
if(orientation == UIInterfaceOrientationLandscapeRight || orientation == UIInterfaceOrientationLandscapeLeft){
CGRect temp = CGRectZero;
temp.size.width = fullScreenRect.size.height;
temp.size.height = fullScreenRect.size.width;
fullScreenRect = temp;
}
if(!statusBarHidden){
CGFloat statusBarHeight = 20;
fullScreenRect.size.height -= statusBarHeight;
}
return fullScreenRect;
}
and this enum:
typedef enum SplitDirection
{
SplitDirectionDown,
SplitDirectionUp
}SplitDirection;
Adding a return to normaal function and adding the arrow would be a great addition.