how to rotate NSString drawinrect in CGContext - ios

how do i rotate a NSString to a certain degree ? when i draw a string together with an image.
i referred this SO question Drawing rotated text with NSString drawInRect but my Ellipse is gone.
//Add text to UIImage
-(UIImage *)addMoodFound:(int)moodFoundCount andMoodColor:(CGColorRef)mColour
{
float scaleFactor = [[UIScreen mainScreen] scale];
UIGraphicsBeginImageContextWithOptions(CGSizeMake(36, 36), NO,scaleFactor);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
//CGContextSetRGBFillColor(context, kCGAggressiveColor);
CGContextSetFillColorWithColor(context,mColour);
CGContextFillEllipseInRect(context, CGRectMake(0, 0, 36, 36));
CGContextSetRGBFillColor(context, 250, 250, 250, 1);
//nsstring missing after adding this 3 line
CGAffineTransform transform1 = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(65));
CGContextConcatCTM(context, transform1);
CGContextTranslateCTM(context, 36, 0);
////////////////////////////////////////////////
[[NSString stringWithFormat:#"%d",moodFoundCount ] drawInRect : CGRectMake(0, 7, 36, 18)
withFont : [UIFont fontWithName:monR size:17]
lineBreakMode : NSLineBreakByTruncatingTail
alignment : NSTextAlignmentCenter ];
CGContextRestoreGState(context);
UIImage *theImage=UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return theImage;
}

CGAffineTransformMakeRotation will rotate around the context's origin (in this case x = 0, y = 0).
To properly rotate your text you need to first translate the origin of the context with the center of the box containing the string, rotate and move back the origin to its original location.
Replace the 3 lines where you're applying the rotation with:
CGContextConcatCTM(context, CGAffineTransformMakeTranslation(18, 18));
CGContextConcatCTM(context, CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(65)));
CGContextConcatCTM(context, CGAffineTransformMakeTranslation(-18, -18));

Related

Why is CGContextDrawImage rotating my image

I'm trying to change the color of an area of my UIImage with CGContext then create a new image from the current state. The original image has the correct orientation but after this, the image turns side ways.
CGRect imageRect = CGRectMake(0, 0, originalImage.size.width, originalImage.size.height);
UIGraphicsBeginImageContextWithOptions(originalImage.size, false, originalImage.scale);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGContextDrawImage(context, imageRect, originalImage.CGImage);
CGContextSetRGBFillColor(context, 255.0f, 255.0f, 255.0f, 1.0f);
CGContextFillRect(context, CGRectMake(5,5,100,100));
CGContextRotateCTM (context, radians(270));
CGContextRestoreGState(context);
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
It's a very easy question.
Because iOS system has 3 different Coordinate System.
UIKit - y axis direction is down
Core Graphics(Quartz) - y axis direction is up
OpenGL ES - y axis direction is up
The originalImage is create by UIKit and the target image is create by Core Graphics, so it should be upside-down.
If you want get the correct image, you can use:
UIImageView* imageV = [[UIImageView alloc] initWithFrame:CGRectMake(100,100, 100, 100)];
imageV.layer.borderColor = [UIColor redColor].CGColor;
imageV.layer.borderWidth = 1;
imageV.image = img;
imageV.layer.transform = CATransform3DRotate(imageV.layer.transform, M_PI, 1.0f, 0.0f, 0.0f);
[self.view addSubview:imageV];
Hope it can help you.

Rotating a NSString in drawRect

I want to rotate my NSString that's at a set location so that it reads from bottom to up.
I know the issue lies in the CGContextTranslateCTM, but I'm not sure how to fix it. If I comment this line, I see my text where I want it, just not rotated. This must be moving my NSString to where it is not visible.
Thoughts?
Here's what I have tried:
NSString * xString = [NSString stringWithFormat:#"%#", self.xStringValue];
CGContextSetFillColorWithColor(UIGraphicsGetCurrentContext(), [[UIColor blackColor] CGColor]);
CGContextSaveGState(UIGraphicsGetCurrentContext());
CGContextTranslateCTM(UIGraphicsGetCurrentContext(), 0, 0);
CGContextRotateCTM(UIGraphicsGetCurrentContext(), M_PI/2);
[xString drawInRect:(CGRectMake(x, y, width, height) withFont:self.Font];
CGContextRestoreGState(UIGraphicsGetCurrentContext());
EDIT:
The code above is drawing my NSString values, but they are being positioned off screen where I can not see them.
This code is actually getting them on screen, just not in the right place.
X and Y are both calculated distances.
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGAffineTransform transform = CGAffineTransformMakeRotation(-90.0 * M_PI/180.0);
CGContextConcatCTM(context, transform);
CGContextTranslateCTM(context, -rect.size.height-x, rect.size.height-y);
CGContextSetFillColorWithColor(UIGraphicsGetCurrentContext(), [[UIColor blackColor] CGColor]);
[xString drawInRect:CGRectMake(x, y, w, h) withFont:self.textFont];
CGContextRestoreGState(context);
}
EDIT THREE:
Solution:
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGContextTranslateCTM(context, point.x, point.y);
CGAffineTransform textTransform = CGAffineTransformMakeRotation(-1.57);
CGContextConcatCTM(context, textTransform);
CGContextTranslateCTM(context, -point.x, -point.y);
CGContextSetFillColorWithColor(UIGraphicsGetCurrentContext(), [[UIColor whiteColor] CGColor]);
[string drawInRect:CGRectMake(x, y, width, height) withFont:font];
CGContextRestoreGState(context);
If you want to rotate a UILabel vertically (90°) you can do :
[_myLabel setTransform:CGAffineTransformMakeRotation(-M_PI / 2)];
The result for a UILabel :

IOS create PDF file with rotation text

I create pdf file. I need to draw rotation text. In current time I have this pdf file
My code which draw the text
............
CGContextTranslateCTM(context, 0, frameRect.origin.y*2);
CGContextScaleCTM(context, 1.0, -1.0);
// Draw the frame.
CTFrameDraw(frame, context);
// Add these two lines to reverse the earlier transformation.
CGContextScaleCTM(context, 1.0, -1.0);
CGContextTranslateCTM(context, 0, (-1)*frameRect.origin.y*2);
I know that I must use CGContextRotateCTM(CGContextRef c, GFloat angle), but I bad understand transformation and I can't do as I need.
The following adds text rotated -90 degrees to the specified context at the yOffset from the top of the page:
+(void)addRotatedLabel:(CGContextRef)context atYOffset:(CGFloat)yOffset{
// -90 degrees
CGFloat rotation = -M_PI / 2.f;
CGContextRotateCTM(context, rotation);
NSString *label = [NSString stringWithFormat:#"%#", #"some text"];
CGSize maxSize = CGSizeMake(300, 12);
UIFont *font = [UIFont systemFontOfSize:7.5f];
CGSize textSize = [label sizeWithFont:font constrainedToSize:maxSize lineBreakMode:NSLineBreakByClipping];
CGRect titleRect = CGRectMake(-yOffset, 32.f - textSize.height + 3.f, textSize.width, textSize.height);
[[UIColor blackColor] setFill];
[label drawInRect:titleRect withFont:font];
CGContextRotateCTM(context, -rotation);
}
It can be easily modified to handle other rotations, font sizes, pass in the NSString, etc.

IOS: CGRect is right, but UIImage flipped

I know i have to translate the coordinate system, when drawing. The thing is that when i use:
CGContextTranslateCTM(_context, 0.0, _size.height);
CGContextScaleCTM(_context, 1.0, -1.0);
My rect of the image is flipped, and the image is 'non-flipped', if i dont use the above my image is flipped, and the rect is non-flipped.
Here's my code:
CGRectMake(60, 100, image.size.width, image.size.height);
CGContextSaveGState(_context);
UIGraphicsBeginImageContext(image.size);
CGContextClearRect(_context, placeholderRect);
CGContextDrawImage(_context, placeholderRect, image.CGImage);
UIGraphicsEndImageContext();
CGContextRestoreGState(_context);
How do i maintain my rect (non-flipped), while the image is flipped?
Thanks
Instead of using CGContextDrawImage use [image drawAtPoint:CGPointMake(0,0)];
The trick may lie in this UIImage method
+ (UIImage *)imageWithCGImage:(CGImageRef)imageRef scale:(CGFloat)scale orientation:(UIImageOrientation)orientation
Where orientation is one of these :)
typedef enum {
UIImageOrientationUp,
UIImageOrientationDown, // 180 deg rotation
UIImageOrientationLeft, // 90 deg CCW
UIImageOrientationRight, // 90 deg CW
UIImageOrientationUpMirrored, // as above but image mirrored along other axis. horizontal flip
UIImageOrientationDownMirrored, // horizontal flip
UIImageOrientationLeftMirrored, // vertical flip
UIImageOrientationRightMirrored, // vertical flip
} UIImageOrientation;
Edit: Update
I just did this simple code sample in a UIView subclass overriding drawrect and it worked perfectly. It doesn't use the UIImage method but works all the same.
UIImage *image = [UIImage imageNamed:#"image.png"];
CGContextRef _context = UIGraphicsGetCurrentContext();
CGContextSaveGState(_context);
CGContextDrawImage(_context, CGRectMake(100, 20, image.size.width, image.size.height), image.CGImage);
CGContextScaleCTM(_context, -1.0f, 1.0f);
CGContextDrawImage(_context, CGRectMake(-300, 20, image.size.width, image.size.height), image.CGImage);
CGContextRestoreGState(_context);

self.bounds confusion

In this code
CGRect contextRect = self.bounds;
will refer which bound? rectangle, imageRect, or whole iOS view.
I am trying to manipulate image using quartz2D, i created this code by looking different examples, and code written between // is from Apple Quartz2D guide draw text.
Thanks in advance,
Regards.
- (void)drawRect:(CGRect)rect
{
CGSize cgs = CGSizeMake(250.0, 400.0);
UIGraphicsBeginImageContext(cgs);
CGRect rectangle = CGRectMake(0,0,cgs.width,cgs.height);
CGRect imageRect = CGRectInset(rectangle, 5.4, 5.4);
imageRect.size.height -= 100;
UIImage *myImage = [UIImage imageNamed:#"pumpkin.jpg"];
[myImage drawInRect:imageRect];
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 10.0);
CGContextSetRGBStrokeColor(context, 0.0, 0.0, 1.0, 1.0);
CGContextStrokeRect(context, rectangle);
//
CGRect contextRect = self.bounds;
CGContextTranslateCTM(context, 0, contextRect.size.height);
CGContextScaleCTM(context, 1, -1);
float w, h;
w = contextRect.size.width;
h = contextRect.size.height;
CGAffineTransform myTextTransform;
CGContextSelectFont (context, "Helvetica-Bold", h/10, kCGEncodingMacRoman);
CGContextSetCharacterSpacing (context, 10);
CGContextSetTextDrawingMode (context, kCGTextFillStroke);
CGContextSetRGBFillColor(context, 0, 1, 0, .5);
CGContextSetRGBStrokeColor(context, 0, 0, 1, 1);
myTextTransform = CGAffineTransformMakeRotation(0);
CGContextSetTextMatrix(context, myTextTransform);
CGContextShowTextAtPoint(context, 0, 50, "Quartz 2D", 9);
//
UIImage *testImg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[testImg drawAtPoint:CGPointMake(35, 10)];
}
self.frame indicates the coords and size of the view in its parent view coordinate system.
self.bounds indicates the coords and size of the view in its own coordinate system. So it always has the same width and height as self.frame, but it has x and y equal to 0.
self.bounds is equal to CGRectMake(0, 0, self.frame.size.width, self.frame.size.height).
So your code:
CGRect contextRect = self.bounds;
is the same as:
CGRect contextRect = rect;

Resources