开发者

How can I modify this code, which rotates a CGImage, not to crop the image on rotate?

This function rotates a CGImage by an arbitrary number of degrees, but it clips the image a bit. How can I avoid the clipping?

Making the rectangle a bit larger seems to distort the image being rotated.

+ (CGImageRef)CGImageRotatedByAngle:(CGImageRef)imgRef angle:(CGFloat)angle {

  float angleInRadians = angle * (M_PI / 180);
  float width = CGImageGetWidth(imgRef);
  float height = CGImageGe开发者_开发知识库tHeight(imgRef);

  CGRect imgRect = CGRectMake(0, 0, width, height);
  CGAffineTransform transform = CGAffineTransformMakeRotation(angleInRadians);
  CGRect rotatedRect = CGRectApplyAffineTransform(imgRect, transform);

  CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
  CGContextRef bmContext = CGBitmapContextCreate(NULL,
                                                 rotatedRect.size.width,
                                                 rotatedRect.size.height,
                                                 8,
                                                 0,
                                                 colorSpace,
                                                 kCGImageAlphaPremultipliedFirst);
  CGColorSpaceRelease(colorSpace);
  CGContextTranslateCTM(bmContext,
                        +(rotatedRect.size.width/2),
                        +(rotatedRect.size.height/2));
  CGContextRotateCTM(bmContext, angleInRadians);
  CGContextTranslateCTM(bmContext,
                        -(rotatedRect.size.width/2),
                        -(rotatedRect.size.height/2));
  CGContextDrawImage(bmContext, CGRectMake(0, 0,
                                           rotatedRect.size.width,
                                           rotatedRect.size.height),
                                           imgRef);

  CGImageRef rotatedImage = CGBitmapContextCreateImage(bmContext);
  CFRelease(bmContext);
  [(id)rotatedImage autorelease];

  return rotatedImage;
}


The code as written does not account for the difference in the sizes of the source and destination images. You need to account for this before or when invoking CGContextDrawImage. The code as written also does not preserve the original aspect ratio of the image -- it uses the destination size and height rather than the original.

The most succinct way to achieve the answer to the OP's question in the example code is to replace the line


    CGContextDrawImage(bmContext, 
                       CGRectMake(0,
                                  0,
                                  rotatedRect.size.width
                                  rotatedRect.size.height), 
                       imgRef);

with


    CGContextDrawImage(bmContext, 
                       CGRectMake((rotatedRect.size.width-width)/2.,
                                  (rotatedRect.size.height-height)/2.,
                                  width,
                                  height), 
                       imgRef);



Not sure I fully get this. These geometry questions are très très difficile.

But just looking at the geometry I would try:

  • Round the rotated width and height up to nearest pixel.

  • Don't do the second translate.

  • Check the sign of the first translate and the first and second angle rotation.

  • Plot the image at rectangle (-width/2, -height/2, width, height).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜