Comments (15)
Are you outputting PNG images and that's what you are looking at? Are you showing the image object inside a GUI? What GUI framework? Which version of python? Given that the python 3 support is much less tested than the python 2 version of the library I'd be curious if switching from 3 to 2 changes your results.
Also what OS?
from aggdraw.
Thanks for the quick response! This is running on Python 2.7 on macOS (10.11), and is being rendered to a PyOpenGL context that's created with PySDL2. It's a runtime environment for cognitive psychology experiments, and all shape drawing is done with aggdraw as a back-end (my pictures are just screenshots).
The relevant drawing code is a bit complicated since there's a "shape object" class and a bunch of subclasses with their own drawing methods, but here's the simplified version:
# create drawing context
self.canvas = Image.new("RGBA", self.dimensions, (0, 0, 0, 0))
self.surface = Draw(self.canvas)
self.surface.setantialias(True)
# create fill
if len(color)==3: # fill colour is given in in object init
color += [255]
self.fill = Brush(tuple(color[:3]), color[3])
# draw shape
self.surface.ellipse([x1, y1, x2, y2], self.stroke, self.fill) # x1, y1, etc. are generated based on given shape dimensions
self.surface.flush() # flush aggdraw drawings to Pillow Image context
self.rendered = numpy.asarray(self.canvas) # render Pillow image to numpy array for PyOpenGL
I'll have to check and see if it still behaves the same if I'm drawing directly to an aggdraw-created context without the Pillow "canvas". For the time being, a workaround that half-fixes it is to create the draw context image with the fill colour of the shape I'm drawing (e.g. Image.new("RGBA", self.dimensions, (192, 192, 192, 0))
makes my example in my original post work as expected).
from aggdraw.
Is there a reason you have your background fill with an alpha of 0? I get similar results to you in my own tests, but if I set the alpha of the Image to 255
then the results make a lot more sense. I'm not sure you can have predictable results when you are saving a transparent image...right?
from aggdraw.
Here is my example code:
import aggdraw
from PIL import Image
im = Image.new("RGBA", (100, 100), (255, 255, 255, 255))
draw = aggdraw.Draw(im)
draw.setantialias(True)
fill = aggdraw.Brush((255, 255, 0, 128))
draw.ellipse((25, 25, 75, 75), 2, fill)
draw.flush()
I've swapped the image fill from black to white and 0 to 255 alpha and I'm kind of wondering if the color of a transparent shape over a transparent background is a little undefined.
from aggdraw.
Or what if you use (255, 255, 255, 0)
as the background? Does that make more sense as a result?
from aggdraw.
Also FYI I get the same results on python 2 and 3 with the version of aggdraw on master (no current changes from last PyPI release).
from aggdraw.
I get this weird affect without using PIL directly and just using aggdraw's Draw
. I wonder if this is a bug in the C++ agg library. aggdraw
does use a pretty old version. It is possible something like this has been fixed. It would be difficult to update aggdraw though.
from aggdraw.
The background fill has an alpha of 0 because the generated images are being used as textures by OpenGL, which handles transparency itself (i.e. all shapes and text in my screenshots above are rendered as textures and are then drawn to the display buffer). In order for overlapping textures to be able to blend, they need to be RGBA. Using a background with full opacity results in everything having a square of the background fill colour around it:
If I use (255, 255, 255, 0)
as the background, the texture gets brighter than it should be if there's any transparency in the shape drawn on it. If set the 'RGB' values of the background are set to the values of the Brush used to draw on it, the opacity works as expected.
Maybe AGG isn't set up to handle transparency properly when drawing to a surface with an alpha channel, so it just uses the same logic as if it's drawing to one with full opacity (i.e blending the brush colour with the background colour)? On a surface with 0 opacity I'd expect it to draw with the unaltered given Brush/Pen colour but with the opacity given (with results like I got with my hacky numpy workaround), but I'm not sure how the logic would work for something being drawn on a surface with, say, half-transparency.
from aggdraw.
There's one fork of aggdraw with the backend updated to AGG 2.4 I've come across, I'll test it out and see if it works. Unfortunately it also has different line join properties (rounded corners by default) which make it not really work as a drop-in replacement for existing projects.
EDIT: Nope, using the 2.4-based aggdraw doesn't fix it either.
from aggdraw.
@a-hurst This should hopefully be fixed in the current master branch and v1.3.1 release I just made. If you get a chance let me know how it goes.
from aggdraw.
@a-hurst I just noticed this is still open. Have you tested this lately? Does this work?
from aggdraw.
@a-hurst sorry, I realize it's been a while since you provided a potential fix and I never tested it. In my own code I used the workaround I mentioned above of setting the canvas RGB values to the RGB values of for the shape drawn on it to make everything look right, so since it was working fine that way I'd forgotten about this.
I just tested this again with 1.3.8, and unfortunately it looks like the bug is still present. Here's a screenshot of a paradigm where the Brush for the black shapes is set to 25% transparency ([0, 0, 0, 64]). Here's what it looks like when the Image.new canvas is created with a background colour of (0, 0, 0, 0):
Here's the exact same thing, except the Image.new canvas is created with a background colour of (255, 255, 255, 0):
I should really come up with a minimum reproducible example for this, but the above at least illustrates the issue.
from aggdraw.
Ok thanks. I reread this whole issue and now re-remember what is going on. This is very likely a bug in agg underneath. Even worse is that you said the agg 2.4 fork of this repository didn't fix your issue. That is really our only solution right now. Maybe if we can get this down to some low-level agg calls we can figure this out.
Note: I want to do something similar to this with our satpy library where we draw a ton of lines on an image with a transparent background and then burn the lines on to another image later (or cache the lines on disk). I'm not sure we need transparent lines so we may not run in to the same issue.
from aggdraw.
While trying to dig up info on the Brush size regression w/ the move to 2.4 (i.e. the larger asterisk in #61), I accidentally stumbled upon this, which I think finally explains this bug: https://sourceforge.net/p/agg/discussion/118993/thread/859d8954/
Basically, the expected type of alpha handling here only works if the destination layer format is pixfmt_rgba32_pre, whereas aggdraw's just using regular pixfmt_rgba32 for RGBA shapes. I'll have to look at the docs a bit more to understand how it differs (and whether it would be easy to substitute for pixfmt_rgba32 in aggdraw's case), but at least now we know why this is happening!
from aggdraw.
Wow! Great find. Any idea what has to happen in the code to make this work?
Side note: What are we going to do about the website being gone?
from aggdraw.
Related Issues (20)
- multline text not supported HOT 1
- Line anti-aliasing issues due to missing sRGB mishandling HOT 5
- Resolve differences after agg 2.2 and agg 2.4 migration HOT 3
- aggdraw.Draw, aggdraw.Pen, aggdraw.Brush, etc... are not extendable (apparently) HOT 1
- Cannot install on Windows HOT 2
- MNT: Stop using ci-helpers in appveyor.yml HOT 1
- documentation has left the chat. HOT 1
- Latest Documentation? HOT 7
- pip install results in error Windows 10 21H1 HOT 4
- aggdraw does not some to be able to find fonts when installed in a venv HOT 3
- No arc symbols? HOT 1
- is there a way to draw squircle (rectangle with rounded edges) ? HOT 4
- Add support to release linux aarch64 wheels HOT 3
- PyPy3.8 support HOT 6
- Windows binaries are missing for aggdraw 1.3.13 on pypi.org HOT 4
- The value in the coordinates list cannot exceed 32767. HOT 1
- Diferences between pip version and source-compiled version HOT 4
- Misleading information in the document HOT 6
- freetype not linked correctly in latest macOS Python 3.11 wheels (1.3.17 and 1.3.18) HOT 19
- Python 3.12 support HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from aggdraw.