bloodbird
asked on
new Stretch Method, Stretch a Trapezoid but not a Retangle.
i have been looking codes to Stretch a Trapezoid for a long time. Is there anyone can help me ?
i have a bitmap(ABmp), i draw a Trapezoid(Trapezoid_A) on it, the two bottom of the Trapezoid is always parallel Y_axis,
then i move the upside bottom to any position(the length of the upside bottom keeps,and it always parallel Y_axis ).
now there is a a new Trapezoid(Trapezoid_B) by old downside bottom and the new upside bottom(the area of Trapezoid_B may less /more than the area of Trapezoid_A ).
what i need is Stretch Trapezoid_A into Trapezoid_B.
the function may like this
NewStretch(ABmp:TBmp; //the source bitmap
ATrapezoid:Array of TPoint; //Old Trapezoid
BTrapezoid:Array of TPoint; //New Trapezoid
BBmp:TBmp //the Dest bitmap
)
by the way, the speed of the function is important, i have wrote one ,but it's too slow to use.
and you can use any component.
could you give me the code?
any comments would be much appricated
thank you in advance
i have a bitmap(ABmp), i draw a Trapezoid(Trapezoid_A) on it, the two bottom of the Trapezoid is always parallel Y_axis,
then i move the upside bottom to any position(the length of the upside bottom keeps,and it always parallel Y_axis ).
now there is a a new Trapezoid(Trapezoid_B) by old downside bottom and the new upside bottom(the area of Trapezoid_B may less /more than the area of Trapezoid_A ).
what i need is Stretch Trapezoid_A into Trapezoid_B.
the function may like this
NewStretch(ABmp:TBmp; //the source bitmap
ATrapezoid:Array of TPoint; //Old Trapezoid
BTrapezoid:Array of TPoint; //New Trapezoid
BBmp:TBmp //the Dest bitmap
)
by the way, the speed of the function is important, i have wrote one ,but it's too slow to use.
and you can use any component.
could you give me the code?
any comments would be much appricated
thank you in advance
ASKER
hi ,developmentguru:
thank you. i uploaded the image to show how it works.
1: the trapezoid is just a selection area. that is to say i am not to drawing on a blank
canvas,but an existing image.
2: what i meant "upside bottom" is top bottom, and :downside bottom" is bottom of a trapezoid.
3: about parallel to the Y axis, that is my mistakes. infact, the top bottom and the bottom do not to be parrallel to Y axis.
please tell me if you need more info
thank you again
stretch-question.jpg
thank you. i uploaded the image to show how it works.
1: the trapezoid is just a selection area. that is to say i am not to drawing on a blank
canvas,but an existing image.
2: what i meant "upside bottom" is top bottom, and :downside bottom" is bottom of a trapezoid.
3: about parallel to the Y axis, that is my mistakes. infact, the top bottom and the bottom do not to be parrallel to Y axis.
please tell me if you need more info
thank you again
stretch-question.jpg
ASKER
the code may like this ( this code is very slow)
tpye
TLine = record
x1,y1:integer; // point1 of the line
x2,y2:integer; // point2 of the line
end;
TTrapezoid = record
bottom:TLine; //bottom of the Trapezoid
top:TLine; //top bottom of the Trapezoid
end;
NewStretch(ABmp:TBitmap; //the source bitmap
ATrapezoid:TTrapezoid ; //Old Trapezoid
BTrapezoid:TTrapezoid ; //New Trapezoid
BBmp:TBitmap //the Dest bitmap
)
var
BTrapezoid_Handle:Hrgn; //handle of BTrapezoid
TopLeft:Tpoint; //topLeft of the BTrapezoid
bottomRight:TPoint; //bottomRight of BTrapezoid
AColor:TRGB;
i,j:integer;
begin
if IS_Parallel(ATrapezoid.bot tom,ATrape zoid.top) then Exit;
if IS_Parallel(BTrapezoid.bot tom,BTrape zoid.top) then Exit;
BTrapezoid_Handle:=CreateP olygonRgn( [(BTrapezo id.bottom. x1,BTrapez oid.bottom .y1),
(BTrapezoid.bottom.x2,BTra pezoid.bot tom.y2),
(BTrapezoid.top.x2,BTrapez oid.top.y2 ),
(BTrapezoid.top.x1,BTrapez oid.top.y1 )],4,2) ;
bottomRight:=GetBottomRigh t(BTrapezo id);
topLeft:=GetTopLeft(BTrape zoid);
for j:=TopLeft.y to BottomRight.y do
for i:=TopLeft.x to BottomRight.x do
begin
if PtInRegion(BTrapezoid) then
begin
BBmp.Picture.Canvas.pixel( i,j):=GetC olorFromBm p(ABmp)
end;
end;
end;
tpye
TLine = record
x1,y1:integer; // point1 of the line
x2,y2:integer; // point2 of the line
end;
TTrapezoid = record
bottom:TLine; //bottom of the Trapezoid
top:TLine; //top bottom of the Trapezoid
end;
NewStretch(ABmp:TBitmap; //the source bitmap
ATrapezoid:TTrapezoid ; //Old Trapezoid
BTrapezoid:TTrapezoid ; //New Trapezoid
BBmp:TBitmap //the Dest bitmap
)
var
BTrapezoid_Handle:Hrgn; //handle of BTrapezoid
TopLeft:Tpoint; //topLeft of the BTrapezoid
bottomRight:TPoint; //bottomRight of BTrapezoid
AColor:TRGB;
i,j:integer;
begin
if IS_Parallel(ATrapezoid.bot
if IS_Parallel(BTrapezoid.bot
BTrapezoid_Handle:=CreateP
(BTrapezoid.bottom.x2,BTra
(BTrapezoid.top.x2,BTrapez
(BTrapezoid.top.x1,BTrapez
bottomRight:=GetBottomRigh
topLeft:=GetTopLeft(BTrape
for j:=TopLeft.y to BottomRight.y do
for i:=TopLeft.x to BottomRight.x do
begin
if PtInRegion(BTrapezoid) then
begin
BBmp.Picture.Canvas.pixel(
end;
end;
end;
It may be later this week before I have time to try to create an example. I can say that this type of manipulation does require a good deal of work no matter how it is accomplished. One way to help reduce the impact of this type of processor intensive manipulation is to make sure the drag operation you do to accomplish the stretch will only try the stretch after the line is placed. This will keep it from trying to stretch it multiple times while the user drags.
An advanced way to handle it would be to offload the processing to the video card but this is quite a chore in itself. As an example: Does the user have a video card capable of being used for this? If not, do you want to write your own version? If they do have a video card, what are it's capabilities? Who is the manufacturer? How much resources does the card have?
I will let you know as I make progress.
An advanced way to handle it would be to offload the processing to the video card but this is quite a chore in itself. As an example: Does the user have a video card capable of being used for this? If not, do you want to write your own version? If they do have a video card, what are it's capabilities? Who is the manufacturer? How much resources does the card have?
I will let you know as I make progress.
ASKER
hi,developmentguru:
becasue this program is designed for a specail user, so i think i can buy one vedio card .
the most important is the speed , if a vedio card can make it fast,i'll go to market to buy it.
i just don't know which kind of vedio card could be useful. and i haven't ever written a vedio_supported program.
i heard about a third_party component----fastlib,and i tried to use it,but as my capability, i don't understand how to use it.
thank you again , developmentguru
becasue this program is designed for a specail user, so i think i can buy one vedio card .
the most important is the speed , if a vedio card can make it fast,i'll go to market to buy it.
i just don't know which kind of vedio card could be useful. and i haven't ever written a vedio_supported program.
i heard about a third_party component----fastlib,and i tried to use it,but as my capability, i don't understand how to use it.
thank you again , developmentguru
Your example shows the right side line moving. Do you plan to have the user drag one line at a time to do the change? Normally these changes are done by dragging points, but I could see where dragging the line would alleviate some issue and possibly make it easier to use. Let me know how you want to handle the manipulation of the trapezoid so I can make my example to match.
ASKER
the cordinate of the vertices of the Trapezoid is given by other fucntions, that's to say ,it can not do the change while dragging. the scetch funtion will be called in a lots of loops,and the image would be very large, because of that , i want it be fast.
How many loops are we talking about? Please understand that the more I know about what you are trying to do, the better I can approximate it and provide you what you are looking for.
ASKER
two loops now
they look like this
for i:=0 to 20 do
begin
for j:=0 to 15 do
Trapeaoid_A:=... //get the vertices of source trapezoid
Trapezoid_B:=... //get the vertices of dest trapezoid
StretchTrapezoid(Srcbmp,De stbmp,Trap ezoid_A,Tr apezoid_B) ;
end;
but , i am trying to figure out a way to use only one loop, eh,i believe i could figure it out
they look like this
for i:=0 to 20 do
begin
for j:=0 to 15 do
Trapeaoid_A:=... //get the vertices of source trapezoid
Trapezoid_B:=... //get the vertices of dest trapezoid
StretchTrapezoid(Srcbmp,De
end;
but , i am trying to figure out a way to use only one loop, eh,i believe i could figure it out
ASKER
i gave you a wrong code ,i forgot to add a "begin,,,end"
it should be this
for i:=0 to 20 do
begin
for j:=0 to 15 do
begin
Trapeaoid_A:=... //get the vertices of source trapezoid
Trapezoid_B:=... //get the vertices of dest trapezoid
StretchTrapezoid(Srcbmp,De stbmp,Trap ezoid_A,Tr apezoid_B) ;
end
end;
it should be this
for i:=0 to 20 do
begin
for j:=0 to 15 do
begin
Trapeaoid_A:=... //get the vertices of source trapezoid
Trapezoid_B:=... //get the vertices of dest trapezoid
StretchTrapezoid(Srcbmp,De
end
end;
I assume I and J are to be used in the call to Stretch Trapezoid? What are the loops doing for you?
ASKER
the i and j , are used to get the vertices of trapezoid
they looks like this
for i:=0 to 20 do
begin
for j:=0 to 15 do
begin
DestBmp:=TBitmap.create;
Trapeaoid_A:=GetTrapezoidA
Trapezoid_B:=GetTrapezoidB
StretchTrapezoid(Srcbmp,De
Destbmp.savetofile(i _ j .bmp);
DestBmp.free;
end
end;
the loops make a selection area(it's a polygon) of the SrcBmp become into some
trapezoid(src trapezoid), each trapzoid(src trapezoid ) change the position of its top
bottom ,and then call the stretch function to get a new bitmap, the new bitmap is all
transparent except the pixels in the area of dest trapezoid, then i could use these bitmap
to form a new picture;
If you would like me to be able to produce something that is ready for you to use I could use the contents of the GetTrapezoidA and GetTrapezoidB functions too. That way I will have tested exactly what you are testing. If not I will just see what I can come up with on my own. I will wait to see if you will post the functions though.
ASKER
could you give me your email ? so i can mail you that code. for some reason,i cant post the code here
ASKER
my email address is escaper@gmail.com
Since we are not supposed to contact outside of EE, I will attempt to help you here. Besides that, others may find the information useful.
I will give you a written breakdown of how I intend to approach this. I will use your coordinate examples to try to give you an idea.
I will call the A -> C line TopH and the B -> D line BottomH (horizontal) lines respectively. I want to figure a minimum step for X and a minimum step for Y. This will establish the fastest (and least accurate) of the methods of traversing and translating coordinates. Once I have these minimums I will take a sample at each point along a line from 0 Y relative along the TopH line. Each coordinate will be translated to the respective coordinate on the original trapezoid and a color sample read, which will be either plotted or listed (I will get back to this later). Continuing the process for each Y until we have finished scanning the BottomH line. Let me know if you have questions on the process.
Once again, I will be doing this in a non-optimized fashion so you understand the process.
I will give you a written breakdown of how I intend to approach this. I will use your coordinate examples to try to give you an idea.
I will call the A -> C line TopH and the B -> D line BottomH (horizontal) lines respectively. I want to figure a minimum step for X and a minimum step for Y. This will establish the fastest (and least accurate) of the methods of traversing and translating coordinates. Once I have these minimums I will take a sample at each point along a line from 0 Y relative along the TopH line. Each coordinate will be translated to the respective coordinate on the original trapezoid and a color sample read, which will be either plotted or listed (I will get back to this later). Continuing the process for each Y until we have finished scanning the BottomH line. Let me know if you have questions on the process.
Once again, I will be doing this in a non-optimized fashion so you understand the process.
I got the selection routine down and will do more tomorrow.
I have defined two buttons TrapA and TrapB. The selection routine is working for both. The A Trapezoid is shown in Red and the B Trapezoid is shown in Blue. I am going to post the source so far so you can play with it. Once the two are defined I will be able to do the core routine to translate between the two. I cleared the picture so I would not have 74,000 lines in the DFM. When you have recreated the project, just set the picture before you start or it will not look like much. Let me know if you have questions to this point.
---DFM---
object Form1: TForm1
Left = 138
Top = 110
Caption = 'Form1'
ClientHeight = 873
ClientWidth = 744
Color = clBtnFace
Font.Charset = ANSI_CHARSET
Font.Color = clWindowText
Font.Height = -14
Font.Name = #23435#20307
Font.Style = []
OldCreateOrder = False
Position = poScreenCenter
OnCreate = FormCreate
OnDestroy = FormDestroy
OnKeyPress = FormKeyPress
PixelsPerInch = 96
TextHeight = 14
object ToolBar1: TToolBar
Left = 0
Top = 0
Width = 744
Height = 23
ButtonWidth = 49
Caption = 'ToolBar1'
ShowCaptions = True
TabOrder = 0
object btnTrapA: TToolButton
Left = 0
Top = 0
Action = defTrapA
end
object btnTrapB: TToolButton
Left = 49
Top = 0
Action = defTrapB
end
end
object Panel1: TPanel
Left = 0
Top = 23
Width = 744
Height = 850
Align = alClient
TabOrder = 1
object PaintBox1: TPaintBox
Left = 1
Top = 1
Width = 742
Height = 848
Align = alClient
OnMouseDown = PaintBox1MouseDown
OnMouseMove = PaintBox1MouseMove
OnPaint = PaintBox1Paint
ExplicitLeft = 0
ExplicitTop = 0
ExplicitWidth = 105
ExplicitHeight = 105
end
object Image: TImage
Left = 0
Top = 0
Width = 635
Height = 800
AutoSize = True
Stretch = True
Visible = False
end
end
object ActionList1: TActionList
OnUpdate = ActionList1Update
Left = 664
Top = 24
object defTrapA: TAction
Caption = 'Trap A'
OnExecute = defTrapAExecute
end
object defTrapB: TAction
Caption = 'Trap B'
OnExecute = defTrapBExecute
end
end
end
---PAS---
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, ComCtrls,math, shellapi,ToolWin, StdCtrls,Shrink,
FastRender, ActnList;
type
TTrapezoid = class
private
fPoints : array [0..3] of TPoint;
fPointsDefined : integer;
function GetPoint(Index: integer): TPoint;
protected
public
procedure AddPoint(Point : TPoint);
procedure Draw(Canvas : TCanvas);
procedure Clear;
property PointsDefined : integer read fPointsDefined;
property Points[Index : integer] : TPoint read GetPoint;
end;
TForm1 = class(TForm)
ToolBar1: TToolBar;
Panel1: TPanel;
Image: TImage;
btnTrapA: TToolButton;
btnTrapB: TToolButton;
ActionList1: TActionList;
defTrapA: TAction;
defTrapB: TAction;
PaintBox1: TPaintBox;
procedure ActionList1Update(Action: TBasicAction; var Handled: Boolean);
procedure FormCreate(Sender: TObject);
procedure defTrapAExecute(Sender: TObject);
procedure defTrapBExecute(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure PaintBox1Paint(Sender: TObject);
procedure PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
procedure FormKeyPress(Sender: TObject; var Key: Char);
private
{ Private declarations }
fDefiningTrapA, fDefiningTrapB : boolean;
fUpdateTrapButtons : boolean;
fBack : TBitmap;
R : TRect;
TrapA, TrapB : TTrapezoid;
LastMouseMove : TPoint;
NeedToErase : boolean;
function GetDefiningTrap: boolean;
procedure SetDefiningTrapA(const Value: boolean);
procedure SetDefiningTrapB(const Value: boolean);
function GetCurrentTrap: TTrapezoid;
property DefiningTrap : boolean read GetDefiningTrap;
property DefiningTrapA : boolean read fDefiningTrapA write SetDefiningTrapA;
property DefiningTrapB : boolean read fDefiningTrapB write SetDefiningTrapB;
property CurrentTrap : TTrapezoid read GetCurrentTrap;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
fUpdateTrapButtons := true;
TrapA := TTrapezoid.Create;
TrapB := TTrapezoid.Create;
R := Rect(0, 0, Image.Width, Image.Height);
fBack := TBitmap.Create;
fBack.Width := Image.Width;
fBack.Height := Image.Height;
fBack.Canvas.CopyRect(R, Image.Canvas, R);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
fBack.Free;
FreeAndNil(TrapB);
FreeAndNil(TrapA);
end;
procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
if Key = char(VK_ESCAPE) then
begin
if DefiningTrap then
begin
CurrentTrap.Clear;
if DefiningTrapA then
fDefiningTrapA := false
else
fDefiningTrapB := false;
PaintBox1.Invalidate;
Key := #0;
fUpdateTrapButtons := true;
end;
end;
end;
procedure TForm1.ActionList1Update(Action: TBasicAction; var Handled: Boolean);
begin
if fUpdateTrapButtons then
if DefiningTrap then
begin
defTrapA.Enabled := false;
defTrapB.Enabled := false;
end
else
begin
defTrapA.Enabled := true;
defTrapB.Enabled := true;
end;
fUpdateTrapButtons := false;
end;
procedure TForm1.defTrapAExecute(Sender: TObject);
begin
fDefiningTrapA := true;
fUpdateTrapButtons := true;
TrapA.Clear;
PaintBox1.Invalidate;
NeedToErase := false;
end;
procedure TForm1.defTrapBExecute(Sender: TObject);
begin
fDefiningTrapB := true;
fUpdateTrapButtons := true;
TrapB.Clear;
PaintBox1.Invalidate;
NeedToErase := false;
end;
function TForm1.GetCurrentTrap: TTrapezoid;
begin
Result := nil;
if not DefiningTrap then
exit;
if DefiningTrapA then
Result := TrapA
else
Result := TrapB;
end;
function TForm1.GetDefiningTrap: boolean;
begin
Result := fDefiningTrapA or fDefiningTrapB;
end;
procedure TForm1.PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
Trap : TTrapezoid;
begin
if DefiningTrap then
begin
Trap := CurrentTrap;
Trap.AddPoint(Point(X, Y));
if Trap.PointsDefined = 4 then
begin
if DefiningTrapA then
fDefiningTrapA := false
else
fDefiningTrapB := false;
fUpdateTrapButtons := true;
end;
PaintBox1.Invalidate;
end;
end;
procedure TForm1.PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
var
Trap : TTrapezoid;
LastPoint : TPoint;
begin
if DefiningTrap then
begin
Trap := CurrentTrap;
if Trap.PointsDefined > 0 then
begin
LastPoint := Trap.Points[Trap.PointsDefined - 1];
with PaintBox1, Canvas do
begin
Pen.Mode := pmXor;
//erase last line
if NeedToErase then
begin
MoveTo(LastPoint.X, LastPoint.Y);
LineTo(LastMouseMove.X, LastMouseMove.Y);
end;
//draw new line
MoveTo(LastPoint.X, LastPoint.Y);
LineTo(X, Y);
LastMouseMove.X := X;
LastMouseMove.Y := Y;
NeedToErase := true;
end;
end;
end;
end;
procedure TForm1.PaintBox1Paint(Sender: TObject);
var
I : integer;
P : TPoint;
begin
with PaintBox1, Canvas do
begin
//set the base image
CopyRect(R, fBack.Canvas, R);
if TrapA.PointsDefined <> 0 then
begin
for I := 0 to TrapA.PointsDefined - 1 do
begin
P := TrapA.Points[I];
Pen.Color := clRed;
Pen.Mode := pmCopy;
Rectangle(P.X - 2, P.Y - 2, P.X + 2, P.Y + 2);
if I = 0 then
MoveTo(P.X, P.Y)
else
LineTo(P.X, P.Y);
end;
if TrapA.PointsDefined = 4 then
LineTo(TrapA.Points[0].X, TrapA.Points[0].Y);
end;
if TrapB.PointsDefined <> 0 then
begin
for I := 0 to TrapB.PointsDefined - 1 do
begin
P := TrapB.Points[I];
Pen.Color := clBlue;
Pen.Mode := pmCopy;
Rectangle(P.X - 2, P.Y - 2, P.X + 2, P.Y + 2);
if I = 0 then
MoveTo(P.X, P.Y)
else
LineTo(P.X, P.Y);
end;
if TrapB.PointsDefined = 4 then
LineTo(TrapB.Points[0].X, TrapB.Points[0].Y);
end;
end;
end;
procedure TForm1.SetDefiningTrapA(const Value: boolean);
begin
fDefiningTrapA := Value;
end;
procedure TForm1.SetDefiningTrapB(const Value: boolean);
begin
fDefiningTrapB := Value;
end;
{ TTrapezoid }
procedure TTrapezoid.AddPoint(Point: TPoint);
begin
Assert(fPointsDefined < 4, 'Attempting to add more than 4 points to ' +
'TTrapezoid.AddPoint');
fPoints[fPointsDefined] := Point;
inc(fPointsDefined);
end;
procedure TTrapezoid.Clear;
begin
fPointsDefined := 0;
end;
procedure TTrapezoid.Draw(Canvas: TCanvas);
begin
end;
function TTrapezoid.GetPoint(Index: integer): TPoint;
begin
Assert(Index < PointsDefined, 'Invalid index for TTrapezoid.GetPoint');
Result := fPoints[Index];
end;
end.
I forgot to mention... the trapezoid selection lets you draw 4 points with connecting lines and you can cancel by hitting the [Esc] key.
ASKER
hi, developmentguru:
thank you, it's a nice test framework, much better than mine. now, it gave me more confidence that i would get a rapidly TTrapezoid.Draw function. thank you again.
thank you, it's a nice test framework, much better than mine. now, it gave me more confidence that i would get a rapidly TTrapezoid.Draw function. thank you again.
I am almost ready to post the initial code. The code is commented well and details other possible approaches. This code is fast, but fast is a relative term. If it is not fast enough for you I am sure you can optimize it fairly easily. If not, you could always try some of the other approaches I mention in the comments. I should be ready to post it in a few more days.
I should also mention... it is fun to play with :-)
I should also mention... it is fun to play with :-)
ASKER
thank you developmentguru:
i am thinking about Stretching a Trapezoid is actrually Stretching two Triangles. Supposed
we have a trapezoid ABCD which top bottom is AB and bottom is CD. To Stretch Trapezoid
ABCD is equal to Stretch triangle ACD and Triangle ABD. if we make a sub function as
StretchTriangle(); it will be more flexible, and we even can stretch any quadrangle by that function.
this is more useful for some this kinds of manipulation. eh.. i guess you had ideas of that...
i am thinking about Stretching a Trapezoid is actrually Stretching two Triangles. Supposed
we have a trapezoid ABCD which top bottom is AB and bottom is CD. To Stretch Trapezoid
ABCD is equal to Stretch triangle ACD and Triangle ABD. if we make a sub function as
StretchTriangle(); it will be more flexible, and we even can stretch any quadrangle by that function.
this is more useful for some this kinds of manipulation. eh.. i guess you had ideas of that...
I think you will see that the method I am using could be applied :-)
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
i am studying your code
The conversion to using triangles would need to be done from the first point doing lines to each point of a line between points 2 and 3. To do this well you would need to implement the pixel color averaging I mention in the comments. You can use this "as is" or modify it to better suit your needs. When I tried it out the algorithm finished almost immediately. Let me know what you think (comment on the solution).
ASKER
hi,
I have read your code. This method is very good. It can not only stretch a trapezoid but also a arbitrary quadrangle. The sample code is simple and well commented making me get your stretching way clearly. I think i am facing two problems with this code.
1: Because of the "Round" things, there must be some pixels lost. we have to paint it to dest trapezoid.
2: I think access the pixels by the function" canvase.pixel[x,y]" would be slower than by function "scanline".I am expecting your way to speed it.
By the way, I learn more from your code and still learning it .
thank you again.
I have read your code. This method is very good. It can not only stretch a trapezoid but also a arbitrary quadrangle. The sample code is simple and well commented making me get your stretching way clearly. I think i am facing two problems with this code.
1: Because of the "Round" things, there must be some pixels lost. we have to paint it to dest trapezoid.
2: I think access the pixels by the function" canvase.pixel[x,y]" would be slower than by function "scanline".I am expecting your way to speed it.
By the way, I learn more from your code and still learning it .
thank you again.
If you run into any loss of pixels it just means that the default number of samples I selected is not high enough. You can always multiply the defaults by... 1.2 or 1.5 to avoid dropping pixels. Just keep in mind that doing that multiplier will proportionally slow it down. As I mention in the code you would want a higher number of samples combined with a list containing colors per location so you can accurately average the results and avoid as much color information loss as possible.
As a side note: If you wanted to convert from a circle to another geometric shape you could still use the same method (without loosing pixels that fall outside the shape but are part of the circle). Doing this would skew the information to basically stretch the circle towards the new shape. This would result in no skew towards the points of the new shape and maximum skew directly between any two points. I am not sure this would be ideal, but then it is up to you to decide that.
As a side note: If you wanted to convert from a circle to another geometric shape you could still use the same method (without loosing pixels that fall outside the shape but are part of the circle). Doing this would skew the information to basically stretch the circle towards the new shape. This would result in no skew towards the points of the new shape and maximum skew directly between any two points. I am not sure this would be ideal, but then it is up to you to decide that.
---I am expecting your way to speed it.
I am not sure I understand... you want me to optimize it now? In order to try to convert this to doing the scan lines I would need to change the algorithm so it processes by scan lines. The processing itself would be faster in one way and slower in another. The only speed increase there would be through the use of the lower level graphics. It would likely be far more productive to look at doing something like this using a 3D api (which then automatically uses the 3D hardware) than to try to handle the lower level manipulations yourself (and making up for a wide array of graphics hardware in your own code).
Is the code not fast enough as it is? I thought it was plenty fast. If it is already fast enough you would be better off spending your time working on more functionality. After all, if it's not broke don't fix it.
Let me know.
I am not sure I understand... you want me to optimize it now? In order to try to convert this to doing the scan lines I would need to change the algorithm so it processes by scan lines. The processing itself would be faster in one way and slower in another. The only speed increase there would be through the use of the lower level graphics. It would likely be far more productive to look at doing something like this using a 3D api (which then automatically uses the 3D hardware) than to try to handle the lower level manipulations yourself (and making up for a wide array of graphics hardware in your own code).
Is the code not fast enough as it is? I thought it was plenty fast. If it is already fast enough you would be better off spending your time working on more functionality. After all, if it's not broke don't fix it.
Let me know.
Normally your axes run as shown:
------X------>
|
|
Y
|
|
\/
I figure that you meant that the two bottom points of the trapezoid are perpendicular to the Y axis (parallel to the X axis). If any two points were parallel to the Y axis then the line between them would be a vertical bar on the left or right side of your shape.
You then make the statement that you move the "upside bottom" to any position... I translate upside as top... the top bottom? If the two bottom points are always on the same Y coordinate then one is the left bottom point and one is the right bottom point. Again later in your dialog you refer to the "downside bottom" and I am equally unsure what that means.
Once you clarify your language and show some images (with text showing your point references in the images) then we can move on. One important thing to note. Any function capable of doing this manipulation will be lossy. If you stretch A into B, then use B to stretch to C, and continue using the output to create new output your image will loose clarity. This could happen easily if you just stretch the area repeatedly during a mouse drag, or the user does the operation repeatedly. Knowing this, the Trapezoid should have the ORIGINAL bitmap associated with it, and it (and the original dimensions of the trapezoid) should always be used to stretch it to the new dimensions.
I will await example images and further explanation.