ID:2396931
 
BYOND Version:512.1448
Operating System:Linux
Web Browser:Firefox 61.0
Applies to:Dream Daemon
Status: Open

Issue hasn't been assigned a status value.
Descriptive Problem Summary: When creating a new icon at runtime on Linux from a jpg file, using the Width() or Height() procs return 0, regardless of actual image size. This issue does not occur on Windows.

Numbered Steps to Reproduce Problem:
1) Download image test
2) Run image test on Linux. Notice no height/width recorded for the jpg icon. Notice that the jpg icon records a lower left pixel.
3) The image test can also be ran on Windows, notice all icons have width/height.

Code Snippet to Reproduce Problem:
var/icon/picture = icon(file("example.jpg"))
var/height = picture.Height()
var/width = picture.Width()


Expected Results: For icons generated with .jpg images to have working width/height procs in Linux.

Actual Results: Icons generated with .jpg images always return 0 in Linux.

Does the problem occur:
Every time? Or how often? Everytime.
In other games? Untested.
In other user accounts? Untested.
On other computers? Untested.

When does the problem NOT occur? The problem does not occur with other image formats (.png, .gif, .dmi was tested).

Did the problem NOT occur in any earlier versions? If so, what was the last version that worked? Untested.

Workarounds: Use Windows or the following snippet when determining sizes on .jpg images.:
proc
jpgwidth(var/icon/I)
if(istype(I))
while(I.GetPixel(.+1,1) != null)
.++

jpgheight(var/icon/I)
if(istype(I))
while(I.GetPixel(1,.+1) != null)
.++


If you clear the cache, host in Dream Daemon on Windows, and join in a separate Dream Seeker instance, does the problem happen there as well?

I'm hoping to find a circumstance that will allow me to test this properly because trying to deal with a Linux-only bug is a nightmare.

[edit]
Also I think your workaround could be tweaked for better performance. For one thing, IIRC you should be able to tell which platform you're running on and use the normal method on Windows if indeed this turns out to be strictly Linux. But beyond that, you can use a binary search method to find the last pixel.

// example for width
var/e, n
. = 128
if(!isnull(I.GetPixel(.,1)))
while(!isnull(I.GetPixel((e=.*2),1))) . = e
else
e = .
. = 0
while(.+1 < e)
n = round((.+e) >> 1)
if(isnull(I.GetPixel(n,1))) e = n
else . = n

The basic algorithm is to try a test spot first; if that succeeds, just keep doubling the coordinate until an upper bound is found. Otherwise if it fails, use that as the upper bound. Then do a binary search to narrow down the actual width.

At every point in the binary search, . is the maximum coordinate that had a pixel and e is the minimum coordinate that did not. So the binary search looks between .+1 and e-1 to test, until it reaches a point where . == e-1. At that point . is the width, since going just 1 pixel beyond that will fail.