您的位置:首页 > 其它

加载图片时报错,请大虾帮忙看看!

2008-11-05 09:32 218 查看
加载图片时报错,请大虾帮忙看看! Delphi / Windows SDK/API
http://www.delphi2007.net/DelphiMultimedia/html/delphi_20061103170415180.html

fbmp:TBitMap ;
fbmp.loadfromfile('c:\abc.bmp');
执行到这一步时报错,提示读stream时出错。图片abc.bmp是经过photoshop从24位压缩到8位的。
如果没有压缩是不会报错的,但压缩后图片还是bmp图片,在Windows下也是可以打开的,就是
在Delphi下打不开,直接在Delphi中的控件Timage中也不能加载,请问哪位知道原因!

var
fbmp:TBitMap ;
begin
fbmp:= TBitMap.Create;
fbmp.loadfromfile('c:\abc.bmp');

fbmp:= TBitMap.Create;

我的代码中是执行过fbmp:= TBitMap.Create;的,只是我在这里没写出来,问题不是出在创建图片对象上。请各位指教指教!

看下错误代码。
PixelFormat 设置下格式看看

好象不能处理过大的图象,我试过最大处理4MB多,应该是图片太大了。

图片还没超过100K;应该不是图片的大小问题!
只有图片被加载后才能设置格式,因为这里加载时就报错了,所以不是PixelFormat!
不知哪位能帮我解答......

Delphi自带的TBitmap不能支持这种压缩格式
必须使用其它的图像库

直接在Delphi自带的图像控件Timage中加载都报错!

把下面的单元包含在你的程序中试试,需要编译一次。

unit GdiplusBitmap;

interface

uses
Windows, SysUtils, ActiveX, Classes, Graphics;

type
TGdipBitmap = class(TBitmap)
public
procedure LoadFromStream(Stream: TStream); override;
procedure SaveToFile(const Filename: string); override;
procedure SaveToStream(Stream: TStream); override;
end;

implementation

const
gpdll = 'gdiplus.dll';

type
TStatus = Integer;

PGdiplusStartupInput = ^TGdiplusStartupInput;
TGdiplusStartupInput = packed record
GdiplusVersion: Integer;
DebugEventCallback: Pointer;
SuppressBackgroundThread: BOOL;
SuppressExternalCodecs: BOOL;
end;

TImageCodecInfo = packed record
Clsid: TGUID; // 能识别特定编码解码器的 GUID。
FormatID: TGUID; // 识别编码解码器格式的 GUID
CodecName: PWCHAR; // 编码解码器名称的字符串
DllName: PWCHAR; // 存放编码解码器的 DLL 的路径名字符串
FormatDescription: PWCHAR; // 描述编码解码器的文件格式的字符串。
FilenameExtension: PWCHAR; // 编码解码器中使用的文件扩展名的字符串
MimeType: PWCHAR; // 编码解码器的多用途网际邮件扩充协议 (MIME) 类型的字符串
Flags: DWORD; // 有关编码解码器的其他信息(ImageCodecFlags若干标志的组合)
Version: DWORD; // 编码解码器的版本号
SigCount: DWORD;
SigSize: DWORD;
SigPattern: PByte; // 表示编码解码器签名的二维字节数组
SigMask: PByte; // 用作筛选器的二维字节数组
end;
PImageCodecInfo = ^TImageCodecInfo;

function GdiplusStartup(var token: DWORD; const input: PGdiplusStartupInput; output: Pointer): TStatus;
stdcall; external gpdll name 'GdiplusStartup';
procedure GdiplusShutdown(token: DWORD);
stdcall; external gpdll name 'GdiplusShutdown';
function GdipCreateBitmapFromStream(stream: ISTREAM; var bitmap: Pointer): TStatus;
stdcall; external gpdll name 'GdipCreateBitmapFromStream';
function GdipCreateBitmapFromHBITMAP(hbm: HBITMAP; hpal: HPALETTE; var bitmap: Pointer): TStatus;
stdcall; external gpdll name 'GdipCreateBitmapFromHBITMAP';
function GdipSaveImageToStream(image: Pointer; stream: ISTREAM; const clsidEncoder: PGUID; const encoderParams: Pointer): TStatus;
stdcall; external gpdll name 'GdipSaveImageToStream';
function GdipDisposeImage(image: Pointer): TStatus;
stdcall; external gpdll name 'GdipDisposeImage';
function GdipCreateHBITMAPFromBitmap(bitmap: Pointer; var hbmReturn: HBITMAP; background: DWORD): TStatus;
stdcall; external gpdll name 'GdipCreateHBITMAPFromBitmap';
function GdipGetImageEncodersSize(var numEncoders, size: Integer): TStatus;
stdcall; external gpdll name 'GdipGetImageEncodersSize';
function GdipGetImageEncoders(numEncoders, size: Integer; encoders: PImageCodecInfo): TStatus;
stdcall; external gpdll name 'GdipGetImageEncoders';
function GdipGetImagePixelFormat(image: Pointer; var format: Integer): TStatus;
stdcall; external gpdll name 'GdipGetImagePixelFormat';

type
TGpBitmap = class
public
Native: Pointer;
constructor Create(stream: IStream); overload;
destructor Destroy; override;
constructor Create(hbm: HBITMAP; hpal: HPALETTE); overload;
function GetHBITMAP: HBITMAP;
function GetPixelFormat: Integer;
procedure Save(stream: IStream; const clsidEncoder: TCLSID);
end;

procedure CheckStatus(Status: TStatus);
begin
if Status <> 0 then
raise Exception.Create('Gdiplus Error!');
end;

{ TGpBitmap }

constructor TGpBitmap.Create(stream: IStream);
begin
CheckStatus(GdipCreateBitmapFromStream(stream, Native));
end;

constructor TGpBitmap.Create(hbm: HBITMAP; hpal: HPALETTE);
begin
CheckStatus(GdipCreateBitmapFromHBITMAP(hbm, hpal, Native));
end;

destructor TGpBitmap.Destroy;
begin
GdipDisposeImage(Native);
end;

function TGpBitmap.GetHBITMAP: HBITMAP;
begin
CheckStatus(GdipCreateHBITMAPFromBitmap(Native, Result, 0));
end;

function TGpBitmap.GetPixelFormat: Integer;
begin
CheckStatus(GdipGetImagePixelFormat(Native, Result));
end;

procedure TGpBitmap.Save(stream: IStream; const clsidEncoder: TCLSID);
begin
CheckStatus(GdipSaveImageToStream(Native, stream, @clsidEncoder, nil));
end;

var
GdiplusStartupInput: TGdiplusStartupInput;
gdipToken: DWord;
ImageFormat: string = '';

procedure SetImageFormat(const Filename: string);
begin
ImageFormat := ExtractFileExt(Filename);
if ImageFormat <> '' then
begin
Delete(ImageFormat, 1, 1);
if CompareText(ImageFormat, 'jpg') = 0 then
ImageFormat := 'jpeg'
else if CompareText(ImageFormat, 'tif') = 0 then
ImageFormat := 'tiff';
end else ImageFormat := 'bmp';
ImageFormat := 'image/' + ImageFormat;
end;

function GetImageEncoderClsid(format: String; var Clsid: TGUID): integer;
var
num, size, i: Integer;
ImageCodecInfo: PImageCodecInfo;
type
InfoArray = array of TImageCodecInfo;
begin
num := 0;
size := 0;
Result := -1;
GdipGetImageEncodersSize(num, size);
if (size = 0) then exit;
GetMem(ImageCodecInfo, size);
if(ImageCodecInfo = nil) then exit;
try
GdipGetImageEncoders(num, size, ImageCodecInfo);
i := 0;
while (i < num) and (CompareText(InfoArray(ImageCodecInfo)[i].MimeType, format) <> 0) do
Inc(i);
if i < num then
begin
Clsid := InfoArray(ImageCodecInfo)[i].Clsid;
Result := i;
end;
finally
FreeMem(ImageCodecInfo, size);
end;
end;

{ TGdipBitmap }

procedure TGdipBitmap.LoadFromStream(Stream: TStream);
var
Adaper: TStreamAdapter;
tmp: TGpBitmap;
begin
Adaper := TStreamAdapter.Create(Stream, soReference);
tmp := TGpBitmap.Create(Adaper);
try
Handle := tmp.GetHBITMAP;
case (tmp.GetPixelFormat shr 8) and $ff of
1: PixelFormat := pf1bit;
4: PixelFormat := pf4bit;
8: PixelFormat := pf8bit;
16: PixelFormat := pf16bit;
24: PixelFormat := pf24bit;
32: PixelFormat := pf32bit;
else PixelFormat := pfCustom;
end;
finally
tmp.Free;
end;
end;

procedure TGdipBitmap.SaveToFile(const Filename: string);
begin
SetImageFormat(Filename);
inherited SaveToFile(Filename);
ImageFormat := '';
end;

procedure TGdipBitmap.SaveToStream(Stream: TStream);
var
tmp: TGpBitmap;
Adaper: TStreamAdapter;
Clsid: TGUID;
begin
if (ImageFormat <> '') and (GetImageEncoderClsid(ImageFormat, Clsid) <> -1) then
begin
tmp := TGpBitmap.Create(Handle, Palette);
try
Adaper := TStreamAdapter.Create(Stream, soReference);
tmp.Save(Adaper, Clsid);
finally
tmp.Free;
end;
end else
inherited SaveToStream(Stream);
end;

initialization
begin
FillChar(GdiplusStartupInput, Sizeof(GdiplusStartupInput), 0);
GdiplusStartupInput.GdiplusVersion := 1;
GdiplusStartup(gdipToken, @GdiplusStartupInput, nil);
TPicture.RegisterFileFormat('bmp', 'BMP File', TGdipBitmap);
TPicture.RegisterFileFormat('Exif', 'TIFF File', TGdipBitmap);
TPicture.RegisterFileFormat('tiff', 'TIFF File', TGdipBitmap);
TPicture.RegisterFileFormat('tif', 'TIFF File', TGdipBitmap);
TPicture.RegisterFileFormat('png', 'PNG File', TGdipBitmap);
TPicture.RegisterFileFormat('gif', 'GIF File', TGdipBitmap);
TPicture.RegisterFileFormat('jpeg', 'JPEG File', TGdipBitmap);
TPicture.RegisterFileFormat('jpg', 'JPG File', TGdipBitmap);
end;
finalization
begin
TPicture.UnregisterGraphicClass(TGdipBitmap);
GdiplusShutdown(gdipToken);
end;

end.

包含上面单元,编译一次,可直接从TImage载入,如果使用TBitmap,可以用以下代码:
var
fbmp:TBitMap ;
tmp: TGdipBitmap;
begin
tmp := TGdipBitmap.Create;
tmp.LoadFromFile('c:\abc.bmp');
fbmp.Assign(tmp);
tmp.Free;
end;

路过

var
fbmp:TBitMap ;
tmp: TGdipBitmap;
begin
tmp := TGdipBitmap.Create;
tmp.LoadFromFile('c:\abc.bmp');
fbmp := TBitmap.Create;
fbmp.Assign(tmp);
tmp.Free;
end

TO:maozefa(阿发伯)
程序中加了以上代码后无法运行!

程序中加了以上代码后无法运行!
==================================================
你用的什么操作系统?

我重新试了一下,上面代码在XP,2000下绝对没有问题的。你的图像能否装进来是另一会事,但是应该不可能无法运行。除非你的操作系统是98。

如果你的操作系统是98,可以下载Gdiplus.DLL到你的系统或者你的程序目录

我的电脑系统是Win2000个人版的,运行之前我也搜索了一下Gdiplus.DLL,系统中可以找到Gdiplus.DLL的,加了GdiplusBitmap之后,可以编译,但不能运行。

有一个gdi+包 你下载一下把pas文件加到你的项目里,,在网上可以找到

To:hongqi162(失踪的月亮)
能不能给个具体的名字!

怎么没人回答。

自带的image不支持这种压缩格式吧。

delphi中就是这样,有时候bmp的在window中能打开,但是在delphi中就不能加载,也可能是你那个本本就不是bmp的,但是后缀是bmp的,这样的文件在window中是能打开的,但是delphi会检测是不是真的bmp文件,如果不是就报错了.....

^

GDI+包下载: http://www.2ccc.com/article.asp?articleid=3131 GDI+已经支持非常的图形格式,图像处理增强,更易用。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: