我知道有很多这样的问题,但是他们的解决方案对我不起作用。
注意:该图片是从Internet下载的。它不是从iPhone
的相机中拍摄的。
我有一个UIImage
。为了进行一些图像处理操作,我使用Metal
并将图像显示在MTKView
中。因此,我将图像转换为CIImage
。
对图像进行所有修改后,我将其转换回CGImage
,然后转换为UIImage
并保存。
结果保存的图像方向错误。
我不确定在哪一步会放宽方向(从UIImage
转换为CIImage
以添加到MTKView
时,或从CIImage
转换为{ {1}},然后放入CGImage
中保存)。因为我不确定,因此下面提供了我为每个步骤尝试过的所有内容:
用于从UIImage
转换为UIImage
:
最初,我只是以这种方式转换图像:
CIImage
然后我尝试使用以下方式:
let let ciImage = CIImage(image: image)
这是方法 let ciImage = CIImage(image: image)?.oriented(forExifOrientation: imageOrientationToTiffOrientation(value: image.imageOrientation))
的实现(我发现它是here):
imageOrientationToTiffOrientation
要从func imageOrientationToTiffOrientation(value: UIImageOrientation) -> Int32
{
switch (value)
{
case .up:
return 1
case .down:
return 3
case .left:
return 8
case .right:
return 6
case .upMirrored:
return 2
case .downMirrored:
return 4
case .leftMirrored:
return 5
case .rightMirrored:
return 7
}
}
转换为CIImage
,然后转换为CGImage
:
我照常将UIImage
转换为CIImage
:
CGImage
然后我将let cgImage = context?.createCGImage(ciImage, from: ciImage.extent)
转换为cgImage
(UIImage
):
imageToSave
let imageToSave = UIImage(cgImage: cgImage, scale: image.scale, orientation: imageOrientation)
和imageOrientation
是原始图像的方向和比例。
结果,保存的图像仍然具有错误的方向。
有趣的是,当我打印这些图像方向原始值时,它们与image.scale
相同的0
,但是正如我所说,保存后方向是错误的。
我很困惑为什么会这样。如果您对如何解决此问题有任何建议,我们将不胜感激。
答案 0 :(得分:2)
TLDR:
let uiImage: UIImage = ...
let ciImage = CIImage(image: uiImage, options:
[.applyOrientationProperty: true,
.properties: [kCGImagePropertyOrientation: CGImagePropertyOrientation(uiImage.imageOrientation).rawValue]])
要将UIImageOrientation
转换为CGImagePropertyOrientation
,此代码使用https://developer.apple.com/documentation/imageio/cgimagepropertyorientation的扩展名
extension CGImagePropertyOrientation {
init(_ uiOrientation: UIImageOrientation) {
switch uiOrientation {
case .up: self = .up
case .upMirrored: self = .upMirrored
case .down: self = .down
case .downMirrored: self = .downMirrored
case .left: self = .left
case .leftMirrored: self = .leftMirrored
case .right: self = .right
case .rightMirrored: self = .rightMirrored
}
}
}
长版:
我刚遇到类似的问题。将UIImage转换为CIImage时,图像可能以错误的方向出现:
let uiImage: UIImage = ...
let ciImage CIImage(image: uiImage) /* does not use uiImage orientation */
最简单的解决方案是使用oriented(_:)
方法来更改方向:
let ciImage = CIImage(image: uiImage)?.oriented(CGImagePropertyOrientation(uiImage.imageOrientation))
/* uses CGImagePropertyOrientation extension (see above) */
这可以,但是oriented(_:)
方法会创建一个新图像。我认为必须有一种方法可以创建没有中间对象的正确定向的CIImage
。还有!尽管我在Internet上的任何地方都找不到它,并且Apple对它的记录不够清楚,所以我将其发布在这里。 @matt向正确的方向迈出了一步,但这还不够。
该解决方案在applyOrientationProperty
描述中被“加密”。
图像可以包含在捕获时显示方向的元数据。 您可以加载 使用imageWithContentsOfURL:或init(data :)将此元数据导入CIImage 当捕获的图像包含方向元数据时。使用任何 initWith:options:如果属性(元数据的NSDictionary) 属性)选项。
重要的部分被强调。那是关键。
在这里不要混淆options
和properties
也很重要。 )
答案 1 :(得分:1)
创建CIImage时从原始UIImage拾取方向的方法是说:
let ciImage = CIImage(image: image, options: [.applyOrientationProperty:true])!
使用完CIImage后,请使用CIContext().writeJPEGRepresentation
将数据保存到磁盘,然后将保留方向元数据。
答案 2 :(得分:0)
您可以尝试此方法
func image(with image: UIImage?, scaledToSizeKeepingAspect newSize: CGSize) -> UIImage? {
var newSize = newSize
var imgHeight = Float(image?.size.height ?? 0.0)
var imgWeight = Float(image?.size.width ?? 0.0)
var fact: Float = 0.0
if imgHeight > imgWeight {
fact = Float(CGFloat(imgHeight) / newSize.width)
} else {
fact = Float(CGFloat(imgWeight) / newSize.height)
}
imgHeight = imgHeight / fact
imgWeight = imgWeight / fact
newSize = CGSize(width: CGFloat(imgWeight), height: CGFloat(imgHeight))
UIGraphicsBeginImageContext(newSize)
// Tell the old image to draw in this new context, with the desired
// new size
image?.draw(in: CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height))
// Get the new image from the context
let newImage: UIImage? = UIGraphicsGetImageFromCurrentImageContext()
// End the context
UIGraphicsEndImageContext()
// Return the new image.
return newImage
}
像这样的调用方法:
image(withImage:image,scaledToSizeKeepingAspect:image.size)
这里image是UIImage对象,您要更改的图像通过此方法传递。