43 comments

[ 0.29 ms ] story [ 103 ms ] thread
why yet another image library? what is the difference between existing solutions?

random google search results: http://image.intervention.io/ http://imanee.io/ https://imagine.readthedocs.io/en/latest/ https://packagist.org/search/?tags=image%20manipulation ...

Maybe he didn't like other libraries? There are many reasons why you would want to write a new library. Fun is one of them.
I completely agree. If no one reproduced existing libraries, how is one supposed to learn library design and all the algorithms? I would love to hire people who wrote their own 3D libraries in JavaScript -- we wouldn't use their libraries of course but it would show that they have a really deep understanding and can contribute to similar software libraries.
It is important to have fun and to learn new things. But it is presented here as a final product, not as a learning experience. Without any explanation, it is "yet another image library" adding to the noise for anyone who is seriously looking for using some image library.
Why do you consider it a "learning experience" and what makes a software library a final product? Every software project has to start somewhere and be published at some point.
It has smart crop based on entropy, ability to compare images, and bezier curves for GD which none of the existing libs have. Other libs are "image manipulation" this one aims to be an "image processing" lib. Also we need libs instead of new programming languages.
Too many features in one library, for my taste. It would have been better to keep the smart cropping and comparing in separate libraries so other environments (nodejs etc) can benefit from them as well.
I have gone through the code before he commented here to see how he did the smart cropping (1. create histogram, 2. calculate entropy) and think he could have maybe made the histogram and the entropy calculation available as separate libraries or use an existing one, but they are not too big either and I think the use cases would anyway involve some sort of image processing most of the time.

The interface to crop smartly definitely belongs in an image library, especially when it is a wrapper around a native program focused on easy of use and a clean interface.

Well the field of "image processing" is big[0]. As oppose to what we are used to in php world which is just "image manipulation" (resize, crop, save to different image formats) in the context of web apps.

> so other environments (nodejs etc)

The algos are in github you can convert it to JS if you want. Theyre both C based so syntax is not that different. If you are looking for node.js version there is already smartcrop.js.

[0] - https://en.wikipedia.org/wiki/Digital_image_processing

(comment deleted)
Why yet another commenter who does not bring anything new to the discussion unlike the OP's image library?
And what exactly are you bringing to the discussion?
I think someone should change the title to indicate that it is a PHP library. "Grafika is an image processing library for PHP"
Aha, so that's why it made it to the front page. Had it had PHP in the title from the beginning HN would have ignored it completely (sadly).
"Oh wow, can't wait to see this!" click "...for PHP..."

It's not 1999 anymore. Please next time put the deprecated legacy tech on the title so we can skip it.

Does this support uint16, fp16 and fp32 channel resolution for dealing with hdr, tiff, and exr images?

Can it maintain that bit-depth while applying image operations?

I find this is where ImageMagick and GraphicsMagick falls down (it converts everything to 8bit images upon read) which was fine a decade ago, but not now.

It blows my mind that nearly all image processing libraries in wide usage are uint8 per channel.

> Grafika is an image processing library for PHP. It can be used to resize, crop, compare, and add watermark on images. It can also create texts, geometric shapes, and apply filters. Its built on top of Imagick and GD.

First paragraph.

So it is just a wrapper over the inferior capabilities of ImageMagick. There are already a done of these on NPM: https://www.npmjs.com/package/gm
> Grafika is an image processing library for PHP

I don't think an NPM library helps here.

Kinda discouraging that everytime I post this lib I am always asked: "there is already imagine, imageXX etc lib out there. why another lib?" I feel like I violated some code of honor or something.

Just to be clear, here's why I made it:

- it aims to be an image processing lib. Not a an image manipulation lib which is just a small subset of image processing. Big difference. Also I fell in love with image processing. :-)

- Smart crop. Not present in other libs. I am surprised that in PHP cropping an image is a fairly common requirement. Yet none of the existing libs have it. I found one from an obscure drupal extension.

- Image compare. Not present in other libs. Fairly important and needed feature esp for CMS yet none existed.

- Advance filters. The default ones provided by GD and Imagick (not ImageMagick) are very basic filters. Right now only Sobel filter is implemented, more will be added in the future.

- Bezier Curves. Imagick is good but GD does not have it so I implemented a bezier curve algorithm manually porting it from a c++ code.

The future

- Seam carving

- More edge filters

- Full anti-aliased shapes and curves in GD. GD does not support anti-aliasing on all its shapes.

- Perhaps face detection but we'll see..

I think this is a worthy library to check out. Might not be for everyone though..

It's a classic but let's quote Jeff Wood : * Indeed. If anything, "Don't Reinvent The Wheel" should be used as a call to arms for deeply educating yourself about all the existing solutions – not as a bludgeoning tool to undermine those who legitimately want to build something better or improve on what's already out there. In my experience, sadly, it's much more the latter than the former.*

https://blog.codinghorror.com/dont-reinvent-the-wheel-unless...

Furthermore we should be happy that the wheel has been reinvented a number of times, the first ones where fairly clunky.

-Unknown

If you keep getting asked the same question, why not put this list of reasons on the lib's homepage? What you have on the page now is not convincing (I'd just create a function for your first example and I don't care about the syntax you show off in the second example) - but the points you made here are good selling points!
For what it's worth, just being able to chain the calls makes this worthwhile. Thanks for making the effort and taking the time to release it!
> Kinda discouraging that everytime I post this lib I am always asked: "there is already imagine, imageXX etc lib out there. why another lib?" I feel like I violated some code of honor or something.

Y'know how people say, "Don't reinvent the wheel?" The emphasis should be on the.

Don't reinvent THE wheel.

Feel free to invent a better wheel.

Better here can mean simpler, which allows users to be more productive. As far as I can tell, you've accomplished this much. So, good job, and thanks for sharing.

I know your reasoning is I should make a new library because X and Y don't exist in the existing ones. But really what most people think of is why not just send a pull request to the existing ones with that new functionality?
Maybe he just wants to build his own thing, or he doesn't like the code from the existing ones, or he doesn't want to commit to learn and write the code just to have his PR ignored or rejected, or he doesn't want to wait until someone notices his work and decides to ship it into the next version.
(comment deleted)
Haters gonna hate.

There are a lot of room for new libs. Gfx needs are infinite. No single library can cover all needs fitting everyone requirements.

Interop between each is the key. And competion leads to success.

Stay tuned with gd 2.3 btw from a (much better aa pov along other things:)

Hey are you the Pierre Joye of libgd?? Thank you for all the hard work.
Yes, my pleasure. Happy you like it :)
Btw, what is the process in contributing to libgd? I'd like to contribute.
Side notes you may update your comparisons using latest GD. imagescale, rotate or affine, which do what you said about 15yo copyresampled
Don't listen to the haters. :)

One thing I'm interested in is blurring. Blurring seems to be pretty CPU intensive, but I'm hoping there's a better way to do it. Right now, I'm using Intervention Image, but I routinely have to blur photos which can take upwards of 2-3s per image (especially for larger ones). Maybe that's something you could tackle? :)

I think it would be helpful to include this information on the project website.
Does it solve some "harder problems" in image processing (at least regarding PHP) like: WebP & WebM support or resizing animated gifs? What are the supported file formats?
(comment deleted)
How does one "smart crop"? The crop method only seems to allow you to crop 1 portion of a 3 x 3 grid...

Thanks for your creation!

Not a big fan of the API here.

I had a teacher that called this "knocking", so that's what I call it. It's better known though as the Sequential Coupling Antipattern[1]. e.g.: Requiring methods to be called in a particular order.

The following works:

  $editor = Grafika\Grafika::createEditor();
  $editor->open( "/Users/jdonat/Desktop/Screen Shot 2016-07-25 at 11.33.53 AM.png" );
  $editor->resizeExact( 200, 200 );
  $editor->save( "edited.jpg", null, 90 );
Whereas this throws `Fatal error: Uncaught exception 'Exception' with message 'No image to edit.' in /private/tmp/grafika/src/Grafika/Gd/Editor.php on line 1056`

  $editor = Grafika\Grafika::createEditor();
  $editor->resizeExact( 200, 200 );
  $editor->open( "/Users/jdonat/Desktop/Screen Shot 2016-07-25 at 11.33.53 AM.png" );
  $editor->save( "edited.jpg", null, 90 );
Required parameters should be required on the constructor, not on a setter. That's basically just requiring someone to know your secret handshake to use your API.

I'd say in general you'd be better off restructuring this to defer GD/ImgMagick selection until it's actually needed, eg: calling save. I'd personally defer applying any of the filters until save.

Also the static factory is gross and old-school php, I'd avoid that.

1. https://en.wikipedia.org/wiki/Sequential_coupling

RAII is another way of putting this. You could use a builder pattern to setup your class, build it and then start deriving value from the object.

Mutable objects that incorporate behavior are largely evil.

What about when you want to resize multilple images using the same editor then?
"Telling a programmer there's already a library to do X is like telling a songwriter there's already a song about love." @counternotions (seen in twitter)