New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Pixel remapping/Swizzling #1115
Comments
As far as I remember our discussion, remapping should actually alter the image. This could be implemented easily in a single |
This comment was marked as spam.
This comment was marked as spam.
This also seems a pretty good candidate to use the value delegate trick (for those unfamiliar, I mean using a |
This comment was marked as spam.
This comment was marked as spam.
This comment was marked as spam.
This comment was marked as spam.
This comment was marked as spam.
This comment was marked as spam.
@Sergio0694 Of course having 2 delegates calling for each coordinate x and y could hit performance in the situation you described. That's why I also included a sample from Kanvas, where a Point struct is just taken in, modified, and then returned. That might at least reduce the delegate count to one. But however you want to implement it, is of course the decision of this team here. I just gave my input on already existing examples for this kind of operation. |
Not sure to fully understand what's supposed to be done for this ticket. My understanding is that we want to:
Am I right? |
@Evangelink yes, the steps are mostly correct, but a few key things missing, for example the extension method. I would do the following: Essential:
API sugar:
Regression tests:
Performance sugar from #1115 (comment):
public static Swizzle<TImageSwizzle>(this IImageProcessingContext context, TImageSwizzle swizzle)
where TImageSwizzle : struct, IImageSwizzle { ... } OFC you may decide to add 8-10 to your implementation immediately. |
FYI @Evangelink in case you were not familiar with these "value delegates" (constrained struct + interface), to add to @antonfirsov's point with respect to 5. and 8., the idea is that once you add the generic constraint, you'd no longer use a You do not want to define a struct with that interface that just wraps some delegate, otherwise that'd defeat the whole point of this optimization (as those calls would remain virtual, just with even more steps due to the extra generic argument). As in (just an example to illustrate the general idea, ignore the actual type names): // Before
class DefaultSwizzle
{
public DefaultSwizzle(Func<Point, Point> swizzler) { }
}
// After
interface ISwizzler
{
Point Swizzle(Point point);
}
class DefaultSwizzle<TSwizzler>
where TSwizzler : struct, ISwizzler
{
public DefaultSwizzle(TSwizzler swizzler) { }
} And following this, you'd have to make the following changes when actually using these types: // Before
var defaultSwizzle = new DefaultSwizzle(xy => /* Some logic... */ xy);
// After
struct MySwizzler : ISwizzler
{
Point Swizzle(Point point) => /* Some logic... */ point;
}
var defaultSwizzle = new DefaultSwizzle<MySwizzler>(default); If you need more examples of this pattern, you can browse the various row processors we use in Hope this helps! 😄 |
Sorry for the delay, I have started to work on this ticket but I'd like some more info. You can see the little I have done so far in the draft PR that I have linked. The first question is functional, I am not sure to understand if the swizzle function we are talking about here is meant to change the value of the pixel at coordinates (x, y) or to provide new coordinates (x', y'). The second part of my questions is technical, and depend upon the previous answer:
|
Provide the new coordinates. If you need better functional understanding I would suggest to look at the OpenCV stuff in the opening post, and maybe try some examples. Are your questions more related to the ImageSharp API suggestions?
See https://github.com/SixLabors/ImageSharp/pull/1388/files#r506247769
You need to work on a new buffer. I would derive from EDIT:
I think it's a better practice to work with Lines 45 to 50 in 78a584e
Processors which do everything in |
@Evangelink I'm sorry, this is total nonsense I told after drinking insufficient amount of coffee. There's no need for resampling for swizzle. |
This feature is implemented in many graphics hardwares at least of most gaming consoles. Adding this feature would enable ImageSharp to natively allow for these specifications of graphics hardware to be supported out of the box.
As per OpenCV naming and implementation this feature is most likely known as "Remapping" or "Point remapping". So as the naming goes, it should incorporate either one.
Point remappings are, as the name suggests, a process to rearrange the pixels from a source to a destination point, where each source point is modified as per following method:
dst(x,y) = src(fx(x,y), fy(x,y))
As for the implementation following this function, it should allow executing an action for both the x- and y-coordinate, and return its modified value respectively. Or an even simpler approach as seen in the Kanvas library of the Kuriimu2 project, where it just takes in a
Point
and returns a new one with the modified coordinates.Sources:
OpenCV documentation on remapping: https://docs.opencv.org/2.4/modules/imgproc/doc/geometric_transformations.html?highlight=remap
Kuriimu2's Kanvas Swizzle interface:https://github.com/FanTranslatorsInternational/Kuriimu2/blob/dev/src/Kontract/Kanvas/IImageSwizzle.cs
The text was updated successfully, but these errors were encountered: