大きな画像を数回に分けてプリンタに転送し、1枚の上に印刷したい

[戻る]
うちだ 2005/03/29(火) 21:10:45
以下の手順でAPIを呼び出して画像を印刷しています
(ソースだと長いので、使用するAPIを順番に列挙しました)
--------------------------------------------------------
::OpenPrinter();//プリンタをオープン
::StartDoc();//印刷ジョブを開始
::StartDocPrinter();//印刷のために文書がスプールされたことを印刷スプーラに通知
::StartPage();//プリンタドライバに、新しいページのデータを受け入れるよう指示
::StretchDIBits( );//解像度変換
::BitBlt();//プリンタ デバイス コンテキストに印刷するデータをコピー
::EndPage();//1 ページ分の書き込みが終了したことをデバイスに通知
::EnumJobs();//印刷中のジョブのステータスをキューから取得
::EndDoc();//印刷ジョブを終了
::EndDocPrinter();指定されたプリンタの印刷ジョブを終了
--------------------------------------------------------

大きな画像の場合は、大きなメモリを確保したくないので
「
画像ファイルからブロック単位で読み込んで、プリンタ(スプール)に転送
」
を繰り返して印刷したいのですが、可能でしょうか?
EndPage()をすると、次のページにうってしまうので、上記の方法がまずいことは分かっ
ています
また、大きなプリンタデバイスコンテキストを作って、::BitBlt()を繰り返すことは可能
だと思うのですが、これでは、大きなプリンタデバイスコンテキストを作るので、メモリ
の節約にはなりません
どのような方法があるのでしょうか?
ご存知名方いましたら教えてください

WinXP pro SP1
VC++6.0

2005/03/30(水) 02:51:14
>EndPage()をすると、次のページにうってしまうので、上記の方法がまずいことは分かっ
>ています
の部分が良く判りません現在指定中の用紙の大きさを超えて印刷するということは
別のページに印刷することだと思うのですが、あなたは改ページしないでどうやって
用紙の大きさを超えた印刷をしようというのでしょうか?

うちだ 2005/03/30(水) 08:38:00
説明が足りずに申し訳ございません
例えば、
・出力するプリンタの解像度が720dpi
・用紙がA3
・Samples Per Pixelが3
・Bits Per Sampleが8
の場合
必要な(プリンタデバイスコンテキストの)メモリサイズが、約300MBになってしまいます
このサイズでは、環境(リソース)によってはスワップを行うので、処理が遅くなってし
まいます
よって、50MBで6回の転送が行うことで回避したいのです
もちろん、ファイルからの読み込み、解像度変換も最大50MB位で数回に分けて行います

2005/03/30(水) 11:55:16
>必要な(プリンタデバイスコンテキストの)メモリサイズが、約300MBになってしまいます
これも良く判りません。どうやってDCのメモリー消費量が得られたのでしょうか?
DIB のメモリー消費量なら計算できるとは思いますが....
それともスプールに溜まる大きさのことなんでしょうか?

>・Samples Per Pixelが3
>・Bits Per Sampleが8
一体これは何でしょうか?Windows で用いる用語ではないので私には解説が必要です

Ban 2005/03/30(水) 13:10:42
> よって、50MBで6回の転送が行うことで回避したいのです

回避という表現もよく分かりませんが、仮に300MB(?)が 50MB×6にできたとして
本当に手動で分割するとスピードが改善するんでしょうか。
DCの内部形式はデバイス依存ですから、特定の環境に対してチューニングする要件でもない限り、
普通は無理/意味がないように思うのですが。
(例えば50MBにしたらお使いのプリンタではハードの内部バッファに納まるとかそういう保証がおありで?)

実メモリの足りない環境でも動く時点で、ソフトとしては十分御の字だと思います。
(性能が要求されるならハードウェア資源を増設するべき)

とおりすがり 2005/03/30(水) 14:27:58
よく分からないけど、バンディングの話?

うちだ 2005/03/30(水) 14:43:56
[[解決]]
この方法では一度に転送するしかないことが分かりました
どうも、ありがとうございます

>島さま
おっしゃるとおり、プリンタDCに割り当てたDIBのサイズです
また、Samples Per Pixeが3、Bits Per Sampleが8とは、1ピクセルが3色(RGB)であり、
その一色が、8ビットで表現されている
つまり、イメージ1ピクセルあたり3バイト必要
と、いうことです

>Banさま
「
回避という表現もよく分かりませんが、仮に300MB(?)が 50MB×6にできたとして
本当に手動で分割するとスピードが改善するんでしょうか。
」
ですが改善します
経験則からなので、「改善することがあります」といったほうがいいですかね
おそらく、大きなメモリを確保する場合にメモリのスワップが発生すると格段に処理が遅
くなってしまいます
なので、大きなイメージを読み込んで、色変等を行って別ファイルを作ったりする場合に
は、ファイルの読み込みサイズを一定までとして処理をおこないます
今回は、プリンタに転送するので、こちらの転送処理も、ブロック単位としたかったのです

Ban 2005/03/30(水) 14:47:39
# 別スレの方式であれば一般的に改善するのは分かるんですけど、
# 「"画面単位"で便利に管理するためのDCやっても改善するのか」は
# 激しく環境に依存しそうで。

Kerry 2005/03/30(水) 15:30:35
別に巨大なビットマップを一度に転送しなくても
少しずつ読み込んで転送すれば良いと思いますが。

StartDoc()
StartPage()
while()
{
    // n分割したビットマップをそれぞれ読み込んで転送
    read()
    StretchDIBits()
    BitBlt()
}
EndPage()
EndDoc()

PATIO 2005/04/04(月) 15:15:15
原理的にはKerryさんの指摘の通りだと思います。
巨大な画像を一気に読み込んでStretchDIBits等をしてしまうと
一時的に二枚の画像が存在してしまうのでメモリを相当食うことになると思います。
やるとしたら小さなビットマップ上に部分読込を行った画像を展開しておいて
その単位でStretchDIBitsをしていくと一時的に消費するメモリを抑える事が出来ると
思いますが、最終的には縮小等を行ったにしても全体画面分はメモリを食います。
これは、どうしようもないと思います。
ドライバの方がある程度でプリンタに送るような事をしない限り、
これを避ける事は出来ないと思います。

PATIO 2005/04/04(月) 15:18:45
因みにAPIの実装から考えるなら、
無理ではないかと思います。
DC側はどのタイミングでどの位置に描画命令がくるか判断できないので
ここまでは先に送っておこうと言うような判断が出来ないと思います。
第一バンドの描画は終わったよと言うのをDCに教えてあげないと無理でしょうから。

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