Page 1 of 1

Paths and rectangles off by one pixel.

Posted: 2018-05-22T10:42:00-07:00
by dasprid
So, in advance, already found this old topic, but didn't want to necro it:
http://www.imagemagick.org/discourse-se ... hp?t=14379

I have the exact same problem with both paths and rectangles. Here is the sample code that I used to trace this back:

Code: Select all

<?php
$image = new Imagick();
$image->newImage(10, 10, '#ffffff');
$image->setImageFormat('png');
$draw = new ImagickDraw();

$draw->setFillColor('red');

$draw->pathStart();
$draw->pathMoveToAbsolute(4, 4);
$draw->pathLineToAbsolute(5, 4);
$draw->pathLineToAbsolute(5, 5);
$draw->pathLineToAbsolute(4, 5);
$draw->pathClose();
$draw->pathFinish();

$draw->rectangle(4, 7, 5, 8);

$draw->point(4, 1);

$image->drawImage($draw);
This should ultimately result in three pixels being drawn. But instead you get the single pixel from the point command and two 2x2 rectangles.

As some people in the previous thread explained, this is because apparently ImageMagick does not work with the upper left pixel corners (as SVG and other vector formats do), but instead with full pixels. On the other hand, people in that thread also say that ImageMagick should work exactly like SVG, so this would definitely be a bug then.

Sidenote: according to the current behaviour, to draw a 1x1 rectangle, you'd have to do the following, but the actual result is no output at all:

Code: Select all

$draw->rectangle(4, 7, 4, 7);

Re: Paths and rectangles off by one pixel.

Posted: 2018-05-22T13:29:56-07:00
by snibgo
For those of us who don't use IMagick, it would help if you showed us the output from your code.

Note that when drawing a path from one pixel to an adjacent pixel, both pixels are drawn. But when drawing from one pixel to the same pixel, a "zero-length path", no pixels are drawn. As IM deals with pixels and not really vectors, I would prefer it to draw one pixel, but the decision was made (a long time ago) to stick to the SVG convention.

Your code includes "pathClose", which I suppose is equivalent to SVG "z". So I would expect these pixels to be drawn: 5,4 5,5 4,5 and finally 4,4. Is that what you get?

Yes, the 4,7,4,7 rectangle is blank, because of the SVG convention.

Re: Paths and rectangles off by one pixel.

Posted: 2018-05-22T15:34:41-07:00
by magick
ImageMagick closely follows the SVG standard. The standard does not permit a rectangle width of 0 but since ImageMagick defines two endpoints for a rectangle, it must represent two identical endpoints as a width of 1. We will add a patch to fix this bug, likely by tomorrow.

Re: Paths and rectangles off by one pixel.

Posted: 2018-05-22T19:01:07-07:00
by snibgo
So, if a rectangle from 4,7 to 4,7 should be drawn (as a single pixel) then I guess that similarly a line from 4,7 to 4,7 should also be drawn (as a single pixel)?

Re: Paths and rectangles off by one pixel.

Posted: 2018-05-23T05:01:11-07:00
by magick
If SVG renders a line with identical start and end points as a point, then yes IM should too. Post a short SVG script here that renders a line as a point and we will ensure ImageMagick renders it as a point as well.

Re: Paths and rectangles off by one pixel.

Posted: 2018-05-23T10:07:46-07:00
by dasprid
Okay, here is some example code for that in SVG:

Code: Select all

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" id="svg8" version="1.1" viewBox="0 0 10 10" height="10" width="10">
    <rect y="1" x="1" height="1" width="1" fill="#000000"/>
    <path d="M 3,3 L 4,3 L 4,4 L 3,4 Z" fill="#000000"/>
</svg>
If you open that in an image viewer, you will notice that the path is exactly one by one pixel in size, just like the rectangle: https://s.dasprids.de/WwWfhQ

Here for comparision the result from my PHP code:
https://s.dasprids.de/WwWf0w

Re: Paths and rectangles off by one pixel.

Posted: 2018-05-23T10:09:07-07:00
by dasprid
snibgo wrote:
2018-05-22T13:29:56-07:00
Yes, the 4,7,4,7 rectangle is blank, because of the SVG convention.
So this means that it is impossible to make a one by one pixel rectangle? since 4,7,4,7 results in nothing, but 4,7,5,8 results in a two by two pixel rectangle?

Re: Paths and rectangles off by one pixel.

Posted: 2018-05-23T10:11:11-07:00
by dasprid
snibgo wrote:
2018-05-22T13:29:56-07:00
Your code includes "pathClose", which I suppose is equivalent to SVG "z". So I would expect these pixels to be drawn: 5,4 5,5 4,5 and finally 4,4. Is that what you get?
That's what I get, yes. But according to the SVG standard, I should get only the 4,4 pixel drawn.

Re: Paths and rectangles off by one pixel.

Posted: 2018-05-23T16:18:32-07:00
by dasprid
To make things simpler, here is the CLI code for a 3x3 image white a dot in the center:

Code: Select all

convert -size 3x3 xc:skyblue -stroke None -fill black -draw "path 'M 1,1 L 2,1 2,2 1,2 Z'" test.png
And here is the exact same path in an SVG:

Code: Select all

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" id="svg8" version="1.1" viewBox="0 0 3 3" height="3" width="3">
    <path d="M 1,1 L 2,1 2,2 1,2 Z" fill="#000000"/>
</svg>
As you can see, the result is not the same :)

Re: Paths and rectangles off by one pixel.

Posted: 2018-06-15T01:52:24-07:00
by dasprid
Since there were no more replies on this, I'm going to breach the subject again. Is this considered wanted behaviour to not conform with the SVG standard or is it a bug?

Re: Paths and rectangles off by one pixel.

Posted: 2018-06-16T09:59:26-07:00
by magick
Rendering in ImageMagick was written before we starting adopting the SVG rendering model. It is designed for increased quality of rendering using floating point calculations between a point and the corresponding integer pixel on the image grid. SVG likely uses integer calculations on an integer grid for more efficient rendering speed. We have not found time to adopt our rendering algorithm to match the SVG rendering model. Since ImageMagick is open-source, any user can contribute this port. We may revisit a solution ourselves but it could be sometime before we get to it.

Re: Paths and rectangles off by one pixel.

Posted: 2018-07-17T17:21:51-07:00
by dasprid
I'm meanwhile looking for a solution which works with the current way ImageMagick handles paths, but don't seem to be able to find one. The problem I'm trying to solve: I have an SVG path definition I'm trying to hand over to ImageMagick to draw the same path. This generally works the path points are further apart than one pixel, but when they are exactly one pixel apart, nothing is drawn at all:

Code: Select all

convert -size 3x3 xc:skyblue -stroke None -fill black -draw "path 'M 1,1 L 1,1 1,1 1,1 Z'" test.png
I assume the only way right now to solve this would be to make the image twice as large, draw all path coordinates multiplied by two and then shrink the image back to 50% size? Although that will fail again as soon as the path distance is 0.5 pixels.

Re: Paths and rectangles off by one pixel.

Posted: 2018-07-17T17:49:29-07:00
by fmw42
I think you need to draw it as a point. See the changelog:

2018-05-28 6.9.9-48 Cristy <quetzlzacatenango@image...>
A SVG rectangle with a width and height of 1, is a point.

Same in IM 7

Re: Paths and rectangles off by one pixel.

Posted: 2018-07-18T11:46:15-07:00
by dasprid
The path doesn't have to be a rectangle though, so that wouldn't really help.

Re: Paths and rectangles off by one pixel.

Posted: 2018-07-18T11:49:44-07:00
by fmw42
Sorry, I thought you were asking how to create a 1x1 rectangle that was only one pixel.