回答編集履歴

2

実装例を反映しました。

2019/11/22 13:28

投稿

eytyet
eytyet

スコア803

test CHANGED
@@ -28,9 +28,139 @@
28
28
 
29
29
 
30
30
 
31
-
31
+ 座標変換を反映した`onImageTap`はこちらです。置き換えて下さい。
32
+
33
+
34
+
32
-
35
+ ```swift
36
+
37
+ @IBAction func onImageTap(_ sender: UITapGestureRecognizer) {
38
+
39
+ guard let image = imageView.image else { return }
40
+
41
+ let pointOnImageView = sender.location(in: imageView)
42
+
43
+ let x = pointOnImageView.x / imageView.frame.width * image.size.width
44
+
45
+ let y = pointOnImageView.y / imageView.frame.height * image.size.height
46
+
47
+
48
+
49
+ if let color = image.color(of: CGPoint(x: x, y: y)) {
50
+
51
+ label.text = String(format: "%4dx%4d - (r:%3d, g:%3d, b:%3d, a:", Int(x), Int(y), color.red, color.green, color.blue) + String(describing: color.alpha) + ")"
52
+
53
+ }
54
+
55
+ }
56
+
57
+ ```
58
+
59
+
60
+
61
+ 点の取得を関数にしました。どこかのファイルに、以下も追加してください。
62
+
63
+
64
+
65
+ ```swift
66
+
67
+ extension UIImage {
68
+
69
+ /// Image上の点の色を返す。cgImageをもち、8bit/色だけ有効。alphaのみは非対応でnilを返す。
70
+
71
+ /// - Parameter point: Image上の色を調べたい点の座標。
72
+
73
+ /// - Returns: 不明のときはnilが返る。各色の値は0-255。alphaがない場合nilを返す。
74
+
75
+ func color(of point: CGPoint) -> (red:Int, green:Int, blue:Int, alpha:Int?)? {
76
+
77
+ guard let cgImage = self.cgImage else { return nil }
78
+
79
+ guard let pixelData = cgImage.dataProvider?.data else { return nil }
80
+
81
+ guard let data = CFDataGetBytePtr(pixelData) else { return nil }
82
+
83
+ guard 0 <= point.x && Int(point.x) < cgImage.width &&
84
+
85
+ 0 <= point.y && Int(point.y) < cgImage.height else { return nil }
86
+
87
+ guard cgImage.bitsPerComponent == 8 else { return nil }
88
+
89
+ print(CGImageAlphaInfo.premultipliedLast.rawValue, CGImageAlphaInfo.premultipliedFirst.rawValue)
90
+
91
+ let byteOrder = cgImage.bitmapInfo.intersection(.byteOrderMask)
92
+
93
+ guard byteOrder == [] || byteOrder == .byteOrder32Big || byteOrder == .byteOrder32Little else { return nil }
94
+
95
+
96
+
97
+ //タップした位置の座標にあたるアドレスを算出
98
+
99
+ let address = Int(point.y) * cgImage.bytesPerRow + Int(point.x) * cgImage.bitsPerPixel / 8
100
+
101
+
102
+
103
+ //それぞれRGBAの値をとる
104
+
105
+ let alphaInfo = CGImageAlphaInfo(rawValue: cgImage.bitmapInfo.intersection(.alphaInfoMask).rawValue)
106
+
107
+ var offset: (red:Int, green:Int, blue:Int, alpha:Int?)
108
+
109
+ if byteOrder == .byteOrder32Little {
110
+
111
+ if [.first, .noneSkipFirst, .premultipliedFirst].contains(alphaInfo) {
112
+
113
+ offset = (2, 1, 0, 3)
114
+
115
+ } else {
116
+
117
+ offset = (3, 2, 1, 0)
118
+
119
+ }
120
+
121
+ } else { // [] || .byteOrder32Big
122
+
123
+ if [.first, .noneSkipFirst, .premultipliedFirst].contains(alphaInfo) {
124
+
125
+ offset = (1, 2, 3, 0)
126
+
127
+ } else {
128
+
129
+ offset = (0, 1, 2, 3)
130
+
131
+ }
132
+
133
+ }
134
+
135
+ // alphaがない場合
136
+
137
+ if [CGImageAlphaInfo.none, .alphaOnly, .noneSkipFirst, .noneSkipLast].contains(alphaInfo) {
138
+
139
+ offset.alpha = nil
140
+
141
+ }
142
+
143
+
144
+
145
+ let r = Int(data[address + offset.red])
146
+
147
+ let g = Int(data[address + offset.green])
148
+
149
+ let b = Int(data[address + offset.blue])
150
+
151
+ let a = offset.alpha != nil ? Int(data[address + offset.alpha!]) : nil
152
+
153
+ return (r, g, b, a)
154
+
155
+ }
156
+
157
+ }
158
+
159
+ ```
160
+
161
+
162
+
33
- また、正しく点を調べられるようになっても、一点だけだと見た目とはだいぶ違う色が取れたりします。今回のように大きい画像を縮小して表示していると、全然違う色を読んでくる場合も多いでしょう。
163
+ なお、正しく点を調べられるようになっても、一点だけだと見た目とはだいぶ違う色が取れたりします。今回のように大きい画像を縮小して表示していると、全然違う色を読んでくる場合も多いでしょう。
34
164
 
35
165
  その場合は縮小は一つの解決策になるかと思います。
36
166
 

1

見出し番号の間違いを修正。

2019/11/22 13:28

投稿

eytyet
eytyet

スコア803

test CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
 
4
4
 
5
- 1.座標変換すればリサイズしなくても可能です。
5
+ (1) 座標変換すればリサイズしなくても可能です。
6
6
 
7
7
  `tapPoint`には「表示されているimageViewの画面上のサイズの点」の座標が入るので、それを元に元画像上の座標を割り出します。
8
8
 
@@ -20,7 +20,7 @@
20
20
 
21
21
 
22
22
 
23
- 2. RGBAの並び
23
+ (2) RGBAの並び
24
24
 
25
25
  RGBAの並びは固定ではありません。試した限りでは、assetに入れたJPEG画像のままではRGBAでしたが、後述のリサイズを通した画像はBGRAでした。これは、`CGImage.bitmapInfo`の情報から判別可能です。
26
26