我真的非常非常接近这里,但我只是不知道为什么会出错。看起来 NSData 或 CGDataProvider 或 CGImage 正在跳过每 8 行,然后用垃圾填充剩余的画布,所以我只得到图像的 1/8 聚集在顶部。
我认为这一定是一些数学错误,但在多次检查代码后,我不确定这可能在哪里。
我正在尝试在 MacOS 上学习一些 Swift,几周后我已经成功做到这一点并开始做一些有趣的事情。如果有人可以帮助我,我将非常感激!
此外,最好知道我是否是有效绘制单个像素的正确途径。人们似乎并不难找到这方面的好例子。
import Foundation
import Cocoa
import UniformTypeIdentifiers
extension CGImage
{
//https://stackoverflow.com/questions/1320988/saving-cgimageref-to-a-png-file
var png: Data?
{
let cfdata: CFMutableData = CFDataCreateMutable(nil, 0)
if let destination = CGImageDestinationCreateWithData(cfdata, String(describing: UTType.png) as CFString, 1, nil)
{
CGImageDestinationAddImage(destination, self, nil)
if CGImageDestinationFinalize(destination)
{
return cfdata as Data
}
}
return nil
}
}
//https://blog.human-friendly.com/drawing-images-from-pixel-data-in-swift
struct PixelData {
var a:UInt8 = 255
var r:UInt8
var g:UInt8
var b:UInt8
}
func pixeldata_to_image(pixels: [PixelData], width: Int, height: Int)->CGImage
{
assert(pixels.count == Int(width * height))
let bitsPerComponent: Int = 8
let bitsPerPixel: Int = 32
let rgbColorSpace = CGColorSpaceCreateDeviceRGB()
let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedFirst.rawValue)
var data = pixels
guard
let providerRef = CGDataProvider(data: NSData(bytes: &data, length: data.count * bitsPerPixel))
else
{
fatalError("CGDataProvider failure")
}
guard
let image = CGImage(
width: width,
height: height,
bitsPerComponent:bitsPerComponent,
bitsPerPixel: bitsPerPixel,
bytesPerRow: width * bitsPerPixel,
space: rgbColorSpace,
bitmapInfo: bitmapInfo,
provider: providerRef,
decode: nil,
shouldInterpolate: true,
intent: .defaultIntent
)
else
{
fatalError("CGImage failure")
}
return image
}
func testUsage()
{
let range_x: Int = 200
let range_y: Int = 200
let greyPixel = PixelData(a: 255, r: 128, g: 128, b: 128)
let blackPixel = PixelData(a: 255, r: 0, g: 0, b: 0)
let whitePixel = PixelData(a: 255, r: 255, g: 255, b: 255)
let yellowPixel = PixelData(a: 255, r: 255, g: 255, b: 0)
let greenPixel = PixelData(a: 255, r: 0, g: 255, b: 0)
let redPixel = PixelData(a: 255, r: 255, g: 0, b: 0)
var pixelData = [PixelData](repeating: greyPixel, count: Int(range_x * range_y))
var index: Int = 0
//populate pixelData
for x in 0 ..< range_x
{
for y in 0 ..< range_y
{
let pixel: PixelData
if x == 0 && y == 0 || x == 0 && y == range_x - 1 || x == 8 && y == 8
{
//grey draw specfic pixels
pixel = greyPixel
}
else if x == y
{
//yellow draw diagonal from top-left to bottom-right
pixel = yellowPixel
}
else if y == 0 || x == 0
{
//dblack raw top line and draw left line
pixel = blackPixel
}
else if y == range_y - 1 || x == range_y - 1
{
//white draw bottom line and draw right line
pixel = whitePixel
}
else if y == range_y / 2 || x == range_x / 2
{
//green draw horizontal center line and draw vertical center line
pixel = greenPixel
}
else
{
pixel = redPixel
}
//print("x:", x, "y:", y, "index:", index, "pixel:", pixel) //sanity check
pixelData[index] = pixel
index += 1
}
}
let image: CGImage = pixeldata_to_image(pixels: pixelData, width: range_x, height: range_y)
try? image.png!.write(to: URL(fileURLWithPath: "pixeldata.png"))
}
正如评论中指出的,我混淆了一些位和字节。我添加了这两行:
let bitsPerByte = 8
let bytesPerPixel: Int = bitsPerPixel/bitsPerByte
然后修改这两行:
-let providerRef = CGDataProvider(data: NSData(bytes: &data, length: data.count * bitsPerPixel))
+let providerRef = CGDataProvider(data: NSData(bytes: &data, length: data.count * bytesPerPixel))
和
-bytesPerRow: width * bitsPerPixel,
+bytesPerRow: width * bytesPerPixel,
现在就像魅力一样!