为什么我打印BMP无法得到灰度图象?(120分)

  • 主题发起人 主题发起人 neural1208
  • 开始时间 开始时间
N

neural1208

Unregistered / Unconfirmed
GUEST, unregistred user!
我用Printer.Canvas.Draw(0, 0, Bitmap)打印得到的图象,没有灰度级别,要么一个区域
都是黑的,要么都是白的。打印其它图象,如JPEG时就能够以不同灰度打印。请问是怎么回事?

还有我从0, 0坐标开始打印图象,但是实际输出的图象距离打印纸的上面和左面仍然
有一定的距离,请问这是什么原因?
 
>> 我用Printer.Canvas.Draw(0, 0, Bitmap)打印得到的图象,没有灰度级别,要么一个区域
>> 都是黑的,要么都是白的。打印其它图象,如JPEG时就能够以不同灰度打印。请问是怎么回事?

看看你的程序

>> 还有我从0, 0坐标开始打印图象,但是实际输出的图象距离打印纸的上面和左面仍然
>> 有一定的距离,请问这是什么原因?

那是你的页边距。
 
我的程序是:
var
Bitmap: TBitmap;
begin

Bitmap := TBitmap.Create;
Bitmap.LoadFromFile('xxx.bmp');
with Printer
begin

begin
Doc;
Printer.Draw(0, 0, Bitmap);
EndDoc;
end;

Bitmap.Free;
end;

换成JPEG格式的图象就没问题.

还有我的程序中怎么设置页边距呢? 调用打印设置对话框,里面也没能找到这样的设置选
项?
 
页边距是你画的时候自己不画那四周的部分,而不是设置的
你用Canvas.CopyRect就可以控制copy多大
 
to Pipi:
可是我是从(0,0)点开始Draw我的图象的,怎么还会有左边和上边的边距呢?
 
那可是打印机,打印机总有物理上打不到的地方嘛
而且你把纸放的地方不同,打出来的边距也不同啊
 
Thanks. 还有就是我碰到的Bitmap没法打印灰度的问题,我的源代码如下:

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls, StdCtrls, Menus;

type
TForm1 = class(TForm)
Edit1: TEdit;
Label1: TLabel;
Button1: TButton;
Image1: TImage;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
end;


var
Form1: TForm1;

implementation

uses Printers;
{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
begin

Image1.Picture.LoadFromFile(Edit1.Text);
// 载入图象
end;


procedure TForm1.Button2Click(Sender: TObject);
begin

Printer.begin
Doc;
Printer.Canvas.StretchDraw(Rect(0, 0,
Printer.PageWidth,
Printer.PageHeight), Image1.Picture.Graphic);
// 打印图象
Printer.EndDoc;

end;
 
什么打印机?我怀疑是打印驱动不好
 
是HP Laser 6L的激光打印机,应该不是打印机的问题,同样的图象,在画笔中打开后打
印就没有问题。
 
改成:
Printer.Canvas.CopyRect(Rect(0, 0,Printer.PageWidth,Printer.PageHeight), Image1.Canvas.Handle,Rect(0, 0,Printer.PageWidth,Printer.PageHeight));
如何?
 
>Bitmap没法打印灰度的问题
不可能啊?你确定是灰度图?怎么转化的?
 
to 卷起千堆雪tyn:
原来的图是真彩的,打印到黑白打印机上当然只能变成灰度了。我的代码中没有做转化
工作,我认为打印的时候会自动转化的,我打印其它图象,如JPEG的真彩图象,输出的
打印结果就是灰度的,但是打印BMP的真彩图,输出的就有我所说的问题。

 
尝试换台打印机,或者尝试换幅BMP试试。
 
to 卷起千堆雪tyn:
换过了,还是这样,应该不是打印机的问题。试过很多BMP图象,打印出来的也都是这样,
而GIF图象打出来的有些是好的,有些也和BMP一样,而JPEG则没有碰到过问题。
另外,我用画笔和其它图象软件打印就没有问题,甚至我用一个Image1控件在Form中载入
图象后,调用Form.Print打印出来也是正常的。
 
真是怪了,明天我搬来打印机试试。
 
BMP图像的打印的确存在这种问题,而从严格意义上来说,DELPHI是无法完成对DDB图像
正确打印的;最好是利用DIB来实现。

type
PPalEntriesArray = ^TPalEntriesArray;
{for palette re-construction}
TPalEntriesArray = array[0..0] of TPaletteEntry;

procedure BltTBitmapAsDib(DestDc : hdc;
x : word;
y : word;
Width : word;
Height : word;
bm : TBitmap);
var
OriginalWidth :LongInt;
dc : hdc;
IsPaletteDevice : bool;
IsDestPaletteDevice : bool;
BitmapInfoSize : integer;
lpBitmapInfo : PBitmapInfo;
hBm : hBitmap;
hPal : hPalette;
OldPal : hPalette;
hBits : THandle;
pBits : pointer;
lPPalEntriesArray : PPalEntriesArray;
NumPalEntries : integer;
i : integer;
begin

{$IFOPT R+}
{$DEFINE CKRANGE}
{$R-}
{$ENDIF}

OriginalWidth := bm.Width;
dc := GetDc(0);
IsPaletteDevice :=
GetDeviceCaps(dc, RASTERCAPS) and RC_PALETTE = RC_PALETTE;
dc := ReleaseDc(0, dc);
if IsPaletteDevice then

BitmapInfoSize := sizeof(TBitmapInfo) + (sizeof(TRGBQUAD) * 255)
else

BitmapInfoSize := sizeof(TBitmapInfo);
GetMem(lpBitmapInfo, BitmapInfoSize);
FillChar(lpBitmapInfo^, BitmapInfoSize, #0);
lpBitmapInfo^.bmiHeader.biSize := sizeof(TBitmapInfoHeader);
lpBitmapInfo^.bmiHeader.biWidth := OriginalWidth;
lpBitmapInfo^.bmiHeader.biHeight := bm.Height;
lpBitmapInfo^.bmiHeader.biPlanes := 1;
if IsPaletteDevice then

lpBitmapInfo^.bmiHeader.biBitCount := 8
else

lpBitmapInfo^.bmiHeader.biBitCount := 24;
lpBitmapInfo^.bmiHeader.biCompression := BI_RGB;
lpBitmapInfo^.bmiHeader.biSizeImage :=
((lpBitmapInfo^.bmiHeader.biWidth *
longint(lpBitmapInfo^.bmiHeader.biBitCount)) div 8) *
lpBitmapInfo^.bmiHeader.biHeight;
lpBitmapInfo^.bmiHeader.biXPelsPerMeter := 0;
lpBitmapInfo^.bmiHeader.biYPelsPerMeter := 0;
if IsPaletteDevice then
begin

lpBitmapInfo^.bmiHeader.biClrUsed := 256;
lpBitmapInfo^.bmiHeader.biClrImportant := 256;
end else
begin

lpBitmapInfo^.bmiHeader.biClrUsed := 0;
lpBitmapInfo^.bmiHeader.biClrImportant := 0;
end;

hBm := bm.ReleaseHandle;
hPal := bm.ReleasePalette;
dc := GetDc(0);
if IsPaletteDevice then
begin

OldPal := SelectPalette(dc, hPal, TRUE);
RealizePalette(dc);
end;

GetDiBits(dc,
hBm,
0,
lpBitmapInfo^.bmiHeader.biHeight,
nil,
TBitmapInfo(lpBitmapInfo^),
DIB_RGB_COLORS);
hBits := GlobalAlloc(GMEM_MOVEABLE,
lpBitmapInfo^.bmiHeader.biSizeImage);
pBits := GlobalLock(hBits);
GetDiBits(dc,
hBm,
0,
lpBitmapInfo^.bmiHeader.biHeight,
pBits,
TBitmapInfo(lpBitmapInfo^),
DIB_RGB_COLORS);
if IsPaletteDevice then
begin

GetMem(lPPalEntriesArray, sizeof(TPaletteEntry) * 256);
{$IFDEF VER100}
NumPalEntries := GetPaletteEntries(hPal,
0,
256,
lPPalEntriesArray^);
{$else
}
NumPalEntries := GetSystemPaletteEntries(dc,
0,
256,
lPPalEntriesArray^);
{$ENDIF}
for i := 0 to (NumPalEntries - 1)do
begin

lpBitmapInfo^.bmiColors.rgbRed :=
lPPalEntriesArray^.peRed;
lpBitmapInfo^.bmiColors.rgbGreen :=
lPPalEntriesArray^.peGreen;
lpBitmapInfo^.bmiColors.rgbBlue :=
lPPalEntriesArray^.peBlue;
end;

FreeMem(lPPalEntriesArray, sizeof(TPaletteEntry) * 256);
end;


if IsPaletteDevice then
begin

SelectPalette(dc, OldPal, TRUE);
RealizePalette(dc);
end;

dc := ReleaseDc(0, dc);
IsDestPaletteDevice :=
GetDeviceCaps(DestDc, RASTERCAPS) and RC_PALETTE = RC_PALETTE;
if IsPaletteDevice then
begin

OldPal := SelectPalette(DestDc, hPal, TRUE);
RealizePalette(DestDc);
end;

StretchDiBits(DestDc,
x,
y,
Width,
Height,
0,
0,
OriginalWidth,
lpBitmapInfo^.bmiHeader.biHeight,
pBits,
lpBitmapInfo^,
DIB_RGB_COLORS,
SrcCopy);

if IsDestPaletteDevice then
begin

SelectPalette(DestDc, OldPal, TRUE);
RealizePalette(DestDc);
end;

GlobalUnLock(hBits);
GlobalFree(hBits);
FreeMem(lpBitmapInfo, BitmapInfoSize);
bm.Handle := hBm;
bm.Palette := hPal;
{$IFDEF CKRANGE}
{$UNDEF CKRANGE}
{$R+}
{$ENDIF}
end;


procedure TForm1.Button1Click(Sender: TObject);
var
ScaleX,ScaleY,Wid,Hei :Integer;
begin

if PrintDialog1.Execute then
begin

Printer.begin
Doc;
ScaleX :=GetDeviceCaps(Printer.Canvas.Handle,LogPixelsX) div PixelsPerInch;
ScaleY :=GetDeviceCaps(Printer.Canvas.Handle,LogPixelsY) div PixelsPerInch;
Wid :=Image1.Picture.Bitmap.Width*ScaleX;
Hei :=Image1.Picture.Bitmap.Height*ScaleY;
BltTBitmapAsDib(Printer.Canvas.Handle,
0,
0,
Wid,
Hei,
Image1.Picture.Bitmap);
Printer.EndDoc;
end;

end;


这样是可以实现灰度效果的;
但是边距以及按显示大小打印,需要自己再修改了。
 
多谢卷起千堆雪tyn,
我用了你的代码,在实际运行中发现一个问题:
如果用你的代码把图按原来大小打印是正常的,但是如果放大打印有时就打印不出
任何东西。我用画笔打印,无论打印原来大小还是放大打印都没有问题,因而不是
打印机的问题。
请问这是什么原因?
 
放大打印应该没有问题吧?
最好是建立内存位图,将内存位图放大后,再赋予Image上,试试打印。
 
to 卷起千堆雪tyn:
进一步检查发现是这样的,只能打印小图象,而打印大图象时就得不到任何东西。
 
大图像有多大?
那我就没有试过了。
按理是不会有问题的。
 
后退
顶部