I am trying load an image from a data :
NSError *error ;
NSString *imagePath = [[NSBundle mainBundle] pathForResource:imageName ofType:#"png"];
NSData *encryptedData = [NSData dataWithContentsOfFile:imagePath];
NSData *decryptedData = [RNDecryptor decryptData:encryptedData
withPassword:PASSWORD
error:&error];
UIImage *image = [UIImage imageWithData:decryptedData];
//adding image
UIImageView *movingImageView = [[UIImageView alloc]initWithImage:image];
[movingImageView setContentMode:UIViewContentModeScaleAspectFit];
[self.scrollView addSubview:movingImageView];
now movingImageView ignores content mode !!! it will be fixed if I declare its frame ! but the problem is my datas are different images with different width size . Any solution ?
EDIT :
Found a solution :
movingImageView.frame = CGRectMake(0, 0, image.size.width/2, image.size.height/2);
According to the documentation:
initWithImage: adjusts the frame of the receiver to match the size of the specified image. It also disables user interactions for the image view by default.`
Obviously the contentMode will have no effect if the imageView and image have the same size.
I guess what you need is to specify the imageView's width (probably the same as scrollView?), and calculate the height according to the image's dimension.
use the following lines. it will fill the image to frame. if large image came it will show image with aspect ratio and some part may clips. try once.
movingImageView.contentMode = UIViewContentModeScaleAspectFill;
movingImageView.clipsToBounds = YES;[self.scrollView addSubview:movingImageView];
Related
I have a UIImageView with size (0,0,414,471). The image with size (0,0,1236,1242) is displayed with UIViewContentModeScaleAspectFit mode in the UIImageView. So the image is nicely displayed. Then I make a rectangle (0,0,100,100) on the image and I like to crop it. Even though the rectangle covered (100,100) on the UIImageView, on the actual image size, (100,100) does not cover the size as shown on the UIImageView. So I make xratio (actual width/display width) and yratio(actual height/display height), then I multiply the rectangle size, to all x,y,width and height of the rectangle. This approach looks like I can crop the area as close as possible as shown on the UIImageView. But still have a bit of area offset and distortion. What could be the best way to crop in this scenario?
My code is shown below
- (void)saveCroppedImage:(UIImage *)image withcroppedRectangle:(CGRect)clippedRect
{
float xratio = image.size.width/displayWidth;
float yratio = image.size.height/displayHeight;
// Crop logic
clippedRect.origin.x *= xratio;
clippedRect.origin.y *= yratio;
clippedRect.size.width *= xratio;
clippedRect.size.height *= yratio;
CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], clippedRect);
UIImage * croppedImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
NSString *imageName =#"Documents/";
imageName = [imageName stringByAppendingString:[CurrentToddlerProfile getUserID]];
imageName = [imageName stringByAppendingString:#".png"];
NSString *pngPath = [NSHomeDirectory() stringByAppendingPathComponent:imageName];
// Write image to PNG
[UIImagePNGRepresentation(croppedImage) writeToFile:pngPath atomically:YES];
// Create file manager
// NSFileManager *fileMgr = [NSFileManager defaultManager];
// NSError *error;
// // Point to Document directory
// NSString *documentsDirectory = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents"];
// // Write out the contents of home directory to console
// NSLog(#"Documents directory: %#", [fileMgr contentsOfDirectoryAtPath:documentsDirectory error:&error]);
}
Are you sure you need two ratios ? If you want your image to have the right proportions, you should use only one ratio.
If you need to fill a rectangle ( Even if UIImageView does it for you ), then first compute the ratio on x axis. Compute the scaled height using this ratio, if it is smaller than the height you need to cover, then compute the ratio on y axis.
Finally, the ratio just computed is the one to use to scale your image.
I have a UIImageView which is sized to 366 x 375 (confirmed by NSLog statement) and a UIImage which is is sized to 400 x 600 (again confirmed with a log statement). I have tried setting the contentMode to preserve the image's aspect ratio, but when I run my app, the image is always distorted.
I tried setting the UIView's content mode to both UIViewContentModeScaleAspectFit and UIViewContentModeScaleAspectFill in turn. In both cases, the photo is still distorted in the same way. I also tried, just for kicks, UIContentModeLeft, which also resulted in the same distort presentation. My understanding is that these 3 modes should have presented very different images.
I've done a ctrl-f through the view controller code, but there is only once occurrence of contentMode and it is where I am setting the property. Are there other properties I should look at that could be interfering?
Here is the code that sets up the image view and accompanying image. This is the only code in the whole project that refers to the image view. Also I am not using any sort of auto layout features, though I don't see why that should affect aspect ratio and content mode anyhow.
NSData *imageData = [NSData dataWithContentsOfURL:filePath];
self.imageView.contentMode = UIViewContentModeScaleAspectFit;
self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, self.height*.11, self.width, self.height*.55)];
self.imageView.image = [UIImage imageWithData:imageData];
NSLog(#"Image height and width are %f and %f", self.imageView.image.size.height, self.imageView.image.size.width);
NSLog(#"imageview height and width are %f and %f", self.imageView.frame.size.height, self.imageView.frame.size.width);
[self.view addSubview: self.imageView];
Why doesn't the contentMode affect how my image is displayed, and how can I fix this? Ultimately I want to use the scale aspect fill option so there is no empty space within the image view but so that the aspect is also preserved.
Try this
self.imageView.contentMode = UIViewContentModeScaleAspectFill
EDIT
self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, self.height*.11, self.width, self.height*.55)];
self.imageView.contentMode = UIViewContentModeScaleAspectFit;
self.imageView.image = [UIImage imageWithData:imageData];
NSLog(#"Image height and width are %f and %f", self.imageView.image.size.height, self.imageView.image.size.width);
NSLog(#"imageview height and width are %f and %f", self.imageView.frame.size.height, self.imageView.frame.size.width);
[self.view addSubview: self.imageView];
Set the content mode after u allocate the imageview
I am going to share my image to Instagram , but before sharing in need to user crop their own photo , so I used VPImageCropperViewController (https://github.com/windshg/VPImageCropper) to crop the image first then share it to Instagram but the result is over scaled image :
Crop area :
and the result :
here is my codes :
- (IBAction)shareIt:(id)sender {
UIGraphicsBeginImageContextWithOptions(captureView.bounds.size, NO, 0.0);
[captureView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * screenshot = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
VPImageCropperViewController *imgCropperVC =
[[VPImageCropperViewController alloc]
initWithImage:image
cropFrame:CGRectMake(0, 100.0f, self.view.frame.size.width,self.view.frame.size.width)
limitScaleRatio:3.0];
imgCropperVC.delegate = self;
[self presentViewController:imgCropperVC animated:YES completion:nil];
}
VPImageCropperDelegate
- (void)imageCropper:(VPImageCropperViewController *)cropperViewController didFinished:(UIImage *)editedImage {
[cropperViewController dismissViewControllerAnimated:YES completion:^{
NSURL *instagramURL = [NSURL URLWithString:#"instagram://location?id=1"];
if ([[UIApplication sharedApplication] canOpenURL:instagramURL]) {
NSURL *url;
docFile.delegate = self;
//Save image to directory
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *savedImagePath = [documentsDirectory stringByAppendingPathComponent:#"savedImage.jpg"];
NSData *imageData = UIImagePNGRepresentation(editedImage);
[imageData writeToFile:savedImagePath atomically:NO];
//load image
NSString *getImagePath = [documentsDirectory stringByAppendingPathComponent:#"savedImage.jpg"];
UIImage *tempImage = [UIImage imageWithContentsOfFile:getImagePath];
//Hook it with Instagram
NSString *jpgPath = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents/Image.ig"];
[UIImageJPEGRepresentation(tempImage, 1.0) writeToFile:jpgPath atomically:YES];
url = [[NSURL alloc] initFileURLWithPath:jpgPath];
docFile = [UIDocumentInteractionController interactionControllerWithURL:url];
[docFile setUTI:#"com.instagram.photo"];
docFile.annotation = #{#"InstagramCaption" : #" #geometrica" };
[docFile presentOpenInMenuFromRect:self.view.bounds inView:self.view animated:YES];
}else {
UIAlertView *errorToShare = [[UIAlertView alloc] initWithTitle:#"Instagram unavailable " message:#"You need to install Instagram" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[errorToShare show];
}
}];
}
It seems like the error here lies in the instatiation of your imgCropperVC. You are telling the cropper to crop out a specific rectangle (with your yellow border's size) from the image you are providing. Since you said in a comment here that the size of the picture is the same size as the screen, and since your result seems to be EXACTLY half of the width (it's cropped directly through his face), I sugges trying
[[VPImageCropperViewController alloc]
initWithImage:image
cropFrame:CGRectMake(0, 100.0f, self.view.frame.size.width*2,self.view.frame.size.width*2)
limitScaleRatio:3.0];
This might have something to do with #2x, though I'm not really sure this solves your issue for other images and in general.
I suspect the original picture to be bigger than the screen, and scaled down to fit it. If this is correct, weird things(not really) happen.
Your screen's size is probably 640px wide. Let's assume the original picture(picture.jpg) has a width of 1280 pixels or something. When showing this in your UIImageView in your ViewController or UIScrollView, it will obviously scale to fit, or else you wouldn't be able to see the entire picture. If you now use your line of code, then you are asking the cropper to crop out a width of 640 (the width of your own screen and rectangle) from a picture that is 1280px wide. The cropper doesn't care how wide your screen is, it just crops out 640px from a 1280px wide image because that's what you told it to do. This will result in the image being cut in half. If your image is scaled down (which it is by default, I guess), you'll need to use this scale in your line of code. If the original picture actually IS 1280px wide, then my above code will work, because I double the rectangle's size (The width of your view is probably 320, this is the same as 640 retina I believe).
If you multiply self.view.fram.size.width and height by the amount the picture has been zoomed, you should get the correct image. This also applies to the "static" 100.0f you send. For your VIEW it's 100f, but if the image is scaled up or down, this will not be correct. You need to multiply this with the same value as well. I'm sure you can get the zoom-scale from the scrollView or imageView or something.
I suggest testing your app with different image sizes. If an image with the exact same pixel-size as your UIView is tested, I think it will work perfectly, and will confirm my suspicion.
Finally I figure it out to crop image size there is a method in project demo called :
- (UIImage *)imageByScalingAndCroppingForSourceImage:(UIImage *)sourceImage targetSize:(CGSize)targetSize;
you can mention your target images size with it some thing like this :
image = [self imageByScalingAndCroppingForSourceImage:image targetSize:CGSizeMake(1024, 1024)];
I'm trying to download an image from an url and display into a cell (sample below):
NSURL *url = [NSURL URLWithString:#"http://images.google.com/intl/en_ALL/images/logos/images_logo_lg.gif"];
NSData *data = [NSData dataWithContentsOfURL:url];
[cell.imageView setImage:[UIImage imageWithData:data]];
Somehow when I display into the cell, it covers the whole cell, bigger than my UIImageView.
But If I display the image locally like below:
[cell.imageView setImage:[UIImage imageNamed:#"defaultProfile.png"]];
It fits perfectly into the UIImageView I set into the cell.
Why is this the case?
use scaleToFit property of imageview
Here is my function for which I draw a metronome image within my iOS program.
When I load it, the metronome image is loaded, but "flies" down from the top left of the screen to the desired position. This is not the behavior I wanted - I simply want the image to appear at the desired position. Could someone enlighten me why this happens, and how to fix it?
Many thanks in advance.
Pier.
- (void) drawMetronomeForBeat: (int) beatNumber withNumberOfBeats:(int) noBeats
{
// remove any previous instances first
if (metronomeImageView)
{
[metronomeImageView removeFromSuperview];
}
NSString * imageName = #"metronome";
NSString * noBeatsStr = [NSString stringWithFormat:#"%d", noBeats];
NSString * beatNumberStr = [NSString stringWithFormat:#"%d", beatNumber];
imageName = [imageName stringByAppendingString:noBeatsStr];
imageName = [imageName stringByAppendingString:#"b"];
imageName = [imageName stringByAppendingString:beatNumberStr];
UIImage* image = [UIImage imageNamed: imageName];
UIImageView * symbolImageView = [[UIImageView alloc] initWithImage:image];
[symbolImageView setFrame:CGRectMake(410.0f, 215.0f, symbolImageView.frame.size.width, symbolImageView.frame.size.height)];
metronomeImageView = symbolImageView;
[self.view addSubview:symbolImageView];
}
Replace this line
[symbolImageView setFrame:CGRectMake(410.0f, 215.0f, symbolImageView.frame.size.width, symbolImageView.frame.size.height)];
with
[symbolImageView setFrame:CGRectMake(410.0f, 215.0f, 22, 22)]; //Change 22, 22 according to size that you need.
The image view will become larger or smaller according to the size of "real image" you are displaying. So it will move some where so that imageview will stay center aligned.
EDIT:
I think you are setting different frame for symbolImageView.
Try this
symbolImageView.frame = metronomeImageView.frame;
I was using the Controller to display the images. I restructured my code so that the images are always "drawn" in the drawRect of the view code, like this..
- (void)drawRect:(CGRect)rect
{
if (metronomeImage)
{
[metronomeImage drawInRect:CGRectMake(410.0f, 215.0f, metronomeImage.size.width, metronomeImage.size.height)];
}
}
This works with no problems - note that I just used drawInRect and just UIImage instead of setFrame and UIImageView. I suppose I'll just follow the convention that anything graphical should be done in the view code, and not the controller.