2009年03月26日

perlのバックスラッシュ感覚でpopenを使う。

パイプってやっかいなイメージがあったので
Win時代はやろうやろうと思ってついにやらなかったのだけれど
unix系の場合は随分と使いやすい様だ。cだとwinでもあるみたいだけど
pipeより使いやすいpopenを使ってみた。
これはいわばperlでいうところのsystem命令か
「``」バックスラッシュでシェル命令を囲んでいるようなものだろう。
先行してperlでいろいろ作っていたのだがそれの互換として考えると


print `ls`



#define BUFSIZE 4096
FILE *r_pipe;
int readed_num;
char buffer[BUFSIZE + 1];
memset(buffer,'\0',sizeof(buffer));

をとりあえず事前に宣言してある前提で


in_pipe = popen("ls","r");
if(in_pipe != NULL){
while(1){
if(feof(in_pipe)) break;
readed_num = fread(buffer,sizeof(char),BUFSIZE,r_pipe);
printf("%s",buffer);
pclose(in_pipe);
}
}

となる。
popenはテキスト系のサンプルが多いが汎用性を考えてfeofをチェックして
その間ループで回している。

「printf」の部分をTprocみたいにしておけば関数化できそうだ。
popenを"w"で実行するとインプット側のパラメータを与えられるのだが
その場合はファイル出力が前提となっているコマンドに限られそうだ。

今回のpopenでとっさに思いついたのがdjpegとcjpegの存在で
jpegの読み込みだけならdjpegをpopenで開けば良いし
書き出しもpopenでcjpegを呼べばいいのだが
単にファイルサイズを落としたいだけなら

system("djpeg a.jpg|cjpeg -optimize -quality 80 -outfile tmp.jpg");

で充分。
現状いろいろ加工が必要なのはデジカメの状態が悪いからで
多分今後デジカメを更新したらこの処理でいいのだろう。

そうするとココログ対応でexifだけ残しておきたいとなると


sprintf(str,"djpeg %s|cjpeg -optimize -quality 80",name);
popen(str,"r");


として元ファイルのexifをまず書き込んでからcjpegの出力のjfifタグ以降を書き込めばいいということになるが
ここまでやるとcjpegの両端パイプを開きたい。
パイプの両端を開く方法はpopenではだめでpipeとforkとdup2を使うのだが
使うかどうか別としてそれはまた、

コマンド呼び出しの方法よりもライブラリーを使う方が一見すっきりしているが
使っていないときのリソースを考えると頻繁に呼び出さないならば使いきりのpopenの方が速い。
リサイズについてはdjpegの-scaleで整数倍ならば落とせる他
jpegtranを使うと8ドット単位だがロスレスでクリップできる。
libjpegを使うコード量とpipeを使うコード量のトレードオフを見たいところだ。

ところで

popen1.c:35: error: stray '\343' in program

なんてのがでて全然意味が分からなかったのだけど
全角スペースが紛れ込んでいたのが原因だった。
全角英語ってhtmlのスパム避けにはいいのだけれど
geditは日本語なんて深く追求しないだろうから
スペースとかフォントとかでどうにかしないといけないと思えた。


ラベル:popen Stray
posted by Xo_ox at 23:24| Comment(0) | C | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
×

この広告は180日以上新しい記事の投稿がないブログに表示されております。