# Summary

ImageAPI Optimize allows you to use your preferred toolkit and optimize (losslessly) the image when it is saved. Practice for web performance suggests that images should be optimized for better loading time. With this module enabled, Google's Page Speed will always give you an A in image optimize.

# Project URL

https://www.drupal.org/project/imageapi_optimize

# Where is the code?

https://www.drupal.org/sandbox/darthsteven/2614582

# Estimated completion date

Unknown

# Dependencies

Drupal 8.2.x

# Who's doing the port?

Steven Jones

# What help do they need?

N/A

# D8 roadmap

This issue is tracking the stuff needed for a minimum viable port: #2797219: [meta] Drupal 8 port

# Background and reference information

#2665972: Drupal 8 port

Comments

tterranigma created an issue. See original summary.

steven jones’s picture

Hi, if we're interested in porting this module to Drupal 8, how should we get involved?

Wondering if I could get commit access to start a new branch of work or if I should start in a sandbox/github?

jcisio’s picture

Hi Steven,

You could start in a sandbox or Github as you prefer, and when you think it's ready, post as a patch. I'll then review and add you as maintainer of 8.x branch.

luksak’s picture

Has anyone started working on this port?

steven jones’s picture

I've not started working on it, but have had some thoughts :)

Shall we get a sandbox repo somewhere spun up to work on it.

I suspect that we'll just want to start from scratch given the extensive changes to Drupal rather than doing a 'straight port'.

luksak’s picture

Yes, makes sense. Do you have time to work on it? I would provide testing, feedback and patches.

steven jones’s picture

So I have a fork of ImageAPI Optimize that does the following:

  • Provides a number of 'pipelines' that can have a number of 'optimizations' in them.
  • Provides a number of optimizations, like using local binaries, resmush.it or Kraken.io
  • Provides an image style effect that can be added to any image style which allows selection of a pipeline to use for that image style.
  • When that image style effect is processed, it swaps out the image toolkit being using to process that image, so that on save, it can do the optimizations etc.

Some of that in D7 is a touch hacky :) But it does work, and gives a nice amount of flexibility, for example, I can configure one image style to have lossy compression, and another to have lossless compression, and another to not have any at all.

Thinking about the architecture of the Drupal 8 module, I feel that there should be two streams of work here:

  1. Get Image API optimizers written up as a plugins. So, sending an image to Kraken, or using a local binary should be contained in a Plugin. These should then be wired up as a pipeline. These pipelines are configurable, I can have 0, 1 or 3, and I can configure as many plugins as I like in each pipeline. I should be able to feed an image into one end of a pipeline and get an image out the other end (or a nice error/exception).
  2. Some way to integrate the pipeline into Drupal's image generation. Either wholesale changing the image toolkit, or a something smarter that allows configuration per image style. Either way, these should just be able to save the image to disk, and then pass it to the selected pipeline from above.

Does that sound sensible?

When I was doing my D7 port, I copied and renamed image styles/effects to pipelines/processors. I think we could essentially do the same here to get a D8 port.
Image styles have a number of effects on them with config, and likewise, pipelines should have a number of processors on them with config. So architecturally I think we can just copy core here.

As for point 2, if we want to provide our pipelines as 'toolkits' that can be swapped out wholesale, then it's kinda easy, we just need to provide our own plugin and wire it all up. Easy.
If we wanted to go the route of changing and image style to have an 'optimization pipeline', then I reckon we could do this via:

  1. Implement a hook_entity_type_alter and swap out the base image style class for one of our own.
  2. Add the ability to select a pipeline to use in the class, and use it during the createDerivative method.
  3. Change the forms for editing an image style to allow selection of a pipeline to use (and maybe have a nice, global default)

I'd argue for shooting for the swapping out the ImageStyle class for our own, it will get us a lovely amount of flexibility :)

luksak’s picture

Thank you for your thoughts! Sounds good :)

Having two ways of using the optimizations as wholesale and being able to define them on a image style basis makes sense. I'd suggest to go for an MVP which provides the wholesale functionality first since this is the more common use case I guess.

In general I have to say that I am not too familiar with the way the image generation process works in general. One important thing to me would be the ability to choose the image toolkit independent of the optimization. The user has to be able to choose between GD and ImageMagick alongside the optimization settings.

I can't really judge which approach to take on the per image style solution. Can anyone else provide feedback on this?

steven jones’s picture

Status: Active » Needs work

Some progress in my fork.

I've got a rough implementation that vaguely works in Drupal 8.2.x :)

Resmush.it integration is working, though I then tried to make it configurable, and that's broken again now.

When for the all-singing all-dancing approach of making it configurable per image style, which was actually quite easy.

steven jones’s picture

Issue summary: View changes
luksak’s picture

Oh nice! About to test it on the current project. I will provide feedback asap.

steven jones’s picture

It'll be very much broken at the moment I suspect, be warned!

steven jones’s picture

steven jones’s picture

Related issues: +#2803711: [kraken] Kraken
luksak’s picture

I have a first feedback: please add a composer.json so I can install the module using composer.

luksak’s picture

When adding a processor to a pipeline I get the following error:

Error: Call to undefined method Drupal\imageapi_optimize\Entity\ImageAPIOptimizePipeline::addImageAPIOptimizeProcessor() in Drupal\imageapi_optimize\Form\ImageAPIOptimizeProcessorFormBase->submitForm() (line 122 of modules/contrib/imageapi_optimize/src/Form/ImageAPIOptimizeProcessorFormBase.php).

Drupal\imageapi_optimize\Form\ImageAPIOptimizeProcessorFormBase->submitForm(Array, Object)
call_user_func_array(Array, Array) (Line: 111)
Drupal\Core\Form\FormSubmitter->executeSubmitHandlers(Array, Object) (Line: 51)
Drupal\Core\Form\FormSubmitter->doSubmitForm(Array, Object) (Line: 583)
Drupal\Core\Form\FormBuilder->processForm('imageapi_optimize_processor_form', Array, Object) (Line: 314)
Drupal\Core\Form\FormBuilder->buildForm('imageapi_optimize_processor_form', Object) (Line: 74)
Drupal\Core\Controller\FormController->getContentResult(Object, Object)
call_user_func_array(Array, Array) (Line: 123)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 574)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 124)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) (Line: 97)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}()
call_user_func_array(Object, Array) (Line: 144)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 64)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 57)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 99)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 78)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 50)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 649)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
luksak’s picture

BTW, all my reports will be in 8.2.0-RC1.

steven jones’s picture

@Lukas von Blarer I've just addressed those two issues. Not 100% sure what should go in the composer.json so just put something vaguely sensible in there for now.

steven jones’s picture

Issue summary: View changes

I've added some child tickets to #2797219: [meta] Drupal 8 port for a minimum viable port to D8.

steven jones’s picture

Status: Needs work » Needs review

Setting to 'Needs review' as I think I've not pushed the basics of a D8 port into place.

Still some cleanup of docs to do, and need to get stuff that wasn't in D7 into D8 (like some tests).

steven jones’s picture

Issue summary: View changes
steven jones’s picture

Now that I have something worthy of becoming the Drupal 8 branch, I've asked for maintainer access in #2805805: Request for maintainer access

jcisio’s picture

Status: Needs review » Fixed

We have releases for D8, so marking this issue as fixed and work will continue on the project issue queue.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

benjifisher’s picture

According to https://www.drupal.org/project/contrib_tracker#statuses this issue should be marked "Needs Review" since it has an alpha (or beta) release, but not a stable one.

I do not have permission to change the status from Closed to NR.

Anonymous’s picture

The 2.0-alpha1 works great!

Integration with the imagemagick module would be nice... e.g. choosing between GD and imagemagick on the image toolkit page, like in the D7 version.

Thanks a lot!

steven jones’s picture

@agx the Drupal 8 version of the module should integrate just fine with GD or ImageMagick. As it's now not a image toolkit, it can be applied totally independently.