2016-02-17 54 views
1

enter image description here我有這樣的方法MTLTexture顯示器UIImages錯誤如果轉換爲紋理

- (id<MTLTexture>) createTextureFromImage:(UIImage*) image device:(id<MTLDevice>) device 
{ 
    CGImageRef imageRef = image.CGImage; 

    // size_t width = CGImageGetWidth(imageRef); 
    // size_t height = CGImageGetHeight(imageRef); 

    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(@"%@", colorSpace); 

    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 = MTLPixelFormatBGRA8Unorm; 

    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; 
} 

當我通過它的圖像,並使用所得到的紋理,它給人的整體圖像的紅色色調。我的MTLRenderPipelineDescriptor的像素格式設置爲MTLPixelFormatBGRA8Unorm,我感覺問題在這裏。我附上了一張圖片樣本,讓您知道它應該是什麼,以及它顯示的是什麼。我知道這不是圖像,就好像我只是將圖像直接添加到視圖效果良好,但這也可能是因爲視圖使用RGBA8顏色值,而metalview使用的是BGRA8顏色值。如果我將像素格式更改爲RGBA8不過,我的應用程序崩潰,並警告

For color attachment 0, the render pipeline's pixelFormat (MTLPixelFormatRGBA8Unorm) does not match the framebuffer's pixelFormat (MTLPixelFormatBGRA8Unorm). 

的唯一的事情是,我不能看到我設置的幀緩衝像素格式。

謝謝!

編輯 - 這是我的圖像經過一次處理代碼後,我將它分成像素數組。

-(UIImage *) script:(NSArray*)pixelArray { 

    float width = self.view.frame.size.width; 
    float height = self.view.frame.size.height; 

    //create drawing context 
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(width, height), NO, 0.0f); 
    CGContextRef context = UIGraphicsGetCurrentContext(); 

    int k = 0; 
    do { 
    for (int y = 0; y < height + 1; y++) 
    { 
     for (int x = 1; x < width; x++) 
     { 


     if (k < array.count){ 
      UIColor* pixelColor = array[k]; 


      CGContextSetFillColorWithColor(context, pixelColor.CGColor); 
      CGContextFillRect(context, CGRectMake(x, y, 1.0f, 1.0f)); 
     } 
     } else { 

     CGContextSetFillColorWithColor(context, [UIColor clearColor].CGColor); 
     CGContextFillRect(context, CGRectMake(x, y, 1.0f, 1.0f)); 
     } 
     k++; 
    } 
    k++; 
    } 
} while (k < 62791); 

//capture resultant image 
UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 
UIGraphicsEndImageContext(); 
return image; 
} 
+0

你需要支持哪些最低的iOS版本?你的目標只是從圖像創建MTLTexture? – curious

+0

是的,我的目標是從圖像中創建一個MTLTexture,正如你所看到的那樣。問題出在RGBA頻道正在切換(我認爲) – crashlog

+0

我只是想說,你可以用較少的代碼實現相同的目標。如果您打算僅支持9+ iOS,您可以使用MetalKit中的MTKTextureLoader,如[此處](http://stackoverflow.com/a/34895822/3014519)(viewDidLoad方法)所述。 – curious

回答

3

這裏有兩個不同的關注點:符合渲染流水線狀態和你的幀緩衝區之間的像素格式,圖像數據,並從它創建紋理的像素格式之間的匹配像素格式。

在第一種情況下,使用MTLPixelFormatBGRA8Unorm是明智的。這必須在您的CAMetalLayer(或MTKView)以及您的渲染管線狀態的主要顏色附件上設置。如果他們不同意,你會得到你提到的例外。這個配置看起來是這樣的:

metalView.colorPixelFormat = MTLPixelFormatBGRA8Unorm; 
// and elsewhere... 
pipelineStateDescriptor.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm; 

在後一種情況下,重要的是,你的圖像數據的組件訂購您選擇的格式爲你的紋理相匹配。您從UIImage獲得的色彩空間爲sRGB,因此您需要指定MTLPixelFormatRGBA8Unorm作爲您紋理的像素格式(您的紋理創建代碼中當前有MTLPixelFormatBGRA8Unorm),或手動交換紅色和藍色通道中的字節。

視圖的像素格式和從圖像創建的紋理不一定是相同的。當您對紋理進行採樣並寫入幀緩衝區時,金屬會調整顏色,因此在着色器中,您始終可以採用RGBA排序。

+0

感謝您的回覆。我得到的問題是,即使紋理和管道格式的MTLPixelFormat都匹配,圖像仍然出現混亂。我認爲這是因爲傳遞給函數的圖像具有RGBA的顏色格式 - 所以在邏輯上我認爲我需要改變它,但是如果我重新創建圖像並交換BGR值的RGB值,解決這個問題= [ – crashlog

+0

我已經在上面添加了一些更詳細的信息,希望對您有所幫助。將圖像紋理的像素格式從BGRA更改爲RGBA後,您的代碼在示例項目中似乎適用於我。 – warrenm

+0

要展開此,UIImage的我在由操作的方式過於複雜的功能,其特徵在於它需要原始圖象處理攝食,讀取每個像素的的UIColor值,將其保存到一個數組,然後重建它與一些一個UIImage某些像素的變化。我將添加該部分的代碼作爲編輯。 – crashlog