Board index » delphi » Pixel precision...

Pixel precision...


2008-06-16 03:38:47 AM
delphi119
I have such code :
for _y := 0 to self._source.Height - 1
do begin
_bytes := self._source.ScanLine[_y];
for _x := 0 to self._source.Width - 1
do begin
_xyz := D3Point(_x, _y, 0);
_x1 := rotate3D(_xyz).x;
_y1 := rotate3D(_xyz).y;
_targetarr := _bitmap.ScanLine[_y1];
_targetarr[_x1 ] := _bytes[_x];
_targetarr[_x1 + 1] := _bytes[_x + 1];
_targetarr[_x1 + 2] := _bytes[_x + 2];
end;
end;
That does copy all pixels from source to bitmap, after rotating them...
But that makes some "white" pixels...! What I do need is some 'Pixel
precision'...
That is 1 pixel from _bytes should light up :
1 pixel at same location
n pixels around same location
I will make "n" vary to have no more "blank" pixels !
How ?
I tried to draw an ellipse at 2D resulting x,y, but that so slow...else it
works !
DH
 
 

Re:Pixel precision...

Quote
That does copy all pixels from source to bitmap, after rotating them...

But that makes some "white" pixels...! What I do need is some 'Pixel
precision'...
The trick is to loop over all destination pixels, applying the inverse
transformation ("white" pixels in the source bitmap don't matter). For
some operations that is not that simple, but if you can do it, do it that
way.
--
Jens Gruschel
www.pegtop.net
 

Re:Pixel precision...

A very good trick...
DH
 

Re:Pixel precision...

That seems to me difficult to implement... If you can help...
Here is the case :
I start from Source:TBitmap
I want to paint it according (xy? z? distance) transformation into a
reuslting Target:TBitmap...
I fill the target canvas with a solid color
self._target.Canvas.Brush.Color := clBlue;
self._target.Canvas.FillRect(TVCL.Rect(_target));
I calculate the source center O, and the target center O2 :
_O := TXYZ.D3(self._source.Width * 0.5, self._source.Height * 0.5, 0);
_O2 := TXYZ.D3(self._target.Width * 0.5, self._target.Height * 0.5, 0);
Then, I do loop Source.ScanLine with _y/_x :
for _y
do for _x
do
Here comes the calculation :
_A := TXYZ.DoOffset( _incline,
TXYZ.D3(- _O.x + _O2.x +
_x, - _O.y + _O2.y + _y, 0),
_O2,
osAdd
);
_incline is (xy? z?
DoOffset just adds the _incline to the given point (adjusted for being
centered, distance = zero) and center (O2)...
You can read it as : rotate (x,y,z) with addition of (xy? z?, and take
center at O2...
The Result (_A), is now the projected 3D point of the Source (x,y) point...
so obviously comes the copy of the bytes :
_targetarr :=
self._target.ScanLine[System.Round(_A.y)];
_ix1 := (_target.Width - System.Round(_A.x)) *
3;
_x0 := _x * 3;
_targetarr[_ix1 ] := _bytes[_x0];
_targetarr[_ix1 + 1] := _bytes[_x0 + 1];
_targetarr[_ix1 + 2] := _bytes[_x0 + 2];
Note : the Target's (Height/Width) are forced to be double of highest
(Width/Height) from Source....so no range error/checking...
How to go to inverse ?
That is from Source.ScanLine (x/y), center O2, what operation to compare
with unrotated (x,y), center O ?
DH
Here are the 2D DoIncline and 3D DoOffset functions :
-------------------------------------------------------------
class function TXY.DoIncline(const _value:TDegrees; const _O:TD2; const
_A:TD2):TD2;
var _cos:TReal;
_delta:TD2;
_sin:TReal;
begin
if TXY.IsDefined(_O) and TXY.IsDefined(_A) and
TMeasure.IsDefined(_value)
then begin
_delta.X := _A.X - _O.X;
_delta.Y := _A.Y - _O.Y;
_cos := TAngle.DoCosinus(_value);
_sin := TAngle.DoSinus(_value);
Result := TXY.D2( _cos * _delta.X - _sin * _delta.Y +
_O.X,
_sin * _delta.X + _cos * _delta.Y +
_O.Y
);
end
else Result := TXY.ValueLessD2;
end;
class function TXYZ.DoOffset(const _value:TD3Incline; const _A:TD3; const
_O:TD3; const _style:TOffsetStyles):TD3;
begin
if TXYZ.IsDefined(_O) and TXYZ.IsDefined(_A) and TXYZ.IsDefined(_value)
then begin
with TXY.DoIncline( _value.xy * IIF(_style = osAdd,
1, -1),
TXY.D2(_O.x, _O.y),
TXY.D2(_A.x, _A.y)
)
do begin
Result.x := y;
Result.y := x;
Result.z := _A.z;
end;
with TXY.DoIncline( _value.z * IIF(_style = osAdd, 1, -1),
TXY.D2(_O.y, _O.z),
TXY.D2(Result.y, Result.z)
)
do begin
Result.x := Result.x;
Result.y := x;
Result.z := y;
end;
end
else Result := TXYZ.ValueLessD3;
end;
 

Re:Pixel precision...

All this stuff is already figured out many times, e.g. in Graphics32. See
GR32_Transforms unit.
Nils
"David HAROUCHE" <XXXX@XXXXX.COM>schreef in bericht
Quote
That seems to me difficult to implement... If you can help...

Here is the case :

I start from Source:TBitmap
I want to paint it according (xy? z? distance) transformation into a
reuslting Target:TBitmap...

I fill the target canvas with a solid color

self._target.Canvas.Brush.Color := clBlue;
self._target.Canvas.FillRect(TVCL.Rect(_target));

I calculate the source center O, and the target center O2 :

_O := TXYZ.D3(self._source.Width * 0.5, self._source.Height * 0.5,
0);
_O2 := TXYZ.D3(self._target.Width * 0.5, self._target.Height * 0.5,
0);

Then, I do loop Source.ScanLine with _y/_x :

for _y
do for _x
do

Here comes the calculation :
_A := TXYZ.DoOffset( _incline,
TXYZ.D3(- _O.x + _O2.x +
_x, - _O.y + _O2.y + _y, 0),
_O2,
osAdd
);

_incline is (xy? z?
DoOffset just adds the _incline to the given point (adjusted for being
centered, distance = zero) and center (O2)...

You can read it as : rotate (x,y,z) with addition of (xy? z?, and take
center at O2...

The Result (_A), is now the projected 3D point of the Source (x,y)
point...

so obviously comes the copy of the bytes :

_targetarr :=
self._target.ScanLine[System.Round(_A.y)];

_ix1 := (_target.Width - System.Round(_A.x)) *
3;
_x0 := _x * 3;

_targetarr[_ix1 ] := _bytes[_x0];
_targetarr[_ix1 + 1] := _bytes[_x0 + 1];
_targetarr[_ix1 + 2] := _bytes[_x0 + 2];

Note : the Target's (Height/Width) are forced to be double of highest
(Width/Height) from Source....so no range error/checking...

How to go to inverse ?

That is from Source.ScanLine (x/y), center O2, what operation to compare
with unrotated (x,y), center O ?

DH

Here are the 2D DoIncline and 3D DoOffset functions :
-------------------------------------------------------------

class function TXY.DoIncline(const _value:TDegrees; const _O:TD2; const
_A:TD2):TD2;

var _cos:TReal;
_delta:TD2;
_sin:TReal;

begin
if TXY.IsDefined(_O) and TXY.IsDefined(_A) and
TMeasure.IsDefined(_value)
then begin
_delta.X := _A.X - _O.X;
_delta.Y := _A.Y - _O.Y;

_cos := TAngle.DoCosinus(_value);
_sin := TAngle.DoSinus(_value);

Result := TXY.D2( _cos * _delta.X - _sin * _delta.Y +
_O.X,
_sin * _delta.X + _cos * _delta.Y +
_O.Y
);
end
else Result := TXY.ValueLessD2;
end;

class function TXYZ.DoOffset(const _value:TD3Incline; const _A:TD3; const
_O:TD3; const _style:TOffsetStyles):TD3;

begin
if TXYZ.IsDefined(_O) and TXYZ.IsDefined(_A) and
TXYZ.IsDefined(_value)
then begin
with TXY.DoIncline( _value.xy * IIF(_style = osAdd,
1, -1),
TXY.D2(_O.x, _O.y),
TXY.D2(_A.x, _A.y)
)
do begin
Result.x := y;
Result.y := x;
Result.z := _A.z;
end;

with TXY.DoIncline( _value.z * IIF(_style = osAdd,
1, -1),
TXY.D2(_O.y, _O.z),
TXY.D2(Result.y, Result.z)
)
do begin
Result.x := Result.x;
Result.y := x;
Result.z := y;
end;
end
else Result := TXYZ.ValueLessD3;
end;



 

Re:Pixel precision...

Thx
I take a look...and I will give it back....
DH
"Nils Haeck" <XXXX@XXXXX.COM>a écrit dans le message de
Quote
All this stuff is already figured out many times, e.g. in Graphics32. See
GR32_Transforms unit.

Nils

"David HAROUCHE" <XXXX@XXXXX.COM>schreef in bericht
news:XXXX@XXXXX.COM...
>That seems to me difficult to implement... If you can help...
>
>Here is the case :
>
>I start from Source:TBitmap
>I want to paint it according (xy? z? distance) transformation into a
>reuslting Target:TBitmap...
>
>I fill the target canvas with a solid color
>
>self._target.Canvas.Brush.Color := clBlue;
>self._target.Canvas.FillRect(TVCL.Rect(_target));
>
>I calculate the source center O, and the target center O2 :
>
>_O := TXYZ.D3(self._source.Width * 0.5, self._source.Height * 0.5,
>0);
>_O2 := TXYZ.D3(self._target.Width * 0.5, self._target.Height * 0.5,
>0);
>
>Then, I do loop Source.ScanLine with _y/_x :
>
>for _y
>do for _x
>do
>
>Here comes the calculation :
>_A := TXYZ.DoOffset( _incline,
>TXYZ.D3(- _O.x + _O2.x
+
>_x, - _O.y + _O2.y + _y, 0),
>_O2,
>osAdd
>);
>
>_incline is (xy? z?
>DoOffset just adds the _incline to the given point (adjusted for being
>centered, distance = zero) and center (O2)...
>
>You can read it as : rotate (x,y,z) with addition of (xy? z?, and take
>center at O2...
>
>The Result (_A), is now the projected 3D point of the Source (x,y)
>point...
>
>so obviously comes the copy of the bytes :
>
>_targetarr :=
>self._target.ScanLine[System.Round(_A.y)];
>
>_ix1 := (_target.Width - System.Round(_A.x))
*
>3;
>_x0 := _x * 3;
>
>_targetarr[_ix1 ] := _bytes[_x0];
>_targetarr[_ix1 + 1] := _bytes[_x0 + 1];
>_targetarr[_ix1 + 2] := _bytes[_x0 + 2];
>
>Note : the Target's (Height/Width) are forced to be double of highest
>(Width/Height) from Source....so no range error/checking...
>
>How to go to inverse ?
>
>That is from Source.ScanLine (x/y), center O2, what operation to compare
>with unrotated (x,y), center O ?
>
>DH
>
>Here are the 2D DoIncline and 3D DoOffset functions :
>-------------------------------------------------------------
>
>class function TXY.DoIncline(const _value:TDegrees; const _O:TD2; const
>_A:TD2):TD2;
>
>var _cos:TReal;
>_delta:TD2;
>_sin:TReal;
>
>begin
>if TXY.IsDefined(_O) and TXY.IsDefined(_A) and
>TMeasure.IsDefined(_value)
>then begin
>_delta.X := _A.X - _O.X;
>_delta.Y := _A.Y - _O.Y;
>
>_cos := TAngle.DoCosinus(_value);
>_sin := TAngle.DoSinus(_value);
>
>Result := TXY.D2( _cos * _delta.X - _sin * _delta.Y
+
>_O.X,
>_sin * _delta.X + _cos * _delta.Y
+
>_O.Y
>);
>end
>else Result := TXY.ValueLessD2;
>end;
>
>class function TXYZ.DoOffset(const _value:TD3Incline; const _A:TD3;
const
>_O:TD3; const _style:TOffsetStyles):TD3;
>
>begin
>if TXYZ.IsDefined(_O) and TXYZ.IsDefined(_A) and
>TXYZ.IsDefined(_value)
>then begin
>with TXY.DoIncline( _value.xy * IIF(_style = osAdd,
>1, -1),
>TXY.D2(_O.x, _O.y),
>TXY.D2(_A.x, _A.y)
>)
>do begin
>Result.x := y;
>Result.y := x;
>Result.z := _A.z;
>end;
>
>with TXY.DoIncline( _value.z * IIF(_style = osAdd,
>1, -1),
>TXY.D2(_O.y, _O.z),
>TXY.D2(Result.y, Result.z)
>)
>do begin
>Result.x := Result.x;
>Result.y := x;
>Result.z := y;
>end;
>end
>else Result := TXYZ.ValueLessD3;
>end;
>
>
>


 

Re:Pixel precision...

"David HAROUCHE" <XXXX@XXXXX.COM>writes
Quote
Thx

I take a look...and I will give it back....

DH

<LARGE SNIP>
HI David, you need to stop overquoting in your replies. You only added 3
new lines of text (and two blank lines), but you still included all the rest
of the largish test below it!
Overquoting is against the borland newsgroups guidelines.
cheers,
Paul