1

在我的应用程序中,我有一个主视图(及其 UIGraphicsGetCurrentContext())和其他几个 CGContextRef 画布。所有这些都是相同的大小,屏幕的大小 - 没有比例因子。

我在辅助画布上绘制,最后在辅助画布上使用 CGBitmapContextCreateImage 并在主画布上使用 CGContextDrawImage 绘制。

在视网膜显示器上,结果很差,所有线条看起来都像素化了。我应该如何处理视网膜显示器上的绘画?

以下是我用来将上下文绘制到主上下文的代码:

void CocoaGraphicsContext::drawContext(GraphicsContext* context, double x, double y, Box* cropBox, Matrix3D* matrix)
{
    CGAffineTransform matInverted;

    if (matrix != NULL)
    {
        CGAffineTransform transMat = CGAffineTransformMake(matrix->vx1, matrix->vy1, matrix->vx2, matrix->vy2, matrix->tx, matrix->ty);
        matInverted = CGAffineTransformInvert(transMat);

        CGContextConcatCTM(_cgContext, transMat);
    }

    CGImageRef cgImage = CGBitmapContextCreateImage(((CocoaGraphicsContext*)context)->cgContext());

    CGContextSaveGState(_cgContext);
    CGContextSetInterpolationQuality(_cgContext, kCGInterpolationNone);

    bool shouldCrop = ((cropBox != NULL) && (cropBox->valid()));

    if (shouldCrop)
    {
        CGContextClipToRect(_cgContext, CGRectMake(cropBox->x(), cropBox->y(), cropBox->width(), cropBox->height()));
    }

    CGContextDrawImage(_cgContext, CGRectMake(x, y, context->width(), context->height()), cgImage);

    CGContextRestoreGState(_cgContext);

    CGImageRelease(cgImage);

    if (matrix != NULL)
    {
        CGContextConcatCTM(_cgContext, matInverted);
    }
}

使用 UIView 类中的 UIGraphicsGetCurrentContext() 获取主要上下文

---- EDITED --- 初始化代码:

void CocoaBitmapContext::init(double width, double height, unsigned int* data)
{
    int bytesPerRow = width * 2  * VT_BITMAP_BYTES_PER_PIXEL;

    if (data == NULL)
    {
        _dataOwner = true;
        _data = (unsigned int*)malloc(bytesPerRow * height * 2);
    }
    else
    {
        _dataOwner = false;
        _data = data;
    }

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

    _cgContext = CGBitmapContextCreate(_data,
                                       width * 2,
                                       height * 2,
                                       VT_BITMAP_BITS_PER_COMPONENT,
                                       bytesPerRow,
                                       colorSpace,
                                       kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little);

    CGContextConcatCTM(_cgContext, CGAffineTransformMakeScale([UIScreen mainScreen].scale, [UIScreen mainScreen].scale));

    CGContextSetShouldAntialias(_cgContext, false);
    CGContextSetRGBStrokeColor(_cgContext, 0.0, 0.0, 0.0, 0.0);

    CGColorSpaceRelease(colorSpace);
}
4

1 回答 1

4

Bitmap sizes are specified in pixels where as sizes on the screen are in points. You can get the screen's scale factor using [UIScreen mainScreen].scale. That is how many pixels are in a point. For devices with retina displays, this value will be 2. You will need to scale the size of your canvas by that factor. You should also concatenate a scale transform immediately after you create the context. When you draw the images, you should still use the screen bounds as the destination rectangle (the scale transform takes care of the scaling).

CGSize canvasSize = [UIScreen mainScreen].bounds.size;
CGFloat scale = [UIScreen mainScreen].scale;
canvasSize.width *= scale;
canvasSize.height *= scale;

UIGraphicsBeginImageContext(canvasSize);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextConcatCTM(context, CGAffineTransformMakeScale(scale, scale));
...
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();

If you are going to display it in an image view, the image view should fill the screen and it's contentMode should be UIViewContentModeScaleToFill.

于 2013-07-14T09:06:19.263 回答