Objective-Cで写真を消しゴムツールのように消したい

このQ&Aのポイント
  • Objective-Cで写真を読み込み、一部を消す方法を教えてください。
  • 参考にさせていただいたお絵かきするアプリを参考にしており、写真を読み込む部分までは実装済みですが、お絵描きする際に写真が消えてしまいます。
  • 黒で描画部分を消しゴムツールにするために、いくつかの変更を加えましたが、うまく動作しません。解決方法を教えてください。
回答を見る
  • ベストアンサー

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

写真を読み込み、その一部を消しゴムツールのように消したいと考えています。 参考にさせていただいたお絵かきするアプリhttp://dev.classmethod.jp/smartphone/iphone/ios-touch-drawing/に、UIImagePickerControllerで写真をUIImageviewに読み込む部分を追加しました。写真を読み込んだ後、お絵描きするためにUIImageviewをタッチすると写真が消えてしまいます。 他に消しゴムツールにするために、黒で描画する部分を以下のように変更、追加しました。 [[UIColor blackColor] setStroke];を [[UIColor colorWithRed:0 green:0 blue:0 alpha:0.0f] setStroke];に変更し、 CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeClear);を追加しました。 作ったものが字数的に貼付けられませんでした。 解決方法または、読み込んだ写真の一部を消す方法を教えていただきたく思い投稿しました。よろしくお願いします。

  • dkong
  • お礼率86% (170/197)

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

  • ベストアンサー
回答No.3

No.1です。 > イメージしている消しゴムツールは、指でなぞったところの写真イメージを消し、透明にしたいと考えています。 > undoは消したくない部分を消したときに戻すのに使いたいと考えています。 であれば、今のやり方で問題ないと思います。 試しに参考にしたプログラムを実際に私の方でも作ってみて描画色指定部分に CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeClear); を追加してみたら、ちゃんと透明色で塗られましたよ。 ちなみに、kCGBlendModeClearを設定したら、 描画色に何を指定しても透明で塗られます。 [[UIColor blackColor] setStroke]; のままでも透明で塗られます。 作ったプログラムを全部貼り付けなくてもdrawLineメソッドだけでも 開示すれば何かアドバイスできるかもしれません。

dkong
質問者

お礼

ありがとうございました。教えてもらったように描画色指定部分に CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeClear);をしていすると、消しゴムツールのようになりました。これを各部分が間違ってました。試しにプログラムを実際に作り、検証していただき本当に感謝しています。たいへん勉強になりました。ありがとうございました。また、機会があれば、よろしくお願いします。

その他の回答 (2)

回答No.2

No.1です。 > なぜか最初にタッチした部分が拡大表示されるようになりました。 参考にしたプログラムのどこをどうさわったかわかりませんが、 説明されているところ以外変更してないのだったら、 まぁそうなるだろうなと思います。 前回の質問と同じようにself.canvasのサイズよりも 読み込んだ写真のサイズの方が大きければ、その写真は self.canvas内で実際のサイズより縮小して表示されます。 一方、タッチ開始後の描画では、drawLineメソッドの [lastDrawImage drawAtPoint:CGPointZero]; の処理で、lastDrawImageに入っている写真イメージを描画しますが この描画方法は元の画像サイズのはみ出た部分を切り捨てる 方法ですので、大きな画像の左上の部分だけが拡大しして 表示されるように見えると思います。 ここを [lastDrawImage drawInRect:self.canvas.bounds]; とすれば、lastDrawImage描画もcanvasに合わせたサイズに 縮小されると思います。 > また、CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeClear);や[[UIColor colorWithRed:0 green:0 blue:0 alpha:0.0f] setStroke];の設定がおかしいのか、消しゴムツールにはなりません。 消しゴムツールって、どんな動作をすることを期待しているのですか? kCGBlendModeClearで描画すれば、その描画部分は透明色で塗られるので なぞったところの写真イメージが消えます。 参考にしたプログラムなら、canvasの下地のviewがたぶん白なので なぞったところが白くなったなら、kCGBlendModeClear指定は 正しく動作していると思います。 そうじゃなくて、自分で描いた線を消しゴムツールでなぞることで なぞったところの線が消え、元の写真イメージが復元されることを 期待しているのでしたら、読み込んだ写真イメージをcanvas.imageに 設定するのではなく、別のimageViewを作ってcanvasの下に その写真を敷けばよいです。 ただ、参考にしたプログラムは、消しゴムツールの替わりにundo機能を 持っていて、描画したのと逆の順に線を消していくことができるように なっています。それを知った上で消しゴムツールも作りたいということ なのでしょうか?

dkong
質問者

お礼

ありがとうございます。勉強になります。

dkong
質問者

補足

イメージしている消しゴムツールは、指でなぞったところの写真イメージを消し、透明にしたいと考えています。 undoは消したくない部分を消したときに戻すのに使いたいと考えています。 しかし、写真イメージに何もおこりません。なぞったところに透明な色がぬられてる?写真イメージの下に写真イメージが重なっている?など考えてみましたが、分かりませんでした。色を黒にしたら写真イメージの上に線は引けます。プログラミングの記述が、字数的に見てもらえないので、分かり難いですが、よろしくお願いします。

回答No.1

> お絵描きするためにUIImageviewをタッチすると写真が消えてしまいます。 参考にしたプログラムをざっと見ると、線を描く処理は、 lastDrawImageの画像を書いてその上にタッチした線を書いて、 それをself.canvas.imageに設定するようになっていますが、 読み込んだ写真はself.canvas.imageだけでなくlastDrawImageにも 設定していますか?

dkong
質問者

お礼

毎回、素早く、的確なご指導ありがとうございます。

dkong
質問者

補足

教えていただいたように、読み込んだ写真をself.canvas.imageだけでなくlastDrawImageにも設定したら、消えなくなりました。しかし、なぜか最初にタッチした部分が拡大表示 されるようになりました。拡大になるような部分はないように思うのですが また、CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeClear);や[[UIColor colorWithRed:0 green:0 blue:0 alpha:0.0f] setStroke];の設定がおかしいのか、消しゴムツールにはなりません。この部分はhttp://realisapp.com/iphone/coregraphics-paint/を参考にしてのですが、無理矢理くっつけてしまいました。 質問ばかりで申し訳ありません。ご指導よろしくお願いします。

関連するQ&A

  • objective-cについて教えてください。

    以前にhtml5のcanvasに写真を読み込み、写真の一部を消したり、ペイントしたりするものを作ったのですが、それをobjective-cで作ろうしています。 [IOS]CoreGraphicsでお絵描きアプリhttp://realisapp.com/iphone/coregraphics-paint/を参考にしています。写真を読み込む部分を付け足したいのですが、どのようにすればいいのでしょうか?写真を読み込んでペイント用のレイヤーを重ねるのではなく、読み込んだ写真に直接ペインとしたり、消したりしたいと考えています。以上のような内容について教えていただきたく思い投稿しました。よろしくお願いします。

  • 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

  • iphoneカメラアプリ開発、合成写真の表示

    iphoneカメラアプリ開発、合成写真の表示 つくりたい機能は、カメラで写真を取る際に、予め用意してあるデフォルト画像(ひこにゃん)を写真の上から重ねて撮影・保存できる機能です。つまり、自分で取った顔写真などにデフォルト画像を合成するアプリです。 現在、撮影画面ではデフォルト画像+写真が表示するのですが(添付画像)、撮影後に「使用」を選択すると、デフォルト画像が消えて、カメラで取った写真だけが残ってしまします。 保存できるのも写真のみで、デフォルト画像は保存できません。 ソースコードは、基本的な参考書に載ってるトイカメラなどを、下記の部分のみ変えて撮影画面にデフォルト画像を表示できるようにしてあります。 【本アプリ】 - (IBAction)doCamera:(id)sender { NSLog(@"カメラ"); if( [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]){ UIImageView *aimageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"test.png"]]; imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera; imagePicker.cameraOverlayView = aimageView; [self presentModalViewController:imagePicker animated:YES]; [imagePicker setDelegate:self]; [imagePicker setAllowsEditing:YES]; [imagePicker.cameraOverlayView release]; } } よろしくお願いします。

    • ベストアンサー
    • Mac
  • ナビゲーションバーのタイトルを2行で表示

    ObjctiveCを用いてiPhoneApp開発の勉強をしています。 タイトルの通り、ナビゲーションバーのタイトルを2行で表示させたいのですがうまくできないので助言をいただきたいです。 こちらのサイトを参考に進めました。 (参考)http://www.yoheim.net/blog.php?q=20121203 こちらのコードをコピペするといろいろとエラーが出てしまうのですが、 まず一行目に表示するラベルのaddSubviewするところで、 [titleView addSubview:taskMessageLabel]; のように記述されていますが、まだtaskMessageLabelは作成されていません。 また、二行目に表示するラベルのtaskMessageLabelはUILabel *taskMessageLabelとすると思うのですが、それもされていません。 いろいろと手直しをし、以下のようにしたのですが、二行目のサブタイトルしか表示されませんでした。 どのようにすれば、きちんと二行でタイトルを表示することができるのでしょうか? 回答お待ちしてます // ナビゲーションバーのtitleに表示する独自Viewを作成します。 UIView *titleView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 40)]; titleView.backgroundColor = [UIColor clearColor]; titleView.opaque = NO; // ☆☆ポイントはここ!! // 以下のように代入して、タイトルに独自Viewを表示します。 self.navigationItem.titleView = titleView; // 1行目に表示するラベルを作成して、 // 上記で作成した独自Viewに追加します。 UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 195, 20)]; titleLabel.font = [UIFont boldSystemFontOfSize:16.0f]; titleLabel.text = @"RSS"; titleLabel.textColor = [UIColor whiteColor]; titleLabel.textAlignment = NSTextAlignmentCenter; titleLabel.backgroundColor = [UIColor clearColor]; [titleView addSubview:titleLabel]; // 2行目に表示するラベルを作成して、 // 上記で作成した独自Viewに追加します。 UILabel *taskMessageLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 20, 195, 40)]; taskMessageLabel.font = [UIFont boldSystemFontOfSize:10.0f]; titleLabel.text = @"サブタイトル"; taskMessageLabel.textColor = [UIColor colorWithRed:104.0f/255.0f green:100.0f/255.0f blue:100.0f/255.0f alpha:1.0f]; taskMessageLabel.textAlignment = NSTextAlignmentCenter; taskMessageLabel.backgroundColor = [UIColor clearColor]; taskMessageLabel.adjustsFontSizeToFitWidth = YES; [titleView addSubview:taskMessageLabel];

  • Objective-Cについて

    今、Objective-Cを独学で勉強しているのですが、 プログラムで int a1; int a2; int b1 = 1; int b2 = 1; a1 = ++b1; a2 = b2++; NSLog(@"変数a1の値は%dです\n", a1); NSLog(@"変数a2の値は%dです\n", a2); NSLog(@"変数b1の値は%dです\n", b1); NSLog(@"変数b2の値は%dです\n", b2); これで「Run」を押すとそれぞれ、 「変数a1の値は2です」 「変数a2の値は1です」 「変数b1の値は2です」 「変数b2の値は2です」 とOutputされるのですが、この時なぜ「a2」が1と出てくるのか分かりません。 どなたか解説お願いします。

  • objective-c

    androidではテキストボックスなどがある画面デザインは主にXMLを使って表示するが objective-cは主にどのようにして画面デザインを表示するのでしょうか。

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

    下記のようにUIViewの上にUIImageViewを配置し、そこにUIImageをUIViewContentModeScaleAspectFitで表示させています。 表示している画像タップして、座標をとりたいと考えています。 UIImageView(UIImage)上だけをタップのエリアにしたいのですが、画面全体がタップのエリアになってしまいます。また、画像のアスペクト比を維持しUIImageViewサイズに収まるように表示しているので、タップでとれたUIImageView上の座標と、画像上の座標にズレができてしまいます。UIImageViewサイズに収まるように表示された画像上の位置から元の画像の座標を取得する方法を教えてください。 #import "ViewController.h" @interface ViewController (){ UIImageView *imageView; } @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. CGRect rect = CGRectMake(0,20, 360, 480); imageView = [[UIImageView alloc] initWithFrame:rect]; imageView.backgroundColor = [UIColor redColor]; //画像のアスペクト比を維持しUIImageViewサイズに収まるように表示 imageView.contentMode = UIViewContentModeScaleAspectFit; UIImage *image = [UIImage imageNamed:@"hoge.png"]; [imageView setImage:image]; [self.view addSubview:imageView]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } /** * タッチされたとき */ - (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { CGPoint p = [[touches anyObject] locationInView:imageView]; float x = p.x; // X座標 float y = p.y; // Y座標 NSLog(@"タップ開始 %f, %f", x, y); } @end

  • objective-cについて教えてください。

    UIImageとCGImageの違いについて調べて、 http://nadegiri.main.jp/?p=61 などを読んだのですが、理解できませんでした。違いや、使い方など教えてください。

  • objective-c

    初心者です。よかったら、どなたかお答えをおねがいします。 #import <Foundation/Foundation.h> int main (void) { const char *words[] = {"asldkfj",";ljasdf",";lkasj","ioisdji"}; /ここ/ int charsize; charsize = sizeof(words) / sizeof(words[0]); int i; for(i = 0; i < charsize ;i++){ NSLog(@"%s is %d characters long",words[i],strlen(words[i])); } return 0; } 上記のソースでは、wordsがポインタ変数になってますが、配列で、 const char words[] = {"asldkfj",";ljasdf",";lkasj","ioisdji"}; にするとエラーがでます。 配列にすると、要素数は判別できるが、文字数は判別できないってことでしょうか? そうだとしたら、理由を教えてください。 よろしくお願いします。

  • objective-cで困っています。

    objective-cをトライ&エラーで試しながら学習しているのですが、 下記の内容で行き詰っており、知恵をお借りしたいと思い投稿しました。 現在tml5のcanvasを使ってお絵描きアプリを作りました。このcanvasに書き込んだデータをiPhoneのカメラロールに保存することをトライしています。いろいろ調べてみると「HTML5 CANVASの描画内容をUIImage経由でカメラロールに保存する」という記事をみつけました。http://lab.spec5zigen.com/archives/html5-canvasの描画内容をuiimage経由でカメラロールに保存する/ その記事を参考に #import "ViewController.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. // UIWebViewのインスタンス化 CGRect rect = self.view.frame; UIWebView *webView = [[UIWebView alloc]initWithFrame:rect]; // Webページの大きさを自動的に画面にフィットさせる webView.scalesPageToFit = YES; // デリゲートを指定 webView.delegate = self; // URLを指定 NSURL *url = [NSURL URLWithString:@"http://xxxxxxxxxxxxxxxxxxxxxx"]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; // リクエストを投げる [webView loadRequest:request]; // UIWebViewのインスタンスをビューに追加 [self.view addSubview:webView]; } - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { if(![[request.URL.scheme] isEqualToString:@"sp5canvas2app"]){ return YES; } NSString * requestString = [[request URL] absoluteString]; NSArray *params = [requestString componentsSeparatedByString:@"data:image/png;base64,"]; // dataFromBase64String // NSData+Base64 Copyright 2009 Matt Gallagher. All rights reserved. // http://www.cocoawithlove.com/2009/06/base64-encoding-options-on-mac-and.html NSData * decodedData = [NSData dataFromBase64String:[params objectAtIndex:1]];//decode base64 to NSData UIImage *image = [UIImage imageWithData:decodedData]; UIImageWriteToSavedPhotosAlbum(image, self, nil, nil);//カメラロールに保存 return NO; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end としてみたのですが、 if(![[request.URL.scheme] isEqualToString:@"sp5canvas2app"]){ の行にExpected identifierというエラーが、 NSData * decodedData = [NSData dataFromBase64String:[params objectAtIndex:1]];の行にNo known class method for selector 'dataFromBase64String:'というエラーが という状況で詰っている状況です。 メソッドの定義や宣言されていないメソッドを使っているなどのエラーということを調べて分かったのですが、objective-cを始めたばかりで初歩的なミスかも知れませんがエラーの対応の仕方がまだまだよくわかっていません。 スキーマなど参考にしたサイトの内容も十分に理解しているのではないのですが、「sp5canvas2app」の部分は自由に変えていいのでしょうか? 解決の仕方を教えていただけないでしょうか? 宜しくお願いします。