如何将 http 下载图像从扩展名转换为另一个?
how to convert idhttp downloaded image from extention to another?
我有这个线程从网络获取图像 url 然后将其保存到内存流然后从内存流保存到文件
我需要将任何下载的图像转换为 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;
当我尝试转换图像并保存时,保存的图像已损坏可能是什么问题?
对此有一个非常简单的解决方案。那就是使用 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 中存在的某些功能。
我有这个线程从网络获取图像 url 然后将其保存到内存流然后从内存流保存到文件
我需要将任何下载的图像转换为 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;
当我尝试转换图像并保存时,保存的图像已损坏可能是什么问题?
对此有一个非常简单的解决方案。那就是使用 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 中存在的某些功能。