質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

iPhone

iPhoneとは、アップル社が開発・販売しているスマートフォンです。 同社のデジタルオーディオプレーヤーiPodの機能、電話機能、インターネットやメールなどのWeb通信機能の3つをドッキングした機器です。

Q&A

解決済

2回答

3033閲覧

swift3におけるCIimage,CGimage処理で実機テストのみトラブルが発生

退会済みユーザー

退会済みユーザー

総合スコア0

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

iPhone

iPhoneとは、アップル社が開発・販売しているスマートフォンです。 同社のデジタルオーディオプレーヤーiPodの機能、電話機能、インターネットやメールなどのWeb通信機能の3つをドッキングした機器です。

0グッド

1クリップ

投稿2017/05/21 14:09

編集2017/05/29 14:12

###前提・実現したいこと
iPhoneアプリ開発に関して、
・表示されている画像を走査して、加工をしたい。
・画像走査

###発生している問題・エラーメッセージ
PC上のシミュレーターでは処理が上手くいくのだが、実機を用いたテストで上手くいかない。
具体的には、ボタンクリックで該当の処理が走り、画像に表示されるはずだが、画像が更新されない。
ボタンもクリックされた状態から戻らない。

・概要
ボタンをクリック

処理functionを呼び出し

function内で画像を走査し、dataへ変換、さらに再生成して戻す

呼び出し元にUIImage返す

上記画像をセット

###該当のソースコード ※修正しました

----画像拡大---- import UIKit import Photos class FAScrollView: UIScrollView{ // MARK: Class properties var imageView:UIImageView = UIImageView() var imageToDisplay:UIImage? = nil{ didSet{ zoomScale = 1.0 minimumZoomScale = 1.0 imageView.image = imageToDisplay imageView.frame.size = sizeForImageToDisplay() imageView.center = center contentSize = imageView.frame.size contentInset = UIEdgeInsetsMake(0, 0, 0, 0) updateLayout() } } var gridView:UIView = Bundle.main.loadNibNamed("FAGridView", owner: nil, options: nil)?.first as! UIView // MARK : Class Functions override func awakeFromNib() { super.awakeFromNib() viewConfigurations() } func updateLayout() { imageView.center = center; var frame:CGRect = imageView.frame; if (frame.origin.x < 0) { frame.origin.x = 0 } if (frame.origin.y < 0) { frame.origin.y = 0 } imageView.frame = frame } func zoom() { if (zoomScale <= 1.0) { setZoomScale(zoomScaleWithNoWhiteSpaces(), animated: true) } else{ setZoomScale(minimumZoomScale, animated: true) } updateLayout() } ---画像拡大→画面遷移---- import UIKit import Photos class FAImageCropperVC: UIViewController { // MARK: IBOutlets @IBOutlet weak var scrollContainerView: UIView! @IBOutlet weak var scrollView: FAScrollView! @IBOutlet weak var collectionView: UICollectionView! @IBOutlet weak var btnZoom: UIButton! @IBOutlet weak var btnCrop: UIButton! @IBAction func zoom(_ sender: Any) { scrollView.zoom() } @IBAction func crop(_ sender: Any) { croppedImage = captureVisibleRect() performSegue(withIdentifier: "FADetailViewSegue", sender: nil) } // MARK: Public Properties var photos:[PHAsset]! // MARK: Private Properties private let imageLoader = FAImageLoader() private var croppedImage: UIImage? = nil // MARK: LifeCycle override func viewDidLoad() { super.viewDidLoad() viewConfigurations() // zoom,cropボタン checkForPhotosPermission() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == "FADetailViewSegue" { let detailVC = segue.destination as? FADetailVC detailVC?.croppedImage = croppedImage } } // MARK: Private Functions private func checkForPhotosPermission(){ //※省略 } private func viewConfigurations() { btnCrop.layer.cornerRadius = btnCrop.frame.size.width/2 btnZoom.layer.cornerRadius = btnZoom.frame.size.width/2 } private func configureImageCropper(assets:[PHAsset]){ if assets.count != 0{ photos = assets collectionView.delegate = self collectionView.dataSource = self collectionView.reloadData() selectDefaultImage() } } private func selectDefaultImage(){ collectionView.selectItem(at: IndexPath(item: 0, section: 0), animated: true, scrollPosition: .top) selectImageFromAssetAtIndex(index: 0) } private func captureVisibleRect() -> UIImage{ var croprect = CGRect.zero let xOffset = (scrollView.imageToDisplay?.size.width)! / scrollView.contentSize.width; let yOffset = (scrollView.imageToDisplay?.size.height)! / scrollView.contentSize.height; croprect.origin.x = scrollView.contentOffset.x * xOffset; croprect.origin.y = scrollView.contentOffset.y * yOffset; let normalizedWidth = (scrollView?.frame.width)! / (scrollView?.contentSize.width)! let normalizedHeight = (scrollView?.frame.height)! / (scrollView?.contentSize.height)! croprect.size.width = scrollView.imageToDisplay!.size.width * normalizedWidth croprect.size.height = scrollView.imageToDisplay!.size.height * normalizedHeight let cr: CGImage? = scrollView.imageView.image?.cgImage?.cropping(to: croprect) let cropped = UIImage(cgImage: cr!) return cropped } private func isSquareImage() -> Bool{ let image = scrollView.imageToDisplay if image?.size.width == image?.size.height { return true } else { return false } } // MARK: Public Functions func selectImageFromAssetAtIndex(index:NSInteger){ FAImageLoader.imageFrom(asset: photos[index], size: PHImageManagerMaximumSize) { (image) in DispatchQueue.main.async { self.displayImageInScrollView(image: image) } } } func displayImageInScrollView(image:UIImage){ self.scrollView.imageToDisplay = image if isSquareImage() { btnZoom.isHidden = true } else { btnZoom.isHidden = false } } } ----呼び出し元------ private func viewConfigurations(){ imageView.image = croppedImage imageView.contentMode = UIViewContentMode.scaleAspectFit } @IBAction func editButton_Clicked(_ sender: Any) { //加工処理 let editedImage = TransparentImage().transparentImage(image: croppedImage) croppedImage = editedImage //画像セット viewConfigurations() } ----呼び出し先(TransparentImage)------ import UIKit import CoreImage class TransparentImage: NSObject { func transparentImage (image: UIImage) -> UIImage{ let editedimage:UIImage // let width :Int = Int((image.size.width)) let width :Int = Int((image.cgImage!.width)) // let height :Int = Int((image.size.height)) let height :Int = Int((image.cgImage!.height)) let imageData = image.cgImage!.dataProvider!.data //cgimageのデータ let datalenght = CFDataGetLength(imageData) var rawData = [UInt8](repeating: 0, count: datalenght) CFDataGetBytes(imageData,CFRange(location: 0, length: datalenght),&rawData) //画像データをrawDataへ転送 let provider = CGDataProvider(dataInfo: nil,data: rawData, size: datalenght,releaseData: releaseData) let colorSpaceRef = image.cgImage!.colorSpace let bitmapInfo = image.cgImage!.bitmapInfo let bitsPerComponent:Int = image.cgImage!.bitsPerComponent let bitsPerPixel = image.cgImage!.bitsPerPixel let bytesPerRow = image.cgImage!.bytesPerRow let cgImage = CGImage(width: width, height: height, bitsPerComponent: bitsPerComponent, bitsPerPixel: bitsPerPixel, bytesPerRow:bytesPerRow, space: colorSpaceRef!, bitmapInfo: bitmapInfo, provider: provider!, decode: nil, shouldInterpolate: false, intent: .defaultIntent) editedimage = UIImage(cgImage:cgImage!, scale:image.scale, orientation:image.imageOrientation) return editedimage } let releaseData: CGDataProviderReleaseDataCallback = { (info: UnsafeMutableRawPointer?, data: UnsafeRawPointer, size: Int) -> () in // https://developer.apple.com/reference/coregraphics/cgdataproviderreleasedatacallback // N.B. 'CGDataProviderRelease' is unavailable: Core Foundation objects are automatically memory managed print("callback") return } }

###補足情報(言語/FW/ツール等のバージョンなど)
swift3
テスト機:7 Plus

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fuzzball

2017/05/22 07:53

「ボタンが押した状態から戻らない」についてですが、transparentImage()の処理が終わらずに無限ループになっているのでしょうか?transparentImage()から処理が抜けているかどうか確認して下さい。
退会済みユーザー

退会済みユーザー

2017/05/22 15:01

処理は抜けてました。ヒントになるかわかりませんが、縦長の画像を処理した時に画像が崩れてしまいました。画像の処理が適切に行われていないように思います。
fuzzball

2017/05/23 04:33 編集

(deleted)
guest

回答2

0

ベストアンサー

CGDataProviderにCFDataGetBytesで取ってきた値を入れていた事が原因でした。
ポインタにし直したら正常に動きました。ありがとうございました。

投稿2017/06/08 14:42

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

気になったところを書き出してみます。

  1. widthとheightをUIImageから取り出していますが、これはscaleが反映されていない値なので、scaleを反映させるか、CGImageからwidth/heightを取り出して下さい。

  2. for x in 1...width {for x in 0..<width {なのでは?

  3. for y in 0...height-2 {はなぜ-2? 一番下のラインを走査しませんが良いのでしょうか?

  4. CGImage生成時のパラメータ(bitsPerComponentなど)は、元画像から取得しないといけないのでは?(意図して変更している場合を除く)

  5. 最後のUIImageの生成は、1の変更に合わせてinit(cgImage:scale:orientation:)を使用しないといけません。

もっと根本的な問題かもしれませんが、とりあえず。

投稿2017/05/23 05:05

fuzzball

総合スコア16731

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/05/24 14:59

回答ありがとうございます!頂いた内容をもとに修正したのですが、1点まだ問題がありました。 上記コードを実行した場合に、上手くいくと画像が青色のフィルタがかかったような状態になるのですが、 全画面表示の画像に対して実行すると上手くいきますが拡大した画像のものを操作すると青色フィルタが途中で止まってしまっているような状態です。forのあたりかなーと思いつつ、ソースを色々いじってみたのですが上手くいかず。。 1が理解できておらず、ここが問題のような気もしています。 scaleは下記で出してみましたが、3になりますが、どこに使ってもエラーになりよくわかっておりません。 let scale :Int = Int(UIScreen.main.scale) あとは比率部分だけだと思うのですが、よくわかっておらず、ご教示いただけないでしょうか?
fuzzball

2017/05/24 23:43

scaleとorientationは元のUIImageから取得しますので、最後の変換は、 UIImage(cgImage:cgImage!, scale:image.scale, orientation:image.imageOrientation) となります。 「拡大した画像」がどういうものか分かりませんが、もしscaleが3.0より大きいUIImageなのであれば、上記の修正で解決すると思います。
退会済みユーザー

退会済みユーザー

2017/05/27 04:53

ありがとうございます、頂いた点や、CGImageのパラメータをオリジナルデータから取得したり等を修正しました。ただ、まだ実機で処理が固まる?問題が解決しませんでした。 return editedimage  の時点で画像は入っており、そこまでは確実に処理は到達しています。 >transparentImage()から処理が抜けているかどうか こちらはどうやって確認すれば確認すれば良いでしょうか? viewConfigurations も処理後も呼ばれているようなのですが、なぜ表示されず止まったような状態になるのか分かりません。。
退会済みユーザー

退会済みユーザー

2017/05/27 06:11

image.cgImage!.bitsPerComponent で取った値が、 テスト:CGBitmapInfo(rawValue: 6) 実機:CGBitmapInfo(rawValue: 8198) となりここが怪しそうです。 下記が参考になりそうなのですが知識不足で意味がわかりません。。 http://one-hand-engineer.seesaa.net/article/380714510.html
fuzzball

2017/05/29 00:48 編集

6と8198は、bitsPerComponentではなくCGBitmapInfoの値でしょうか? だとすると、 シミュレータ:6 = CGBitmapInfo.byteOrderDefault | CGImageAlphaInfo.noneSkipFirst 実機:8198 = CGBitmapInfo.byteOrder32Little | CGImageAlphaInfo.noneSkipFirst (※ただし.byteOrderDefaultは実際には定義されていない。値は0) となりますが、これはRGBAの並び順とアルファの種類を表すものです。 ここがおかしくても、色やアルファが変になるだけで処理に影響は出ないと思います。 現在の質問内のコードにはピクセル(ドット)を操作するコードが含まれていませんが、この状態でも「止まったような状態」になるのでしょうか? あと、bitsPerComponent、bitsPerPixel、bytesPerRowの値を教えていただけるでしょうか? 可能であれば「拡大した画像」の生成コードも教えて下さい。
退会済みユーザー

退会済みユーザー

2017/05/29 14:18

文字数制限で保存できなかったので一部削除してしまいましたが、更新しました。 >6と8198は、bitsPerComponentではなくCGBitmapInfoの値でしょうか? はいそうです、失礼しました。 >現在の質問内のコードにはピクセル(ドット)を操作するコードが含まれていませんが、この状態でも「止まったような状態」になるのでしょうか? はい、実機テストではそうなってしまいました。PC上では正常に動きます。 bitsPerComponent:8 bitsPerPixel:32 bytesPerRow:12096 image.size.width:3024.0 image.size.height:4032.0 です。自分が混乱していて大変恐縮ですが、問題が現在2点発生しています。 1.PC上では正常に動くにも関わらず、実機テストでは動かない 2.PCのテスト環境でピクセルの色を変化させると、その適用が画面の2/3程度の高さにしかかからない。 でして、途中で2をご質問してしまいましたが、まずは1をどうにかしたいと考えております。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問