问题已经解决,参考了Devexpress的cxImage的源码,weiwei81123的思路是对的,由于没有JPEG的源码,猜测JPEG的Loadfromstream只能从开始位置读。
源代码如下: (哈哈,从数据库的BLOB字段读取图形也顺便解决了)
function IsPictureEmpty(APicture: TPicture): Boolean;
begin
Result := not Assigned(APicture.Graphic) or APicture.Graphic.Empty;
end;
procedure SavePicture(APicture: TPicture; var AValue: string);
var
AStream: TMemoryStream;
begin
if not Assigned(APicture) or IsPictureEmpty(APicture) then
AValue := ''
else Begin
AStream := TMemoryStream.Create;
try
APicture.Graphic.SaveToStream(AStream);
AStream.Position := 0;
SetLength(AValue, AStream.Size);
AStream.ReadBuffer(AValue[1], AStream.Size);
finally
AStream.Free;
end;
end;
end;
type
TMemoryStreamReadOnly = class(TCustomMemoryStream)
public
procedure SetBuffer(const Buffer; Count: Longint);
function Write(const Buffer; Count: Longint): Longint; override;
end;
procedure TMemoryStreamReadOnly.SetBuffer(const Buffer; Count: Longint);
begin
SetPointer(@Buffer, Count);
end;
function TMemoryStreamReadOnly.Write(const Buffer; Count: Longint): Longint;
begin
Result := 0;
end;
procedure LoadPicture(APicture: TPicture; AGraphicClass: TGraphicClass;
const AValue: Variant);
{ Paradox graphic BLOB header - see DB.pas}
type
TGraphicHeader = record
Count: Word; { Fixed at 1 }
HType: Word; { Fixed at $0100 }
Size: Longint; { Size not including header }
end;
var
AGraphic: TGraphic;
AHeader: TGraphicHeader;
ASize: Longint;
AStream: TMemoryStreamReadOnly;
begin
if VarType(AValue) = varString then // Field.Value -> stored as string
begin
AStream := TMemoryStreamReadOnly.Create;
try
ASize := Length(AValue);
if ASize >= SizeOf(TGraphicHeader) then
begin
AStream.SetBuffer(string(AValue)[1], ASize);
AStream.Position := 0;
AStream.Read(AHeader, SizeOf(AHeader));
if (AHeader.Count <> 1) or (AHeader.HType <> $0100) or
(AHeader.Size <> ASize - SizeOf(AHeader)) then
AStream.Position := 0;
end;
if AStream.Size > 0 then
try
if AGraphicClass = nil then
APicture.Bitmap.LoadFromStream(AStream)
else
begin
AGraphic := AGraphicClass.Create;
try
AGraphic.LoadFromStream(AStream);
APicture.Graphic := AGraphic;
finally
AGraphic.Free;
end;
end;
except
APicture.Assign(nil);
end
else
APicture.Assign(nil);
finally
AStream.Free;
end;
end
else
APicture.Assign(nil);
end;
procedure SavePictureToStream(aPicture : TPicture; Stream: TStream);
Var
L: Word;
S : String;
Begin
S := APicture.Graphic.ClassName;
L := Length(S);
Stream.Write(L, SizeOf(L));
Stream.Write(S[1], Length(S));
SavePicture(aPicture,S);
WriteString(Stream,S);
end;
function LoadPictureFromStream(Stream: TStream): TPicture;
Var
GraphicClass: TGraphicClass;
L: Word;
S: String;
begin
Stream.Read(L, SizeOf(L));
SetLength(S, L);
Stream.Read(S[1], Length(S));
RegisterClasses([TIcon, Graphics.TBitmap, TJPEGImage, TMetafile]);
GraphicClass := TGraphicClass(GetClass(S));
S := ReadString(Stream);
result := TPicture.Create;
LoadPicture(Result,GraphicClass,S);
end;