libpng生成とpng出力

[戻る]
Nemo 2005/06/14(火) 10:02:21
環境:Win2k SP4、 VC++6.0

画像処理ソフトを作っていて、libjpegのコンパイルは出来たのですが、
どうもlibpngのライブラリ生成が上手く行ってないようで、
色々検索して調べてみたのですが、どうも上手く行きません。
自分でもどこがどう悪いのかが分かりません・・・。
落としてきたのは1.2.8のソースです。見つけた情報とファイル等は古いせいかコンパイルが出
来ません。

ちなみに、バイナリ(?)があったので、それを利用し、ビルドまで出来たのですが、
(http://gnuwin32.sourceforge.net/packages/libpng.htm [Developer files])
今度は実行時に「LIBPNG13.DLLが見つかりません」とエラーが出ます。。
PNG入出力を扱ってるソフトでDLLが同梱されてるのを観た事が無いので、
やはり自分でコンパイルしてみないと駄目なんでしょうか?
落とした1.2.8ソースのScriptsフォルダのワークスペースからのビルドでは駄目でした。

ゆう 2005/06/14(火) 14:27:21
zlibも入手しましたか?
libpng単体ではコンパイルできませんよ。

Nemo 2005/06/14(火) 15:45:23
はい、zlibも落としまして、こちらはすんなりコンパイル通りました。
その後、libpng1.2.8のScriptsフォルダにあるmakefile.mscをソースディレクトリに入れ
て、
zlibフォルダとライブラリも同じ所に移動してメイクしてみましたが駄目でした・・・。
>コマンド ラインの警告 D4002 : 認識不可能なオプション '-AL' を無視しました。
>NMAKE : fatal error U1077: 'cl' : リターン コード '0x2'
のようにエラーが出ます。
何か、makefileの編集など必要なのでしょうか・・・?

tetrapod 2005/06/14(火) 16:52:21
makefile.msc は太古の MS-DOS 用 Microsoft-C 5.1 用だと書かれています。
-AL ってのが Large Model つまり 16bit MS-DOS 用コンパイルオプションだし。

どうせやるなら scripts\makefile.vcawin32 を使いましょう。

d:\libpng-1.2.8 ディレクトリにて
copy scripts\makefile.vcawin32 makefile
makefile を編集 -I..\zlib を適切なディレクトリに変更
(例えば -I..\zlib-1.2.2 とか)
nmake

でうまくいくと思われます。

Nemo 2005/06/14(火) 20:10:24
レスありがとうございます。
言われた通り、makefile.vcawin32にして、ディレクトリを編集したら上手く行きました。
しかし、ちょっと気になるのですが、自分が拾ってきたlibよりも容量が4倍くらいあるのと、
コンパイルの最後の方で
>        del libpng.lib
>E:\MyProjects\lpng128\libpng.lib が見つかりませんでした。
と言う風に出ます。けれど、一応ちゃんとlibpng.libは生成されました。

試しに、今まで使ってたのと入れ替えてビルドしてみたところ、
リンク時に外部シンボル〜は未解決です。のエラーが出ました。。
>libpng.lib(png.obj) : error LNK2001: 外部シンボル "_inflateReset" は未解決です
一度クリーンしてから、元に戻したらエラーは全く出ませんでした。

tetrapod 2005/06/15(水) 10:46:31
>        del libpng.lib
makefile にそう書かれているので
>E:\MyProjects\lpng128\libpng.lib が見つかりませんでした。
と表示されるのは仕方ないでしょう。気にしなくていいです。

>一度クリーンしてから、元に戻したらエラーは全く出ませんでした。
一度作成失敗してますからね。クリーンしてやり直して正解です。

>自分が拾ってきたlibよりも容量が4倍くらいあるのと、
ウチで作った libpng.lib は 318320bytes となりました。
デバッグ情報を削除したら 133540bytes となりました (cygwin strip 使用)
リンクできるように戻すと 296044bytes となりました (cygwin ranlib 使用)
ダウンロードしてきた lib は実はインポートライブラリかもしれません。
インポートライブラリなら中身は無いのでサイズは小さくて当然です。

あまり深くキニシナイほうがよさそうです。

masa 2005/06/15(水) 20:04:56
レスありがとうございます。
一応出来たのはいいんですが、ヘッダファイル等をディレクトリに入れて
png.hをインクルードしても上述の通り、
>リンク時に外部シンボル〜は未解決です。のエラーが出ました。。
となるんですよね・・・。その点、インポートライブラリはlibpng13.dllがありませんという
だけで、コンパイルは通ります・・・。
どうすればよいでしょうか・・・?

wood 2005/06/16(木) 06:28:12
回答ではありません
HN名「Nemo」と「masa」は同一人物でしょうか?、同一人物なら統一してください

Nemo 2005/06/16(木) 08:40:41
すいません、たまたま同じIDを使ってしまいました。
Nemoです。紛らわしいことしてすいません。

未だ、リンク時の外部シンボル未解決エラー出ます。

tetrapod 2005/06/16(木) 08:59:49
当然ながら zlib.lib はリンクしてあるのですよね?
inflate*** は libpng ではなく zlib の関数です。
インポートライブラリを使えば、実行時 DLL を探しに行くだけです。
開発環境に DLL インストール済みだったらエラーにならないし、
客先に DLL がなかったら実行時エラーになるだけの話。

ゆう様のコメントでわかっているとばかり思いましたが...

Nemo 2005/06/16(木) 10:10:39
すいません、zlibはlibpng.libコンパイル時のみ必要かと思ってました。
リンクでzlib.libを入れたら、上述のリンクエラーは出なくなりましたが、今度は

MSVCRT.lib(MSVCRT.dll) : error LNK2005: _sprintf はすでに LIBCD.lib
(sprintf.obj) で定義されています
MSVCRT.lib(MSVCRT.dll) : error LNK2005: _strncpy はすでに LIBCD.lib
(strncpy.obj) で定義されています
MSVCRT.lib(MSVCRT.dll) : error LNK2005: _fflush はすでに LIBCD.lib(fflush.obj) 
で定義されています
MSVCRT.lib(MSVCRT.dll) : error LNK2005: _malloc はすでに LIBCD.lib(dbgheap.obj) 
で定義されています
MSVCRT.lib(MSVCRT.dll) : error LNK2005: _free はすでに LIBCD.lib(dbgheap.obj) で
定義されています
LINK : warning LNK4098: defaultlib "MSVCRT" は他のライブラリの使用と競合していま
す; /NODEFAULTLIB:library を使用してください
Debug/Gradiator.exe : fatal error LNK1169: 1 つ以上の複数回定義されているシンボルが見
つかりました

という風に出ました。
インポートライブラリというのは プロジェクトの設定 で リンク 一般の
オブジェクト/ライブラリモジュール と言うところにライブラリファイル名を入れればいいんで
すよね・・・?
ソースの方には
#include "png.h"
#pragma comment(lib, "libpng.lib")
としか記述してませんが。

Nemo 2005/06/16(木) 10:16:10
度々すいません、インポートライブラリとはDLL内の関数を呼び込むものですね。
しかし、libpng13.dllを探さずに、客先にDLL無しで創りたいということでした。

どうやら、コンパイル済みの小さいファイルはインポートライブラリだったせいで、
実行時にDLLが見つからないエラーになったのですね。
基本的な事が分かってないようでした。すいません。。

tetrapod 2005/06/16(木) 10:37:02
LNK2005 はライブラリの不整合から発生します。
VC++6 においては、ライブラリが8種類存在し、それぞれ
デバッグ有無・シングル/マルチスレッド・静的/動的 の違いがあります。
うまく動かそうとするには、8種のうちの適切な1つを選ばなければなりません。

さて zlib をうまくコンパイルできていれば、上記8種類のライブラリのうち
4種類が生成されているはずです(シングルスレッドモデルは生成されない)

# アセンブラを使った高速モデル/C だけの中速モデルがあるので8種生成されていますが
# 両者に本質的違いは無いので、実質4種類。

Nemo さんがどれをつかいたいかによって、使うべきライブラリを選んでください。

Win32(MFC)アプリケーション+静的結合、を使いたいと推測されるので
・Win32_LIB_Release(Win32_LIB_ASM_Release) を Release 構成で使用する
・Win32_LIB_DEBUG(Win32_LIB_ASM_Debug) を Debug 構成で使用する
・アプリケーションプログラムのほうをマルチスレッド構成にする
の3点でうまくいきそうな気がします。

Nemo 2005/06/16(木) 20:39:46
一応、Releaseモードでの生成は上手く行っていると思うんですが、
どうも上に書いたような再定義エラーを幾つか吐きます。また1種類しか生成されません。
「アクティブな構成の設定」で設定したモードのライブラリのみを生成しました。
Win32_LIB_Release でマルチスレッドにしてビルドすると400KB弱にもなりました。(そんなも
のなのかな??)
ASMでは
>'ml' は、内部コマンドまたは外部コマンド、
>操作可能なプログラムまたはバッチ ファイルとして認識されていません。
>c:\winnt\system32\cmd.exe の実行エラー
と、ビルド出来ませんでした。
ただし、makefile.vcawin32 を使ったメイクでは310KBのが生成されたのでこれを使ってます
が、同様のエラーは吐き出されます。

このエラーを避けるにはどうすればよいでしょうか。。
ちなみに、libpng.libでの静的結合したpng関連の関数を使わなければ、このエラーは吐きませ
んでした。
アプリケーションの方はマルチスレッドにしてみましたが同様でした。

>MSVCRT.lib(MSVCRT.dll) : error LNK2005: _malloc はすでに LIBCD.lib
(dbgheap.obj) で定義されています
>MSVCRT.lib(MSVCRT.dll) : error LNK2005: _free はすでに LIBCD.lib(dbgheap.obj) 
で定義されています
>LINK : warning LNK4098: defaultlib "MSVCRT" は他のライブラリの使用と競合していま
す; /NODEFAULTLIB:library を使用してください

ゆう 2005/06/16(木) 22:56:37
> /NODEFAULTLIB:library を使用してください
書いてあるまんまです。
/NODEFAULTLIB:LIBCD.lib
/NODEFAULTLIB:MSVCRT.lib
って書いてください。

またはライブラリを作る時に"MFCの共有DLLを使用"でも
いいかもしれません。

Nemo 2005/06/16(木) 23:41:25
[[解決]]
一応コンパイル自体はエラーが出ないようになりました。
言われた通り、無視するライブラリにエラーに出てくるライブラリを指定したらエラーが無くな
りました。

しかし、pngのwrite関連の関数を使うと混合モードになって
「ハンドルされてない例外 は ***.exe(NTDLL.DLL)にあります。0xC0000005:Access 
Violation。」
というメッセージが出て停止します。
またpng出力関係でお世話になるかもしれませんが、
助言を下さった皆様ありがとうございました。

tetrapod 2005/06/17(金) 08:08:33
「ml が無い」エラーは http://www.masm32.com/ あたりから masm を取得すれば解決です。
が、既に述べたとおり Win32_LIB_Release と Win32_LIB_ASM_Release の違いは速度だけ。

LNK2005 を /NODEFAULTLIB で抑制していいのは、絶対に問題が無いことが保証できる場合だ
けです。
原因を理解せず使うと、必ず問題が生じます。実際問題が生じているようですし。

だからアプリケーションの構成に対して適切なライブラリを選択して使う必要があります。
Makefile.vcawin32 そのままでは1種類しか libpng.lib が作られないので、
適宜コンパイルオプションを修正し、作り直す必要があります。

ゆう 2005/06/17(金) 10:30:20
>適宜コンパイルオプションを修正し、作り直す必要があります。
私もそう思います。
ちょっと気になってはいたのですが、
LIBCD.libはデバッグバージョン、MSVCRT.libはリリースバージョンですね。
zlibがデバッグでlibpngがリリース、又はその逆で作ってしまっているようです。
昨日いじった限りでは、fmake使わなくても
projects\visualc6の中にlibpng.dswってファイルがあります。
ダブルクリックすると当然VC++が起動して、途中にzlib.dspの場所を
聞いてきますから指定してやると、きちんとプロジェクトが開けます。
あとはアクティブな構成を選んでビルドするだけです。
(便利になったなあ)
設定で"MFCを使用しない"以外にすれば、/NODEFAULTLIB は使わなくて済むはずです。

Nemo 2005/06/17(金) 11:46:52
なるほど。
ということで、zlibのプロジェクトファイルを開いて色々試したところ、
マルチスレッドにしたら、本体の方の例の/NODEFAULTLIB を使わずにビルド出来ました。

ただし、それとは別なのかもですが、pngファイルを扱う上でのエラーはまだ出ます。
出来る限りMFCは使いたく無いのですが、MFCを使わなければならないのでしょうか・・・。
根本的には問題は解決してませんね・・・。すいません。。

Nemo 2005/06/17(金) 11:56:19
すいません、追加です。
MFCを使用しない 以外にすると50近くのエラーを吐きます。本体の方で。
(zlib, libpngそれぞれ MFCを使用してないにしてます)
また、エラーではなく、ライブラリの競合がwarningで確認されました。
それぞれのライブラリは、LIB Releaseで同様にビルドしてるはずなのですが・・・。

ゆう 2005/06/17(金) 12:12:51
>ということで、zlibのプロジェクトファイルを開いて色々試したところ、
zlib側ではなくlibpng側のプロジェクトで試してください。
説明が足りませんでした。すみません。

>MFCを使用しない 以外にすると50近くのエラーを吐きます。本体の方で。
本体はMFC使っていないのですか?MSVCRT.libはMFCが使うライブラリですよ。

_mallocという関数がMSVCRTとLIBCの両方に存在しているんです。
通常MFCを使う場合はMSVCRT、使わない場合はLIBCを用いるのですが、
本体がMFCでライブラリが非MFC、またはその逆の場合、バッティングして
しまうのです。
本体がMFC使っていなければ問題は起きないはずです。

>(zlib, libpngそれぞれ MFCを使用してないにしてます)
どうしてもこうしたいのであれば、/NODEFAULTLIBを使う必要があります。
あとは、MFCバージョンのlibと非MFCバージョンのlibを別々に作るとか。

ちなみに質問している"ゆう"さんは別人です。

Nemo 2005/06/17(金) 12:38:48
自分も説明不足でした。
libpng.libの方も同様にzlibと同じく非MFC、マルチスレッド等でビルドしたものを使ってま
す。
で、本体の方も非MFCでビルドしてます。
libpng,zlib二つとも作り直したら、ちゃんとwarning以外はエラー無しでビルドされます。
(warning LNK4098: defaultlib "LIBCMT" は他のライブラリの使用と競合しています)
MSVCRTに関するエラーも全く無くなりました。
肝心のwrite_png関数をコメントアウトすればwarningさえ出ません。
しかし、他の関数の部分でもmallocは使ってます。。
このwrite_png関数を使うと、どうしてもwarningと実行時エラーになります。
実行時エラーは実際にpng書き込み関数を使ったところで止まります。

YuO [E-Mail] 2005/06/17(金) 12:53:15
> 本体はMFC使っていないのですか?MSVCRT.libはMFCが使うライブラリですよ。

MSVCRTはCRTがDLLの場合に使われるライブラリです。
MFCを使っていなくても,使用するCRTとして「マルチスレッド(DLL)」を選択すれば,
MSVCRT.libがリンクされます。


> (warning LNK4098: defaultlib "LIBCMT" は他のライブラリの使用と競合しています)

LIBCMTは,使用するCRTが「マルチスレッド」の時に使われるものです。

使われるライブラリは,
シングルスレッド:LIBC
マルチスレッド:LIBCMT
マルチスレッド(DLL):MSVCRT
です。

どこかにCRTがシングルスレッドのものが混じっていませんか?

ゆう 2005/06/17(金) 13:11:25
>MSVCRTはCRTがDLLの場合に使われるライブラリです。
そうなんですか。勉強になります。ありがとうございました。

>どこかにCRTがシングルスレッドのものが混じっていませんか?
私もそう思います。本体がシングルスレッドとか。
エラーに関しては、本体がデバッグ環境でリリース版の
libを使っているとか。

Nemo 2005/06/17(金) 13:46:24
なるほど、そういう仕組みになってるんですね。
分かりやすくまた更に勉強になりました。
確かに、本体がシングルスレッドになっており、
ゆう さんのおっしゃるとおり、本体デバッグ環境でReleaseのlibを使ってました。
なので、マルチスレッドにした後で、試しにRelease環境でビルドしてみました。
すると、ライブラリの競合警告は出なくなりました。
ただし依然としてpngの書き込み関数のところで混合モードで停止するのは変わりませんでし
た。

古いスレッドには追加発言できません。