如何将idhttp下载的图像从扩展转换为另一个?

时间:2016-07-24 03:36:38

标签: delphi indy10 delphi-xe8 idhttp

我有这个线程从网络获取图像网址,然后将其保存到内存流然后从内存流保存到文件

我需要转换任何下载到gif图像的图像,所以我会做这样的事情

unit downloadimgThread;

interface
uses Windows, SysUtils, Classes, dialogs, IdSSLOpenSSL, IdHttp, IdUri, System.AnsiStrings, Graphics, Jpeg, Vcl.Imaging.GIFImg, PNGImage;


type
  TDownloadUpdateVisualEvent = procedure(Sender: TObject; Anameofimg: String;
    var Aimagelocate: String) of object;

type
  TURLDownload = class(TThread)
  private
    FOnUpdateVisual: TDownloadUpdateVisualEvent;
    FURL: String;
    Fnameofimg: string;
    FPathImage: string;
    FFileNameImage: string;
    ImageName: string;
    PathURL: string;
    procedure DoUpdateVisual;
  protected
    procedure Execute; override;
  public
    constructor Create(Thrdid: Pointer; const AUrl: String;
      Const AOutPathImages: string; AOnUpdateVisual: TDownloadUpdateVisualEvent;
      Anameofimg: String); reintroduce;
    property URL: string read FURL write FURL;
    property PathImage: string read FPathImage;
    property FileNameImage: string read FFileNameImage;

  end;



var
URLDOWNLOAD: TURLDownload;

implementation

{ TURLDownload }



function JpgToGif(ms: TMemoryStream): Boolean;
var
  gif: TGIFImage;
  jpg: TJPEGImage;
begin
  Result := False;

  gif := TGIFImage.Create;
  try
    jpg := TJPEGImage.Create;
    try
      //jpg
      ms.Position := 0;
      jpg.LoadFromStream(ms);
      jpg.DIBNeeded;
      gif.Assign(jpg);

      //save...
      ms.Clear;
      gif.SaveToStream(ms);
      Result := True;
    finally
      jpg.Free;
      jpg := nil;
    end;
  finally
    gif.Free;
    gif := nil;
  end;
end;

constructor TURLDownload.Create(Thrdid: Pointer; const AUrl, AOutPathImages: string; AOnUpdateVisual: TDownloadUpdateVisualEvent; Anameofimg: String);
var
URI: TIdURI;
begin
inherited Create(false);
FreeOnTerminate := True;
FURL := AUrl;
FOnUpdateVisual := AOnUpdateVisual;
Fnameofimg := Anameofimg;
FPathImage := AOutPathImages;

URI := TIdURI.Create(AUrl);
try
ImageName := URI.Document;
PathURL := URI.path;
finally
URI.Free;
end;

end;

procedure TURLDownload.DoUpdateVisual;
begin
if Assigned(FOnUpdateVisual) then
FOnUpdateVisual(self, Fnameofimg, FFileNameImage);
end;

procedure TURLDownload.Execute;
var
aMs: TMemoryStream;
aIdHttp: TIdHttp;
IdSSL: TIdSSLIOHandlerSocketOpenSSL;
path: string;
dir: string;
SPEXT : String;
itsimage: string;
responsechk: Integer;
begin
dir := AnsiReplaceText(PathURL, '/', '');

if (ImageName = '') then
begin
exit;
end;

SPEXT := ExtractFileExt(ImageName);
ImageName := Copy(ImageName, 1, Length(ImageName) - Length(SPEXT));

path := PathImage + '\' + ImageName + '.gif';

if fileexists(path) then
begin
FFileNameImage := path;
if Assigned(FOnUpdateVisual) then
begin
Synchronize(DoUpdateVisual);
end;
exit;
end
else

if not fileexists(path) then
begin
aMs := TMemoryStream.Create;
aIdHttp := TIdHttp.Create(nil);
IdSSL := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
try

IdSSL.SSLOptions.Method := sslvTLSv1;
IdSSL.SSLOptions.Mode := sslmUnassigned;
aIdHttp.HTTPOptions := [hoForceEncodeParams] + [hoNoProtocolErrorException];
aIdHttp.IOHandler := IdSSL;
aIdHttp.AllowCookies := True;
aIdHttp.Request.UserAgent := 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0';
aIdHttp.HandleRedirects := True;
aIdHttp.RedirectMaximum := 3;
try
aIdHttp.Head(trim(FURL));
except
end;
itsimage := aIdHttp.Response.ContentType;
responsechk := aIdHttp.ResponseCode;

if responsechk <> 200 then
begin
FFileNameImage := 'error';

if Assigned(FOnUpdateVisual) then
begin
Synchronize(DoUpdateVisual);
end;
exit;
end;


if (itsimage = 'image/gif') then
begin
try
aIdHttp.Get(trim(FURL), aMs);
except
end;
aMs.SaveToFile(path);
end else if (itsimage = 'image/jpeg') then
begin
try
aIdHttp.Get(trim(FURL), aMs);
except
end;
if JpgToGif(aMs) then
begin
aMs.SaveToFile(path);
end;
end;


try
if aIdHttp.Connected then
aIdHttp.Disconnect;

except

end;


finally
aMs.Free;
IdSSL.Free;
aIdHttp.Free;
end;
end;

FFileNameImage := path;

if Assigned(FOnUpdateVisual) then
begin
Synchronize(DoUpdateVisual);
end;

end;

end.

在这个单元中,我尝试检查图像类型是否为jpg然后将其转换为gif并将其专门保存在此代码行中

if (itsimage = 'image/jpeg') then
begin
try
aIdHttp.Get(trim(FURL), aMs);
except
end;
if JpgToGif(aMs) then
begin
aMs.SaveToFile(path);
end;
// function to convert 
function JpgToGif(ms: TMemoryStream): Boolean;
var
  gif: TGIFImage;
  jpg: TJPEGImage;
begin
  Result := False;

  gif := TGIFImage.Create;
  try
    jpg := TJPEGImage.Create;
    try
      //jpg
      ms.Position := 0;
      jpg.LoadFromStream(ms);
      jpg.DIBNeeded;
      gif.Assign(jpg);

      //save...
      ms.Clear;
      gif.SaveToStream(ms);
      Result := True;
    finally
      jpg.Free;
      jpg := nil;
    end;
  finally
    gif.Free;
    gif := nil;
  end;
end;

当我尝试转换图像并保存时,保存的图像已损坏可能是什么问题?

1 个答案:

答案 0 :(得分:5)

有一个非常简单的解决方案。这就是使用FMX Bitmap而不是默认VCL Bitmap,因为它允许在加载时自动格式识别,并根据您提供给SaveToFile方法的文件名的文件扩展名选择保存时自动格式化。

这是一个简单的代码,首先将OpenDialog中选择的图像加载到Memory stream中,然后加载到Bitmap中,然后将图像保存为GIF格式。

procedure TForm1.Button1Click(Sender: TObject);
var Bitmap: FMX.Graphics.TBitmap;
    MS: TMemoryStream;
begin
  if OpenDialog1.Execute then
  begin
    MS := TMemoryStream.Create;
    MS.LoadFromFile(OpenDialog1.FileName);
    Bitmap := FMX.Graphics.TBitmap.Create;
    Bitmap.LoadFromStream(MS);
    Bitmap.SaveToFile('D:\Proba.gif');
  end;
end;

正如您所看到的,您只需要几行就可以在所有支持的格式之间转换图像。

您可以在此处查看支持的内容: http://docwiki.embarcadero.com/Libraries/XE8/en/FMX.Graphics.TBitmapCodecManager#Supported_Image_Formats

确保您确实使用FMX.Graphics.TBitmap,方法是为其所在的文件指定完整的命名空间。

注意:使用VCL应用程序并不意味着您无法使用Fire Monkey中存在的某些功能。