Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/drupal/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 当使用CGContext缩放到较小尺寸时,CGImage的像素数据不完整_Ios_Uiimage_Core Graphics_Cgimage - Fatal编程技术网

Ios 当使用CGContext缩放到较小尺寸时,CGImage的像素数据不完整

Ios 当使用CGContext缩放到较小尺寸时,CGImage的像素数据不完整,ios,uiimage,core-graphics,cgimage,Ios,Uiimage,Core Graphics,Cgimage,我在512x512大小的透明背景上有一个白色圆圈的png图像: 无法在堆栈溢出上看到此处,因此它再次显示在黑色背景的UIImageView中: 我正在尝试使用高质量插值和抗锯齿将图像缩小到不同的大小,然后读取像素信息并继续处理 使用常规的CGContext进行缩放: private func scaleImageAntialiased(_ cgImage: CGImage, _ size: CGSize) -> CGImage { UIGraphicsBeginImageCo

我在512x512大小的透明背景上有一个白色圆圈的png图像:

无法在堆栈溢出上看到此处,因此它再次显示在黑色背景的
UIImageView
中:

我正在尝试使用高质量插值和抗锯齿将图像缩小到不同的大小,然后读取像素信息并继续处理

使用常规的
CGContext
进行缩放:

private func scaleImageAntialiased(_ cgImage: CGImage, _ size: CGSize) -> CGImage {

    UIGraphicsBeginImageContext(size)
    guard let context = UIGraphicsGetCurrentContext() else { fatalError() }

    context.interpolationQuality = .high
    context.setShouldAntialias(true)

    context.draw(cgImage, in: CGRect(origin: .zero, size: size))

    guard let image = UIGraphicsGetImageFromCurrentImageContext()?.cgImage else { fatalError() }
    return image
}
然后,我使用
dataProvider
CFDataGetBytePtr
读取像素信息:

var image = UIImage(named: "Round_512")!.cgImage!

let width: size_t = image.width
let height: size_t = image.height

let cfData = image.dataProvider!.data!
let dataPtr = CFDataGetBytePtr(cfData)
let bytesPerPixel = 4
var data: [GLubyte] = Array(UnsafeBufferPointer(start: dataPtr, count: width * height * bytesPerPixel))
在我尝试将新尺寸设置为4x4px或更低之前,一切正常

let size = 4
let newSize = CGSize(width: size, height: size)
image = scaleImageAntialiased(image, newSize) 
而缩放后的图像在
UIImageView

原始RGBA字节数据缺少两行信息:

[3, 3, 3, 3,   75, 75, 75, 75,   74, 74, 74, 74,   3, 3, 3, 3, 
 0, 0, 0, 0,     0, 0, 0, 0,       0, 0, 0, 0,     0, 0, 0, 0, 
 75, 75, 75, 75, 254, 254, 254, 254, 254, 254, 254, 254, 74, 74, 74, 74, 
 0, 0, 0, 0,     0, 0, 0, 0,       0, 0, 0, 0,     0, 0, 0, 0]
(我格式化了
打印(数据)
的上述结果,使其更加明显)。如您所见,第二行和第四行字节返回0,而不是与其他两行具有相同的值(对称)

只有当我首先使用
CGContext
缩放图像,然后尝试使用上述方法读取图像时,才会出现此问题。如果我拍摄缩放后的图像,将其保存到一个文件中,然后从该4x4文件中读取像素信息(使用相同的方法),我会得到预期的结果

所以缩放本身是有效的。像素的读取也很有效。只有组合没有

有人能解释为什么会这样吗?

为了完整起见,这里有一个用于512px图像的文件和一个完整的游乐场文件,您可以使用它来重现问题:

import UIKit
import GLKit
import PlaygroundSupport

private func scaleImageAntialiased(_ cgImage: CGImage, _ size: CGSize) -> CGImage {

    UIGraphicsBeginImageContext(size)
    guard let context = UIGraphicsGetCurrentContext() else { fatalError() }

    context.interpolationQuality = .high
    context.setShouldAntialias(true)

    context.draw(cgImage, in: CGRect(origin: .zero, size: size))

    guard let image = UIGraphicsGetImageFromCurrentImageContext()?.cgImage else { fatalError() }
    return image
}

var image = UIImage(named: "Round_512")!.cgImage!

let size = 4
let newSize = CGSize(width: size, height: size)
image = scaleImageAntialiased(image, newSize)

let width: size_t = image.width
let height: size_t = image.height

let cfData = image.dataProvider!.data!
let dataPtr = CFDataGetBytePtr(cfData)
let bytesPerPixel = 4
var data: [GLubyte] = Array(UnsafeBufferPointer(start: dataPtr, count: width * height * bytesPerPixel))

print(data)

let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
imageView.image = UIImage(cgImage: image)
imageView.backgroundColor = .black

PlaygroundPage.current.liveView = imageView

// Save the test image
let path = playgroundSharedDataDirectory.appendingPathComponent("Saved.png")
let pngData = UIImagePNGRepresentation(imageView.image!)
//try! pngData?.write(to: path)

我相信
CGImage
使用32字节的倍数。。。如果只有4个像素,每个像素由4个字节表示,则每行的数据将被“填充”(填充的数据将被忽略)

如果检查图像:

print(image.bytesPerRow)
您将看到它打印的是
32
而不是
16

您要使用:

let bytesPerRow = image.bytesPerRow
var data: [GLubyte] = Array(UnsafeBufferPointer(start: dataPtr, count: height * bytesPerRow))
因此
height*bytesPerRow
而不是
width*height*bytesperpoixel