[ANN] Ruby/GD2 alternative to Ruby/GD

Hi all,

I'm a fairly recent Ruby convert, and I'd appreciate some help getting my first library in a form suitable for mass consumption.

The library I wrote is an alternative to Ruby/GD. I wrote it because I wasn't satisfied with the original; in particular, there was no support for creating images from JPEG or PNG data already in memory. My alternative is 100% Ruby, relying on Ruby/DL to link with the gd shared library.

Most of the gd API is available albeit in quite different form, because I tried to write an interface The Ruby Way. Here is a taste:

   include GD2
   image = File.open('image.png') { |f| Image.load(f) }
   image.resize! 200, 300
   image.draw do |pen|
     pen.color = image.palette.find! Color.new(1.0, 0.75, 0.5)
     pen.thickness = 2
     pen.move_to 25, 50
     pen.line_to 175, 50
     pen.move -150, 25
     pen.font = Font::TrueType.new('/usr/share/fonts/times.ttf', 20)
     pen.text 'Hello, world!'
   end
   File.open('new-image.png', 'w') { |f| f.write(image.png_data) }

I needed this library for another project, but I'd like to make it available for anyone else who might also find it useful. Since this is my first Ruby project of any significance, I'd appreciate some feedback and guidance on what is good and what could be better, and especially norms for packaging and documentation.

Here is my preliminary release:

     ftp://ftp.mars.org/pub/ruby/ruby-gd2-0.1.tar.gz

Thanks for any help,

···

--
Rob Leslie
rob@mars.org

A 'fairly recent Ruby convert', huh? Sure doesn't look like it :slight_smile: Great job.

Dan

Hi,

The library I wrote is an alternative to Ruby/GD. I wrote it because
I wasn't satisfied with the original; in particular, there was no
support for creating images from JPEG or PNG data already in memory.
My alternative is 100% Ruby, relying on Ruby/DL to link with the gd
shared library.

It's good to have another "Ruby Way" library.

  image.resize! 200, 300
  image.draw do |pen|
    pen.color = image.palette.find! Color.new(1.0, 0.75, 0.5)

I don't think resize! and find! do not require bang sign in the name.
Note that, unlike Scheme, bang sign indicates "more dangerous"
alternatives to non bang ones in Ruby, for example, sub (returns
modified copy of the receiver) and sub! (modifies the receiver in
place).

              matz.

···

In message "Re: [ANN] Ruby/GD2 alternative to Ruby/GD" on Sat, 5 Nov 2005 13:36:29 +0900, Rob Leslie <rob@mars.org> writes:

Hi matz,

  image.resize! 200, 300
  image.draw do |pen|
    pen.color = image.palette.find! Color.new(1.0, 0.75, 0.5)

I don't think resize! and find! do not require bang sign in the name. Note that, unlike Scheme, bang sign indicates "more dangerous" alternatives to non bang ones in Ruby, for example, sub (returns modified copy of the receiver) and sub! (modifies the receiver in place).

Actually, I was conscious of this; the non-bang Image#resize does not modify the receiver but returns a new image instead. Also, Palette#find never modifies the palette, but Palette#find! allocates the color if it doesn't already exist.

So I didn't use the bang sign without reason, but perhaps it's a bit much to have non-destructive image operations? (Besides #resize, there is also #rotate, #crop, #uncrop, and #polar_transform.)

Thanks for the feedback.

Cheers,
   -rob

···

On Nov 5, 2005, at 5:01 AM, Yukihiro Matsumoto wrote:

Hi,

···

In message "Re: [ANN] Ruby/GD2 alternative to Ruby/GD" on Sat, 5 Nov 2005 23:08:32 +0900, Rob Leslie <rob@mars.org> writes:

I don't think resize! and find! do not require bang sign in the
name. Note that, unlike Scheme, bang sign indicates "more
dangerous" alternatives to non bang ones in Ruby, for example, sub
(returns modified copy of the receiver) and sub! (modifies the
receiver in place).

Actually, I was conscious of this; the non-bang Image#resize does not
modify the receiver but returns a new image instead. Also,
Palette#find never modifies the palette, but Palette#find! allocates
the color if it doesn't already exist.

Hmm, I should have checked the API before making comments, sorry. But
I still feel something weird with find!, but I can't express myself well.

              matz.

Rob Leslie wrote:

>> image.resize! 200, 300
>> image.draw do |pen|
>> pen.color = image.palette.find! Color.new(1.0, 0.75, 0.5)
>
> I don't think resize! and find! do not require bang sign in the
> name.

Actually, I was conscious of this; the non-bang Image#resize does not
modify the receiver but returns a new image instead. Also,
Palette#find never modifies the palette, but Palette#find! allocates
the color if it doesn't already exist.

So I didn't use the bang sign without reason, [...]

Hi Rob,

This is based on a cursory look, so forgive the inaccuracies.

IMHO, resize! is fine but find! & allocate! could be better.

You've already, perhaps, checked out other API's available
from interfaces to other languages. Some are listed here:

( None for Ruby -- you'll rectify that with an e-mail, later :-? )

A clean-looking Lisp one I found is here:
http://www.weitz.de/cl-gd/

Always a good idea to keep an eye on the competition.

----- ----- ----- ----- -----

[...] but perhaps it's a bit much to have non-destructive
image operations?

You surely wouldn't want to be doing non-destructive operations
/accidentally/ on an in-memory copy. IOW, you might insist
that *all* operations are destructive and provide an explicit
dup/clone method to prevent excessive memory loading (?)

    pen.color = image.palette.find! Color.new(1.0, 0.75, 0.5)

A possibility here is:

          image.palette.find_color(1.0, 0.75, 0.5, :exact, :alloc)

- where the first arg can be a Color, otherwise the first three args
are R-G-B (with the rest as options). It's a tough call when there
are multiple options but I tend away from adding methods for various
option combinations ...

   e.g. avoid: find_exact_color(...)
                find_color_alloc(...)
                find_exact_color_alloc(...)
                ... etc.

- when each is a variation on find_color(...).

(That may not apply to what you've written but the Lisp version
uses the 'options' approach.)

In general, the fewer methods - the better, IMO.

I wonder if red= , green=, blue= could be improved by, say:

    rgb = (nil, 45, nil) # ?
    rgb = (-1, 45, -1) # ?

- presumably, setting more than one gives a gain and it's fairly
readable.
No? - OK, I'm nowhere near as close to this as you are :wink:

Alternatives are well worth exploring to squeeze every ounce of
usability out of the API design.
(Reduces the number of moaners later, also, I expect :slight_smile:

But, hey - Thanks !!
I hope to acquire the skills to use this soon :))

daz

···

On Nov 5, 2005, at 5:01 AM, Yukihiro Matsumoto wrote:

PUBLISH A GEM !!!!!! please!!!!
oh, so nice ... adding imaging to rails apps .... mmmm
j.

···

On 11/5/05, Yukihiro Matsumoto <matz@ruby-lang.org> wrote:

Hi,

In message "Re: [ANN] Ruby/GD2 alternative to Ruby/GD" > on Sat, 5 Nov 2005 23:08:32 +0900, Rob Leslie <rob@mars.org> writes:

>> I don't think resize! and find! do not require bang sign in the
>> name. Note that, unlike Scheme, bang sign indicates "more
>> dangerous" alternatives to non bang ones in Ruby, for example, sub
>> (returns modified copy of the receiver) and sub! (modifies the
>> receiver in place).
>
>Actually, I was conscious of this; the non-bang Image#resize does not
>modify the receiver but returns a new image instead. Also,
>Palette#find never modifies the palette, but Palette#find! allocates
>the color if it doesn't already exist.

Hmm, I should have checked the API before making comments, sorry. But
I still feel something weird with find!, but I can't express myself well.

matz.

--
"http://ruby-lang.org -- do you ruby?"

Jeff Wood

Yukihiro Matsumoto a écrit :

Hi,

>> I don't think resize! and find! do not require bang sign in the
>> name. Note that, unlike Scheme, bang sign indicates "more
>> dangerous" alternatives to non bang ones in Ruby, for example, sub
>> (returns modified copy of the receiver) and sub! (modifies the
>> receiver in place).
>
>Actually, I was conscious of this; the non-bang Image#resize does not
>modify the receiver but returns a new image instead. Also,
>Palette#find never modifies the palette, but Palette#find! allocates
>the color if it doesn't already exist.

Hmm, I should have checked the API before making comments, sorry. But
I still feel something weird with find!, but I can't express myself well.

              matz.

find usually takes a block, doesn't it?

Perhaps Palette#find should be Palette#include? and Palette#find! should
be Palette#add! ? Doesn't it make sense?

···

In message "Re: [ANN] Ruby/GD2 alternative to Ruby/GD" > on Sat, 5 Nov 2005 23:08:32 +0900, Rob Leslie <rob@mars.org> writes:

--
Lionel Thiry

Personal web site: http://users.skynet.be/lthiry/