Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
gegl
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
104
Issues
104
List
Boards
Labels
Milestones
Merge Requests
5
Merge Requests
5
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
GNOME
gegl
Commits
7fee74fc
Commit
7fee74fc
authored
Jul 22, 2017
by
Øyvind "pippin" Kolås
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
transform: remove outdated comment and simplify code
parent
600d10a0
Changes
1
Hide whitespace changes
Inline
Sidebyside
Showing
1 changed file
with
14 additions
and
119 deletions
+14
119
operations/transform/transformcore.c
operations/transform/transformcore.c
+14
119
No files found.
operations/transform/transformcore.c
View file @
7fee74fc
...
...
@@ 833,141 +833,38 @@ transform_affine (GeglOperation *operation,
GEGL_ACCESS_WRITE
,
GEGL_ABYSS_NONE
);
/*
* This code uses a (novel?) trick by Nicolas Robidoux that
* minimizes tile buffer reallocation when affine transformations
* "flip" things.
*
* Explanation:
*
* Pulling a scanline (within such a square tile) back to input
* space (with the inverse transformation) with an arbitrary
* affine transformation may make the scanline go from right to
* left in input space even though it goes form left to right in
* input space. Similarly, a scanline which is below the first one
* in output space may be above in input space. Unfortunately,
* input buffer tiles are allocated with a bias: less elbow room
* around the context_rect (square of data needed by the sampler)
* is put at the left and top than at the right and bottom. (Such
* asymetrical elbow room is beneficial when resizing, for
* example, since input space is then traversed from left to right
* and top to bottom, which means that the left and top elbow room
* is not used in this situation.) When the affine transformation
* "flips" things, however, the elbow room is "on the wrong side",
* and for this reason such transformations run much much slower
* because many more input buffer tiles get created. One way to
* make things better is to traverse the output buffer tile in an
* appropriate chosen "reverse order" so that the "short" elbow
* room is "behind" instead of "ahead".
*
* Things are actually a bit more complicated than that. Here is a
* terse description of what's actually done, without a full
* explanation of why.
*
* Let's consider a scanline of the output tile which we want to
* fill. Pull this scanline back to input space. Assume that we
* are using a freshly created input tile. What direction would
* maximize the number of pulled back input pixels that we can fit
* in the input tile? Because the input tile is square and most of
* the extra elbow room is at the bottom and right, the "best"
* direction is going down the diagonal of the square,
* approximately from top left to bottom right of the tile.
*
* Of course, we do not have control over the actual line traced
* by the output scanline in input space. But what the above tells
* us is that if the inner product of the pulled back "scanline
* vector" with the vector (1,1) (which corresponds to going
* diagonally from topleft to bottomright in a square tile) is
* negative, we are going opposite to "best". This can be
* rectified by filling the output scanline in reverse order: from
* right to left in output space.
*
* Similarly, when one computes the next scanline, one can ask
* whether it's the one above or below in output space which is
* most likely to "stick out". Repeating the same argument used
* for a single scanline, we see that the sign of the inner
* product of the inverse image of the vector that points straight
* down in output space with the input space vector (1,1) tells us
* whether we should fill the output tile from the top down or
* from the bottom up.
*
* Making the "best" happen requires stepping in the "right
* direction" both w.r.t. to data pointers and geometrical steps.
* In the following code, adjusting the "geometrical steps" so they
* go in the right direction is done by modifying the inverse
* Jacobian matrix to minimize the number of "geometrical
* quantities" floating around. It could be done leaving the
* Jacobian matrix alone.
*/
/*
* Set the inverse_jacobian matrix (a.k.a. scale) for samplers
* that support it. The inverse jacobian will be "flipped" if the
* direction in which the ROI is filled is flipped. Flipping the
* inverse jacobian is not necessary for the samplers' sake, but
* it makes the following code shorter. Anyway, "sane" use of the
* inverse jacobian by a sampler only cares for its effect on
* sets: only the image of a centered square with sides aligned
* with the coordinate axes, or a centered disc, matters,
* irrespective of orientation ("lefthand" VS "righthand")
* issues.
*/
#if 0
const gint flip_x =
inverse.coeff [0][0] + inverse.coeff [1][0] < (gdouble) 0.
?
(gint) 1
:
(gint) 0;
const gint flip_y =
inverse.coeff [0][1] + inverse.coeff [1][1] < (gdouble) 0.
?
(gint) 1
:
(gint) 0;
#else
/* XXX: not doing the flipping tricks is faster with the adaptive
* sampler cache that has been added */
const
gint
flip_x
=
0
;
const
gint
flip_y
=
0
;
#endif
/*
* Hoist most of what can out of the while loop:
*/
const
gdouble
base_u
=
inverse
.
coeff
[
0
][
0
]
*
((
gdouble
)
0
.
5

flip_x
)
+
inverse
.
coeff
[
0
][
1
]
*
((
gdouble
)
0
.
5

flip_y
)
+
const
gdouble
base_u
=
inverse
.
coeff
[
0
][
0
]
*
((
gdouble
)
0
.
5
)
+
inverse
.
coeff
[
0
][
1
]
*
((
gdouble
)
0
.
5
)
+
inverse
.
coeff
[
0
][
2
];
const
gdouble
base_v
=
inverse
.
coeff
[
1
][
0
]
*
((
gdouble
)
0
.
5

flip_x
)
+
inverse
.
coeff
[
1
][
1
]
*
((
gdouble
)
0
.
5

flip_y
)
+
const
gdouble
base_v
=
inverse
.
coeff
[
1
][
0
]
*
((
gdouble
)
0
.
5
)
+
inverse
.
coeff
[
1
][
1
]
*
((
gdouble
)
0
.
5
)
+
inverse
.
coeff
[
1
][
2
];
inverse_jacobian
.
coeff
[
0
][
0
]
=
flip_x
?

inverse
.
coeff
[
0
][
0
]
:
inverse
.
coeff
[
0
][
0
];
inverse
.
coeff
[
0
][
0
];
inverse_jacobian
.
coeff
[
1
][
0
]
=
flip_x
?

inverse
.
coeff
[
1
][
0
]
:
inverse
.
coeff
[
1
][
0
];
inverse
.
coeff
[
1
][
0
];
inverse_jacobian
.
coeff
[
0
][
1
]
=
flip_y
?

inverse
.
coeff
[
0
][
1
]
:
inverse
.
coeff
[
0
][
1
];
inverse
.
coeff
[
0
][
1
];
inverse_jacobian
.
coeff
[
1
][
1
]
=
flip_y
?

inverse
.
coeff
[
1
][
1
]
:
inverse
.
coeff
[
1
][
1
];
inverse
.
coeff
[
1
][
1
];
while
(
gegl_buffer_iterator_next
(
i
))
{
GeglRectangle
*
roi
=
&
i
>
roi
[
0
];
gfloat
*
restrict
dest_ptr
=
(
gfloat
*
)
i
>
data
[
0
]
+
(
gint
)
4
*
(
flip_x
*
(
roi
>
width

(
gint
)
1
)
+
flip_y
*
(
roi
>
height

(
gint
)
1
)
*
roi
>
width
);
gfloat
*
restrict
dest_ptr
=
(
gfloat
*
)
i
>
data
[
0
];
gdouble
u_start
=
base_u
+
inverse
.
coeff
[
0
][
0
]
*
(
roi
>
x
+
flip_x
*
roi
>
width
)
+
inverse
.
coeff
[
0
][
1
]
*
(
roi
>
y
+
flip_y
*
roi
>
height
);
inverse
.
coeff
[
0
][
0
]
*
(
roi
>
x
)
+
inverse
.
coeff
[
0
][
1
]
*
(
roi
>
y
);
gdouble
v_start
=
base_v
+
inverse
.
coeff
[
1
][
0
]
*
(
roi
>
x
+
flip_x
*
roi
>
width
)
+
inverse
.
coeff
[
1
][
1
]
*
(
roi
>
y
+
flip_y
*
roi
>
height
);
inverse
.
coeff
[
1
][
0
]
*
(
roi
>
x
)
+
inverse
.
coeff
[
1
][
1
]
*
(
roi
>
y
);
gint
y
=
roi
>
height
;
do
{
...
...
@@ 981,14 +878,12 @@ transform_affine (GeglOperation *operation,
&
inverse_jacobian
,
dest_ptr
,
GEGL_ABYSS_NONE
);
dest_ptr
+=
(
gint
)
4

(
gint
)
8
*
flip_x
;
dest_ptr
+=
(
gint
)
4
;
u_float
+=
inverse_jacobian
.
coeff
[
0
][
0
];
v_float
+=
inverse_jacobian
.
coeff
[
1
][
0
];
}
while
(

x
);
dest_ptr
+=
(
gint
)
8
*
(
flip_x

flip_y
)
*
roi
>
width
;
u_start
+=
inverse_jacobian
.
coeff
[
0
][
1
];
v_start
+=
inverse_jacobian
.
coeff
[
1
][
1
];
}
while
(

y
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment