为什么JPEG文件不能正确读取?(100分)

  • 主题发起人 主题发起人 x3000
  • 开始时间 开始时间
X

x3000

Unregistered / Unconfirmed
GUEST, unregistred user!
我用Delphi7写的保存图形文件到流中的代码,在读取时别的正常,就是TJPEGImage读不出来。有谁知道什么原因吗?谢谢

procedure SaveGraphicToStream(Graphic: TGraphic; Stream: TStream);
var
L: Word;
S: String;
begin
S := Graphic.ClassName;
L := Length(S);
Stream.Write(L, SizeOf(L));
Stream.Write(S[1], Length(S));
Graphic.SaveToStream(Stream);
end;

function LoadGraphicFromStream(Stream: TStream): TGraphic;
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));
Result := GraphicClass.Create;
Result.LoadFromStream(Stream)
end;
 
为何不用TIamge读取呢?
 
Stream.Position:=0; //加上这一句看看?
Stream.Read(L, SizeOf(L));
。。。
 
>> Stream.Write(S[1], Length(S));
有問題, Length得到的是有几個字符, 但一個字符要占8位, 寫入就不對了
 
用TImage来读写吧,会更方便
 
文件中不仅有图形文件还有其它数据,所以不能stream.postion := 0;

>> Stream.Write(S[1], Length(S));
>>有問題, Length得到的是有几個字符, 但一個字符要占8位, 寫入就不對了
这个也没问题,我跟踪了一下,能正确读取TJPEGImage这个字符串,关键就是

GraphicClass := TGraphicClass(GetClass(S));
Result := GraphicClass.Create;
Result.LoadFromStream(Stream)
这几句话,TBitmap,TIcon和TMetaFile就可以正确读取,但TJPEGImage能创建,但在LoadfromStream时只读了一部分,没有JPEG源码,所以就不知道怎么回事了
 
TGraphic
TJPEGImage
是不同的类。所以读写时应用不同的方法。
你的save方法本身存的就不是jpeg的流
读取同样的道理,我没有做过,不知道是否正确。但是Tjpegimage没有象你这样读写的。
 
我是用TIamge
 
TJPEGImage 文件要做转换,请转换成TBmpimage格式就可
 
1.我做的是一个类似CAD的画图软件,这个是个比较基础的类,所以不能使用TImage控件。只能自己做。
2.当保存时,我看了一下保存的文件,发现确实将JPEG的原始文件保存进了我产生的文件中,所以保存应该是正确的。
3.将JPEG文件转换成TBitmap也可以,但就是造成文件太大,失去了JPEG文件的优势。
 
保存时,先保存到另一个Stream,然后写入大小,再拷过来
读出时,先读出大小,然后解到另一个Stream中,再用Result.LoadFromStream去读
 
一般图形编辑软件在编辑时为bmp格式,存储时再做转换,jpeg 文件虽然比较小但会造成文件失真,如果考虑存储空间的话,你可以把流先压缩(不一定要转为jpeg)再存储,读出时再解压。希望能对你有所帮助!
 
问题已经解决,参考了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;
 
后退
顶部