Paths and rectangles off by one pixel.

IMagick is a native PHP extension to create and modify images using the ImageMagick API. ImageMagick Studio LLC did not write nor does it maintain the IMagick extension, however, IMagick users are welcome to discuss the extension here.
Post Reply
dasprid
Posts: 12
Joined: 2014-07-12T11:30:52-07:00
Authentication code: 6789

Paths and rectangles off by one pixel.

Post by dasprid » 2018-05-22T10:42:00-07:00

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);

snibgo
Posts: 10829
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Paths and rectangles off by one pixel.

Post by snibgo » 2018-05-22T13:29:56-07:00

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.
snibgo's IM pages: im.snibgo.com

User avatar
magick
Site Admin
Posts: 10849
Joined: 2003-05-31T11:32:55-07:00

Re: Paths and rectangles off by one pixel.

Post by magick » 2018-05-22T15:34:41-07:00

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.

snibgo
Posts: 10829
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Paths and rectangles off by one pixel.

Post by snibgo » 2018-05-22T19:01:07-07:00

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)?
snibgo's IM pages: im.snibgo.com

User avatar
magick
Site Admin
Posts: 10849
Joined: 2003-05-31T11:32:55-07:00

Re: Paths and rectangles off by one pixel.

Post by magick » 2018-05-23T05:01:11-07:00

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.

dasprid
Posts: 12
Joined: 2014-07-12T11:30:52-07:00
Authentication code: 6789

Re: Paths and rectangles off by one pixel.

Post by dasprid » 2018-05-23T10:07:46-07:00

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

dasprid
Posts: 12
Joined: 2014-07-12T11:30:52-07:00
Authentication code: 6789

Re: Paths and rectangles off by one pixel.

Post by dasprid » 2018-05-23T10:09:07-07:00

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?

dasprid
Posts: 12
Joined: 2014-07-12T11:30:52-07:00
Authentication code: 6789

Re: Paths and rectangles off by one pixel.

Post by dasprid » 2018-05-23T10:11:11-07:00

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.

dasprid
Posts: 12
Joined: 2014-07-12T11:30:52-07:00
Authentication code: 6789

Re: Paths and rectangles off by one pixel.

Post by dasprid » 2018-05-23T16:18:32-07:00

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 :)

dasprid
Posts: 12
Joined: 2014-07-12T11:30:52-07:00
Authentication code: 6789

Re: Paths and rectangles off by one pixel.

Post by dasprid » 2018-06-15T01:52:24-07:00

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?

User avatar
magick
Site Admin
Posts: 10849
Joined: 2003-05-31T11:32:55-07:00

Re: Paths and rectangles off by one pixel.

Post by magick » 2018-06-16T09:59:26-07:00

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.

dasprid
Posts: 12
Joined: 2014-07-12T11:30:52-07:00
Authentication code: 6789

Re: Paths and rectangles off by one pixel.

Post by dasprid » 2018-07-17T17:21:51-07:00

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.

User avatar
fmw42
Posts: 24003
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Paths and rectangles off by one pixel.

Post by fmw42 » 2018-07-17T17:49:29-07:00

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

dasprid
Posts: 12
Joined: 2014-07-12T11:30:52-07:00
Authentication code: 6789

Re: Paths and rectangles off by one pixel.

Post by dasprid » 2018-07-18T11:46:15-07:00

The path doesn't have to be a rectangle though, so that wouldn't really help.

User avatar
fmw42
Posts: 24003
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Paths and rectangles off by one pixel.

Post by fmw42 » 2018-07-18T11:49:44-07:00

Sorry, I thought you were asking how to create a 1x1 rectangle that was only one pixel.

Post Reply