通过delphi来实现*.jpg压缩(100分)

  • 主题发起人 主题发起人 电暖气
  • 开始时间 开始时间

电暖气

Unregistered / Unconfirmed
GUEST, unregistred user!
通过delphi来实现*.jpg压缩
例如将一个图象a.jpg[3412字节],压缩成b.jpg[800字节].

 
你在研究压缩算法![:)]
 
调整jpg的压缩率就可以了
 
jpg已经是压缩格式的
再压也差不了几K
 
我只是需要在程序中来实现,不是研究压缩算法!,谁有办法?
 
[:)][:)]除非不用JPeg压缩
 
Yes,adjust the jpeg.compressionquality to do it!
 
我看见很多高手自己编写的程序,有该功能。所以认为在delphi高手肯定有人可以实现。
 
压缩一个JPEG文件
unit JpegConv;

interface

uses Windows, Graphics, SysUtils, Classes;

procedure CreateThumbnail(InStream, OutStream: TStream;
Width, Height: Integer; FillColor: TColor=clWhite); overload;
procedure CreateThumbnail(const InFileName, OutFileName: string;
Width, Height: Integer; FillColor: TColor=clWhite); overload;

implementation

uses Jpeg;

procedure CreateThumbnail(InStream, OutStream: TStream;
Width, Height: Integer; FillColor: TColor=clWhite);
var
JpegImage: TJpegImage;
Bitmap: TBitmap;
Ratio: Double;
ARect: TRect;
AHeight, AHeightOffset: Integer;
AWidth, AWidthOffset: Integer;
begin
// Check for invalid parameters
if Width<1 then
raise Exception.Create('Invalid Width');
if Height<1 then
raise Exception.Create('Invalid Height');
JpegImage:=TJpegImage.Create;
try
// Load the image
JpegImage.LoadFromStream(InStream);
// Create bitmap, and calculate parameters
Bitmap:=TBitmap.Create;
try
Ratio:=JpegImage.Width/JpegImage.Height;
if Ratio>1 then
begin
AHeight:=Round(Width/Ratio);
AHeightOffset:=(Height-AHeight) div 2;
AWidth:=Width;
AWidthOffset:=0;
end
else
begin
AWidth:=Round(Height*Ratio);
AWidthOffset:=(Width-AWidth) div 2;
AHeight:=Height;
AHeightOffset:=0;
end;
Bitmap.Width:=Width;
Bitmap.Height:=Height;
Bitmap.Canvas.Brush.Color:=FillColor;
Bitmap.Canvas.FillRect(Rect(0,0,Width,Height));
// StretchDraw original image
ARect:=Rect(AWidthOffset,AHeightOffset,AWidth+AWidthOffset,AHeight+AHeightOffset);
Bitmap.Canvas.StretchDraw(ARect,JpegImage);
// Assign back to the Jpeg, and save to the file
JpegImage.Assign(Bitmap);
JpegImage.SaveToStream(OutStream);
finally
Bitmap.Free;
end;
finally
JpegImage.Free;
end;
end;

procedure CreateThumbnail(const InFileName, OutFileName: string;
Width, Height: Integer; FillColor: TColor=clWhite); overload;
var
InStream, OutStream: TFileStream;
begin
InStream:=TFileStream.Create(InFileName,fmOpenRead);
try
OutStream:=TFileStream.Create(OutFileName,fmOpenWrite or fmCreate);
try
CreateThumbnail(InStream,OutStream,Width,Height,FillColor);
finally
OutStream.Free;
end;
finally
InStream.Free;
end;
end;
 
程序很简单。我已经调成如下:
procedure TForm1.Button2Click(Sender: TObject);
var
jpgstream:TJPEGImage;
begin
//---1---
//JPG流 //uses jpeg
jpgstream:= TJPEGImage.Create;

jpgstream.LoadFromFile('C:/My Documents/0008.jpg');
Image1.Picture.Bitmap.Assign(jpgstream);
//jpgstream.Assign(image1.picture.bitmap);
jpgstream.CompressionQuality:=7;//压缩质量
jpgstream.Compress;
jpgstream.SaveToFile('C:/bak.jpg');
//jpgstream.SaveToStream(memoryStream);//保存为JPG流
//使用JPG流 image.Picture.Assign(jpgstream);
jpgstream.free;
end;
★★★★★★★★★★★★★★★★★★★★★★★★★
★★★★★但是我一直没有解决关键的问题★★★★★
★★★★★★★★★★★★★★★★★★★★★★★★★
就是在压缩处理后,没有保存jpeg文件到硬盘前。我没能实现显示压缩后的jpeg文件在image2上。
因为我一直通过调整一个控件TrackBar1.Position滑块的位置来实时观看压缩的效果
,所以我不可能实时每次保存压缩后的文件。只有认为合适了才可保存。
使用的方法是用流
程序如下:[如有高人,请回答,另外给加分]
procedure TForm1.Button4Click(Sender: TObject);
var
ms1:TMemoryStream;
ms2:TMemoryStream;
jpgstream:TJPEGImage;
bmpstream:Tbitmap;
w_jpg_Length:word; //放置原来没压缩jpeg的文件大小
begin
//--------1----------
//打开要处理图形文件*.jpg
//if OpenDialog1.Execute then
//begin
//---2---初始化
ms1:=TMemoryStream.Create; //申请ms1内流
ms2:=TMemoryStream.Create; //申请ms2内流
jpgstream:= TJPEGImage.Create;
bmpstream:=Tbitmap.Create;

//---3---得出原始要压缩文件的大小尺寸-->w_jpg_Length
ms1.clear;
ms1.Position:=0;
ms1.LoadFromFile('C:/My Documents/0008.jpg');
w_jpg_Length :=ms1.Size; //将文件*.jpg长度的字节数送入变量w_jpg_Length
//Edit1.Text :=inttostr(w_jpg_Length);

//---4---
//jpgstream.LoadFromStream(ms1);
jpgstream.LoadFromFile('C:/My Documents/0008.jpg');
bmpstream.Assign(jpgstream);

//jpgstream.SaveToFile('C:/0008bak.jpg');
//Image2.Picture.Bitmap.Assign(jpgstream);
//压缩质量的值随滑块变化而变化[范围是1--100,默认=7]
jpgstream.CompressionQuality:=TrackBar1.Position;
jpgstream.Compress;

//---x---得到压缩后的实际尺寸大小
ms2.Clear;
ms2.Position:=0;
jpgstream.SaveToStream(ms2);
w_jpg_Length :=ms2.Size;
Edit2.Text :=inttostr(w_jpg_Length);

//---x+1---将压缩后的数据显示在image2上
////jpgstream.LoadFromStream(ms2);
bmpstream.Assign(jpgstream);
jpgstream.Modified:=true;

//---x+2---开始压缩
Image2.Picture.Bitmap.Assign(jpgstream); //显示*.jpg文件在Image2上

//---x+3--将压缩后的jpeg文件保存在C:/0008bak.jpg
jpgstream.SaveToFile('C:/0008bak.jpg');
//Image2.Picture.Bitmap.Assign(jpgstream);

//jpgstream.LoadFromFile('C:/0008bak.jpg');
//Image2.Picture.Bitmap.Assign(jpgstream);
//---n---释放资源
bmpstream.free; //
jpgstream.free; //释放jpgstream内流
ms2.free; //释放ms2内流
ms1.free; //释放ms1内流

//end;
end;
 
好像已经解决了:(
 
当然在压缩完后才显示在image上了!!
 
//---x+2---开始压缩
Image2.Picture.Bitmap.Assign(jpgstream); //显示*.jpg文件在Image2上
该句在Image2上显示的仍然是压缩前的图象 [虽然此时此刻已经压缩处理了]
 
同意YB_unique
 
这个问题该结束了。
最好的答案在http://www.delphibbs.com/delphibbs/dispq.asp?lid=745533
在此谢谢各位、更谢谢斑竹:卷起千堆雪tyn
 

Similar threads

后退
顶部