UIImage Flip Image Direction - ios

For a certain UIImageView animationImages, I wish to create 2 arrays - one per each direction.
I have png files I can load into one of the directions, and I wish to flip each image and add it to second direction array.
I tried to do something like this:
_movingLeftImages = [NSMutableArray array];
_movingRightImages = [NSMutableArray array];
int imagesCounter = 0;
while (imagesCounter <= 8)
{
NSString* imageName = [NSString stringWithFormat:#"movingImg-%i", imagesCounter];
UIImage* moveLeftImage = [UIImage imageNamed:imageName];
[_movingLeftImages addObject:moveLeftImage];
UIImage* moveRightImage = [UIImage imageWithCGImage:moveLeftImage.CGImage scale:moveLeftImage.scale orientation:UIImageOrientationUpMirrored];
[_movingRightImages addObject:moveRightImage];
imagesCounter++;
}
Upon the relevant event, I load the UIImageView animationImages with the relevant array; like this:
if ( /*should move LEFT event*/ )
{
movingImageView.animationImages = [NSArray arrayWithArray:_movingLeftImages];
}
if ( /*should move RIGHT event*/ )
{
movingImageView.animationImages = [NSArray arrayWithArray:_movingRightImages];
}
The images are not flipped. They remain as they where.
Any idea how to handle this?

use this code for animating images
UIImageView * animatedImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 200,200)];
NSArray *imageNames = #[#"bird1.png", #"bird2.png"];
animTime =.0;
[animatedImageView setAnimationImages:imageNames] ;
animatedImageView.animationDuration = animTime;
animatedImageView.animationRepeatCount = 1;
[self.view addSubview: animatedImageView];
[animatedImageView startAnimating];

Related

ios imageview animation using array causes semaphore_wait_trap

I'm trying to animate an imageview by providing it with an array of images. These images have been extracted from a spritesheet having lots of images one after the other.
Here is my code:
-(NSMutableArray*)getIndividualImagesFromImage:(UIImage*)collectionOfEmoticonImages
{
NSMutableArray *imagesArray = [[NSMutableArray alloc] init];
//Let's find out the total number of images in this big image
int totalEmoticonImages = collectionOfEmoticonImages.size.width/WIDTH_HEIGHT_OF_EMOTICONS;
for(int emoticonIndex = 0; emoticonIndex < totalEmoticonImages; emoticonIndex++)
{
//crop the image at each index and put smaller images in the array
UIImage *croppedImage = [[UIImage alloc] init];
croppedImage = [self cropImage:collectionOfEmoticonImages atIndex:emoticonIndex];
[imagesArray addObject:croppedImage];
}
return imagesArray;
}
-(void)getEmoticonImageViewAnimating:(NSInteger)index
{
imagesArray = [self getIndividualImagesFromImage:[emoticonsPNGImages objectAtIndex:index]];
//Animate using the images in imagesArray
emoImageView.animationImages = [NSArray arrayWithArray:imagesArray];
emoImageView.animationDuration = 2;
emoImageView.animationRepeatCount = 1;
[emoImageView startAnimating];
[self performSelector:#selector(animationDidFinish) withObject:nil
afterDelay:emoImageView.animationDuration];
}
Everything works fine if I comment [emoImageView startAnimating]; line. But with this statement, animation works fine for 6 times but then I get a semaphore_wait_trap on trying to run it 7th time.
Any pointers?

NSMutableArray creates issue for images

I have an array with dictionaries in it. Each dictionary contains UIImage & String values.
But when I try to delete object using
[arr removeObjectAtIndex:button.tag];
then it just decreases the count but image (Object) is not deleted.
So, my Images are overlapping when try to delete.
It also creates problem when I try to add objects in the array
[arr insertObject:dict atIndex:0];
so, I used
[_postObj.arr_images addObject:dict]; instead of insertObject
Help me to solve this
Objects use reference counting and both NSMutableArray and UIImageView will retain the UIImage object.
This means that removing it from the array will not automatically remove it from the UIImageView and you must remove it from both explicitly:
[arr removeObjectAtIndex:button.tag];
_imageView.image = nil;
Problem is in your frame setting of UIImageView. Please try using below code (not tested by myself) and see if this fixes the issue for you. Basically, I am adjusting X position of images based on previous image's width.
CGFloat imageXM = 5.0;
CGFloat imageXPos = 0;
for (UIImage *image in arr_images) {
CGRect imageFrame = CGRectMake(imageXPos + imageXM, 0.0, image.size.width, image.size.height);
imageXPos = imageXPos + image.size.width;
UIImageView *imageView = [[UIImageView alloc] initWithFrame:imageFrame];
imageView.contentMode = UIViewContentModeScaleAspectFit;
imageView.image = image;
[scl addSubview:imageView];
}
As in your code
[picker dismissViewControllerAnimated:YES completion:^{
[arr_images insertObject:chosenImage atIndex:0];
[self scrollImages_Setup2];
}];
[arr_images insertObject:chosenImage atIndex:0]; that means you need only one image to display on scroll view. Then why you take a loop:
-(void)scrollImages_Setup2
{
for (int k=0; k<arr_images.count; k++) {
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake((CGRectGetWidth(scl.frame) * k) + CGRectGetWidth(scl.frame), 0, CGRectGetWidth(scl.frame), CGRectGetHeight(scl.frame))];
imageView.contentMode = UIViewContentModeScaleAspectFit;
imageView.image=[arr_images objectAtIndex:k] ;
[scl addSubview:imageView];
}
scl.contentSize = CGSizeMake((CGRectGetWidth(scl.frame) * arr_images.count)+CGRectGetWidth(scl.frame), CGRectGetHeight(scl.frame));
}
You just right the code only for display the Image. you don't need to scroll view for displaying only one image. I think you are not clear what you want.
Your problem regarding the overwriting the images because of loop. so remove the loop, when you display a single image. Please remove the scrollview contentSize, because image_array will increase, when you add the multiple images in array and size width will be large. so remove arr_images.count as well.

How to animate by changing the background image and chnage the position of an UIImageView

I am interested in obtaining an animation that not only animates from point A to point B but also changes the background image.
Say the initial position is 0,0 and the finis one is 0,100 ; the duration is 1 second, and i have 4 images for the background, then i want the background to change every 0/4 seconds and 25 px.
Until now I have the next code that animates the images but i still need to implement the movement and I don't know how to do just that.
Thanks in advance and here is what code I have until now:
UIImageView * animatedImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 50,50)];
testArray = [[NSArray alloc] initWithObjects:[UIImage imageNamed:#"test_1.png"], [UIImage imageNamed:#"test_2.png"], [UIImage imageNamed:#"test_3.png"],nil];
animTime =3.0;
[animatedImageView setAnimationImages:testArray] ;
animatedImageView.animationDuration = animTime;
animatedImageView.animationRepeatCount = 1;
[self.view addSubview: animatedImageView];
[animatedImageView startAnimating];
UPDATE:
I have implemented the answer of Mobile Project Lab into my code
// I have a pathArray that is in C style and is bidimensional, that stores the path in reverse
// the maps is a 2d tile map
// the dimensions of the tiles are 64x64 px
//thes size of the character is 128x128
for (int possitionInThePathArray = sizeOfPathArray - 1; possitionInThePathArray >= 0; possitionInThePathArray--) {
xWalkingDirection = pathArray[possitionInThePathArray-1][1] - pathArray[possitionInThePathArray][1];
yWalkingDirection = pathArray[possitionInThePathArray-1][0] - pathArray[possitionInThePathArray][0];
if (xWalkingDirection== 0 && yWalkingDirection == -1){
//walking animation to North for 1 tile
NSArray *testArray;
float animTime;
testArray = [[NSArray alloc] initWithObjects:[UIImage imageNamed:#"scientist_s0.png"],
[UIImage imageNamed:#"scientist_s1.png"],
[UIImage imageNamed:#"scientist_s2.png"],
[UIImage imageNamed:#"scientist_s3.png"],
[UIImage imageNamed:#"scientist_s4.png"],
[UIImage imageNamed:#"scientist_s5.png"],
[UIImage imageNamed:#"scientist_s6.png"],
[UIImage imageNamed:#"scientist_s7.png"],
[UIImage imageNamed:#"scientist_s8.png"],
[UIImage imageNamed:#"scientist_s9.png"], nil]; // 4th image added
animTime = 10.0; // time is changed to 10.0
[myCharacterFrame setAnimationImages:testArray];
myCharacterFrame.animationDuration = animTime;
myCharacterFrame.animationRepeatCount = 1;
[myCharacterFrame startAnimating];
[UIView animateWithDuration:animTime
animations:^{
myCharacterFrame.frame = CGRectOffset(myCharacterFrame.frame, 0.0f, -64.0f); // move 100 on x axis, 0 on y axis
}
completion:^(BOOL finished){
NSLog(#"animation done");
}];
yMyCharacterFrame = yMyCharacterFrame-64.0;
myCharacterFrame.frame = CGRectMake(xMyCharacterFrame, yMyCharacterFrame, 128, 128);
myCharacterFrame.image = [UIImage imageNamed:#"scientist_s0.png"];
}else if (xWalkingDirection== 1 && yWalkingDirection == 0){
//walking animation to Est for 1 tile
.....
//and so on for all the four directions of walking
The issue that I am facing now is that the animation are not triggered correctly, so that one animation takes places before the code moves on
NSArray *testArray;
float animTime;
UIImageView *animatedImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
testArray = [[NSArray alloc] initWithObjects:[UIImage imageNamed:#"test_001.png"], [UIImage imageNamed:#"test_002.png"],[UIImage imageNamed:#"test_001.png"], [UIImage imageNamed:#"test_002.png"], nil]; // 4th image added
animTime = 1.0; // time is changed to 1.0
[animatedImageView setAnimationImages:testArray];
animatedImageView.animationDuration = animTime;
animatedImageView.animationRepeatCount = 1;
[self.view addSubview: animatedImageView];
[animatedImageView startAnimating];
[UIView animateWithDuration:animTime
animations:^{
animatedImageView.frame = CGRectOffset(animatedImageView.frame, 100.0f, 0.0f); // move 100 on x axis, 0 on y axis
}
completion:^(BOOL finished){
NSLog(#"animation done");
}];

Retrieve the name of the UIImage at a specific point in a UIScrollView

I'm having trouble getting my head around this; I've looked around for answers on here but either nothing directly applies to my question or I just can't make sense of it. (I am relatively new to this, so apologise if there is an obvious answer.)
I am inserting an array of UIImages (contained within a UIImageView) into a UIScrollView. I can programmatically scroll to points in the ScrollView, but I need to be able to identify by name which image is currently being shown after scrolling (so I can compare the image to one in another ScrollView).
How I have created my arrays and added the images to the ImageView and ScrollView is below.
ViewController.m
-(void)viewDidLoad {
...
// Store the names as strings
stringArr = [[NSMutableArray arrayWithObjects:
#"img0",
#"img1",
#"img2",
#"img3",
nil] retain];
// Add images to array
dataArr = [[NSMutableArray arrayWithObjects:
[UIImage imageNamed:[stringArr objectAtIndex:0]],
[UIImage imageNamed:[stringArr objectAtIndex:1]],
[UIImage imageNamed:[stringArr objectAtIndex:2]],
[UIImage imageNamed:[stringArr objectAtIndex:3]],
nil] retain];
// Use a dictionary to try and make it possible to retrieve an image by name
dataDictionary = [NSMutableDictionary dictionaryWithObjects:dataArr forKeys:stringArr];
i = 0;
currentY = 0.0f;
// Set up contents of scrollview
// I'm adding each of the four images four times, in a random order
for (imageCount = 0; imageCount < 4; imageCount++) {
// Add images from the array to image views inside the scroll view.
for (UIImage *image in reelDictionary)
{
int rand = arc4random_uniform(4);
UIImage *images = [dataArr objectAtIndex:rand];
imgView = [[UIImageView alloc] initWithImage:images];
imgView.contentMode = UIViewContentModeScaleAspectFit;
imgView.clipsToBounds = YES;
// I have tried to use this to tag each individual image
imgView.tag = i;
i++;
CGRect rect = imgView.frame;
rect.origin.y = currentY;
imgView.frame = rect;
currentY += imgView.frame.size.height;
[scrollReel1 addSubview:reel1_imgView];
[reel1_imgView release];
}
}
scrollReel.contentSize = CGSizeMake(100, currentY);
[self.view addSubview:scrollReel];
...
}
This is how I am working out where I am in the ScrollView (currentOffset), and also exactly which image I need to retrieve (symbolNo). The value of symbolNo is correct when I test it, but I am unsure how to use the value with respect to image name retrieval.
NSInteger currentOffset = scrollReel.contentOffset.y;
NSInteger symbolNo = (currentOffset / 100) + 1;
Thanks in advance for any assistance.
There is no way to do this. The UIImage object doesn't store its name once it's loaded.
You could get around this by using the tag property on the image views if all your images have numerical names.
Otherwise you'll need to find a new way to model your data.
You basically need the reverse mapping of what you had. Here is a quick and dirty solution
NSMutableDictionary *indexToImageMap = [NSMutableDictionary new];
for (imageCount = 0; imageCount < 4; imageCount++) {
// Add images from the array to image views inside the scroll view.
for (UIImage *image in reelDictionary)
{
int rand = arc4random_uniform(4);
UIImage *images = [dataArr objectAtIndex:rand];
imgView = [[UIImageView alloc] initWithImage:images];
imgView.contentMode = UIViewContentModeScaleAspectFit;
imgView.clipsToBounds = YES;
// I have tried to use this to tag each individual image
imgView.tag = i;
i++;
[indexToImageMap setObject:imgView forKey:[NSNumber numberWithInt:i];
CGRect rect = imgView.frame;
rect.origin.y = currentY;
imgView.frame = rect;
currentY += imgView.frame.size.height;
[scrollReel1 addSubview:reel1_imgView];
[reel1_imgView release];
}
}
And to look it up you do
NSInteger currentOffset = scrollReel.contentOffset.y;
NSInteger symbolNo = (currentOffset / 100) + 1;
NSImage *image = [indexToImageMap objectForKey:[NSNumber numberWithInt:symbolNo]];
Subclass image view and add imageName property. if i understand what you are asking this should work.
#import <UIKit/UIKit.h>
#interface myImageView : UIImageView
{
__strong NSString *imageName;
}
#property (strong) NSString *imageName;
#end
#import "myImageView.h"
#implementation myImageView
#synthesize imageName;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
#end
then use a dictionary to keep everything instead of array + dictionary.
myImageView *imgView1 = [[myImageView alloc] init];
[imgView1 setImageName:#"image_name_here"];
[imgView1 setImage:[UIImage imageNamed:#"image_name_here"]];
NSMutableDictionary *dicti = [[NSMutableDictionary alloc] init];
[dicti setObject:imgView1 forKey:#"image_name_here_1"];
[dicti setObject:imgView2 forKey:#"image_name_here_2"];
[dicti setObject:imgView... forKey:#"image_name_here_..."];
when you find the imageView you can search image in dictionary. because you know name of the imageView now.

Trouble with animation on UIImageView

I have 7 images which i'm trying to make fade in/out of 1 ImageView. I have stored all the images in an array, and then have a loop to display each image and fade into the next, however, when i run the program only the last 2 images show up. Any ideas on why this is? and how to fix it? Code is below.
imageArray = [NSArray arrayWithObjects:
[UIImage imageNamed:#"image 0.jpg"],
[UIImage imageNamed:#"image 1.jpg"],
[UIImage imageNamed:#"image 2.jpg"],
[UIImage imageNamed:#"image 3.jpg"],
[UIImage imageNamed:#"image 4.jpg"],
[UIImage imageNamed:#"image 5.jpg"],
[UIImage imageNamed:#"image 6.jpg"],
nil];
self.imageview.backgroundColor = [UIColor blackColor];
self.imageview.clipsToBounds = YES;
int count = [imageArray count];
for (int i = 0; i <count-1 ; i++)
{
UIImage *currentImage = [imageArray objectAtIndex: i];
UIImage *nextImage = [imageArray objectAtIndex: i +1];
self.imageview.image = [imageArray objectAtIndex: i];
[self.view addSubview:self.imageview];
CABasicAnimation *crossFade = [CABasicAnimation animationWithKeyPath:#"contents"];
crossFade.duration = 5.0;
crossFade.fromValue = (__bridge id)(currentImage.CGImage);
crossFade.toValue = (__bridge id)(nextImage.CGImage);
[self.imageview.layer addAnimation:crossFade forKey:#"animateContents"];
self.imageview.image = nextImage;
};
Some things to note:
1) You are doing everything synchronously on a loop that has no delay between each transition, there's no point in animating a if on the next loop it will be replaced by the next and so on, until the last 2. Also, you are adding your imageView as a subview every time, also unnecessary.
2) You are changing the .image property of the imageView, and then changing the contents of the layer. Might as well use an UIView and have the same effect.
My recommendation is to make a method to swap from one image to the next, and have a NSTimer call the function every x amount of seconds until you passed through them all.
Edit: For the future:
self.imageview.backgroundColor = [UIColor blackColor];
self.imageview.clipsToBounds = YES;
are completely unnecessary :)
The .backgroundColor is drawn over by the UIImage you are displaying.
The .clipsToBounds is the default behavior of UIImageView (it shrinks/expands your image to it's size, but never draws outside)

Resources