前提・実現したいこと
Swift初心者です。
勉強のため、画像をカメラまたはフォトライブラリから取り込み、フーリエ変換するアプリを作ろうとしています。
アプリの流れとしては、
1.カメラまたはフォトライブラリから画像を取り込む。
2.画面遷移し、取り込んだ画像を白黒画像に変換したものを表示する。
3.「画像をフーリエ変換」ボタンを押すことで、表示されている画像に対してフーリエ変換が行われる。
4.フーリエ変換が終了すると同時に、画面遷移しフーリエ変換した後の画像を表示する。
上記4にて、Thread 1: EXC_BAD_ACCESSエラーが出てしまいました。
色々試した結果、どうやらCGImage.initにて生成した画像をUIImage形式に変換し、UIImageViewに表示させようとするとエラーが発生しているようです。
どなたか解決方法を教えて頂けないでしょうか。
発生している問題・エラーメッセージ
Thread 1: EXC_BAD_ACCESS (code=1, address=0x10833c020) // addressの部分はビルドごとに変わります。
該当のソースコード
ConfirmViewController
1import UIKit 2 3class ConfirmViewController: UIViewController { 4 5 let dft = 1 // flag 6 let idft = -1 7 8 @IBOutlet weak var fourierButton: UIButton! 9 10 override func viewDidLoad() { 11 super.viewDidLoad() 12 13 // Do any additional setup after loading the view. 14 15 // 前画面から渡された画像をセット 16 confirmImage.image = originalImage 17 fourierButton.layer.cornerRadius = 10.0 18 19 } 20 21 /* 22 // MARK: - Navigation 23 24 // In a storyboard-based application, you will often want to do a little preparation before navigation 25 override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 26 // Get the new view controller using segue.destination. 27 // Pass the selected object to the new view controller. 28 } 29 */ 30 @IBOutlet weak var confirmImage: UIImageView! 31 32 // 前画面から渡された画像を格納するための変数 33 var originalImage: UIImage? 34 35 // 「画像をフーリエ変換」ボタンをタップした時の処理 36 var transformImage: UIImage? 37 @IBAction func fourierButtonAction(_ sender: Any) { 38 39 // 表示されている画像から輝度値を取得する 40 let imageData = getByteArrayFromImage(image: confirmImage.image!) 41 42 // 得られた輝度値を二次元離散フーリエ変換する 43 // 画像のwidth,heightを取得 44 let width = Int((confirmImage.image?.size.width)!) 45 let height = Int((confirmImage.image?.size.height)!) 46 print(width) 47 print(height) 48 // サンプル数 49 let length = imageData.count 50 // 実数部分と虚数部分を格納する配列 51 var re = [Double](repeating: 0, count: length) 52 var im = [Double](repeating: 0, count: length) 53 54 for i in 0..<length{ 55 re[i] = Double(imageData[i]) 56 im[i] = 0 57 } 58 59 // 転置 60 dft_swap2(re: &re, im: &im, width: width, height: height) 61 // 二次元離散フーリエ変換 62 dft_idft2(re: &re, im: &im, width: width, height: height, flag: dft) 63 // 得られた二次元配列をもとに画像を生成 64 let releaseData: CGDataProviderReleaseDataCallback = { (info: UnsafeMutableRawPointer?, data: UnsafeRawPointer, size: Int) -> () in 65 print("callback") 66 return 67 } 68 let provider = CGDataProvider.init(dataInfo: nil, data: re, size: length, releaseData: releaseData) 69 let bitsPerComponent:Int = 8 70 let bitsPerPixel:Int = bitsPerComponent // グレースケールなので 71 let bytesperRow:Int = width 72 let colorSpaceRef = CGColorSpaceCreateDeviceGray() 73 let bitmapInfo = CGBitmapInfo.byteOrderMask 74 let renderingIntent = CGColorRenderingIntent.defaultIntent 75 if let cgImage = CGImage.init(width: width, height: height, bitsPerComponent: bitsPerComponent, bitsPerPixel: bitsPerPixel, bytesPerRow: bytesperRow, space: colorSpaceRef, bitmapInfo: bitmapInfo, provider: provider!, decode: nil, shouldInterpolate: false, intent: renderingIntent) { 76 transformImage = UIImage(cgImage: cgImage) 77 } 78 79 self.performSegue(withIdentifier: "goAfterFourierTransform", sender: nil) 80 } 81 //画面遷移時に画像を渡す 82 override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 83 if let afterViewController = segue.destination as? AfterFourierTransformViewController{ 84 //次の画面のインスタンスに取得した画像を渡す 85 afterViewController.nextOriginalImage = transformImage 86 } 87 } 88 89 90 // 輝度値を取得する関数 91 func getByteArrayFromImage(image: UIImage) -> [Int] { 92 // まずUIImage形式の画像をCGImage形式に変換する。 93 let imageRef = image.cgImage 94 // CGImageのプロバイダー 95 let imageProvider = imageRef?.dataProvider 96 let imageData = imageProvider?.data 97 let length = CFDataGetLength(imageData) 98 // RGBA輝度値を最初に格納する配列 99 var rawData = [UInt8](repeating: 0, count: length) 100 CFDataGetBytes(imageData, CFRange(location: 0, length: length), &rawData) 101 // 得たRGBA輝度値をグレースケールに変換 102 var gray = [Int](repeating: 0, count: length/4) 103 for i in 0..<length/4 { 104 gray[i] = Int(0.299*Double(rawData[4*i]) + 0.587*Double(rawData[4*i + 1]) + 0.114*Double(rawData[4*i + 2])) 105 } 106 107 return gray 108 } 109 110 /////////////////////////////////////////////////////////////////////////////////// 111 /////////////////////////////////////////////////////////////////////////////////// 112 /////////////////////////////////////////////////////////////////////////////////// 113 114 115 //二次元配列の転置 116 func dft_swap2(re:inout [Double], im:inout [Double], width:Int, height:Int){ 117 var temp:Double = 0.0 118 for i in 0..<height/2{ 119 for j in 0..<width/2{ 120 temp = re[width*i + j] 121 re[width*i + j] = re[width*(height/2+i) + width/2 + j] 122 re[width*(height/2+i) + width/2 + j] = temp 123 124 temp = im[width*i + j] 125 im[width*i + j] = im[width*(height/2+i) + width/2 + j] 126 im[width*(height/2+i) + width/2 + j] = temp 127 128 temp = re[width*i + width/2 + j] 129 re[width*i + width/2 + j] = re[width*(height/2+i) + j] 130 re[width*(height/2+i) + j] = temp 131 132 temp = im[width*i + width/2 + j] 133 im[width*i + width/2 + j] = im[width*(height/2+i) + j] 134 im[width*(height/2+i) + j] = temp 135 } 136 } 137 } 138 139 // 一次元配列の離散フーリエ変換 140 func dft_idft(re: inout [Double], im: inout [Double], num: Int, flag: Int){ 141 var temp_re = [Double](repeating: 0.0, count: num) 142 var temp_im = [Double](repeating: 0.0, count: num) 143 var coefficient: Double = 0.0 144 145 if(flag == idft){ 146 coefficient = Double(num) 147 } else { 148 coefficient = 1.0 149 } 150 151 for i in 0..<num { 152 for j in 0..<num { 153 temp_re[i] += re[j]*cos(2.0*Double.pi*Double(i)*Double(j)/Double(num)) + Double(flag)*im[j]*sin(2.0*Double.pi*Double(i)*Double(j)/Double(num)) 154 temp_im[i] += im[j]*cos(2.0*Double.pi*Double(i)*Double(j)/Double(num)) - Double(flag)*re[j]*sin(2.0*Double.pi*Double(i)*Double(j)/Double(num)) 155 } 156 temp_re[i] /= coefficient 157 temp_im[i] /= coefficient 158 } 159 160 for i in 0..<num { 161 re[i] = temp_re[i] 162 im[i] = temp_im[i] 163 } 164 } 165 166 167 168 // 二次元配列の離散フーリエ変換 169 func dft_idft2(re: inout [Double], im: inout [Double], width: Int, height: Int, flag: Int){ 170 var temp_re = [Double](repeating: 0.0, count: width*height) 171 var temp_im = [Double](repeating: 0.0, count: width*height) 172 173 // 二次元配列を一行ずつ横方向に離散フーリエ変換していく 174 for i in 0..<height { 175 for j in 0..<width { 176 temp_re[j] = re[i*width + j] 177 temp_im[j] = im[i*width + j] 178 } 179 180 dft_idft(re: &temp_re, im: &temp_im, num: width, flag: flag) 181 182 183 for j in 0..<width { 184 re[i*width + j] = temp_re[j] 185 im[i*width + j] = temp_im[j] 186 } 187 } 188 189 // 次は一列ずつ縦方向に離散フーリエ変換していく 190 for j in 0..<width { 191 for i in 0..<height { 192 temp_re[i] = re[i*width + j] 193 temp_im[i] = im[i*width + j] 194 } 195 196 dft_idft(re: &temp_re, im: &temp_im, num: height, flag: flag) 197 198 for i in 0..<height { 199 re[i*width + j] = temp_re[i] 200 im[i*width + j] = temp_im[i] 201 } 202 } 203 // 最終的にre[i]とim[i]が二次元離散フーリエ変換されたのちの配列となる 204 } 205}
AfterFourierTransformViewController
1 2import UIKit 3 4class AfterFourierTransformViewController: UIViewController { 5 6 @IBOutlet weak var fourierImage: UIImageView! 7 8 9 override func viewDidLoad() { 10 super.viewDidLoad() 11 12 // Do any additional setup after loading the view. 13 14 fourierImage.image = nextOriginalImage 15 } 16 17 18 var nextOriginalImage: UIImage? 19 20 /* 21 // MARK: - Navigation 22 23 // In a storyboard-based application, you will often want to do a little preparation before navigation 24 override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 25 // Get the new view controller using segue.destination. 26 // Pass the selected object to the new view controller. 27 } 28 */ 29}
試したこと
AfterFourierTransformViewController
1fourierImage.image = nextOriginalImage
の部分をコメントアウトすると画面遷移されましたので、この部分でエラーが起きているようです。
ConfirmViewControllerにて、試しに画面遷移をする前に、同じ画面上にフーリエ変換後の画像を表示させてみようとしました。
ConfirmViewController
1@IBOutlet weak var afterImage: UIImageView! // フーリエ変換後の画像を表示するImageView
を追加し、フーリエ変換したのちに
ConfirmViewController
1afterImage.image = transformImage
で画像を表示させようとしたところ、この部分でエラーが起きました。
以上から考えるに、どうやら二次元配列から生成した画像をUIImageViewに表示させようとするとエラーが発生するようですが、その解決方法が分かりません、、。
補足情報(FW/ツールのバージョンなど)
Swift4
Xcode10beta
回答1件
あなたの回答
tips
プレビュー
下記のような回答は推奨されていません。
このような回答には修正を依頼しましょう。
また依頼した内容が修正された場合は、修正依頼を取り消すようにしましょう。
2018/09/26 03:55
2018/09/26 04:00
2018/09/26 04:42
2018/09/26 04:51
2018/09/26 04:59
2018/09/26 05:09
2018/09/26 05:11
2018/09/26 05:28
2018/09/26 06:04