Bergutov Ruslan
Bergutov Ruslan

Reputation: 157

Low pixel density when rotation UIImage

I have found a couple algorithm for our application to rotate annotations on MKMapView, and in every algorithm pixel density of image is crashing. Here is the example, green arrow annotation: Green arrow annotation example

Algorithm

Maybe someone knows algorithm or extension to perform correct rotation of image?

Upvotes: 1

Views: 58

Answers (1)

Rob
Rob

Reputation: 437632

Rather than UIGraphicsBeginImageContext, use UIGraphicsBeginImageContextWithOptions with zero for the last parameter. That will maximize the screen resolution to match your device's screen (e.g. retina).


Even when you create the retina resolution image, when you rotate a bitmap, you're going to be introducing some further pixelation. You may get the sharper results if you draw it yourself (e.g. in the drawRect of the annotation view's subclass):

@interface CustomUserAnnotationView : MKAnnotationView

@property (nonatomic) CGFloat angle;
@property (nonatomic) CGFloat lineWidth;
@property (nonatomic, strong) UIColor *strokeColor;
@property (nonatomic, strong) UIColor *fillColor;

@end

@implementation CustomUserAnnotationView

- (instancetype)initWithAnnotation:(id<MKAnnotation>)annotation reuseIdentifier:(NSString *)reuseIdentifier {
    self = [super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier];

    if (self) {
        self.lineWidth = 2;
        self.strokeColor = [UIColor lightGrayColor];
        self.fillColor = [UIColor greenColor];
        self.backgroundColor = [UIColor clearColor];
        self.frame = CGRectMake(0, 0, 50, 50);            
    }

    return self;
}

// you should probably `setNeedsDisplay` on the other properties' setters, too, but I'm assuming angle is the only one we're worried about right now.

- (void)setAngle:(CGFloat)angle {
    _angle = angle;
    [self setNeedsDisplay];
}

- (void)drawRect:(CGRect)rect {
    CGPoint center = CGPointMake(self.bounds.size.width / 2.0, self.bounds.size.height / 2.0);
    CGFloat radius = (MIN(self.bounds.size.width, self.bounds.size.height) - self.lineWidth) / 2.0;

    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint:   [self pointAtRadius:radius       percentAngle:0.0 center:center angleOffset:self.angle]];
    [path addLineToPoint:[self pointAtRadius:radius       percentAngle:0.4 center:center angleOffset:self.angle]];
    [path addLineToPoint:[self pointAtRadius:radius * 0.6 percentAngle:0.5 center:center angleOffset:self.angle]];
    [path addLineToPoint:[self pointAtRadius:radius       percentAngle:0.6 center:center angleOffset:self.angle]];
    [path closePath];
    path.lineWidth = self.lineWidth;
    path.lineJoinStyle = kCGLineJoinRound;

    [self.fillColor setFill];
    [path fill];

    [self.strokeColor setStroke];
    [path stroke];
}

- (CGPoint)pointAtRadius:(CGFloat)radius percentAngle:(CGFloat)percentAngle center:(CGPoint)center angleOffset:(CGFloat)angleOffset {
    CGFloat angle = M_PI * 2.0 * percentAngle + angleOffset;
    return CGPointMake(center.x + radius * sin(angle), center.y - radius * cos(angle));
}

@end

enter image description here

Upvotes: 1

Related Questions