gpt4 book ai didi

ios - 如何在 iOS8 中以原始分辨率显示自制位图

转载 作者:塔克拉玛干 更新时间:2023-11-02 10:02:32 25 4
gpt4 key购买 nike

我正在为 iOS 开发一个通用应用程序,它将动态生成它自己的全屏位图(指向字节缓冲区中 32 位像素数据的指针)。它对触摸事件使用react,并且需要在用户触摸时以响应方式进行绘图(例如缩放/平移)。在我的应用程序开始时,我可以看到我的视网膜 iPad 和 iPod Touch 上的显示缩放了 2 倍。我的代码当前正确创建和显示位图,但分辨率为显示器原始分辨率的 1/2。我可以使用 View 的 nativeBounds 查看原始分辨率,但我想以原始分辨率创建和显示我的位图而不进行任何缩放。我尝试在 drawRect() 方法中更改变换比例,但它没有正常工作。下面是我的 drawRect 代码:

- (void)drawRect:(CGRect)rect
{
UInt32 * pixels;
pixels = (UInt32 *)[TheFile thePointer];
NSUInteger width = [TheFile iScreenWidth];
NSUInteger height = [TheFile iScreenHeight];
NSUInteger borderX = [TheFile iBorderX];
NSUInteger borderY = [TheFile iBorderY];
NSUInteger bytesPerPixel = 4;
NSUInteger bytesPerRow = bytesPerPixel * width;
NSUInteger bitsPerComponent = 8;

CGContextRef context = UIGraphicsGetCurrentContext();
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef gtx = CGBitmapContextCreate(pixels, width-borderX*2, height-borderY*2, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaNoneSkipLast | kCGBitmapByteOrder32Big);
CGImageRef myimage = CGBitmapContextCreateImage(gtx);

CGContextSetInterpolationQuality(gtx, kCGInterpolationNone); // does this speed it up?

// Create a rect to display
CGRect imageRect = CGRectMake(borderX, borderY, width - borderX*2, height - borderY * 2);

// Need to repaint the background that would show through (black)
if (borderX != 0 || borderY != 0)
{
[[UIColor blackColor] set];
UIRectFill(rect);
}

// Transform image (flip right side up)
CGContextTranslateCTM(context, 0, height);
CGContextScaleCTM(context, 1.0, -1.0);

// Draw the image
CGContextDrawImage(context, imageRect, myimage); //image.CGImage);

CGColorSpaceRelease(colorSpace);
CGContextRelease(gtx);
CGImageRelease(myimage);

} /* drawRect() */

编辑: 下面的答案通过使用 UIImageView 解决了性能问题,通过在 UIImage 的初始化中设置适当的显示比例解决了缩放问题。当 UIImage 比例与显示比例匹配时,它将以设备的原始分辨率以 1:1 的比例显示位图。

最佳答案

您的代码的问题在于,在创建结果图像后,代码将图像绘制到为 drawRect: 配置的当前图形上下文中。绘制图像的是 CPU。这就是为什么需要 70 毫秒。使用 UIImageView 渲染图像或将其设置为层的内容不由 CPU 处理,这样,它由 GPU 处理。 GPU 擅长这样的事情,所以在这种情况下它要快得多。由于 drawRect: 导致 Core Animation 创建一个在这种情况下无用的支持位图,因此您应该创建没有 drawRect: 的图像:

- (UIImage *)drawBackground {
UIImage *output;
UInt32 * pixels;
pixels = (UInt32 *)[TheFile thePointer];
NSUInteger borderX = [TheFile iBorderX];
NSUInteger borderY = [TheFile iBorderY];
NSUInteger width = [TheFile iScreenWidth] - 2 * borderX;
NSUInteger height = [TheFile iScreenHeight] - 2 * borderY;
NSUInteger bytesPerPixel = 4;
NSUInteger bytesPerRow = bytesPerPixel * width;
NSUInteger bitsPerComponent = 8;
CGFloat scale = [UIScreen mainScreen].scale;

// create bitmap graphic context
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef gtx = CGBitmapContextCreate(pixels,
width,
height,
bitsPerComponent,
bytesPerRow,
colorSpace,
kCGImageAlphaNoneSkipLast |
kCGBitmapByteOrder32Big);

// create image
CGImageRef myimage = CGBitmapContextCreateImage(gtx);
output = [UIImage imageWithCGImage:myimage
scale:[UIScreen mainScreen].scale
orientation:UIImageOrientationUp];

// clean up
CGColorSpaceRelease(colorSpace);
CGContextRelease(gtx);
CGImageRelease(myimage);

return output;
}

当用户触发事件时,假设您使用手势识别器:

- (IBAction)handleTap:(UITapGestureRecognizer *)tap {
UIImage *background = [self drawBackground];

// when background view is an UIImageView
self.backgroundView.image = background;
// self.backgroundView should have already set up in viewDidLoad
// based on your code snippet, you may need to configure background color
// self.backgroundView.backgroundColor = [UIColor blackColor];
// do other configuration if needed...

// when background view is an UIView or subclass of UIView
self.backgroundView.layer.contents = (id)background.CGImage;
// not like UIImageView, the size of background view must exactly equals
// to the size of background image. Otherwise the image will be scaled.
}

我在一个测试项目中写了这个函数:

static UIImage *drawBackground() {
// allocate bitmap buffer
CGFloat scale = [UIScreen mainScreen].scale;
CGRect screenBounds = [UIScreen mainScreen].bounds;
NSUInteger borderWidth = 1 * 2; // width of border is 1 pixel
NSUInteger width = scale * CGRectGetWidth(screenBounds) - borderWidth;
NSUInteger height = scale * CGRectGetHeight(screenBounds) - borderWidth;
NSUInteger bytesPerPixel = 4;

// test resolution begin
// tested on a iPhone 4 (320 x 480 points, 640 x 960 pixels), iOS 7.1
// the image is rendered by an UIImageView which covers whole screen.
// the content mode of UIImageView is center, which doesn't cause scaling.
width = scale * 310;
height = scale * 240;
// test resolution end

UInt32 *pixels = malloc((size_t)(width * height * bytesPerPixel));

// manipulate bitmap buffer
NSUInteger count = width * height;
unsigned char *byte = (unsigned char *)pixels;
for (int i = 0; i < count; i = i + 1) {
byte[0] = 100;
byte = byte + 1;
byte[0] = 100;
byte = byte + 1;
byte[0] = 0;
byte = byte + 2;
}

// create bitmap grahpic context
NSUInteger bytesPerRow = bytesPerPixel * width;
NSUInteger bitsPerComponent = 8;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef gtx = CGBitmapContextCreate(pixels,
width,
height,
bitsPerComponent,
bytesPerRow,
colorSpace,
kCGImageAlphaNoneSkipLast |
kCGBitmapByteOrder32Big);

// create image
CGImageRef myimage = CGBitmapContextCreateImage(gtx);
UIImage *output = [UIImage imageWithCGImage:myimage
scale:scale
orientation:UIImageOrientationUp];

// clean up
CGColorSpaceRelease(colorSpace);
CGContextRelease(gtx);
CGImageRelease(myimage);
free(pixels);

return output;
}

我在 iPhone 4 设备上对其进行了测试。对我来说似乎没问题。这是屏幕截图: image created from bitmap

关于ios - 如何在 iOS8 中以原始分辨率显示自制位图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27903380/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com