2016-07-24 35 views
1

我有这个线程从网络获得图像的URL,然后将其保存到内存流然后从内存流保存到文件如何将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; 

当我尝试将图像转换,并将其保存在图像

保存是腐败的编辑可能是什么问题?

+0

我不认为你可以通过简单的任务从JPEG(一个24位彩色图像)转换为GIF(一个8位彩色图像)。您需要一个图像库来执行抖动或其他从24位到8位的下采样。 – HeartWare

+0

你究竟是什么意思与*损坏*?如果它不是@HeartWare提到的颜色深度,请提供一个样本(原始和转换后的)图像。 –

+0

jpg和gif在内部完全不同。你拥有的图像没有损坏,它是一个JPEG格式。将图像重命名为.jpg并查看它是否有效。那里有很多gif公用程序和组件。 –

回答

5

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

这是一个简单的代码,首先将在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中存在的某些功能。

+0

我无法使用FMX,因为我的项目是一个dll应用程序 –

+0

您不需要使用整个FMX。你只需要使用FMX的一小部分,就是'FMX.Graphics'单元,并且可以编译成一个DLL。我现在只是测试了一下。 – SilverWarior

相关问题