#swift #image #multidimensional-array
#swift #изображение #многомерный массив
Вопрос:
Мне интересно, как я могу превратить UIImage во что-то полезное и изменяемое. Код Java для обработки того, что мне нужно, будет выглядеть примерно так:
BufferedImage img= ImageIO.read(file);
Raster raster=img.getData();
int w=raster.getWidth(),h=raster.getHeight();
int pixels[][]=new int[w][h];
for (int x=0;x<w;x )
{
for(int y=0;y<h;y )
{
pixels[x][y]=raster.getSample(x,y,0);
}
}
Мне нужно изменить альфа-значения в изображении, посетив каждый пиксель изображения.
Комментарии:
1. возможно, вам повезет больше, если сначала поискать, как это сделать в Objective-C (подсказка — это не будет похоже на Java), а затем преобразовать код ObjC в Swift.
2. Я очень удивлен, что в Swift нет stl для работы с изображениями / пикселями
3. В Swift очень мало стандартной библиотеки. Класс UIImage импортируется из Cocoa, поэтому вам нужно изучить методы обработки изображения на основе Cocoa. Вы даже можете найти фильтр CoreImage, который может применять любой эффект, который вам нужен, без необходимости самостоятельно редактировать альфа-значения.
Ответ №1:
Непроверенный, но я думаю, что это либо сработает, либо должно быть очень близко.
import UIKit
import CoreGraphics
var uiimage = UIImage(contentsOfFile: "/PATH/TO/image.png")
var image = uiimage.CGImage
let width = CGImageGetWidth(image)
let height = CGImageGetHeight(image)
let colorspace = CGColorSpaceCreateDeviceRGB()
let bytesPerRow = (4 * width);
let bitsPerComponent :UInt = 8
let pixels = UnsafePointer<UInt8>(malloc(width*height*4))
var context = CGBitmapContextCreate(pixels, width, height, bitsPerComponent, bytesPerRow, colorspace,
CGBitmapInfo());
CGContextDrawImage(context, CGRectMake(0, 0, CGFloat(width), CGFloat(height)), image)
for x in 0..width {
for y in 0..height {
//Here is your raw pixels
let offset = 4*((Int(width) * Int(y)) Int(x))
let alpha = pixels[offset]
let red = pixels[offset 1]
let green = pixels[offset 2]
let blue = pixels[offset 3]
}
}
Комментарии:
1. вы это поняли?
Ответ №2:
Если вам действительно нужно преобразование в 2D-массив, преобразуйте изображение в байтовый массив с помощью CGContext, а затем разделите массив на части. CGContext использует диапазон цветов 0 … 255 вместо 0 … 1. Байтовый массив будет в формате rgba.
Пример кода с преобразованием в 0 … 1:
import UIKit
import CoreGraphics
func pixelData() -> [UInt8]? {
let dataSize = size.width * size.height * 4
var pixelData = [UInt8](repeating: 0, count: Int(dataSize))
let colorSpace = CGColorSpaceCreateDeviceRGB()
let context = CGContext(data: amp;pixelData,
width: Int(size.width),
height: Int(size.height),
bitsPerComponent: 8,
bytesPerRow: 4 * Int(size.width),
space: colorSpace,
bitmapInfo: CGImageAlphaInfo.noneSkipLast.rawValue)
guard let cgImage = self.cgImage,
let context = context else { return nil }
context.draw(cgImage, in: CGRect(origin: .zero, size: size))
return pixelData
}
func pixelMatrix() -> [[[Float]]]? {
guard let pixels = pixelData() else {
return nil
}
var data: [[[Float]]] = []
let width = Int(size.width)
let height = Int(size.height)
for y in 0..<height {
var row: [[Float]] = []
for x in 0..<width {
let offset = 4 * ((width * y) x)
let red = Float(pixels[offset]) / 255
let green = Float(pixels[offset 1]) / 255
let blue = Float(pixels[offset 2]) / 255
let alpha = Float(pixels[offset 3]) / 255
let pixel = [red, green, blue, alpha]
row.append(pixel)
}
data.append(row)
}
return data
}