【问题标题】:RGB Data from CGImage in Swift来自 Swift 中 CGImage 的 RGB 数据
【发布时间】:2014-07-18 16:53:27
【问题描述】:

我尝试在 Swift 中构建阅读 RGB pixel data。 获取基本的图像信息是没有问题的,但我认为我的指针和字节偏移有问题:

let provider:CGDataProviderRef = CGImageGetDataProvider(inImage)
let data:NSData = CGDataProviderCopyData(provider)
let bytes: COpaquePointer = data.bytes // Needs to be changed to ConstUnsafePointer<()> in xCode beta3
let bytePointer = UnsafePointer<UInt8>(bytes)

println("Pixel Data:\n")

var printString:String = ""

    for var row:Int = 0; row < Int(height); row++ {
    for var col:Int = 0; col < Int(width); col++ {

        var pixel:UInt8 = bytePointer[row * Int(bytesPerRow) + col * Int(bytesPerPixel)]
        printString += "("

        for var x = 0; x < Int(bitsPerPixel); x++ {
            printString += pixel[x]
        }

        printString += ")"

        if col < Int(width) - 1 {
            printString += ","
        }

    }
    printString += "\n"
}

println(printString)

(我将 Int 转换为变量 bytesPerRow 等,因为它们是 UInt8)

我得到了一个 4x2 像素的图像,其中包含两行以下像素:红色、绿色、蓝色、白色。所以我期待这个输出(没有alpha):

(ff0000), (00ff00), (0000ff), (ffffff)
(ff0000), (00ff00), (0000ff), (ffffff)

printString += pixel[x]编译时出现错误

“UInt8”没有名为“下标”的成员

我认为它可以快速附加到字符串中。我试图将其转换为字符串,但这也不起作用。所以也许我对指针做错了。

如何获得正确的输出?

编辑:

@David 让我走上了正确的道路。但是在第一个 8 Byte 之后发生了奇怪的事情。这可能是@heinrich-giesen 建议的填充字节吗?

我的 3 次测试的原始图像数据如下所示:

Pic1: 3Byte/Pixel, no Alpha, 4 pixelWidth, 2 pixelHeight, [red, green, blue white; red, green, blue white]
Raw Data: <ff000000 ff000000 ffffffff ff000000 ff000000 ffffffff>

Pic2: 4Byte/Pixel, Alpha, 4 pixelWidth, 2 pixelHeight, [red, green, blue white (alpha); red, green, blue white]
Raw Data: <ff000000 00ff0000 0000ff00 ffffff00 ff0000ff 00ff00ff 0000ffff ffffffff>

如果您查看原始数据,很明显我期望输出如下:

Pic1
(ff,00,00), (00,ff,00), (00,00,ff), (ff,ff,ff)
(ff,00,00), (00,ff,00), (00,00,ff), (ff,ff,ff)

Pic2
(ff,00,00,00), (00,ff,00,00), (00,00,ff,00), (ff,ff,ff,00)
(ff,00,00,ff), (00,ff,00,ff), (00,00,ff,ff), (ff,ff,ff,ff)

但我的代码生成的真正输出是这样的:

Pic1   
((ff, 00, 00, ), (00, 00, ff, ), (00, ff, ff, ), (ff, ff, 00, ))
((ff, 00, 00, ), (00, 00, ff, ), (00, ff, 00, ), (ff, 00, 00, ))

Pic2 
((ff, 00, 00, ff, ), (00, 00, ff, ff, ), (00, ff, ff, 00, ), (ff, ff, 00, 00, )) 
((ff, 00, 00, ff, ), (00, 00, ff, 00, ), (00, ff, 00, 00, ), (ff, 00, 00, 00, ))

现在构建输出的代码是这样的:

    for var row:Int = 0; row < Int(height) ; row++ {

        printString += "("

        for var col:Int = 0; col < Int(width); col++ {

            printString += "("

            for var x = 0; x < Int(bytesPerPixel); x++ {

                var pixel:UInt8 = bytePointer[row * Int(bytesPerRow) + col * Int(bytesPerPixel) + x * Int(bytesPerPixel)]
                printString += NSString(format:"%02x, ", pixel)

            }

            printString += ")"

            if col < Int(width) - 1 {
                printString += ", "
            }

        }
        printString += ")\n"
    }

println(printString)

那么是否有填充(如原始数据输出中的空格)?我试图在最初的 8 个之后跳过一个和两个,但这不会产生不那么令人困惑的输出。 8 个字节后出现中断。有什么建议吗?

【问题讨论】:

    标签: macos pointers swift core-graphics


    【解决方案1】:

    您的代码看起来有点奇怪。你确定线路:

        for var x = 0; x < Int(bitsPerPixel); x++ {
    

    正确吗?你真的是指 bitsPerPixel 而不是 bytesPerPixel 吗? (或 samplesPerPixel 或任何它在 swift 中的东西)。你确定一个组件(一个样本)有 8 位吗?一个像素没有填充字节?

    还有一点:heightwidth 是什么?它们是图像size 的组成部分吗?那是错的。您必须使用pixelsWidepixelsHigh。图像的size 仅表示应描述图像的大小——以英寸或厘米或 (1/72) 英寸(称为点)表示。这与像素数无关。但是你在像素上工作!

    【讨论】:

    • 是的,它应该是每像素字节数。我修好了。我确定一个组件有 8 位。原始数据显示非常漂亮。有关更多详细信息,请查看我对 @David 答案的评论。但是还有一个问题。 (高度和宽度是pixelWidth和pixelHeight。我只是有点懒所以我给他们取了更短的名字:let width:UInt = CGImageGetWidth(inImage) let height:UInt = CGImageGetHeight(inImage)
    • 在 for var x = 0; - 循环最后一个乘法 x*bytePerPixel 是错误的。只用 x 替换它,因为 x 迭代像素内的组件,而不是像素。
    【解决方案2】:

    将 bytePointer 更改为 UnsafePointer&lt;UInt32&gt; 并更新循环以使用移位 (>>) 和掩码 (& 0xff) 访问单词的各个字节。

        var pixel:UInt32 = bytePointer[row * Int(bytesPerRow) + col * Int(bytesPerPixel)]
        printString += NSString(withFormat:"(%08x)", pixel)
    

    这也会为您提供 Alpha 通道,但您会得到偏差。

    【讨论】:

    • 谢谢,前 16 个字节的效果很好。基本上从 Swift-Book 中转移它的例子,如果有 alpha:let redComponent = (pixel &amp; 0xFF000000) &gt;&gt; 24 let greenComponent = (pixel &amp; 0x00FF0000) &gt;&gt; 16 let blueComponent = (pixel &amp; 0x0000FF00) &gt;&gt; 8 let blueComponent = pixel &amp; 0x000000FF 但是在 16 字节之后,事情变得很奇怪。你可以看看我对这个问题的编辑吗?
    猜你喜欢
    • 2011-08-29
    • 2010-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-14
    相关资源
    最近更新 更多