We are coding in iOS 7.x and I came to the following code snippet:
if ( condition ) {
if (UIScreen.mainScreen.scale > 1) {
self.canvas.image = [myImage imageScaledToFitSize:CGSizeMake(30,30)];
} else {
self.canvas.image = [myImage imageScaledToFitSize:CGSizeMake(60,60)];
}
}
Is this the proper way to code? If this "retina" check is the way to go, then it should
be placed everywhere in the code.
If this UIScreen.mainScreen.scale is not correct, could you please point the correct way to go for retina/non-retina display handling?
Seems a bit hardcoded; better would be:
if ( condition ) {
CGFloat scale = UIScreen.mainScreen.scale;
self.canvas.image = [myImage imageScaledToFitSize:CGSizeMake(60.0 / scale, 60.0 / scale)];
}
However it's not clear to me what the 60 signifies...
Related
Update: partially working implementation below.
I've asked a couple questions on this previously here and here.
The first works great to determine if the "image" rect is sufficiently contained inside the "crop" rect.
The second works a little bit, but something's off in my implementation of it that it doesn't really work.
I'm now looking at the problem a little differently, and would like to change the behavior:
When the user begins to rotate the image, I'll run the check method (below) to determine if it needs fixing or not.
If it does need fixing, rather than waiting until the user has finished rotating it, I'd like to resize the image simultaneously to fit the bounds. Is there a simpler (or more reliable) way to implement this behavior?
I'm going to block rotation greater than 35ยบ in either direction so that we don't have to worry about severe enlargements.
Assumptions/Constraints:
I'm using AutoLayout
Point of rotation will be the center of the crop rect, which may or may not be the center of the image rect.
This demonstrates it working with a square crop, but the user can resize it to whatever, so I imagine it's going to bite me in the ass even more so when it's not square.
Code:
- (BOOL)rotatedView:(UIView*)rotatedView containsViewCompletely:(UIView*)cropView {
// If this method returns YES, good! if NO, bad!
CGPoint cropRotated[4];
CGRect rotatedBounds = rotatedView.bounds;
CGRect cropBounds = cropView.bounds;
// Convert corner points of cropView to the coordinate system of rotatedView:
cropRotated[0] = [cropView convertPoint:cropBounds.origin toView:rotatedView];
cropRotated[1] = [cropView convertPoint:CGPointMake(cropBounds.origin.x + cropBounds.size.width, cropBounds.origin.y) toView:rotatedView];
cropRotated[2] = [cropView convertPoint:CGPointMake(cropBounds.origin.x + cropBounds.size.width, cropBounds.origin.y + cropBounds.size.height) toView:rotatedView];
cropRotated[3] = [cropView convertPoint:CGPointMake(cropBounds.origin.x, cropBounds.origin.y + cropBounds.size.height) toView:rotatedView];
// Check if all converted points are within the bounds of rotatedView:
return (CGRectContainsPoint(rotatedBounds, cropRotated[0]) &&
CGRectContainsPoint(rotatedBounds, cropRotated[1]) &&
CGRectContainsPoint(rotatedBounds, cropRotated[2]) &&
CGRectContainsPoint(rotatedBounds, cropRotated[3]));
}
Taking even yet a different spin on this, I'm getting there. But as you can see in the .gif, eventually the calculations get out of whack because the rotation really isn't what I should be using to calculate the new size. How can I implement this with the correct geometry to ensure the image always resizes correctly? For time saving, I put this into an Xcode project so you don't have to fiddle around building your own: https://github.com/r3mus/RotationCGRectFix.git
- (IBAction)gestureRecognized:(UIRotationGestureRecognizer *)gesture {
CGFloat maxRotation = 40;
CGFloat rotation = gesture.rotation;
CGFloat currentRotation = atan2f(_imageView.transform.b, _imageView.transform.a);;
NSLog(#"%0.4f", RADIANS_TO_DEGREES(rotation));
if ((currentRotation > DEGREES_TO_RADIANS(maxRotation) && rotation > 0) || (currentRotation < DEGREES_TO_RADIANS(-maxRotation) && rotation < 0)) {
return;
}
CGAffineTransform rotationTransform = CGAffineTransformRotate(self.imageView.transform, rotation);
gesture.rotation = 0.0f;
if (gesture.state == UIGestureRecognizerStateChanged) {
CGFloat scale = sqrt(_imageView.transform.a * _imageView.transform.a + _imageView.transform.c * _imageView.transform.c);
if ((currentRotation > 0 && rotation > 0) || (currentRotation < 0 && rotation < 0))
scale = 1 + fabs(rotation);
else if (currentRotation == 0)
scale = 1;
else
scale = 1 - fabs(rotation);
CGAffineTransform sizeTransform = CGAffineTransformMakeScale(scale, scale);
CGPoint center = _imageView.center;
_imageView.transform = CGAffineTransformConcat(rotationTransform, sizeTransform);
_imageView.center = center;
}
}
Gif:
I am trying to experiment with UIViews on screen and using pan gestures. So I got some open source code from another project that I am looking at - and trying to learn a few things from it.
-(BOOL)isPointContainedWithinBezelRect:(CGPoint)point {
CGRect leftBezelRect;
CGRect tempRect;
CGFloat bezelWidth = 20;
CGRectDivide(self.view.bounds, &leftBezelRect, &tempRect, bezelWidth, CGRectMinXEdge);
return CGRectContainsPoint(leftBezelRect, point);
}
I understand that CGRectDivide function "Slices up a rect", but thats as far as I can make out.
I hope to get more clarification regarding the function. Also, how does the function return value vide a false / true value?
void CGRectDivide(
CGRect rect,
CGRect *slice,
CGRect *remainder,
CGFloat amount,
CGRectEdge edge
)
The CGRectDivide method splits a CGRect into two CGRects based on the CGRectEdge and distance from the rectangle side amount provided to the method.
Source
You should check
https://developer.apple.com/library/ios/documentation/graphicsimaging/reference/CGGeometry/Reference/reference.html#//apple_ref/c/func/CGRectDivide
and
http://nshipster.com/cggeometry/
But it seems that this method could be simplified to
-(BOOL)isPointContainedWithinBezelRect:(CGPoint)point {
CGRect leftBezelRect = self.view.bounds;
leftBezelRect.size.width = 20;
return CGRectContainsPoint(leftBezelRect, point);
}
or even to
-(BOOL)isPointContainedWithinBezelRect:(CGPoint)point {
return CGRectContainsPoint(self.view.bounds, point) && (point.x <= 20);
}
I am using tesseract on my iOS device and it was working properly until recently it started to crash on me. I have been testing with the same image over and over again and prior to now I had it working about 75 times consecutively. The only thing I can think of is that I deleted the app from my iOS device and then ran it again through Xcode.
I am far from an expert on tesseract and I could really use some advice on what to do next, it would truly be a disappointment for all the hours I put in to go to waste because I cannot read the image anymore. Thank you
This is the crash error it appears to happen when the tesseract file in this method
- (BOOL)recognize
{
int returnCode = _tesseract->Recognize(NULL);// here is where the arrow points on the crash
return (returnCode == 0) ? YES : NO;
}
This is an old question from Alex G and I don't see any answer.
Does anyone find the root cause and solution? Please advice. Many thanks.
I hope you are using AVCaptureSession to take continuously photo and passing to tesseract after some image processing.
So before passing UIImage to tesseract for recognising you should check with this:
CGSize size = [image size];//your image
int width = size.width;
int height = size.height;
if (width < 100 || height < 50) {//UIImage must contain some some size
//Consider as invalid image
return;
}
//This condition is not mandatory.
uint32_t* _pixels = (uint32_t *) malloc(width * height * sizeof(uint32_t));
if (!_pixels) {
return;
//Consider as invalid image
}
I am trying to do collision detection between a rectangle and a circle. I came up with this method:
-(BOOL) isCollidingRect:(CCSprite *) spriteOne WithSphere:(CCSprite *) spriteTwo {
float diff = ccpDistance(spriteOne.position, spriteTwo.position);
float obj1Radii = [spriteOne boundingBox].size.width/2;
float obj2Radii = [spriteTwo boundingBox].size.width/2;
if (diff < obj1Radii + obj2Radii) {
return YES;
} else {
return NO;
}
}
and this is how I check it:
if ([self isCollidingRect:player WithSphere:blocker] == true) {
[self playerdeathstart];
}
This seems to work properly on the side of the rectangle but it doesn't above or below it. On the top and bottom, the collision occurs too early.
Is there a way I can get this collision to detected properly? Thank you for your help.
You can use CGRectIntersectsRect to achieve this.
-(BOOL) isCollidingRect:(CCSprite *) spriteOne WithSphere:(CCSprite *) spriteTwo {
return CGRectIntersectsRect([spriteOne boundingBox],[spriteTwo boundingBox]);
}
It is not pixel perfect but as i understand that is not necessary in this case.
This is not a solution for those who use Cocos2d-ObjC, but will help for Cocos2d-x devs (for instance, personally I found this topic because was searching for the same for my c++ game).
Cocos2d-x has method "intersectsCircle" for Rect class.
Here is how I solved in my c++ project almost the same problem as one described by you:
bool ObstacleEntity::hasCollisionAgainst(cocos2d::Sprite *spr)
{
cocos2d::Rect rect = cocos2d::Rect( spr->getPositionX(), spr->getPositionY(), spr->getBoundingBox().size.width, spr->getBoundingBox().size.height);
float rw = this->getBoundingBox().size.width / 2;
float rh = this->getBoundingBox().size.height / 2;
float radius = ( rw > rh ) ? rw : rh;
cocos2d::Vec2 center( this->getPositionX() + rw, this->getPositionY() + rh );
return rect.intersectsCircle( center, radius );
}
Passed Sprite here is rectangle, while ObstacleEntity always is almost ideally round.
Note that anchor points for all entities are set to lower left corner in my case.
I have written a code that I use for cropping purpose. The scenario is like, It has 4 uiviews
1) Top
2) Left
3) Right
4) Bottom
Each uiview is resized according to the desired change and the main uiview has a uiimageview which contains an image. when I run the code on iPhone 3, 3GS, iPad 2, iPad 4 it works fine but when i run it on iPhone 4G, it generates very undesired result. I know my code calculations are fine thats why they are working fine on every device except the iPhone 4G.
What will the issue be ? Any ideas ? Is uiview calculations are different for iPhone 4 or any other reason ?
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
// messageLabel.text = #"Drag Detected";
commonCropT = leftRect.frame.origin.y; // left.y or Right.y or Top.H is same thing
commonCropB = lowerRect.frame.origin.y;// left.H or Right.H or lower.y is same thing
commonCropL = leftRect.frame.size.width; //
commonCropR = rightRect.frame.origin.x;//
commonCropH = leftRect.frame.size.height;// left.width and right.width
leftYT = leftRect.frame.origin.y;
leftH = leftRect.frame.size.height;
leftYB = leftYT + leftH;
leftW = leftRect.frame.size.width; // leftXR
rightXL = rightRect.frame.origin.x;
rightW = rightRect.frame.size.width;
rightXR = rightXL + rightW;
rightYT = rightRect.frame.origin.y;
rightH = rightRect.frame.size.height;
rightYB = rightH + rightYT;
if (isTappedOnUpperLeftCorner)
{
if (commonCropR - movedPoint.x <= kWidthDifference)
return;
if (movedPoint.y < commonCropT )
{
commonCropH = commonCropH + (commonCropT - movedPoint.y);
}
else if (movedPoint.y > commonCropT )
{
if (commonCropB - movedPoint.y <= kHeightDifference ) {
return;
}
commonCropH = commonCropH - (movedPoint.y - commonCropT);
}
commonCropL = movedPoint.x;
commonCropT = movedPoint.y;
NSLog(#" cropW = %d ",cropW);
[upperRect setFrame:CGRectMake(upperRect.frame.origin.x, upperRect.frame.origin.y, upperRect.frame.size.width, commonCropT)];
[leftRect setFrame:CGRectMake(leftRect.frame.origin.x, commonCropT, commonCropL, commonCropH)];
[rightRect setFrame:CGRectMake(commonCropR, commonCropT, rightRect.frame.size.width, commonCropH)];
}
}
I believe the problem you're running into is similar to a problem I'm seeing. With the retina display the touch coordinates may be non-integral, e.g. 23.5. If you use non-integral value with the frame of a view you may run into this kind of behavior. It appears that UIView doesn't support non-integral values.
Use roundf() or a similar function at some point in your calculations to avoid this problem.