UIImage remove some pixels issue - iphone

I have the application where user can erase image.
So if user touches some px of the image, alfa of these pixels should become lower.
For instance, if I touched (0,0) pixel of the image one time, (0,0) px opacity should become 0.9. If I touched that px 10 times I shouldn't see image at point (0,0).
What is the best approach to implement that?

This is the coe by which you can detect the touch values
CGPoint StartPoint = [touch previousLocationInView:self];
CGPoint Endpoint = [touch locationInView:self];
NSString *str = [NSString stringWithFormat:#"%f",StartPoint.x];
NSString *strlx = [NSString stringWithFormat:#"%f",StartPoint.y];
NSString *strcx = [NSString stringWithFormat:#"%f",Endpoint.x];
NSString *strcy = [NSString stringWithFormat:#"%f",Endpoint.y];
here touch is the object for UITouch.
I cann't say anything about the opacity.

If you want it fast (as in real time fast) you'll need to use OpenGL.
The best way to do it to create a mask of alpha values which will be applied on the original image using a custom built shader.
The easier way but slower is to get the raw pixels from the UIImage
and applying the alpha values on the raw pixels array and then turning it back to a UIImage (here is a nice example)

Related

Change color of pixel based on touch point

I want to change the color where user touch on image. I got some code to get the image data which is below
NSString * path = [[NSBundle mainBundle] pathForResource:#"filename" ofType:#"jpg"];
UIImage * img = [[UIImage alloc]initWithContentsOfFile:path];
CGImageRef image = [img CGImage];
CFDataRef data = CGDataProviderCopyData(CGImageGetDataProvider(image));
const unsigned char * buffer = CFDataGetBytePtr(data);
I know I can easily get the touch point but my questions are below
As we know in retina display 1 point = 2 pixel so, do I know need to change the colour of 2 pixel for single touch point? Please correct me If I am wrong anywhere?
How to get this two pixel from image data?
Add a gesture recognizer to the UIImageView that presents the image. When that recognizer is triggered, the location you care about will be...
// self.imageView is where you attached the recognizer. This == gestureRecognizer.view
CGPoint imageLocation = [gestureRecognizer locationInView:self.imageView];
Resolving this location to a pixel location device independently can be done by determining the scale factor of the image.
To get the image location, apply that scale factor to the gesture location...
CGPoint pixel = CGPointMake(imageLocation.x*image.scale, imageLocation.y*image.scale)
This should be the correct coordinate for accessing the image. The remaining step is to get the pixel data. This post provides a reasonable-looking way to do that. (Also haven't tried this personally).

Xcode - Google Street View api 3D panorama

My goal is to use the Google Street View API to display a full pledged panorama scrollable street view image to the user. Basically the API provides me with many images where I can vary the direction, height, zoom, location etc. I can retrieve all these and hope to stitch them together and view it. The first question is, do you know any resources that demoes this full google street view demo working? Where a user can swipe around to move street view around, just like in that old iOS 5 Map Street View thing that I am sure we all miss...
If not, I will be basically downloading hundreds of photos that differ in vertical and horizontal direction. Is there a library or API or resource or method where I can stitch all these photos together to make a big panorama and make it so the user can swipe to view the big panorama on the tiny iPhone screen?
Thanks to everyone!
I threw together a quick implementation to do a lot of this as a demo for you. There are some excellent open source libraries out there that make an amateur version of StreetView very simple. You can check out my demo on GitHub: https://github.com/ocrickard/StreetViewDemo
You can use the heading and pitch parameters from the Google StreetView API to generate tiles. These tiles could be arranged in a UIScrollView as both Bilal and Geraud.ch suggest. However, I really like the JCTiledScrollView because it contains a pretty nice annotation system for adding pins on top of the images like Google does, and its datasource/delegate structure makes for some very straight forward image handling.
The meaty parts of my implementation follow:
- (UIImage *)tiledScrollView:(JCTiledScrollView *)scrollView imageForRow:(NSInteger)row column:(NSInteger)column scale:(NSInteger)scale
{
float fov = 45.f / scale;
float heading = fmodf(column*fov, 360.f);
float pitch = (scale - row)*fov;
if(lastRequestDate) {
while(fabsf([lastRequestDate timeIntervalSinceNow]) < 0.1f) {
//continue only if the time interval is greater than 0.1 seconds
}
}
lastRequestDate = [NSDate date];
int resolution = (scale > 1.f) ? 640 : 200;
NSString *path = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/streetview?size=%dx%d&location=40.720032,-73.988354&fov=%f&heading=%f&pitch=%f&sensor=false", resolution, resolution, fov, heading, pitch];
NSError *error = nil;
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:path] options:0 error:&error];
if(error) {
NSLog(#"Error downloading image:%#", error);
}
UIImage *image = [UIImage imageWithData:data];
//Distort image using GPUImage
{
//This is where you should try to transform the image. I messed around
//with the math for awhile, and couldn't get it. Therefore, this is left
//as an exercise for the reader... :)
/*
GPUImagePicture *stillImageSource = [[GPUImagePicture alloc] initWithImage:image];
GPUImageTransformFilter *stillImageFilter = [[GPUImageTransformFilter alloc] init];
[stillImageFilter forceProcessingAtSize:image.size];
//This is actually based on some math, but doesn't work...
//float xOffset = 200.f;
//CATransform3D transform = [ViewController rectToQuad:CGRectMake(0, 0, image.size.width, image.size.height) quadTLX:-xOffset quadTLY:0 quadTRX:(image.size.width+xOffset) quadTRY:0.f quadBLX:0.f quadBLY:image.size.height quadBRX:image.size.width quadBRY:image.size.height];
//[(GPUImageTransformFilter *)stillImageFilter setTransform3D:transform];
//This is me playing guess and check...
CATransform3D transform = CATransform3DIdentity;
transform.m34 = fabsf(pitch) / 60.f * 0.3f;
transform = CATransform3DRotate(transform, pitch*M_PI/180.f, 1.f, 0.f, 0.f);
transform = CATransform3DScale(transform, 1.f/cosf(pitch*M_PI/180.f), sinf(pitch*M_PI/180.f) + 1.f, 1.f);
transform = CATransform3DTranslate(transform, 0.f, 0.1f * sinf(pitch*M_PI/180.f), 0.f);
[stillImageFilter setTransform3D:transform];
[stillImageSource addTarget:stillImageFilter];
[stillImageFilter prepareForImageCapture];
[stillImageSource processImage];
image = [stillImageFilter imageFromCurrentlyProcessedOutput];
*/
}
return image;
}
Now, in order to get the full 360 degree, infinite scrolling effect Google has, you would have to do some trickery in the observeValueForKeyPath method where you observe the contentOffset of the UIScrollView. I've started implementing this, but did not finish it. The idea is that when the user reaches either the left or right side of the view, the contentOffset property of the scrollView is pushed to the opposite side of the scrollView. If you can get the content to align properly, and you set up the contentSize just right, this should work.
Finally, I should note that the Google StreetView system has a limit of 10 images/second, so you have to throttle your requests or the IP address of the device will be blacklisted for a certain amount of time (my home internet is now blacked out from StreetView requests for the next few hours 'cause I didn't understand this at first).
you need to use UIScrollView, set its clipSubviews property to true, add all the images to the UIScrollView and the UIScrollView's contentsOffset according to the images.
You should use the method described on this post: http://mobiledevelopertips.com/user-interface/creating-circular-and-infinite-uiscrollviews.html
You will have to make some factory to transform images to the good size and to your viewport (iPhone/iPad). And then add some buttons where you can clicked to go to the next place.
Unfortunately, if you want to go to a globe version (instead of a tube one), I think you'll need to go full openGL to display images in this 3D surface.

uiimage not being put into subview correctly

This is a difficult problem to explain... but i'll do my best.
First a background on the problem, basically i am creating a paint like app for ios and wanted to add a functionality that allows the user to select part of the image (multi-touch shows an opaque rectangle) and delete/copy-paste/rotate that part. I have got the delete and copy-paste working perfectly but the rotation is another story. To rotate the part of the image I first start by copying the part of the image and setting it to be the background of the selected rectangle layer, then the user rotates by an arbitrary angle using a slider. The problem is that sometimes the image ends up being displayed from another location of the rectangle (meaning the copied image hangs off the wrong corner of the rectangle). I thought this could be a problem with my rectangle.frame.origin but the value for that seems to be correct through various tests. It also seems to change depending on the direction that the drag goes in...
These Are Screens of the problem
In each of the above cases the mismatched part of the image should be inside the grey rectangle, i am at a loss as to what the problem is.
bg = [[UIImageView alloc] initWithImage:[self crop:rectangle.frame:drawImage.image]];
[rectangle addSubview:bg];
drawImage is the users drawing, and rectangle is the selected grey area.
crop is a method which returns a part of a given image from a give rect.
I am also having trouble with pasting an arbitrarily rotated image.. any ideas on how to do that?
Edit: adding more code.
-(void)drawRect:(int)x1:(int)y1:(int)x2:(int)y2{
[rectangle removeFromSuperview];
rectangle = [[UIView alloc] initWithFrame:CGRectMake(x1, y1, x2-x1, y2-y1)];
rectangle.backgroundColor = [UIColor colorWithRed:0.9 green:0.9 blue:0.9 alpha:0.6];
selectionImage = drawImage.image;
drawImage.image = selectionImage;
[drawImage addSubview:rectangle];
rectangleVisible = true;
rectangle.transform = transformation;
Could it have anything to do with how i draw my rectangle? (above) I call this method from a part of a touchesMoved method (below) which may cause the problem (touch 1 being in the wrong location may cause width to be negative?) if so, is there an easy way to remedy this?
if([[event allTouches] count] == 2 && !drawImage.hidden){
NSSet *allTouches = [event allTouches];
UITouch *touch1 = [[allTouches allObjects] objectAtIndex:0];
UITouch *touch2 = [[allTouches allObjects] objectAtIndex:1];
[self drawRect:[touch1 locationInView:drawImage].x :[touch1 locationInView:drawImage].y:
[touch2 locationInView:drawImage].x :[touch2 locationInView:drawImage].y];
}
I'm not sure if this is your problem, but it looks like you are just assuming that touch1 represents the upper left touch. I would start out by standardizing the rectangle.
// Standardizing the rectangle before making it the frame.
CGRect frame = CGRectStandardize(CGRectMake(x1, y1, x2-x1, y2-y1));
rectangle = [[UIView alloc] initWithFrame:frame];

Alternative for UIPicker

Is there any other method for a SLOT-MACHINE app? This because a UIPICKER method doesn't have a slow animation effect.
This could be done using CALayer animation.
Your main slotMachineView layer's class will need to be CATransformLayer to allow 3D transforms of the sublayers.
Let's say you have 10 square images that represent the symbols on the reel. For each of your images, create a CALayer who's contents property is one of your images. Then to each layer you'll need to apply 2 transforms:
First you'll need to rotate each layer (2 * PI) / 10 about its X axis
Then translate some distance (which you'll need to calculate) along
the Z axis.
Now add these layers to your view's layer. You should now see a get "cylinder" of images around the X axis.
To rotate the cylinder you'll need to adjust the first transform - either with a CAAnimation or by using a timer and adjusting the X axis rotation by an offset she the timer fires.
I'll leave it to you to figure out the full implementation details - but here's some code to load and create an initial "reel"
int imageCount = 16;
for (int i = 0; i < imageCount; i++) {
// Load image from the bundle
NSString * fileName = [NSString stringWithFormat: #"Image-%d", i];
NSString * filePath = [[NSBundle mainBundle] pathForResource: fileName ofType: #"jpeg"];
UIImage * image = [UIImage imageWithContentsOfFile: filePath];
// Create a layer with the image as content - My image size was 60x60
CALayer * imageLayer = [CALayer layer];
imageLayer.bounds = (CGRect){CGPointZero, {60.0, 60.0}};
imageLayer.contents = (id)image.CGImage;
imageLayer.position = (CGPoint){CGRectGetMidX(self.view.bounds), CGRectGetMidY(self.view.bounds)};
// Set the initial image transform - I've hardcoded the translate along the
// z-axis to 150, but this will vary depending on the number of images
// and their size - you'll need to do some maths to work it out... sines or
// cosines or somesuch
CGFloat angle = (2.0 * M_PI) / imageCount * i;
CATransform3D transform = CATransform3DMakeRotation(angle, 1.0, 0.0, 0.0);
transform = CATransform3DTranslate(transform, 0.0, 0.0, 150.0);
imageLayer.transform = transform;
[self.layers addObject: imageLayer];
[self.view.layer addSublayer: imageLayer];
}
}
To rotate it, all you need to do is change the rotation part of the transform. For extra credit, you could add an increasing shadow to the layers as they move away from the centre.
You could use UIImageView for each digit/symbol, and animate the movement of the images that yo display. Using UIPicker there would be limited to letters and digits; with UIImageView you could add other typical slot-machine visuals, such as cherries, etc.
Are we doing your homework?
Use vertical UIScrollViews side by side, have paging enabled, UIImageViews for the views.
It will look flat by default - but it would be functionally equivalent.
You'd need a bit of Core Animation / Core Graphics to make it look more like the UIPickerView.

Way to draw NSString on a curved path? [duplicate]

Is there a set of string attributes I can specify that will draw the text at an angle when I call:
[label drawAtPoint:textStart withAttributes:attributes];
Here's an example that uses a transform to rotate the drawing context. Essentially it's just like setting a color or shadow, just make sure to use -concat instead of -set.
CGFloat rotateDeg = 4.0f;
NSAffineTransform *rotate = [[NSAffineTransform alloc] init];
[rotate rotateByDegrees:rotateDeg];
[rotate concat];
// Lock focus if needed and draw strings, images here.
[rotate release];
NSString itself doesn't have rotation, but you can rotate the context. The string will always be drawn "horizontally" as far as the coordinate space goes, but what actual direction that corresponds to depends on the context. Just use NSAffineTransform to spin it as needed.