下载为 PNG 时 UIImage 到 MTLTexture
UIImage to MTLTexture when downloaded as PNG
我的用例是用户在 phone 上拍了一张自己的照片,然后将其作为 JPEG 格式上传到图像托管服务。然后其他用户可以下载该图像,然后将该图像映射到金属纹理以用于游戏。
我的问题是,如果我下载该图像并将其简单地显示在 UIImageView 中,它看起来是正确的,但是当我获取下载的图像并将其转换为金属纹理时,它会被镜像并顺时针旋转 90 度。我知道镜像图像是由于金属具有不同的坐标系,但我不明白旋转问题。当我打印已传递到我的函数的图像的详细信息时,它与正确显示的 UIImageView 具有所有相同的方向详细信息,所以我不知道问题出在哪里。附件是我的函数,它为我提供了 MTLTexture。
- (id<MTLTexture>) createTextureFromImage:(UIImage*) image device:(id<MTLDevice>) device
{
image =[UIImage imageWithCGImage:[image CGImage]
scale:[image scale]
orientation: UIImageOrientationLeft];
NSLog(@"orientation and size and stuff %ld %f %f", (long)image.imageOrientation, image.size.width, image.size.height);
CGImageRef imageRef = image.CGImage;
size_t width = self.view.frame.size.width;
size_t height = self.view.frame.size.height;
size_t bitsPerComponent = CGImageGetBitsPerComponent(imageRef);
size_t bitsPerPixel = CGImageGetBitsPerPixel(imageRef);
CGColorSpaceRef colorSpace = CGImageGetColorSpace(imageRef);
CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(imageRef);
// NSLog(@"%@ %u", colorSpace, alphaInfo);
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault | alphaInfo;
// NSLog(@"bitmap info %u", bitmapInfo);
CGContextRef context = CGBitmapContextCreate( NULL, width, height, bitsPerComponent, (bitsPerPixel / 8) * width, colorSpace, bitmapInfo);
if( !context )
{
NSLog(@"Failed to load image, probably an unsupported texture type");
return nil;
}
CGContextDrawImage( context, CGRectMake( 0, 0, width, height ), image.CGImage);
MTLPixelFormat format = MTLPixelFormatRGBA8Unorm;
MTLTextureDescriptor *texDesc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:format
width:width
height:height
mipmapped:NO];
id<MTLTexture> texture = [device newTextureWithDescriptor:texDesc];
[texture replaceRegion:MTLRegionMake2D(0, 0, width, height)
mipmapLevel:0
withBytes:CGBitmapContextGetData(context)
bytesPerRow:4 * width];
return texture;
}
在Metal
中坐标颠倒。但是,您现在有一种更简单的方法来加载纹理 MTKTextureLoader
:
import MetalKit
let textureLoader = MTKTextureLoader(device: device)
let texture: MTLTexture = textureLoader.newTextureWithContentsOfURL(filePath, options: nil)
这将使用位于 filePath
的图像为您创建一个具有适当坐标的新 texture
。如果您不想使用 NSURL
,您还可以使用 newTextureWithData
和 newTextureWithCGImage
选项。
我的用例是用户在 phone 上拍了一张自己的照片,然后将其作为 JPEG 格式上传到图像托管服务。然后其他用户可以下载该图像,然后将该图像映射到金属纹理以用于游戏。
我的问题是,如果我下载该图像并将其简单地显示在 UIImageView 中,它看起来是正确的,但是当我获取下载的图像并将其转换为金属纹理时,它会被镜像并顺时针旋转 90 度。我知道镜像图像是由于金属具有不同的坐标系,但我不明白旋转问题。当我打印已传递到我的函数的图像的详细信息时,它与正确显示的 UIImageView 具有所有相同的方向详细信息,所以我不知道问题出在哪里。附件是我的函数,它为我提供了 MTLTexture。
- (id<MTLTexture>) createTextureFromImage:(UIImage*) image device:(id<MTLDevice>) device
{
image =[UIImage imageWithCGImage:[image CGImage]
scale:[image scale]
orientation: UIImageOrientationLeft];
NSLog(@"orientation and size and stuff %ld %f %f", (long)image.imageOrientation, image.size.width, image.size.height);
CGImageRef imageRef = image.CGImage;
size_t width = self.view.frame.size.width;
size_t height = self.view.frame.size.height;
size_t bitsPerComponent = CGImageGetBitsPerComponent(imageRef);
size_t bitsPerPixel = CGImageGetBitsPerPixel(imageRef);
CGColorSpaceRef colorSpace = CGImageGetColorSpace(imageRef);
CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(imageRef);
// NSLog(@"%@ %u", colorSpace, alphaInfo);
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault | alphaInfo;
// NSLog(@"bitmap info %u", bitmapInfo);
CGContextRef context = CGBitmapContextCreate( NULL, width, height, bitsPerComponent, (bitsPerPixel / 8) * width, colorSpace, bitmapInfo);
if( !context )
{
NSLog(@"Failed to load image, probably an unsupported texture type");
return nil;
}
CGContextDrawImage( context, CGRectMake( 0, 0, width, height ), image.CGImage);
MTLPixelFormat format = MTLPixelFormatRGBA8Unorm;
MTLTextureDescriptor *texDesc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:format
width:width
height:height
mipmapped:NO];
id<MTLTexture> texture = [device newTextureWithDescriptor:texDesc];
[texture replaceRegion:MTLRegionMake2D(0, 0, width, height)
mipmapLevel:0
withBytes:CGBitmapContextGetData(context)
bytesPerRow:4 * width];
return texture;
}
在Metal
中坐标颠倒。但是,您现在有一种更简单的方法来加载纹理 MTKTextureLoader
:
import MetalKit
let textureLoader = MTKTextureLoader(device: device)
let texture: MTLTexture = textureLoader.newTextureWithContentsOfURL(filePath, options: nil)
这将使用位于 filePath
的图像为您创建一个具有适当坐标的新 texture
。如果您不想使用 NSURL
,您还可以使用 newTextureWithData
和 newTextureWithCGImage
选项。