みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

objective-cで困っています教えてください

objective-cをトライ&エラーで試しながら学習をしている初心者です。タッチした所を中心にまず100×100の正方形を表示し、その後スライダーで正方形の大きさを決めてから画像のトリミングをしたいのですが、正方形が表示されないのと、タッチした位置と切り取られる位置がずれています。上記の内容で行き詰っており、知恵をお借りしたいと思い投稿しました。宜しくお願いします。
ViewController.mの内容

#import "ViewController.h"

@interface ViewController (){
//
UILabel *label;
//
UIImageView *uv;
//中心の位置
float v;
// X座標
float x;
// Y座標
float y;

}

@end

@implementation ViewController

- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.


//写真の表示
CGRect rect_uv = CGRectMake(0,20, 360, 360);
UIImageView *imageView = [[UIImageView alloc] initWithFrame:rect_uv];
//画像のアスペクト比を維持しUIImageViewサイズに収まるように表示
imageView.contentMode = UIViewContentModeScaleAspectFit;
UIImage *image = [UIImage imageNamed:@"hoge.png"];
[imageView setImage:image];
[self.view addSubview:imageView];



// UISliderのインスタンス化
CGRect rect_sd = CGRectMake(50, 400, 200, 10);
UISlider *slider = [[UISlider alloc]initWithFrame:rect_sd];
// スライダーの最小値,最大値,値を設定
slider.minimumValue = 0;
slider.maximumValue = 500;
slider.value = 100;
// スライドしている最中に値を調べられるようにする.デフォルトでYESだがサンプルのため
slider.continuous = YES;
// スライダーの値が変更されたときに呼ばれるメソッドを設定
[slider addTarget:self
action:@selector(slider_ValueChanged:)
forControlEvents:UIControlEventValueChanged];
// スライダーをビューに追加
[self.view addSubview:slider];



// ラベルの設置
CGRect rect_lb = CGRectMake(300, 400, 100, 30);
label = [[UILabel alloc]initWithFrame:rect_lb];
[self.view addSubview:label];


// 標準ボタン例文
UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btn.frame = CGRectMake(50, 450, 100, 30);
[btn setTitle:@"切り取り" forState:UIControlStateNormal];
[btn addTarget:self action:@selector(trim:)
forControlEvents:UIControlEventTouchDown];
[self.view addSubview:btn];

}

- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}




/**
* スライダーの値が変更されたとき
*/
- (void)slider_ValueChanged:(id)sender
{
UISlider *slider = sender;

// スライダーの値をログに記述
NSLog(@"スライダーの値:%f", slider.value);

// ラベルのテキストを設定
//float v = slider.value;
v = slider.value;
label.text = [NSString stringWithFormat:@"%2.f",v];

//四角形を描画
CGContextRef context = UIGraphicsGetCurrentContext(); // コンテキストを取得
CGContextStrokeRect(context, CGRectMake(x,y,v,v)); // 四角形の描画
}


/**
* タッチされたとき
*/
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
// 1.anyObjectメソッドでいずれか1つのタッチを取得
// 2.locationViewメソッドで対象となるビューのタッチした座標を取得
CGPoint p = [[touches anyObject] locationInView:self.view];
x = p.x; // X座標
y = p.y; // Y座標
NSLog(@"タップ開始 %f, %f", x, y);


//四角形を描画
CGContextRef context = UIGraphicsGetCurrentContext(); // コンテキストを取得
CGContextStrokeRect(context, CGRectMake(x,y,100,100)); // 四角形の描画


}


/**
* 切り取りボタンが押されたとき呼ばれるtrimメソッド
*/
-(void)trim:(UIButton*)button{
// ここに何かの処理を記述する
// (引数の button には呼び出し元のUIButtonオブジェクトが引き渡されてきます)


// 切り抜き元となる画像を用意する。
//UIImage *srcImage = /* UIImagePickerなどから取得したUIImage */
UIImage *srcImage = [UIImage imageNamed:@"hoge.png"];

// 切り抜く位置を指定するCGRectを作成する。
CGRect trimArea = CGRectMake(x, y, v, v);

// CoreGraphicsの機能を用いて、
// 切り抜いた画像を作成する。
CGImageRef srcImageRef = [srcImage CGImage];
CGImageRef trimmedImageRef = CGImageCreateWithImageInRect(srcImageRef, trimArea);
UIImage *trimmedImage = [UIImage imageWithCGImage:trimmedImageRef];


// 画像表示例文
//UIImage *img = [UIImage imageNamed:@"hoge.png"];
UIImageView *iv = [[UIImageView alloc] initWithImage:trimmedImage];
[self.view addSubview:iv];
}

@end

投稿日時 - 2015-03-28 08:43:57

QNo.8944278

すぐに回答ほしいです

質問者が選んだベストアンサー

まず、正方形が表示されない理由は
---------------------------------------------
//四角形を描画
CGContextRef context = UIGraphicsGetCurrentContext(); // コンテキストを取得
CGContextStrokeRect(context, CGRectMake(x,y,v,v)); // 四角形の描画
---------------------------------------------
の記述箇所がまずいからだと思います。
これはどこに書いてもいいものではありません。
http://ameblo.jp/yusuke-s9th-tech/entry-11179466733.html
に例があるように、drawRectメソッドの中に書く必要があります。
drawRectメソッドの中なら、画面描画用のコンテキストが確保
された状態で呼ばれるのでUIGraphicsGetCurrentContextを
実行するとコンテキストが返ってきます。現在記述している箇所だと、
おそらくコンテキストはNULLが返ってきているのではないかと思います。

あと、描画色も指定する必要があると思います。
そのあたりは、先ほど紹介したURLを参考にしてください。

なお、四角形を書くだけなら、透明のUIViewを作って
http://hachinobu.hateblo.jp/entry/2014/01/20/165713
のように境界線を描画するよう指定する方法もあります。
最終的に複雑な図形にしたいならやはりコンテキストに描画する
必要があります。


次に、タッチした位置と切り取られる位置がずれている理由は、

タッチした位置を取得するのに
CGPoint p = [[touches anyObject] locationInView:self.view];
x = p.x; // X座標
y = p.y; // Y座標
で、self.viewの座標を求めているのに対して、

切り取りは
CGRect trimArea = CGRectMake(x, y, v, v);
CGImageRef trimmedImageRef = CGImageCreateWithImageInRect(srcImageRef, trimArea);
と、画像イメージに対してそのままself.viewの座標を指定しています。

しかし、画像イメージは
CGRect rect_uv = CGRectMake(0,20, 360, 360);
UIImageView *imageView = [[UIImageView alloc] initWithFrame:rect_uv];
とself.viewの20ピクセル下から表示しているため、ずれているのだと思います。
あと、読み込んだ画像のサイズがもし360x360でなかったら、
imageView.contentMode = UIViewContentModeScaleAspectFit;
により、360x360に合うように自動的に画像が縮小表示される可能性もありますので、
そのあたりの調整も必要かもしれません。
いずれにしても、適切な座標変換をする必要があるということです。

座標変換は、
http://qiita.com/edo_m18/items/06e55b60f4d7adb9e0ea
で解説されているconvert***系メソッドが使えます。

投稿日時 - 2015-03-28 11:01:23

お礼

丁寧な対応ありがとうございます。四角形は透明のUIViewの方法で思っているようにできました。タッチの座標がずれるのは教えていただいたconvertメソッドでy方向の20ずれはなくなりました。convertメソッドだけで、拡大縮小された画像から狙ったところが切り抜けるのでしょうか?
Convertメソッド勉強していきたいです。また、よろしくお願いします。

投稿日時 - 2015-03-30 12:19:15

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(2)

ANo.2

No.1です。

一つ見落としていました。
正方形が表示されない件ですが、もしdrawRectメソッドの中で
正しく描画できたとしてもまだ問題があります。

UIViewに正方形を描画しても、その上にimageViewが乗りますから、
結局imageViewの裏に隠れて見えないことになります。

結局、背景色透明のUIViewをimageViewより上に乗せ、
そのUIViewのdrawRectを実装するか、
あるいはそのUIViewの境界線で四角形を表示する必要があると思います。

投稿日時 - 2015-03-28 15:12:35

あなたにオススメの質問