View Full Version : image resizing, optimize
hi, i found this code liying around:
procedure ResizeBitmap(imgo, imgd: TBitmap; nw, nh: Integer);
var
xini, xfi, yini, yfi, saltx, salty: single;
x, y, px, py, tpix: integer;
PixelColor: TColor;
r, g, b: longint;
function MyRound(const X: Double): Integer;
begin
Result := Trunc(x);
if Frac(x) >= 0.5 then
if x >= 0 then Result := Result + 1
else
Result := Result - 1;
//Result := Trunc(X + (-2 * Ord(X < 0) + 1) * 0.5);
end;
begin
// Set target size
imgd.Width := nw;
imgd.Height := nh;
// Calcs width & height of every area of pixels of the source bitmap
saltx := imgo.Width / nw;
salty := imgo.Height / nh;
yfi := 0;
for y := 0 to nh - 1 do
begin
// Set the initial and final Y coordinate of a pixel area
yini := yfi;
yfi := yini + salty;
if yfi >= imgo.Height then yfi := imgo.Height - 1;
xfi := 0;
for x := 0 to nw - 1 do
begin
// Set the inital and final X coordinate of a pixel area
xini := xfi;
xfi := xini + saltx;
if xfi >= imgo.Width then xfi := imgo.Width - 1;
// This loop calcs del average result color of a pixel area
// of the imaginary grid
r := 0;
g := 0;
b := 0;
tpix := 0;
for py := MyRound(yini) to MyRound(yfi) do
begin
for px := MyRound(xini) to MyRound(xfi) do
begin
Inc(tpix);
PixelColor := ColorToRGB(imgo.Canvas.Pixels[px, py]);
r := r + GetRValue(PixelColor);
g := g + GetGValue(PixelColor);
b := b + GetBValue(PixelColor);
end;
end;
// Draws the result pixel
imgd.Canvas.Pixels[x, y] :=
rgb(MyRound(r / tpix),
MyRound(g / tpix),
MyRound(b / tpix)
);
end;
end;
end;
and its kinda reall slow, so does anyone know how to do scanline instead of direct pixle?
Harry Hunt
23-09-2003, 10:33 PM
Scanline is no big deal really. All you need to remember is that when using scanlines, the pixel format is important.
Here's an example:
const
MaxPixelCount = 65536; // Change this if necessary
type
TRGBArray = array[0..MaxPixelCount - 1] of TRGBTriple;
pRGBArray = ^TRGBArray;
var
I, J: Integer;
Row: pRGBArray;
begin
Bitmap := TBitmap.Create;
Bitmap.Width := 400;
Bitmap.Height := 300;
Bitmap.PixelFormat := pf24Bit; // 1 Byte per color
for J := 0 to Bitmap.Height - 1 do
begin
Row := Bitmap.ScanLine[J];
for I := 0 to Bitmap.Width - 1 do
begin
Row[I].rgbtRed := Random(256);
Row[I].rgbtGreen := Random(256);
Row[I].rgbtBlue := Random(256);
end;
end;
end;
This example should generate some random color noise but I think it illustrates quite well how to access individual pixels using scanlines. Make sure that the color values you assign to rgbtRed, Green and Blue are between 0 and 255. You will get some really funky results if your values are either too large or too small.
Alimonster
24-09-2003, 09:57 PM
I could rewrite it to use Scanline tomorrow if you want (not tonight unfortunately - been a hectic week).
EDIT: as a thought, Anders Melander (cool Delphi dude who wrote a gif component, maybe called TGifImage) has a zip somewhere out there that deals with this - it's called resample.zip or something like that. Sorry about being hazy on the details but his site has been down for a while, unfortunately (his life got too busy to maintain it IIRC from news://borland.public.graphics). It's meant to be quite good if you {$DEFINE USE_SCANLINE} or something like that. Umm, maybe this vague info will be helpful, though it may involve more than a little hunting around :?
Alimonster
29-09-2003, 09:00 AM
Aaah! Here's another example of me forgetting about things! Sigh. By "tomorrow", of course, I meant "quite a few days from the time of that post".
Whoops. It'll get rewritten soon-ish if you still want that, dUmAsS. In my defence, it's been a busy few days (and I have a promotion interview on Wednesday, so hopefully once that's done things will get quiet again).
hi, thanks man :)
no problems, ive been busy myself. and it involves a suprise car on my bday yay :shock: :D :D :D
um, i tryed myself but failed missrebly :) (scanline index out of range)
heres the code
procedure ResizeBitmapNew(imgo, imgd: TBitmap; nw, nh: Integer);
const
MaxPixelCount = 65536; // Change this if necessary
type
TRGBArray = array[0..MaxPixelCount - 1] of TRGBTriple;
pRGBArray = ^TRGBArray;
var
Row: pRGBArray;
var
xini, xfi, yini, yfi, saltx, salty: single;
x, y, px, py, tpix: integer;
PixelColor: TColor;
r, g, b: longint;
function MyRound(const X: Double): Integer;
begin
Result := Trunc(x);
if Frac(x) >= 0.5 then
if x >= 0 then Result := Result + 1
else
Result := Result - 1;
//Result := Trunc(X + (-2 * Ord(X < 0) + 1) * 0.5);
end;
begin
// Set target size
imgd.Width := nw;
imgd.Height := nh;
// Calcs width & height of every area of pixels of the source bitmap
saltx := imgo.Width / nw;
salty := imgo.Height / nh;
yfi := 0;
for y := 0 to nh - 1 do
begin
Row := imgd.ScanLine[y];
// Set the initial and final Y coordinate of a pixel area
yini := yfi;
yfi := yini + salty;
if yfi >= imgo.Height then yfi := imgo.Height - 1;
xfi := 0;
for x := 0 to nw - 1 do
begin
// Set the inital and final X coordinate of a pixel area
xini := xfi;
xfi := xini + saltx;
if xfi >= imgo.Width then xfi := imgo.Width - 1;
// This loop calcs del average result color of a pixel area
// of the imaginary grid
r := 0;
g := 0;
b := 0;
tpix := 0;
for py := MyRound(yini) to MyRound(yfi) do
begin
for px := MyRound(xini) to MyRound(xfi) do
begin
Inc(tpix);
PixelColor := ColorToRGB(imgo.Canvas.Pixels[px, py]);
r := r + GetRValue(PixelColor);
g := g + GetGValue(PixelColor);
b := b + GetBValue(PixelColor);
end;
end;
// Draws the result pixel
Row[x].rgbtRed := MyRound(r / tpix);
Row[x].rgbtGreen := MyRound(g / tpix);
Row[x].rgbtBlue := MyRound(b / tpix);
{ imgd.Canvas.Pixels[x, y] :=
rgb(MyRound(r / tpix),
MyRound(g / tpix),
MyRound(b / tpix)
); }
end;
end;
end;
as you can see im crap at image work :)
Harry Hunt
02-11-2003, 06:52 AM
You need to do Bitmap.PixelFormat := pf24Bit; with all your bitmaps...
Also, make sure that the values you assign to rgtbRed,... never get larger than 255 or smaller than 0 or you'll get really weird results.
Powered by vBulletin® Version 4.2.5 Copyright © 2024 vBulletin Solutions Inc. All rights reserved.