-
-
Notifications
You must be signed in to change notification settings - Fork 52
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
JImage
Implementation for J-Objects
#399
base: main
Are you sure you want to change the base?
Conversation
Codecov Report
@@ Coverage Diff @@
## master #399 +/- ##
==========================================
- Coverage 96.13% 95.63% -0.51%
==========================================
Files 35 36 +1
Lines 1527 1535 +8
==========================================
Hits 1468 1468
- Misses 59 67 +8
Continue to review full report at Codecov.
|
src/shorthands/JImage.jl
Outdated
clipshape(clipargs...) | ||
function _JImage(pos, img, centering, shapeargs, shape) | ||
if shape != false | ||
shape(shapeargs...) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One minor thing:
I think we should mention(in the docstring) that shape
should be a valid Luxor shape(a luxor function).
eg: rect, box, poly etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"valid Luxor shape" I'm not aware of this concept. :) Do you mean a built-in Luxor function - eg one that constructs paths, or one that generates points for polygons...? (Not trying to be awkward, just I get worried in case I'm not providing the tools you folks need for your cool constructions!)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean a built-in Luxor function - eg one that constructs paths
Yeah! We need shape to be a valid luxor function. Since a user may interpret it as entering a full shape name eg: rectangle instead of rect
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We mean any kind of function either their own or more likely a Luxor drawing function. Mostly those which provide the clipping action (so yeah a drawing function 😂)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, yes. Perhaps any function that has an action
parameter/keyword...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another thing I want to mention is that shape
should by typed to Method
.
eg: If there's a variable circle = Object(...)
, and user passes circle as an argument, it will throw the Objects of type Javis.Object are not callable
error and maybe use a try catch block to give out a better error message?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea - error handling is something we need to reckon with @Sov-trotter . I agree with your thoughts and will see what I can do.
@Wikunia and @Ved-Mahajan - I think the interface for Object(
JImage(
pos = O,
img = readpng("my_picture.png"),
centering = true;
shapeargs = (pt = O, r = 40, action = :clip),
shape = circle,
scaleargs = .5
),
) What is left to do is add documentation and tests as of this moment. Anything else you guys can think of? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some small comments for improvement and clarification/docstrings.
Can do another review after test cases are added.
src/shorthands/JImage.jl
Outdated
if shape != false | ||
shape(shapeargs...) | ||
end | ||
scale(scaleargs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would really like to have automatic scaling by checking the size of the shape and that of the image.
For the shape it would be awesome to be able to call it with :clip
/ :path
automatically but it seems action
isn't always a keyword argument which makes that a bit hard. Any idea on that @cormullion ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, following on from my question (#399 (comment)) not all graphic construction functions are similar in having an action keyword. We'd have to compile a list and see which ones could be updated...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you interested in standardizing the functions though such that all have an option which provide using the action
as a kwarg?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps we can make a list of possible functions as an issue at Luxor.jl. It might be easy or not, not too sure how many are affected...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since this spawned off another issue, shall we resolve this comment @Wikunia and @cormullion ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I decided to close this conversation as I do not think automatic scaling is feasible as all shapes can define a bounding box differently within Luxor.
To find that bounding box for a shape depends on the arguments provided by such a shape.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can find a BoundingBox for a lot of "shapes" using eg pathtopoly()
:
@draw begin
circle(O, 100, :stroke)
circle(O, 100, :path)
bbox = BoundingBox(pathtopoly()[1])
box(bbox, :stroke)
end
If you can convert a shape to a polygon, then you can get a bounding box that way. Are there any other shapes in Luxor that you'd like BoundingBox to work on?
Sorry I kinda missed your example from the PR text. I think that looks great. I was wondering whether we could combine it with the other
|
You should be able to use Luxor 2.16 now and use |
This is nearly ready for merging, but somehow the CI is failing and I am having trouble running the test suite locally on my own machine. Thoughts @Wikunia ? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just some minor things. I assume #455 fixes your test cases
true; | ||
shape = circle, | ||
shapeargs = nothing, | ||
scaleargs = 1, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add another test case with different shapeargs and different scale args.
- `img::String`: Expects the path to an image | ||
- `centering::Bool`: Centers the object at `pos` | ||
- `shapeargs`: Arguments to be passed to a given shape type | ||
- `shape`: A Luxor shape function such as `circle`, `box`, etc. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would have shape
before shapeargs
and maybe add an example which shows what shapeargs
and scaleargs
do?
Hey @Wikunia , yes, that would help here as well as @cormullion pointing out a nice method that can help with automatic scaling! |
I think using bounding boxes might be an easy way to fit images into shapes. Here's some pseudo code: # determine BoundingBox:
bbox = BoundingBox(box(O, 100, 100) # a simple rect
center = Point(60, -20)
radius = 120
bbox = BoundingBox(box(center, 2radius, 2radius)) # or a circle
bbox = BoundingBox(star(O, 100, 6, 0.5, vertices=true)) # or a poly
bbox = BoundingBox(first(pathtopoly())) # or the current path
# get image
img = readpng(...)
# calculate a scale factor, after determining whether you're fitting the
# image (to see all of it) or filling (to occupy all the shape):
imagefit = true
if imagefit
boxside = max(boxwidth(bbox), boxheight(bbox))
imageside = max(img.width, img.height)
else
boxside = min(boxwidth(bbox), boxheight(bbox))
imageside = min(img.width, img.height)
end
scalefactor = boxside/imageside
# draw clipping shape here
# finally place the image
@layer begin
translate(boxmiddlecenter(bbox))
scale(scalefactor)
placeimage(img, centered=true)
end Not sure if this reliably works in all situations or in your Javis framework though... :) |
Hey @cormullion , |
Codecov Report
@@ Coverage Diff @@
## master #399 +/- ##
===========================================
- Coverage 96.26% 26.92% -69.34%
===========================================
Files 36 35 -1
Lines 1634 1608 -26
===========================================
- Hits 1573 433 -1140
- Misses 61 1175 +1114
Continue to review full report at Codecov.
|
Hey @cormullion , So, I ran into the problem that I have been running into with different shape type functions. P.S. Here are the shapes I have found that do not support building a
And instead return a |
Unfortunately So I've added a return statement to julia> circle(O, 10, :path)
(Point(-10.0, -10.0), Point(10.0, 10.0)) So you can now go: @draw begin
pt1, pt2 = circle(O, 100, :stroke)
box(BoundingBox(pt1, pt2), action=:stroke)
end or even @draw begin
circle(O, 100, :stroke)
bbox = BoundingBox(circle(O, 100))
box(bbox, :stroke)
end and similarly for
I suppose these are breaking changes (if anyone is relying on circle returning a Boolean...!). Perhaps we'll go for Luxor 3.0! Please check it out on the current Luxor! |
@Wikunia - I have a potentially radical new proposal based on some thoughts you had earlier for this PR: What if instead of adding a |
Hey everyone! Object(
31:45,
JPoly(
[Point(-100, 0), Point(0, -100), Point(100, 0), Point(80, 100), Point(-80, 100)],
"white",
1,
:fill,
true,
false,
"../test/refs/dispatch.png",
:inset,
),
) As I was working through this syntax, it made me wonder if @cormullion , would you be opposed to me making a Luxor PR to allow image placement inside of shapes such as @Wikunia , what do you think of this syntax? Finally, here is code and a gif demonstrating some of the functionality: Object(1:15, JBox(O, 200, 200, "white", :clip, false, "../test/refs/dispatch.png", :inset))
Object(
16:30,
JStar(O, 200, "white", 1, 5, 0.5, 0, :fill, false, "../test/refs/dispatch.png", :clip),
)
Object(
31:45,
JPoly(
[Point(-100, 0), Point(0, -100), Point(100, 0), Point(80, 100), Point(-80, 100)],
"white",
1,
:fill,
true,
false,
"../test/refs/dispatch.png",
:inset,
),
) Also of note, this functionality will require the latest version of Luxor which I know will break morphing sadly..... 😢 |
Why does the latest Luxor break morphing? |
Haha, yes, probably (opposed), initially! 🤣🤣 Well, you'd have to persuade me - it would certainly be something that would need a fair bit of justification, to take account of the increased complexity, maintenance burden, introduction of (more) inconsistencies, testing, documentation, and so on., assuming there's no performance impact. But if you make a testable PR (with some benchmarks), we could discuss it... |
Hey @Wikunia ! This is ready for review! Here is sample code to use to test out this feature's functionality: using Javis
video = Video(400, 400)
origin(Point(200, 200))
function ground(args...)
background("black")
sethue("white")
end
Background(1:90, ground)
Object(1:15, JBox(O, 200, 200, "white", :clip, false, "../test/refs/dispatch.png", :inset))
Object(
16:30,
JStar(O, 200, "white", 1, 5, 0.5, 0, :fill, false, "../test/refs/dispatch.png", :clip),
)
Object(
31:45,
JPoly(
[Point(-100, 0), Point(0, -100), Point(100, 0), Point(80, 100), Point(-80, 100)],
"white",
1,
:fill,
true,
false,
"../test/refs/dispatch.png",
:inset,
),
)
Object(46:60, JEllipse(O, 200, 100, "white", 1, :fill, "../test/refs/dispatch.png", :inset))
Object(61:75, JCircle(O, 100, "white", 1, :fill, "../test/refs/dispatch.png", :inset))
Object(76:90, JRect(O, 200, 100, "white", 1, :fill, "../test/refs/dispatch.png", :inset))
render(video; framerate = 5, pathname = "test.gif") Also, @cormullion - that makes complete sense. P.S. @Sov-trotter - I am pinging you as well as this is somewhat altering the utilization of your J-Objects syntax. |
I currently can't run your test as I get the error which also seems to appear in the test cases:
|
@@ -39,3 +39,58 @@ JCircle(p1::Point, p2::Point; kwargs...) = | |||
JCircle(midpoint(p1, p2), distance(p1, p2) / 2; kwargs...) | |||
|
|||
JCircle(radius::Real; kwargs...) = JCircle(O, radius; kwargs...) | |||
|
|||
""" | |||
TODO: Add Documentation! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
currently I have no idea what :inset
and :clip
mean to be honest 😄
Seems like :clip
positions the image somewhere else but I don't really have the option to move the image or have I?
Also for me a scale_factor
is a number and not a symbol. Maybe scale_type
or something but I would first need to know what they do to give my comment on that 😄
Make sure to update the |
PR Checklist
If you are contributing to
Javis.jl
, please make sure you are able to check off each item on this list:CHANGELOG.md
with whatever changes/features I added with this PR?Project.toml
+ set an upper bound of the dependency (if applicable)?test
directory (if applicable)?Link to relevant issue(s)
Closes #388
How did you address these issues with this PR? What methods did you use?
This is a proposed implementation idea for adding images to J-Objects easily. I was inspired by some of the conversation in #388 and wanted to create something easily like
But could not get this syntax to work as when you have two separate objects - say JCircle which clips a circle shape and JImage - the clipping does occur but as JCircle does not "see" JImage, the expected output (i.e. the JImage is not clipped in a circle shape) does not occur. This PR introduces syntax such that you can write:
Which acts as a fully qualified Javis object (i.e. you can perform actions with it). Furthermore, clipping and outlining can be supported with the following kwarg syntax:
So this picture will be cliipped by passing shapeargs and a Luxor shape function.
Picture of cat from Twitch Artist ChargedAsylum and owner AftonSteps
Disclaimer
I have not added tests or docs as of yet as I am waiting to see what the thought is with this possible syntax.
Pinging @Wikunia and @Sov-trotter for thoughts!