Visual C++ 歷來對 JPEG 等常見圖形格式支援不足,而 Delphi/C++ Builder 內建強大的 TJPEGImage 類別。本文展示如何將 Delphi 的 JPEG 功能封裝為 DLL,供 VC++ 呼叫,實現「幾分鐘內讓 VC++ 用上 JPEG」的 DIY 方案。
LoadLibrary 載入 DLL,GetProcAddress 取得函數指標,封裝為 C++ 類別使用library ImageLib;
uses SysUtils, Classes, MainFn in 'MainFn.pas';
exports
CreateJPEGImage, LoadJPEGImage, FreeJPEGImage, DrawJPEGImage;
begin end.
unit MainFn;
interface
uses SysUtils, Classes, Windows, Graphics, JPEG;
function CreateJPEGImage: TJPEGImage; stdcall; export;
function LoadJPEGImage(image: TJPEGImage; szFileName: PChar): LongBool; stdcall; export;
procedure FreeJPEGImage(image: TJPEGImage); stdcall; export;
procedure DrawJPEGImage(hdc: HDC; x, y: Integer; image: TJPEGImage); stdcall; export;
implementation
function CreateJPEGImage: TJPEGImage;
var img: TJPEGImage;
begin
try img := TJPEGImage.Create; Result := img; except Result := nil; end;
end;
function LoadJPEGImage(image: TJPEGImage; szFileName: PChar): LongBool;
var fn: string;
begin
try fn := StrPas(szFileName); image.LoadFromFile(fn); Result := True; except Result := False; end;
end;
procedure FreeJPEGImage(image: TJPEGImage);
begin image.Free; end;
procedure DrawJPEGImage(hdc: HDC; x, y: Integer; image: TJPEGImage);
var Canvas: TCanvas;
begin
Canvas := TCanvas.Create;
try Canvas.Handle := hdc; Canvas.Draw(x, y, image); finally Canvas.Free; end;
end;
end.
typedef void* PJPEG; // 不透明指標對應 TJPEGImage
typedef PJPEG (__stdcall* CREATEJPEGIMAGE)();
typedef BOOL (__stdcall* LOADJPEGIMAGE)(PJPEG, LPCSTR);
typedef void (__stdcall* FREEJPEGIMAGE)(PJPEG);
typedef void (__stdcall* DRAWJPEGIMAGE)(HDC, int, int, PJPEG);
class CTDlg : public CDialog {
HINSTANCE m_hLib;
CREATEJPEGIMAGE pCreateJPEGImage;
LOADJPEGIMAGE pLoadJPEGImage;
FREEJPEGIMAGE pFreeJPEGImage;
DRAWJPEGIMAGE pDrawJPEGImage;
public:
BOOL OnInitDialog() {
m_hLib = LoadLibrary("ImageLib.dll");
pCreateJPEGImage = (CREATEJPEGIMAGE)GetProcAddress(m_hLib, "CreateJPEGImage");
pLoadJPEGImage = (LOADJPEGIMAGE)GetProcAddress(m_hLib, "LoadJPEGImage");
pFreeJPEGImage = (FREEJPEGIMAGE)GetProcAddress(m_hLib, "FreeJPEGImage");
pDrawJPEGImage = (DRAWJPEGIMAGE)GetProcAddress(m_hLib, "DrawJPEGImage");
}
void OnDestroy() { if (m_hLib) FreeLibrary(m_hLib); }
void OnPaint() {
CPaintDC dc(this);
PJPEG pJPEG = (*pCreateJPEGImage)();
if (pJPEG) {
if ((*pLoadJPEGImage)(pJPEG, "c:\\test.jpg"))
(*pDrawJPEGImage)(dc.m_hDC, 0, 0, pJPEG);
(*pFreeJPEGImage)(pJPEG);
}
}
};
void* 對應 Delphi 物件實例,不需知道內部結構SaveJPEGImage、GetJPEGDimensions、SetJPEGQuality 等功能CJPEGImage RAII 類別,自動管理生命週期TMemoryStream) 避免臨時檔案此法同樣適用於 C++Builder、Free Pascal、Lazarus 等支援 stdcall DLL 匯出的語言,實現跨語言的圖形功能復用。