ややプログラム紀行

博士2年のプログラムに関する日記

UIImageの編集

ずっと書かなくてすいませんでした

でも今Xcodeアップデート中だからできねえ・・・

その間にお風呂でも入ってきますわ

その前に少し書いておこう

観察して分かったことですが

ペイントソフトのペン(?)といったら主に3つあると思います

まず鉛筆

背景関係なく塗りつぶすものです

正直これは簡単なんですけど、残りの二つがよくわからん

次に筆(?)

なんか少しぼけた感じに塗られる

でも、背景色はけっこう塗りつぶされる(上書きされる)

これのやり方は模索中です

いずれ考えたやり方を書いてみます

最後にスプレー(?)

だいぶぼやけた感じに塗られる

1点をずっと塗っているとだんだん濃くなってくる

筆とスプレーの違いがよくわかりませんが、上書き具合と

筆はカーソル移動で塗られるのに対して、

スプレーはボタンを押している間はずっと塗られるのかな?

まあいいや、すみません

こんどまとめます

お風呂入ってくるノシ

あがった

どうでもいいですが、macってwindowsにはないかっこよさがありますね

Xcodeのアップデート終わったと思ったらコンポーネントのダウンロードが始まった

終わったけど

えっと、画像の編集ですが、基本的にはこのサイトと同じことをしています

http://news.mynavi.jp/column/iphone/004/index.html

参考にさせてもらいました

ここでは、自分で用意したバッファーから画像を作ってみようと思います

まずバッファーの作成ですが、自分はここでだいぶ躓きました

C++じゃないからnewが使えない〜!みたいな

でも、メモリを確保する関数はCにもありましたし、Objective-Cではコードの中に、平然と(?)Cの関数を使えました

Cのmallocって関数を使います

使い方は

UInt8* buffer = malloc(width*height*4);

こんな感じです

UInt8はC++のunsigned intで、8ビット、つまり1バイトです

unsignedとはマイナスになることがないよ〜っていみです(詳しくはググってね!)

引数はバイトですが、4倍をしてるのはあとで説明します

まあこれでメモリ確保できました

Releaseについてですが、ARCがどこまでやってくれるかわかりませんが、とりあえず僕は書いてません

このbufferをいろいろいじってく訳ですが、中身はとても簡単です

いわゆるBGRAというものになってます、ARGBじゃないです

つまり、

青、緑、赤、透度

と並んでいて、この4つで1つのピクセル情報となってます

さっき、メモリ確保で4倍したのはこのためです

それぞれ1バイトなので0〜255までの値を入れることができ、

青、緑、赤は255に近づくと色が濃くなっていき

透明度は0に近づくにつれ透明になっていきます(255で無透明)

例えば紫は255,0,255,255という具合です

これでデータをいじったら、画像に変換です

まずは、CFDataに変換します

CFから始まるものはCore Foundationの類いです

CFDataは名前の通りデータを扱います

CFDataRef cfData = CFDataCreate( 0, buffer, (CFIndex)width*height*4);

こんなかんじで

CFDataRefとは名前から推測するに、参照用で書き込め得ないんだと思います(よくわからん)

CFDataCreateの第1引数は0安定

CFAllocatorRefを渡すことになってるんだけど、自分でアロケーターつくってガリガリやってる人向けなんでしょうね

0にするとデフォルトのが使われるんだと思います

第2引数にはバッファーのポインター

第3引数にはCFIndexとかいうのを渡すらしいですが、調べてみたらこれはどうやらsigned longの型名をかえたやつっぽいです

ここにはバッファーのサイズを渡せばいいので、普通にwidth*height*4をしてCFIndexに型変換するのがいいんじゃないかと思います

次にCGDataProviderに変換します

CGから始まるのはCore Graphics系です(確か)

このProviderは僕もよくわからないんですが、画像を扱うものらしいです

CGDataProviderRef cgData = CGDataProviderCreateWithCFData(cfData);

でCFDataから一気に変換します

次にCGImageに変換です

これはさっきと同じCore Graphics系ですね

この変換は引数が多いんですが、まあやってみます

CGImageRef cgImage = CGImageCreate( width, height,

bitsPerComponent, bitsPerPixel, bytesPerRow,

colorSpace, bitmapInfo, cgData, nil, shouldInterpolate, intent);

長いっす(´・ω・`)

最初のwidth,heightは普通に入れます

型がsize_tとかいうやつですが、普通に型変換できました

bitsPerComponentは青、緑、赤、透明度とありますが、その1つずつ(青だけみたいな)のビット量(たぶん)

今回は8です

bitsPerPixelは1ピクセルに何ビット使うか

今回は8*4=32です

bytesPerRowは横列に何バイトつかうか

今回は4*widthです

colorSpaceは・・・マジくせ者なんだよ・・・

こいつのせいで・・・こいつのせいで・・・

僕は、最初に普通のやり方でUIImageを作り、そこから情報を受け取ることでこの関数の引数たちを埋めてました

でも、ブログに書く時、「引数の意味が分かってれば予めUIImageを作ってそこから情報得るひつようないんじゃね?!」と思いました

でもここで詰んだ・・・

colorSpaceについてはググってみてください

僕は今はこいつの作り方を知らないので、最初にUIImageを作り、そこから情報を得るというやりかたにします(詳しくは最初の方にはったサイトにかいてある)

一応colorSpace取得方法

UIImage* img;

CGImageRef cgImage = img.CGImage;

CGImageColorRef colorSpace = CGImageGetColorSpace(cgImage);

です

なんか吹っ切れたわー残り全部UIImageから情報取得でやるわー

CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(cgImage);

bool shouldInterpolate = CGImageGetShouldInterpolate(cgImage);

CGColorRenderingIntent intent = CGImageGetRenderingIntent(cgImage);

shouldInterpolateってやつ、書き換え可能かどうかのステータスなんだと思うけど、画像を書き換え可能ってどういうことだろう

まだまだ記事にするには早すぎたのか・・・!!!!

ちなみにですが、Objective-C Referenceで画像を編集するには絶対その画像のコピーをつくってそれを編集する必要があるって書いてあった気がします

あとはこんな感じで

img = [[UIImage alloc] initWithCGImage:cgImage];

ImageView.image = img;

なぜバッファーから画像を作ることにこだわるかというと、バッファーを切り替えることができるからです

でも、僕のかすかな予測ですが、バッファーを複数にするとバグがおこる気がする

まあくわしくはいずれの記事で

なんか記事にして、まだまだわからんなーっておもいました