웹에 있는 이미지를 표시해야 할 것 같아 간단하게 라이브러리 형태로 만들었어요.
TBitmap을 class helper로 확장했습니다.
소스가 몇 줄 되지 않으니 설명은 생략합니다.
iOS(아이폰5), Android(Nexus 7), 윈도우(Windows 7)에서 모두 정상 동작 확인했습니다.
참고하세요^^
사용법
procedure TForm3.Button1Click(Sender: TObject); var Size: Int64; begin Image1.Bitmap.LoadFromUrl('https://t1.daumcdn.net/cfile/tistory/2353573E529FDAAC03', Size); Memo1.Lines.Add('1 : ' + Format('W: %d, H: %d, S: %d', [Image1.Bitmap.Width, Image1.Bitmap.Height, Size])) end; procedure TForm3.Button2Click(Sender: TObject); begin Image1.Bitmap.LoadFromUrl('https://t1.daumcdn.net/cfile/tistory/2353573E529FDAAC03'); Memo1.Lines.Add('2 : ' + Format('W: %d, H: %d', [Image1.Bitmap.Width, Image1.Bitmap.Height])) end; procedure TForm3.Button3Click(Sender: TObject); begin Image1.Bitmap.LoadThumbnailFromURL('https://t1.daumcdn.net/cfile/tistory/2353573E529FDAAC03', 100, 100); Memo1.Lines.Add('3 : ' + Format('W: %d, H: %d', [Image1.Bitmap.Width, Image1.Bitmap.Height])) end;
쓰레드로 처리하도록 변경해 사용법의 첫번째 사이즈 정보를 얻어오는 부분은 제외됩니다.
(깃허브의 소스코드를 참고하세요. https://github.com/hjfactory/FMX.Devgear)
구현부
unit FMX.Devgear.HelperClass; interface uses System.Classes, FMX.Graphics; type TBitmapHelper = class helper for TBitmap public procedure LoadFromUrl(AUrl: string); procedure LoadThumbnailFromUrl(AUrl: string; const AFitWidth, AFitHeight: Integer); end; implementation uses System.SysUtils, System.Types, IdHttp, IdTCPClient, AnonThread; procedure TBitmapHelper.LoadFromUrl(AUrl: string); var _Thread: TAnonymousThread; begin _Thread := TAnonymousThread .Create( function: TMemoryStream var Http: TIdHttp; begin Result := TMemoryStream.Create; Http := TIdHttp.Create(nil); try try Http.Get(AUrl, Result); except Result.Free; end; finally Http.Free; end; end, procedure(AResult: TMemoryStream) begin if AResult.Size > 0 then LoadFromStream(AResult); AResult.Free; end, procedure(AException: Exception) begin end ); end; procedure TBitmapHelper.LoadThumbnailFromUrl(AUrl: string; const AFitWidth, AFitHeight: Integer); var Bitmap: TBitmap; scale: Single; begin LoadFromUrl(AUrl); scale := RectF(0, 0, Width, Height).Fit(RectF(0, 0, AFitWidth, AFitHeight)); Bitmap := CreateThumbnail(Round(Width / scale), Round(Height / scale)); try Assign(Bitmap); finally Bitmap.Free; end; end; end.
안드로이드 환경에서 8bit GIF 이미지가 표시되지 않는경우
아래와 같이 FMX.Graphics.Android.pas 파일을 수정하세요. 결과적으로 IsGIFStream 메소드에서 GIF 여부를 파악하는 부분이 잘못되어 있어 8bit GIF 표시에 문제가 있습니다.
class function TBitmapCodecAndroid.IsGIFStream(const Stream: TStream): Boolean; const IDCharCount = 3; type GIFByteArray = array[0..IDCharCount-1] of Byte; const GifBytes: GIFByteArray = ($47, $49, $46); // G I F var I: Integer; PrevPosition: Int64; ReadBytes: GIFByteArray; begin if (Stream = nil) or (Stream.Size < IDCharCount) then Exit(False); Result := True; PrevPosition := Stream.Position; try Stream.ReadBuffer(ReadBytes, IDCharCount); for I := Low(ReadBytes) to High(ReadBytes) do if ReadBytes[I] <> GifBytes[I] then Exit(False); finally Stream.Position := PrevPosition; end; end;