I've tried to build reading RGB pixel data in Swift. Getting the basic Image Information is no problem, but I think I've got something wrong with the pointer and the byte-offset:
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)
(I cast Int to the variables bytesPerRow, etc because they are UInt8)
I got a 4x2px Image wich contains two rows of following pixels: Red, Green, Blue, White. So I expect this output (There is no alpha):
(ff0000), (00ff00), (0000ff), (ffffff)
(ff0000), (00ff00), (0000ff), (ffffff)
I get a error when compiling at printString += pixel[x]
'UInt8' does not have a member named 'subscript'
I thought it could just be appended to a string in swift. I've tried to convert it to a string but this won't work either. So maybe I'm doing something wrong with the pointers.
How do i get a proper output?
edit:
@David got me on a right track I think. But after the first 8 Byte weird thing happen. Might this be padding byted @heinrich-giesen suggested?
My raw image data for 3 tests looks like this:
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>
If you look at the raw data its pretty clear that I expect a output like:
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)
But the real output my code generates is this:
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, ))
The code to build the output is this now:
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)
So is there a padding (Like the space in the output of the raw data)? I've tried to skip one and two after the initial 8 but this won't yield less confusing outputs. Something breaks after 8 Bytes. Suggestions?