2005. január 31., hétfő
Resize a *.jpg image and save the result to a file (2)
Problem/Question/Abstract:
Before importing an image (jpg) into a database, I would like to resize it (reduce its size) and generate the corresponding smaller file. How can I do this?
Answer:
Load the JPEG into a bitmap, create a new bitmap of the size that you want and pass them both into SmoothResize then save it again ... there's a neat routine JPEGDimensions that gets the JPEG dimensions without actually loading the JPEG into a bitmap, saves loads of time if you only need to test its size before resizing.
{ ... }
type
TRGBArray = array[Word] of TRGBTriple;
pRGBArray = ^TRGBArray;
{ ... }
procedure SmoothResize(Src, Dst: TBitmap);
var
x, y: integer;
xP, yP: integer;
xP2, yP2: integer;
SrcLine1, SrcLine2: pRGBArray;
t3: integer;
z, z2, iz2: integer;
DstLine: pRGBArray;
DstGap: integer;
w1, w2, w3, w4: integer;
begin
Src.PixelFormat := pf24Bit;
Dst.PixelFormat := pf24Bit;
if (Src.Width = Dst.Width) and (Src.Height = Dst.Height) then
Dst.Assign(Src)
else
begin
DstLine := Dst.ScanLine[0];
DstGap := Integer(Dst.ScanLine[1]) - Integer(DstLine);
xP2 := MulDiv(pred(Src.Width), $10000, Dst.Width);
yP2 := MulDiv(pred(Src.Height), $10000, Dst.Height);
yP := 0;
for y := 0 to pred(Dst.Height) do
begin
xP := 0;
SrcLine1 := Src.ScanLine[yP shr 16];
if (yP shr 16 < pred(Src.Height)) then
SrcLine2 := Src.ScanLine[succ(yP shr 16)]
else
SrcLine2 := Src.ScanLine[yP shr 16];
z2 := succ(yP and $FFFF);
iz2 := succ((not yp) and $FFFF);
for x := 0 to pred(Dst.Width) do
begin
t3 := xP shr 16;
z := xP and $FFFF;
w2 := MulDiv(z, iz2, $10000);
w1 := iz2 - w2;
w4 := MulDiv(z, z2, $10000);
w3 := z2 - w4;
DstLine[x].rgbtRed := (SrcLine1[t3].rgbtRed * w1 + SrcLine1[t3 + 1].rgbtRed *
w2 +
SrcLine2[t3].rgbtRed * w3 + SrcLine2[t3 + 1].rgbtRed * w4) shr 16;
DstLine[x].rgbtGreen := (SrcLine1[t3].rgbtGreen * w1 + SrcLine1[t3 +
1].rgbtGreen * w2 +
SrcLine2[t3].rgbtGreen * w3 + SrcLine2[t3 + 1].rgbtGreen * w4) shr 16;
DstLine[x].rgbtBlue := (SrcLine1[t3].rgbtBlue * w1 + SrcLine1[t3 + 1].rgbtBlue
* w2 +
SrcLine2[t3].rgbtBlue * w3 + SrcLine2[t3 + 1].rgbtBlue * w4) shr 16;
inc(xP, xP2);
end;
inc(yP, yP2);
DstLine := pRGBArray(Integer(DstLine) + DstGap);
end;
end;
end;
function LoadJPEGPictureFile(Bitmap: TBitmap; FilePath, Filename: string): boolean;
var
JPEGImage: TJPEGImage;
begin
if (Filename = '') then
{No filename so nothing to load - return false ...}
Result := false
else
begin
try
JPEGImage := TJPEGImage.Create;
try
JPEGImage.LoadFromFile(FilePath + Filename);
Bitmap.Assign(JPEGImage);
Result := true;
finally
JPEGImage.Free;
end;
except
Result := false;
end;
end;
end;
function SaveJPEGPictureFile(Bitmap: TBitmap; FilePath, Filename: string;
Quality: integer): boolean;
begin
Result := true;
try
if ForceDirectories(FilePath) then
begin
with TJPegImage.Create do
begin
try
Assign(Bitmap);
CompressionQuality := Quality;
SaveToFile(FilePath + Filename);
finally
Free;
end;
end;
end;
except
raise;
Result := false;
end;
end;
function JPEGDimensions(Filename: string; var X, Y: Word): boolean;
var
SegmentPos: integer;
SOIcount: integer;
b: byte;
begin
Result := false;
with TFileStream.Create(Filename, fmOpenRead or fmShareDenyNone) do
begin
try
Position := 0;
Read(X, 2);
if (X <> $D8FF) then
exit;
SOIcount := 0;
Position := 0;
while (Position + 7 < Size) do
begin
Read(b, 1);
if (b = $FF) then
begin
Read(b, 1);
if (b = $D8) then
inc(SOIcount);
if (b = $DA) then
break;
end;
end;
if (b <> $DA) then
exit;
SegmentPos := -1;
Position := 0;
while (Position + 7 < Size) do
begin
Read(b, 1);
if (b = $FF) then
begin
Read(b, 1);
if (b in [$C0, $C1, $C2]) then
begin
SegmentPos := Position;
dec(SOIcount);
if (SOIcount = 0) then
break;
end;
end;
end;
if (SegmentPos = -1) then
exit;
if (Position + 7 > Size) then
exit;
Position := SegmentPos + 3;
Read(Y, 2);
Read(X, 2);
X := Swap(X);
Y := Swap(Y);
Result := true;
finally
Free;
end;
end;
end;
Feliratkozás:
Megjegyzések küldése (Atom)
Nincsenek megjegyzések:
Megjegyzés küldése