忍者ブログ
  • 2017.10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 2017.12
メディアンカット(3)
とありあえず、ええ感じになったのでwindows版のしょぼいbmpからpngに変換するツールを公開

bmp2png.exe (元ファイル).bmp (先ファイル).png [カラー色数]

(制約)RGBカラーのみ対応。カラー色数は1~256。動作保証・損害責任なし。
   別途zlib1.dll・libpng12.dllが必要。

ダウンロード(v1)カットしたまま(速い)
ダウンロード(v2)カットして近い色(遅い)

ライセンスは下記条件を満たせばフリー。

・コメントで使用した旨のメッセージ、または当記事へのブログからのリンク等
 他への紹介するメディアを所持している場合、紹介すること。

・同等の機能を満たすより良いフリーのツールが見つかったら教えてくらさい。

PR
【2013/07/24 07:30 】 | C/C++ | 有り難いご意見(0)
                                    
メディアンカット(2)
実際にメディアンカットを実装してみた。

●オリジナル


●gimpのインデックスカラー256色


●メディアンカットv1(直方体のまま)


●メディアンカットv2(球で一番近いもの)


メディアンカットはすべてのR・G・Bで最も長いものをミディアンで切る実装。
オリジナルがなぜかWeb上では青が紫に見えてしまう。
なんか設定で変えられるのかも・・・
ローカルに保存すると青は青だ。

gimpさんはすごいです。もしかしたらパレット操作だけでなく
何か別の操作をしてるのかも。
【2013/07/22 06:42 】 | C/C++ | 有り難いご意見(0)
                                    
gccリンカの謎(2)
ldのmanに書いてあった。
           The linker will search an archive only once, at the location where
           it is specified on the command line.  If the archive defines a
           symbol which was undefined in some object which appeared before the
           archive on the command line, the linker will include the
           appropriate file(s) from the archive.  However, an undefined symbol
           in an object appearing later on the command line will not cause the
           linker to search the archive again.

           See the -( option for a way to force the linker to search archives
           multiple times.

           You may list the same archive multiple times on the command line.

           This type of archive searching is standard for Unix linkers.
           However, if you are using ld on AIX, note that it is different from
           the behaviour of the AIX linker.
というか、AIXだと違うのか!?
【2013/02/17 07:42 】 | C/C++ | 有り難いご意見(0)
                                    
gccリンカの謎
gccの-lオプションが効かない時があるのでその原因を確かめてみた。


$ gcc  pp4.c pp.c pp2.c
/tmp/ccj9EogJ.o: In function `func':
pp2.c:(.text+0x7): undefined reference to `link2'
/tmp/cchGaury.o: In function `main':
pp.c:(.text+0x11): undefined reference to `link1'
collect2: ld はステータス 1 で終了しました

こんなソースがある場合、link1とlink2を含むlibpp3.soで解決する必要がある
当初、ソース1個以上指定した後の-lオプションのみが有効かと思いきや
リンクメッセージがないと-lが効かないという話を教えてもらったので試してみた。

$ gcc  pp4.c -l pp3 pp.c pp2.c
/tmp/ccj9EogJ.o: In function `func':
pp2.c:(.text+0x7): undefined reference to `link2'
/tmp/cchGaury.o: In function `main':
pp.c:(.text+0x11): undefined reference to `link1'
collect2: ld はステータス 1 で終了しました

あら、ほんとだ。pp4.cはlink1もlink2も依存していないため
これでもエラーが起こる・・・。

$ gcc  pp4.c pp.c -l pp3 pp2.c


では、link1に依存するpp.cの後に-l pp3を移動させると
エラーはなくなった~

てっきり
/tmp/ccj9EogJ.o: In function `func':
pp2.c:(.text+0x7): undefined reference to `link2'
みたいなのが出ると思ったのだけどそうでもないらしい。
つまり・・・
-lオプションは最後に書けということですなぁ。

バージョンによっては直ってるgccもあるらしい。
【2013/02/16 20:23 】 | C/C++ | 有り難いご意見(0)
                                    
cout vs printf (2)
なぜ、coutのほうが遅いのか?

どうやら double型が特に遅いみたいである。

で、かくかくしかじか辿っていった結果。

一因がnum_putクラスが遅いことが分かった。

num_putのdo_putオーバーライド

class my_numput : public std::num_put<char>
{
protected:
iter_type do_put(iter_type out, ios_base& str, char_type fill, double val) const
{
char buf[50], *bufp = buf;
sprintf(buf, "%g", val);
copy(buf, buf + strlen(buf), out);

return out;
}
};


localeにnum_putを追加

loc = new locale(locale::classic(), new my_numput);
cout.imbue(*loc);


●実行方法1~3で計測してみることにした。
実行方法1

cout << d ;


実行方法2

char buf[50], *bufp = buf;
sprintf(buf, "%g", d);
fputs(buf, stdout);


実行方法3

fprintf(stdout, "%g", d);


結果(ms)

実行方法1(改良後←改良なし)
0.836←0.992

実行方法2
0.768

実行方法3
0.652


情報整理
・num_putが遅いことには間違いない。
・coutは doubleを置換する場合、try catchを行っている。
・coutのostream の出力方法は4×nバイト または1バイトのみである。
・coutのostreambufの出力方法はnバイト または1バイトのみである。
・coutのnum_putの出力対象はchar型のiter_typeなので出力方法は1バイトのみである。
・coutはostreambufでバッファを抽象化し、osteramで循環キューを抽象化している。

結論
coutまわりはクラスが立て込んでいて、ostreambufにフォーマッタがあればいいが
フォーマッタはostreamはlocaleに散らばっている。
これらはostreamが使うワーク領域がostearmbufが管理するワーク領域が
異なっていることに起因しているのかもしれない。
ただし、num_putの中身がどうなっているのか未確認のため怪しい。
また、printf系はバッファを素直にI/Oにしているため
FILEポインタのみを通しているのに対し、writerと媒体の距離が近いのに対し
cout系はostreamからnum_putを経てostreambufの間を1バイトずつ細切れで渡していってる模様。
writerとバッファの距離は遠そうなイメージ?

そんなこんなで、よっぽど最適化されるようにならないと
関数を読んでるだけのprintf系に追いつくのは厳しいと思われる。
きっとjavaの初期のころってこういう課題をなんとかインラインになるように
頑張ったんだろうなと。

しかし、C++の場合はジェネリックはテンプレート頼みだし
coutなんて標準ライブラリだからインラインにする前に
コンパイル済みの関数に紐づくんじゃないかなぁと。
【2013/01/06 18:12 】 | C/C++ | 有り難いご意見(0)
                                    
| ホーム | 次ページ>>