ラベル 画面解像度 の投稿を表示しています。 すべての投稿を表示
ラベル 画面解像度 の投稿を表示しています。 すべての投稿を表示

2018年11月15日木曜日

タッチ座標の色情報を得る

やりたいこと

UIImageViewをタッチしたピクセルの色情報とアルファ値を得る。
たとえば赤いピクセルをタッチしたら
r:255.0 g:0.0 b:0.0 a:255.0
などと出るように。

やり方

タッチ位置に相当するImageViewに貼られたImageのアドレスを参照し、色情報を得る。
ImageViewに表示したImageはたいてい縮小か拡大されてるので、画面のタッチ位置からImage上の位置を計算する。

Image上の位置から画像データのメモリ上のアドレスを計算する。
アドレス計算時は1ピクセルを何バイトで扱っているのかの考慮が必要。(4バイトだった)
Retinaディスプレイの場合、縦横ともデータが2.0倍とかなるので(最近は3.0倍もあるんだっけ?)それも考慮に入れてアドレス計算要。
(注:Retinaで2.0のscaleを得て計算したらかえってうまくいかなかったので、以下のコードでは1.0を代入してある。おそらく画面比率の計算とかを二重にやっちゃってるんじゃないかと思うんだけど、よくわからねぇ…(^^;)ゞ
画面のタッチ位置とオリジナルImage上の位置の変換をしなければ、Retina解像度を考慮に入れたやり方でうまくいくんじゃないかと思う…)

サイトを参考にUIImageを拡張して機能を付けた。

画像の本当の大きさとImageView上に貼られた画像の比率を計算する過程でAVFoundationをimport要。

注意点

CGImageは必ずしもRGBAの順番で並んでいるわけじゃないそうな。
CGImageのCGImageAlphaInfo.rawValueでどういう並びなのか調べられる。
以下のコードではRGBAの並びとして書いている。

コード

Swift4.1
import UIKit
import AVFoundation

let pixelDataBytesSize = 4; //1ピクセルのバイト数

extension UIImage {
func getColor(pos: CGPoint) -> (color:UIColor, r:CGFloat, g:CGFloat, b:CGFloat, a:CGFloat) {
let imageData = self.cgImage?.dataProvider?.data //画像データ
let data:UnsafePointer = CFDataGetBytePtr(imageData) //画像データのポインタ(配列扱い)を得るらしい
let scale:CGFloat = 1.0 //UIScreen.main.scale //画面のスケール(Retinaなら多分2.0〜3.0)を得る(コメントアウト中)
//任意のピクセルアドレスを計算
let address:Int = ((Int(self.size.width) * Int(pos.y * scale)) + Int(pos.x * scale)) * pixelDataBytesSize
//RGBαの各値を得る
let r = CGFloat(data[address])
let g = CGFloat(data[address + 1])
let b = CGFloat(data[address + 2])
let a = CGFloat(data[address + 3])
return (UIColor(red: r / 255, green: g / 255, blue: b / 255, alpha: a / 255), r, g, b, a)
}
}

class ViewController: UIViewController {
@IBOutlet weak var myLabel: UILabel!
@IBOutlet weak var myImageView: UIImageView!

override func viewDidLoad() {
super.viewDidLoad()
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
//imageView上の実表示フレーム
let presentedFrame = AVMakeRect(aspectRatio: (myImageView.image?.size)!, insideRect: myImageView.bounds)
let marginX = presentedFrame.origin.x //上部のマージン
let marginY = presentedFrame.origin.y //左のマージン
if let touch = touches.first as UITouch? {
let loc = touch.location(in: myImageView) //タッチ座標
let image = myImageView.image
//画面上のタップ位置とimage上のタップ位置の変換
let tapX = (image?.size.width)! / presentedFrame.size.width * (loc.x - marginX)
let tapY = (image?.size.height)! / presentedFrame.size.height * (loc.y - marginY)
let color = image?.getColor(pos: CGPoint(x: tapX, y: tapY))
myLabel.textColor = color?.color
myLabel.text = "r:\(color!.r.description) g:\(color!.g.description) b:\(color!.b.description) a:\(color!.a.description)"
}
}
}

参考サイト

2016年6月14日火曜日

すべてのiPhoneに対応させない

注意:結論から言うと、うまくいきませんでした。

解像度が多すぎる

アンドロイドスマホほどじゃないとは思うが、iPhoneは解像度とアスペクト比のバリエーションが多い。
執筆時現在、以下の画面サイズに対応させなければいけない。
  • RetinaのiPhone4sで640×960
  • 縦にサイズが伸びたiPhone5が640×1136
  • iPhone6では4.7インチで750×1334
  • 最新のiPhone6 Plusでは5.5インチで1242×2208

このうちiPhone4sだけは縦が短いので、うまく画面を作らないと、それ以外の画面で横がはみ出したり上下に黒い帯を表示させることになってしまう。

正直、いちいちこんないっぱい対応してられるか! と思う。
これにiPadの対応までするとなるとますますだ。(iPadはアスペクト比が一緒だからレイアウト変更などは一種類で済むが)
俺のせこいアプリなんかはiPhone4sの解像度でだけ作って、iPhone6s Plusだろうがスケーリングモードで拡大して表示してくれるとありがたい。
要はiPhoneのアプリをiPadで使う時みたいに、多少表示が粗く見えても2倍とかに拡大してくれればいいのだ。

そういう風に作れないだろうか?
さらに、それでアップルの審査をパスできるだろうか?(最低iPhone5のサイズに対応せんと怒られるのではないか?)

対応させないためには

みなさん頑張って各解像度に対応させてるのか、検索してもスケーリングモードで表示させる方法があまり出てこない。
どうやらアプリ起動時に表示されるLaunch Screen(スプラッシュスクリーンともいうのだな)をどの解像度(機種)の分をインストールするか/しないかで対応解像度を選べるらしい…ということだけ風の便りで聞いていた。


そこでLaunch ScreenにiPhone4s(3.5インチ)用のLaunchScreenだけ入れiTunesConnectにアップロードし、スクリーンショットも3.5インチ画面のみをアップロードしてみた。
しかし「審査提出」ボタンを押すと「アプリが他のサイズ用に対応してるから、それ用のスクリーンショットもアップロードしろ」と出てしまった。

チェックボックス全てOFFにしてみる

最低限のLaunch Image
XcodeのLaunchImageの画面でスクリーンショットの入ってない枠が残ってるせいかと思い、LaunchImageのインスペクタでチェックボックスを全てOFFにしてみたが、やっぱりiTunesConnectで同じエラーになる。

もしかしたらちゃんとしたやり方あるんだろうとは思うけど、近い将来サポートされなくなる3.5インチにこだわって作っててもしょうがないのであきらめることにした。
あ〜、全部の解像度対応してやりますよ! このヤロー!(TДT)(iPadを除く)

やっぱりサポートされなくなった

2016/6/14のアップルのイベントでiOS10について発表があり、iPhone4sが非対応になったようだ。
これで、若干のアスペクト比の違いはあれど全て縦長になったので(iPadを除く)、デザインはしやすくなったかな。

iPadのスケーリング表示はどうなる?

iPadってiPhoneしか対応してないアプリを使う場合、現状ではiPhone4sの解像度をスケーリング表示させてるけど、これからはどうなるんだろうな。
iPhone5の解像度をスケーリング表示するようになるの?

iPad対応版を作るんであれば、どのみち今までどおり縦長なiPhone、正方形に近いiPadの両方のデザインを作らないといけませんな。こっちはもう早くからあきらめてる。