Mielőtt hozzálátnánk a forráskód megismeréséhez, nézzük át röviden, mit is fog a programunk megvalósítani.
Lehetősége lesz a felhasználónak több kép egyidejű betöltésére, melyek elérési útvonalait egy ListBox-ban fogjuk összegyűjteni. Az elkészítendő thumbnail-ek beállítható szélességi és magassági paraméterekkel fognak rendelkezni. Megadható lesz, hogy milyen színű legyen a hátterük, valamint az is, hogy milyen előtaggal rendelkezzen az elkészült thumbnail fájlneve. Ezen kívül egy kimeneti könyvtár is specifikálható, ahová az elkészült képek eltárolásra kerülnek. Ezek után lássuk mindennek a megvalósítását.
Első lépésként létrehozunk egy AddParameters nevű függvényt, mely segítségével olvasási, illetve írási engedélyt adunk a lemezről beolvasandó, illetve a lemezre kiírandó állományoknak, valamint a thumbnail elkészítésére vonatkozó paramétereket átadjuk egy másik függvénynek, mely magát a kicsinyített képet fogja létrehozni.
procedure AddParameters(const InFileName, OutFileName: string;
ThWidth, ThHeight: Integer; FillColor: TColor=clWhite);
var
InStream, OutStream: TFileStream;
begin
InStream:=TFileStream.Create(InFileName,fmOpenRead);
try
OutStream:=TFileStream.Create(OutFileName,fmOpenWrite or fmCreate);
try
CreateThumbnail(InStream,OutStream,ThWidth,ThHeight,FillColor);
finally
OutStream.Free;
end;
finally
InStream.Free;
end;
end;
Láthatjuk, hogy a függvényünk is vár paramétereket, melyeket továbbad a CreateThumbnail nevű függvénynek, ami az eredeti kép átméretezését fogja elvégezni a következő módon:
procedure CreateThumbnail(InStream, OutStream: TStream;
ThWidth, ThHeight: Integer; FillColor: TColor=clWhite);
var
JpegImage: TJpegImage;
Bitmap: TBitmap;
Ratio: Double;
ARect: TRect;
AHeight, AHeightOffset: Integer;
AWidth, AWidthOffset: Integer;
begin
Megvizsgáljuk, hogy az elkészítendő thumbnail szélességi, illetve magassági adatai valósak-e.
if ThWidth<1 then
raise Exception.Create('Hibás szélesség érték!');
if ThHeight<1 then
raise Exception.Create('Hibás magasság érték!');
Létrehozunk egy jpeg típusú kép tárolására alkalmas változót.
JpegImage:=TJpegImage.Create;
try
Ezután betöltjük az InStream paraméterben kapott képet a JpegImage változóba.
JpegImage.LoadFromStream(InStream);
A thumbnail képet úgy készítjük el, hogy létrehozunk egy bitmap képet, majd kitöltjük a FillColor paraméterben beállított színnel. Ezután ráhelyezzük az eredeti kép arányosan kicsinyített mását. A művelet befejeztével átkonvertáljuk az egészet jpeg képpé.
Bitmap:=TBitmap.Create;
Try
Meghatározzuk az eredeti kép szélesség/magasság arányát, majd eltároljuk azt a Ratio nevű változóban. Ezt a későbbiekben felhasználjuk a kicsinyített kép létrehozására.
Ratio:=JpegImage.Width/JpegImage.Height;
Amennyiben az arány egynél nagyobb értéket ad eredményül, a kép biztosan fekvő, hiszen a szélessége nagyobb, mint a magassága.
Ebben az esetben előfordulhat, hogy az elkészítendő thumbnail bitkép magassága nagyobb lesz, mint maga a lekicsinyített kép magassága. Ekkor a kapott kicsinyített képet a bitkép területének közepére kell helyeznünk. Azt, hogy a thumbnail alsó és felső szélétől milyen távolságra legyen a kicsinyített kép, az AHeightOffset változóban kapjuk meg. A thumbnail szélességét a ThWidth, míg magasságát a ThHeight paraméterek tartalmazzák.
AHeight:=Round(ThWidth/Ratio);
AHeightOffset:=(ThHeight-AHeight) div 2;
AWidth:=ThWidth;
AWidthOffset:=0;
end
Amennyiben az arány egy vagy annál kisebb, akkor vagy egyenlő oldalú, vagy fekvő elhelyezkedésű az eredeti kép.
A fentiekhez hasonló módon itt is meg kell adnunk azt az eltolási értéket, mely azt határozza meg, hogy túl kicsi szélességi érték esetén a lekicsinyített kép a bitkép bal és jobb oldalától milyen távolságra essen.
AWidth:=Round(ThHeight*Ratio);
AWidthOffset:=(ThWidth-AWidth) div 2;
AHeight:=ThHeight;
AHeightOffset:=0;
end;
Ezután létrehozunk egy bitképet azokkal a szélességi és magassági adatokkal, melyeket a felhasználó állított be, és kitöltjük a megadott háttérszínnel.
Bitmap.Width:=ThWidth;
Bitmap.Height:=ThHeight;
Bitmap.Canvas.Brush.Color:=FillColor;
Bitmap.Canvas.FillRect(Rect(0,0,ThWidth,ThHeight));
Létrehozunk a fent kapott eltolási értékeknek megfelelően egy téglalapot, melyre a StrechDraw függvénnyel kifeszítjük az eredeti képet megfelelő arányban kicsinyítve.
ARect:=Rect(AWidthOffset,AHeightOffset,AWidth+AWidthOffset,AHeight+AHeightOffset);
Bitmap.Canvas.StretchDraw(ARect,JpegImage);
A Jpeg osztály Assign metódusával a bitmap-en levő képet átkonvertáljuk, majd elmentjük azt.
JpegImage.Assign(Bitmap);
JpegImage.SaveToStream(OutStream);
A munka végeztével felszabadítjuk a bitmap és a jpeg által lefoglalt területeket.
finally
Bitmap.Free;
end;
finally
JpegImage.Free;
end;
end;
Most nézzük meg, honnan is hívjuk meg az AddParameters nevű függvényt, mely aztán továbbítja a kapott paramétereket az előbb tárgyalt CreateThumbnail függvénynek.
procedure TForm1.CreateButtonClick(Sender: TObject);
var
i: Integer;
InFileName, OutFileName: string;
FilePath, FileName: string;
Begin
A ListBox1-be betöltött képek elérési útvonalait szétbontjuk.
for i:=0 to ListBox1.Items.Count-1 do
begin
InFileName:=ListBox1.Items[i];
A FilePath-ban tároljuk el a kép elérési útvonalát, míg a FileName-ben a kép nevét.
FilePath:=ExtractFilePath(InFileName);
FileName:=ExtractFileName(InFileName);
Amennyiben nem adunk meg kimeneti könyvtárnak semmit, a thumbnail-ek abba a könyvtárba kerülnek eltárolásra, amelyből be lettek töltve. Ellenkező esetben a megadott könyvtár lesz a mentés helye.
if OutDirEdit.Text<>'' then
Az IncludeTrailingBackSlash függvénnyel biztosítjuk, hogy a kimeneti könyvtár neve ’\’ jelre végződjön.
FilePath:=IncludeTrailingBackSlash(OutDirEdit.Text);
A thumbnail nevét a Concat függvénnyel állítjuk össze az alábbi módon:
OutFileName:=Concat(FilePath,PrefixEdit.Text,FileName);
Ezután az összeállított paramétereket átadjuk az AddParameters függvénynek, mely gondoskodik azok további felhasználásáról.
AddParameters(InFileName,OutFileName,SpinEdit1.Value,SpinEdit2.Value,Shape1.Brush.Color);
A StatusBar-on kiíratjuk, hogy a konvertálási művelet során az összes kép közül eddig hány darabnak a thumbnail-je készült el.
Application.ProcessMessages;
StatusBar1.SimpleText:=IntToStr(i+1)+' / '+IntToStr(ListBox1.Items.count)+' kész';
end;
end;
Ne felejtsük el, hogy a jpeg képekkel történő műveletekhez a uses listában fel kell sorolnunk a JPEG unit nevét is.