
@blerner @leif that’s a but in 2htdp/image (a library I maintain), but it is also a bug in pict
:

#lang racket/base
(require file/convertible
racket/class
racket/gui/base)
(require (prefix-in p: pict))
(define bp
(read-bitmap
(open-input-bytes
(convert (p:rectangle 0 0) 'png-bytes 'fallback))))
(send bp get-width) ;; ==> 1
(send bp get-height) ;; ==> 1

It isn’t obvious to me what the right behavior is here, but I’ve pushed a change that produces a 1x1 bitmap in that case

(but => bug)

@leif: you wrote earlier “it is probably a bug in the 2htdp library”; I just want to put out that the error message contains the line:

blaming: <pkgs>/gui-lib/mrlib/image-core.rkt
(assuming the contract is correct)

(lines)

Sure. I blamed 2htdp/image because pict didn’t fail. Although I personally thought making a 1x1 transparent png was the right thing to do here as apparently pngs can’t have a 0 width or height.

Where is that speced? I couldn’t find that fact anywhere…

But yup, it was certainly the gui lib that tried to make the actual 0x0 picture. :slightly_smiling_face:

Going back to a related question: do you happen to know how to ask a convertible what its width will be, if I try to convert it?

@blerner I honestly forget. Here is an unofficial SO answer while I track down the actual spec: https://stackoverflow.com/questions/7909212/how-to-create-empty-0x0-image

@blerner The closest thing that the convert library seems to support (by default) is: 'png-bytes+bounds
, which gives you the width and height at the same time as converting the image.

You ‘could’ use 'png-bytes+bounds8
, which automatically pads the png image.

This gives the effect of a 0x0 image being padded. And then it gives you the amount of padding added to each side.

I tried that, and consistently got #f as my output. Looks like the snip doesn’t respond to that message

So in the case of (convert empty-image 'png-bytes+bounds8)
, you get a 6x6 sized png with 3 pixels of padding on the left, top, right, and bottom.

Would be lovely if it did….

Ah, sad.

Then nope, I highly suspect it’s not possible. :confused:

Png-bytes+bounds I can understand why it fails, since it promises to return the actual bytes and bounds, and can’t return a 0*0 image. But the padded version ought to work, and just doesn’t seem to be supported right now

Okay

I think I have a solution.

Its ugly and terrible, but….

convert to pdf-bytes.

Then use the racket-poppler package to get the width and height of the pdf page.

Oh good grief. Srsly?

Ya, that is worse than just catching the exception. :disappointed:

Well now thanks to Robby’s fix, there won’t be an exception to catch… Irony.

But ya, the convert library is kind of…lacking, imo.

I wonder if the contract for png-bytes+bounds might not be better as (list (or/c bytes default) num num num num), instead of (or/c (list bytes num num num num) default)…

In that you could get the bounds even if you couldn’t get the bytes

Eh, something you pass into the convert library might not even make sense to be a png file. In which case having it return default/c is the right thing.

What would be much better would be having a ‘width and ‘height convert targets.

I can see efficiency reasons why that might not be ideal (eg if the image is recomputed each time, in order to measure it), but as an API that would be helpful

FYI, here is the png spec that makes a 0x0 png invalid: http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html

I absolutely agree.

Honestly, I would just scrap the file/convert
library altogether. Its a great idea, but its just too rigid in so many ways.

file/convertible
*

Well, it’s a nice trick that works with snips that I can’t statically predict what that are, so it’s got that going for it :-)

Sure. I think a convertiblity library absolutely must exist. Its just this particular instance which is too rigid.

I’ve actually been working on a replacement for use with video.

@blerner if you want to avoid catching the exception, you can check to see if the image has either a 0 width or a 0 height.

Yesss, that’s exactly my question. I don’t have an image, I have a snip — how do I ask the snip for its dimensions, if I don’t know for certain that it’s an image-snip?

get-extent

but maybe non–2htdp/image snips don’t have this problem, so maybe you can get the image out?

Currently, my code for this case is simply, [(convertible? snip)
(let ((converted
(with-handlers ([exn:fail:contract?
(λ(e) 'conversion-failure)])
(convert snip 'png-bytes 'conversion-failure))))
(if (equal? converted 'conversion-failure)
(display (add-empty-image "")
out)
(display (add-image (convert snip 'png-bytes))
out)))]

(I’ll note that image-snip%
is an unrelated thing, which is slightly confusing to me at this point :slightly_smiling_face: )

so I don’t have a dc<%> to give to (send a-snip get-extent dc x y)
. unless that’s not the get-extent you meant?

If you want to work around the bug, I suggest you check to see if the snip is actually an image?
from 2htdp/image and if it has either a 0 width or a 0 height and then do the “conversion” yourself.

A bitmap dc would work fine for this purpose.

But that’s probably not the most direct approach

(If you want to stick with the code you have above, I suggest you use a regexp match on the error message so you don’t accidentally catch real bugs. I think that would also be just fine.)

so using get-extent, it would be something like [(convertible? snip)
(let* ((bm (new bitmap-dc%))
(width (box 0))
(height (box 0)))
(send snip get-extent bm 0 0 width height)
(if (or (= (unbox width) 0) (= (unbox height) 0))
(display (add-empty-image "") out)
(display (add-image (convert snip 'png-bytes))
out)))]
?

I’m not sure what would go wrong exactly but you should probably put a 1x1 bitmap into the bitmap-dc.

(Also you don’t have to add an image to the html page when it is 0x0, right? You could just put something less? Maybe nothing?)

Also, you can use define
in the rhs of a cond
:

right, that’s what the add-empty-image is doing; it’s letting me put a non-image placeholder into the resulting output

[(convertible? snip)
(define bm (make-object bitmap-dc% (make-bitmap 1 1))))
(define wb (box 0))
... etc

good to know, thanks. I wasn’t certain about the scoping, so didn’t bother

It is scoped to that arm of the cond

(to the square brackets)

yup, makes sense. I think I’d gotten so used to BSL that I forgot normal racket allows defines in places where they make sense :wink:

@samth re: the GH issue, is racket7 easy to build these days? I haven’t tried it yet.

@lexi.lambda should be just make

but how can I write Racket without DrRacket? :)

oh, I see… racket7 does not imply racket-on-chez.

right

no need to miss out on DrRacket

:slightly_smiling_face:

so I should just expect make base
to give me an ordinary Racket installation with a slower and less buggy expander?

yes

and maybe a slower IO system

exciting

you might want to build less than that

if I want to install drracket, I don’t really have a choice, do I?

true

I did notice that make base
did not set up static-links into the pkgs/
dir… I don’t remember how those got set up in my normal from-source installation in the first place.

make
sets them up for the pkgs that are in there

okay. I seem to remember I stopped using make
for some reason, but I don’t remember what the reason was.

I think I wanted to not install the whole main-distribution.

aww, my raco setup
segfaulted.

if you can get a stack trace that would be a useful bug report

@samth I have a crash report, but re-running raco setup
worked. should I still open an issue?

Yes

@samth Alex’s program still fails on the new expander

Worth reporting on the bug