Restrirct Boundary 320 x 480, while scaling UIImage - iphone

I am working on Interior Decoration Application, we can add Sofa, Table, Chair Table Lamp on Camera screen then can scale UIImage with touch to zoom picture. But by zooming we don't want to increase UIImage Size greater then 320 x 480, I mean want to restrict in iphone Boundary.
any suggestion, I had implemented and tried, but couldn't get exact solution. I use to check on base of center but this approach is not working, want some thing like Edge detection may be that would be exact solution,
Already Thanks, looking forwards
here is some code that I am using to Resize my UIImageView
-(BOOL)isValidSizeForView:(UIView *)myView forSize:(CGSize)size
{
BOOL Decision = NO;
CGRect rect = myView.frame;
CGRect BoundRect = CGRectMake(0, 0, 320, 480);
float MinX = (BoundRect.origin.x+(myView.frame.size.width/2));
float MaxX = ((BoundRect.origin.x+BoundRect.size.width)-(myView.frame.size.width/2));
float MinY = (BoundRect.origin.y+(myView.frame.size.height/2));
float MaxY = ((BoundRect.origin.y+BoundRect.size.height)-(myView.frame.size.height/2));
if(rect.origin.x > MinX && rect.origin.x< MaxX && rect.origin.y> MinY && rect.origin.y<MaxY)
{
Decision = YES;
}
else
{
printf(":( no sorry \n");
}
return Decision;
}

You could get the maximum zoomed size for your image by doing something like this:
- (CGSize)zoomedSizeForImage:(UIImage *)image constrainedTo:(CGSize)maxSize {
CGFloat width = image.size.width;
CGFloat height = image.size.height;
if (width > maxSize.width) {
width = maxSize.width;
height = height * maxSize.width / width;
}
if (height > maxSize.height) {
width = width * maxSize.height / height;
height = maxSize.height;
}
return CGSizeMake(width, height);
}

Related

Using CATiledLayer to display a large image that has been programmatically split into tiles

I'm running into an issue with using CATiledLayer... I have a large image, a map, that is 4726 x 2701. Basically I'm needing to break this image into tiles and be able to zoom in to view a lot of detail, but also be able to zoom all the way out and see the entire map. Using my current implementation it works perfectly if the zoomlevel of the scrollview is set to 1.0 (the maximum zoomscale), but if you zoom out the tile are replaced incorrectly.
Here the zoomlevel is set to 1.0. The map looks perfect.
But if the zoomlevel is all the way out (0.2 I believe) the map is all messed up. I should be seeing the entire map not just two tiles.
Here is how I'm getting the tiles from the large image:
- (UIImage *)tileForScale:(CGFloat)scale row:(int)row col:(int)col {
float tileSize = 256.0f;
CGRect subRect = CGRectMake(col*tileSize, row * tileSize, tileSize, tileSize);
CGImageRef tiledImage = CGImageCreateWithImageInRect([mapImage CGImage], subRect);
UIImage *tileImage = [UIImage imageWithCGImage: tiledImage];
return tileImage;
}
I'm displaying the tiles exactly like Apple does in the PhotoScroller application.
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGFloat scale = CGContextGetCTM(context).a;
CATiledLayer *tiledLayer = (CATiledLayer *)[self layer];
CGSize tileSize = tiledLayer.tileSize;
tileSize.width /= scale;
tileSize.height /= scale;
int firstCol = floorf(CGRectGetMinX(rect) / tileSize.width);
int lastCol = floorf((CGRectGetMaxX(rect)-1) / tileSize.width);
int firstRow = floorf(CGRectGetMinY(rect) / tileSize.height);
int lastRow = floorf((CGRectGetMaxY(rect)-1) / tileSize.height);
for (int row = firstRow; row <= lastRow; row++) {
for (int col = firstCol; col <= lastCol; col++) {
UIImage *tile = [self tileForScale:scale row:row col:col];
CGRect tileRect = CGRectMake(tileSize.width * col, tileSize.height * row,
tileSize.width, tileSize.height);
tileRect = CGRectIntersection(self.bounds, tileRect);
[tile drawInRect:tileRect];
}
}
}
Also, here is the code where I'm setting the levels of detail, which returns 4 for my image:
- (id)initWithImageName:(NSString *)name andImage:(UIImage*)image size:(CGSize)size {
self = [super initWithFrame:CGRectMake(0, 0, size.width, size.height)];
if (self) {
_imageName = [name retain];
mapImage = [image retain];
CATiledLayer *tiledLayer = (CATiledLayer *)[self layer];
tiledLayer.levelsOfDetail = [self zoomLevelsForSize:mapImage.size];
}
return self;
}
- (NSUInteger)zoomLevelsForSize:(CGSize)imageSize {
int zLevels = 1;
while(YES) {
imageSize.width /= 2.0f;
imageSize.height /= 2.0f;
if(imageSize.height < 256.0 || imageSize.width < 256.0) break;
++zLevels;
}
return zLevels;
}
I'm assuming it has something to do with the tile size and the zoom scale, but I really have no clue how to solve the problem. I can't seem to find any solutions to my issue on the Google. Any help would be great! :)
You have a leak in - (UIImage *)tileForScale:(CGFloat)scale row:(int)row col:(int)col.
CGImageRef tiledImage = CGImageCreateWithImageInRect([mapImage CGImage], subRect);
Don't forget to release the CGImageRef: CGImageRelease(tiledImage);
I think there's a bug where the scale is incorrectly set in the sample code.
I have the following:
CGFloat scale = CGContextGetCTM(context).a;
scale = 1.0f / roundf(1.0f / scale);
if (scale == INFINITY) {
scale = 1.0f;
}

How restrict movement in animateWithDuration

I'm creating app where UILabel object will move over the screen. My question is how I can restrict the label to go over the specific border. For example if the label have a message, I want have the whole message visible, not just the first part of it.
This is the code:
#define kHeight 320.0
#define kWidth 400.0
#define kTransitionDuration 1.50
#define kTopPlacement 80.0
- (void)myMover {
for (UIView *view in self.view.subviews) {
if( [view isKindOfClass:[UILabel class]]){
[UIView animateWithDuration:4.0 animations:^{
//set the point from where the move will start
[self setRandomLocationForLabel:view];
}];
}
}
}
- (void) setRandomLocationForView:(UIView *)view
{
[view sizeToFit];
CGRect messageViewBounds = CGRectMake(round((self.view.bounds.size.width - kWidth) / 2.0),
200, kWidth, kHeight);
CGRect newFrame = CGRectMake( 0, 300, 100 , 20 );
while (view.frame.size.width > kWidth) {
newFrame.size.width /= 2;
newFrame.size.height /= 2;
}
view.frame = newFrame;
CGFloat x = (CGFloat) (arc4random() % (int) messageViewBounds.size.width + view.frame.size.width/2);
CGFloat y = (CGFloat) (arc4random() % (int) messageViewBounds.size.height + view.frame.size.height/2);
view.center = CGPointMake (x,y);
}
Thank you for any advice!
Since you have the view you know its size. By knowing the width you know how far you need to position the center of the view from left or right (half the width). By knowing the height you know how from top or bottom (half the height).
Now you can calculate the rectangle that contains only the valid center points for that view by taking the full view and create an inset rectangle with half the width of your view subtracted on both left and right and half the height of your view subtracted on both top and bottom.
CGSize viewSize = view.bounds.size; // The view you are positioning
CGRect rectOfValidCenters = CGRectInset(self.view.bounds, // The view you are placing it in
viewSize.width/2.0, // subtract the width/2 from left and right
viewSize.height/2.0); // subtract the height/2 form top and bottom
CGFloat randomX = // generate random value from 0.0 to 1.0
CGFloat randomY = // generate random value from 0.0 to 1.0
// Random valid center point is:
// ( minX + randomX * width , minY + randomY * height)
//
// if x and y are zero then the view's center will be in the upper left
// of the rect of valid centers (making its upper left corner be in the
// top left of the view it's placed in).
// if x and y are one then the view's center will be in the lower right
// of the rect of valid centers (making its lower right corner be in the
// lower right of the view it's placed in).
CGPoint randomValidPoint = CGPointMake(CGRectGetMinX(rectOfValidCenters) + randomX * CGRectGetWidth(rectOfValidCenters),
CGRectGetMinY(rectOfValidCenters) + randomY * CGRectGetHeight(rectOfValidCenters));
view.center = randomValidPoint;
My question is how I can restrict the label to go over the specific border. For example if the label have a message, I want have the whole message visible, not just the first part of it.
You will need to take into account the length/width and height of the label when determining the random position it should land on. As such, your random selection should land in the area of
CGSize labelSize = [messageString sizeWithFont:messageString.font
constrainedToSize:maximumLabelSize
lineBreakMode:messageString.lineBreakMode];
CGFloat minX = 0;
CGFloat minY = 0;
CGFloat maxX = self.view.frame.size.width - labelSize.width;
CGFloat maxY = self.view.frame.size.height - labelSize.height;
// Use minX/Y and maxX/Y in your random co-ordinate algorithm

How to rotate original image without resizing(not expand width or height) the image

I have rotate the image using UIRotationGestureRecognizer and it's working fine. But the image width & height increased.
Original Image Size: x = 85.000000, y = 83.000000, width = 150.000000, height = 150.000000
After rotating image size : x = 54.476551, y = 52.476551, width = 211.046906, height = 211.046906
How to handle this problem? I am trying like this:
recognizer.view.transform = CGAffineTransformRotate(recognizer.view.transform, recognizer.rotation);
recognizer.rotation = 0;
CGAffineTransform transform = self.view.transform;
if (UIDeviceOrientationLandscapeLeft == deviceOrientation) {
transform = CGAffineTransformRotate(transform, -(M_PI / 2.0));
} else {
transform = CGAffineTransformRotate(transform, M_PI / 2.0);
}
self.view.transform = transform;
I hope it helps

How to make border image to be fitted as per aspectfit uiimageview size?

In my application i have 2 uiimageview.one imageview contains the image that user selects either from photo library or take picture from camera.contentmode of this imageview is aspectfit so that image is not stretched if it is of lesser size.There is other imageview which contains image that is border to that first imageview.when user selects a image that is of similar size of imageview then border is appropriate place.but when image is of lesser size border is not coming properly.there is gap between border image and selected photo image.i dont want that gap.How can i fix this?
The issue got solved by using following code:
-(CGRect)frameForImage:(UIImage*)image inImageViewAspectFit:(UIImageView*)imageView
{
float imageRatio = image.size.width / image.size.height;
float viewRatio = imageView.frame.size.width / imageView.frame.size.height;
if(imageRatio < viewRatio)
{
float scale = imageView.frame.size.height / image.size.height;
float width = scale * image.size.width;
float topLeftX = (imageView.frame.size.width - width) * 0.5;
return CGRectMake(topLeftX, 0, width, imageView.frame.size.height);
}
else
{
float scale = imageView.frame.size.width / image.size.width;
float height = scale * image.size.height;
float topLeftY = (imageView.frame.size.height - height) * 0.5;
return CGRectMake(0, topLeftY, imageView.frame.size.width, height);
}
}

UIScrollView height to adjust when width is adjusted

I have a UIScrollView and I wanted the frame height to adjust proportionally when I adjust the width, is this possible? Basically I am talking about auto adjusting the frame height of the UIScrollView when I adjust the width of the UIScrollView? I have tried setting the autoResizingMask to UIViewAutoresizingFlexibleWidth and height, but this doesn't work
I don't think there's an automatic way to do it. but you can added a UIView+SCaleAddition to do this:
#interface UIView(RespectScale)
- (void)setWidthRespect:(float)w;
- (void)setHeightRespect:(float)h;
#end
#implement UIView(RespectScale)
- (void)setWidthRespect:(float)w
{
float scale = self.bounds.size.width / self.bounds.size.height;
float h = w/scale;
CGRect bounds = self.bounds
bounds.size.width = w;
bounds.size.height = h;
self.bounds = bounds;
}
- (void)setHeightRespect:(float)h
{
// write it your own
}
#end
You can do:
//get old proportions
CGFloat proportion = scrollView.frame.size.width / scrollView.frame.size.height;
CGRect frame = scrollView.frame;
frame.size.width = new_width;
frame.size.height = new_width * proportion;
scrollView.frame = frame;