This tutorial can be considered as a continuation of http://drupal.org/node/460132.

Its purpose is to create single-page and double-page thumbnails of PDF files:

  • without selecting ImageMagick as the default toolkit, as GD is often the preferred toolkit
  • using imagecache so that the creation process is automated

Example

An example of result can be seen here.

The libraries you need on your server:

  • ImageMagick
  • Ghostscript

The Drupal modules you need to install and enable:

  • Content Construction Kit Module
  • FileField Module
  • ImageAPI: enable both ImageAPI GD2 and ImageAPI ImageMagick
  • ImageCache 6.x-2.0-beta10
  • ImageCache Actions: enable Imagecache Custom Actions too
  • FileField Paths, Pathauto and Transliteration

Instructions

  1. Select GD2 as your default toolkit
  2. Patch ImageCache 6.x-2.0-beta10 with this patch
  3. Create a new imagecache preset with a custom imagecache action to generate a single-page thumbnail. Code is: (do not include the <?php ?> tag)
    <?php
    $w = 246; // change to your preferred thumbnail width
    if (!_imageapi_imagemagick_convert($image->source.'[0]', $image->source.'.png', array(0 => '-thumbnail '.$w))) return FALSE;
    $img = imagecreatefrompng($image->source.'.png');
    file_delete($image->source.'.png');
    $image->resource = $img;
    $image->toolkit = 'imageapi_gd';
    $image->info = array('extension' => 'jpeg');
    return TRUE;
    ?>
    
  4. Create a new imagecache preset with a custom imagecache action to generate a double-page thumbnail. Code is: (do not include the <?php ?> tag)
    <?php
    $w = 256; // change to your preferred thumbnail width (this is the width of *one* page)
    if (!_imageapi_imagemagick_convert($image->source.'[0]', $image->source.'0.png', array(0 => '-thumbnail '.$w))) return FALSE;
    if (!_imageapi_imagemagick_convert($image->source.'[1]', $image->source.'1.png', array(0 => '-thumbnail '.$w))) return FALSE;
    $data = getimagesize($image->source.'0.png');
    $h = $data[1];
    $img1 = imagecreatefrompng($image->source.'0.png');
    $img2 = imagecreatefrompng($image->source.'1.png');
    $img3 = imagecreatetruecolor($w * 2, $h);
    imagecopy($img3, $img1, 0, 0, 0, 0, $w, $h);
    imagecopy($img3, $img2, $w, 0, 0, 0, $w, $h);
    imagedestroy($img1);
    imagedestroy($img2);
    file_delete($image->source.'0.png');
    file_delete($image->source.'1.png');
    $color = imagecolorallocate($img3, 0xBE, 0xC0, 0xC2); //grey line
    imageline($img3, $w, 0, $w, $h, $color);
    imagecolordeallocate($img3, $color);
    $image->resource = $img3;
    $image->toolkit = 'imageapi_gd';
    $image->info = array('extension' => 'jpeg');
    return TRUE;
    ?>
    
  5. Add a FileField to a content type so that you can upload PDF files
  6. Ensure that FileField Path settings are set so that file's path will be properly sanitized
  7. Set display of this field to the desired thumbnail preset

Et voilà !

See also

PDF to ImageField is a module that solves this sort of task without custom code

Comments

tomdisher’s picture

I followed this step by step and I get an error now...

* user warning: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'N u.fid = f.fid WHERE f.filepath = 'sites/default/files/CalendarJan2010_0.pdf' L' at line 1 query: SELECT nid, f.fid FROM upload AS u INNER JOIN files AS f N u.fid = f.fid WHERE f.filepath = 'sites/default/files/CalendarJan2010_0.pdf' LIMIT 1 in /home/******/public_html/magazine/sites/all/modules/imagecache_actions/utility.inc on line 275.
* ImageMagick reported an error: convert: unable to open image `sites/default/files/CalendarJan2010_0.pdf': No such file or directory. convert: missing an image filename `sites/default/files/CalendarJan2010_0.pdf.png'.

Here is the HTML:

Only local images are allowed.

Looks like the file is never created...

Any pointers?

anrikun’s picture

It is a bug in sites/all/modules/imagecache_actions/utility.inc
See http://drupal.org/node/491038

tomdisher’s picture

Thanks Anrikun... that got me half way there.

I'm still getting the second error.

ImageMagick reported an error: convert: unable to open image `sites/default/files/test.pdf': No such file or directory. convert: missing an image filename `sites/default/files/test.pdf.png'.

HTML is this: img src="http://********/sites/default/files/imagecache/CREATETHEPDFIMAGE/test.pdf"

Any ideas?

anrikun’s picture

Are you sure Ghostscript is installed on your server?

tomdisher’s picture

My host tells me that it is installed. Is there a way to verify?

Update:

I've installed a new Drupal installation and I'm still getting the same problem.

The HTML code generated is img src="http://*****/sites/default/files/imagecache/CONVERTPDF/test.pdf"

anrikun’s picture

Maybe you should try on your local computer first. Are you using Windows? You can easily install ImageMagick and Ghostscript on Windows.

tomdisher’s picture

I've verified that GS and imagamagick are running via SSH...

perhaps this is a versions issue?

tomdisher’s picture

Ok...

I've got it!

There were a few things wrong. First, I didnt have the transliteration module installed. You may want to mention that it should be (Its a pre-requisite anyways, but it did not give me a warning.)

Second, I had to apply to my imageapi_imagemagick.module:

--- imageapi_imagemagick.module 2009-04-24 16:03:26.000000000 +0700
+++ imageapi_imagemagick.module.new 2009-04-24 16:04:38.000000000 +0700
@@ -191,7 +191,8 @@ function _imageapi_imagemagick_convert_e
     1 => array('pipe', 'w'), // stdout
     2 => array('pipe', 'w')  // stderr
   );
-  if ($h = proc_open($convert_path .' '. $command_args, $descriptors, $pipes, $_SERVER['DOCUMENT_ROOT'])) {
+  global $base_url;
+  if ($h = proc_open($convert_path .' '. $command_args, $descriptors, $pipes, $_SERVER['DOCUMENT_ROOT'].$base_url)) {
     $output = '';
     while (!feof($pipes[1])) {
       $output .= fgets($pipes[1]);

Imagemagick was trying to run in the default directory and not my drupal directory.

I'm still having one issue, though. The image file is still ".pdf" It shows up, though.... I'll try to track down this error as well.

Thanks for the help anrikun!

anrikun’s picture

The image file is still ".pdf"

It is normal, it's not an error!

Thanks for the info about transliteration, I will add it!

landry’s picture

With the fix from http://drupal.org/node/491038, and this fix for imageapi (which should be reported to its issue queue, no ?), i was able to get the thumb generation working.

Just a minor notice : if you use filefield_path module, care to have the path to your uploaded file not containing spaces (ie if using [title] token for example) or sanitize it by checking 'Cleanup using Pathauto.', otherwise convert will try to access a path with spaces and fail.

Now, how to get the imagecache style to also insert a link to the original file around the jpeg thumbnail... i know you can do that in your wysiwyg editor, but it works fine for imagefields and other filefields, it could be good to also have that working out of the box.

edit: it seems like hacking insert/templates/imagecache-insert-image.tpl.php as seen in http://drupal.org/node/632240 could do the trick, but it's a bit.. hackish.

Thanks!

anrikun’s picture

Do it like you would with any imagecache image:
1) Edit the display of your content type (/admin/content/node-type/CONTENT_TYPE_NAME/display)
2) Choose "PRESET_NAME image linked to image" as the formatter of your filefield.
When the user clicks on the thumbnail, it will load the PDF.

landry’s picture

Yeah, that works for field display outside of content itself, but my concern is using it with the insert module, so that the pdf thumbnail in the page body links to the pdf file.
With the hack from http://drupal.org/node/632240 it works. Anyway, thanks for your tutorial, really helpful.

dfdavis’s picture

Hi, I have followed all the instructions, installed Imagemagick and Ghostscript (local MAMP server) and applied the various patches. Imagemagick seems to be working fine and the custom action can convert images but not from PDFs. I would be grateful for any advise on what could be going wrong. This is the error message:

ImageMagick reported an error: convert: unable to create temporary file `sites/default/files/xxx/xxx.pdf': Permission denied @ error/pdf.c/ReadPDFImage/381. convert: missing an image filename `sites/default/files/xxx/xxx.pdf0.png' @ error/convert.c/ConvertImageCommand/2919.

Thanks in advance.

anrikun’s picture

Hi, are you sure that ImageMagick is correctly configured to convert PDFs?
You should try to convert a PDF file directly from command line to see if it works (Read http://www.imagemagick.org/Usage/ and http://www.imagemagick.org/Usage/formats/#vector)
If it works, then make sure that ImageMagick has write permissions in sites/default/files.

dfdavis’s picture

Hi anrikun,
Thanks for your reply.
The weird thing is, it works from command line:

/opt/local/bin/convert 'sites/default/files/xxx/xxx.pdf[0]' -thumbnail 256 -quality '75' 'sites/default/files/xxx/xxxpdf0.png'

Permissions for sites/default/files are set to 777

I even tried running the command as _www, which worked too.
sudo -u _www /opt/local/bin/convert 'sites/default/files/xxx/xxx.pdf[0]' -thumbnail 256 -quality '75' 'sites/default/files/xxx/xxx.pdf0.png'

I think I have overlooked something obvious, but I can't figure it out.

anrikun’s picture

Then I think the best way is to do all the tutorial again from the start and check each step.
Maybe you missed one step?

dfdavis’s picture

Hi,
I have just followed the tutorial again - step by step on a fresh installation of Drupal.

But, I am still getting the same results
ImageAPI ImageMagick debugging information:

* ImageMagick command: /opt/local/bin/convert 'sites/default/files/press/pdf/cover.pdf[0]' -thumbnail 256 -quality '75' 'sites/default/files/press/pdf/cover.pdf0.png'
* ImageMagick output:

And the error:

ImageMagick reported an error: convert: unable to create temporary file `sites/default/files/press/pdf/cover.pdf': Permission denied @ error/pdf.c/ReadPDFImage/381. convert: missing an image filename `sites/default/files/press/pdf/cover.pdf0.png' @ error/convert.c/ConvertImageCommand/2919.

Could it be that ImageMagick is trying to create a temporary file which already exists? ... "sites/default/files/press/pdf/cover.pdf"

I can get it all to work with uploaded image files and as before it works from commandline:
/opt/local/bin/convert 'sites/default/files/press/pdf/cover.pdf[0]' -thumbnail 256 -quality '75' 'sites/default/files/press/pdf/cover.pdf0.png'

I would be very grateful for any further clues.

anrikun’s picture

There seems to be a problem with the temp directory ImageMagick tries to write into.
Please read this: http://www.imagemagick.org/discourse-server/viewtopic.php?f=1&t=9448
You need to find where this temp directory is and ensure its chmod is 777.

mplewis’s picture

Does anyone know if this patch has been committed? Is it going to be incorporated into the next release of the ImageCache module?

Also, does anyone know if the ImageCache Actions module bug mentioned above (http://drupal.org/node/491038) is still a problem? It doesn't look like it's been resolved yet.

Thanks!

anrikun’s picture

Please post your request that this patch should be committed into ImageCache in ImageCache module's issues.

About ImageCache Actions module's bug, I think it has been fixed only in HEAD at the moment.

lemmers’s picture

I've been trying to get this to work with thickbox. I tried adding a new preset using a custom action and assigned thickbox to use that as the default, but I just get a bunch of computer code in the thickbox pop up. Using the thickbox default setting "original image" results in a blank thickbox.

This was a great tutorial and I have everything working, but would love to implement thickbox also.

Possible?

joel_guesclin’s picture

I have installed this and it works fine, but.....
I'm trying to produce a thumbnail of a PDF file (one page) as per the instructions in point 3. Everything is installed and works fine. I can produce a thumbnail of the publication. So I know ImageMagick works, GD Toolkit works, and the script provided works.
The trouble starts when I want to produce a thumbnail for some "exotic" PDFs - namely, one in Russian with Cyrillic characters, and the other in Bengali. The script "works" inasmuch as it produces a jpg file, but the result is ugly in the extreme, very bad quality and the actual texts seems to be to wide for the page and get chopped off in the middle.
I fiddled around for ages, and then thought I had better get back to basics and try seeing what happened when I modified various settings using ImageMagick in the command line.
My first discovery was that when I tried doing this:

convert -thumbnail 190 "bnleaf.pdf[0]" "bnleaf.jpg"

all I got was a black rectangle. Conclusion, ImageMagick doesn't seem to like converting directly from PDF to JPG (which presumably is why it goes through the PNG stage first in the script shown here).

Then I tried this:

convert -thumbnail 190 "bnleaf.pdf[0]" "bnleaf.png"

and bingo! Exactly the result I want!

So my conclusion is that I want to use the script but leave out the bit that converts from PNG to JPG and just work with the PNG file (actually I can't see any reason not to do this anyway to be honest, unless it is to accommodate IE6).
The trouble is, I can't work out how to do this. I've never worked with image manipulation before so I have no idea what the "image resource" is. I have tried all sorts of things but I usually just end up with a dead link. I'm also puzzled because the Custom Action doc says you should return an Image object, yet this script just returns "TRUE". I would be very grateful for an explanation or some pointers in the right direction.

anrikun’s picture

Near the end of the script, just change:

$image->info = array('extension' => 'jpeg');

to:

$image->info = array('extension' => 'png');

Be sure also to use the latest versions of ImageMagick and GhostScript.

joel_guesclin’s picture

I have tried doing this, but it still does not appear to work.
Here is the code:

$w = 190; // change to your preferred thumbnail width
if (!_imageapi_imagemagick_convert($image->source.'[0]', $image->source.'.png', array(0 => '-thumbnail '.$w))) return FALSE;
$img = imagecreatefrompng($image->source.'.png');
//file_delete($image->source.'.png');
$image->resource = $img;
$image->toolkit = 'imageapi_gd';
$image->info = array('extension' => 'png');
return TRUE;

As you can see, I commented out the file_delete to see the intermediary file. The result I get is:
1) In the "files" directory I get the intermediate .png file which is perfect, exactly what I want
2) In the "files/imagecache/pdf-press" directory I get a file called "original-file.pdf.jpg". But in fact it seems to be a png file (The Gimp can't open it, but when I change the extension to .png then Gimp can open it. However, the quality of this file is completely unusable.
Apparently therefore, it is whatever happens between the imagemagick convert and the return of the file converts it from a good png to a bad one.
What I want is to get the file created by the imagemagick "convert" without it being modified. Is this possible and if so how?

anrikun’s picture

Haven't you set another imagecache action after the custom action?
I don't understand how you can get a .pdf.jpg file at the end.

joel_guesclin’s picture

Not as far as I am aware. I have just put in the custom action, that is all. The only thing I want to do is get a PNG file thumbnail of the front page of a PDF.
My impression is that the image is being "damaged" by the passage through GD and I would like to just get back the PNG as it comes out of ImageMagick tbecause I have checked this and it is fine). But is it possible to do this?
To complicate things further, I have just tried doing the same operation (with Bengali and Russian) on a different installation, and it works! Either in PNG or in Jpeg.
On the "working" installation I have:
Ghostscript 8.6.3
GD Version "2.0 or higher" (according to PHPInfo)
ImageMagick 6.3.7

I will check my Mac and the host service (on both of which I am having problems) but I think they are pretty similar. Is there anything else that could vary in the installation?

joel_guesclin’s picture

As I said in the first reply, on the "working" installation (Ubuntu Gutsy Gibbon) I have:
Ghostscript 8.6.3
GD Version "2.0 or higher" (according to PHPInfo)
ImageMagick 6.3.7

On the Mac I have
Ghostscript 8.6.4
GD Version "bundled (2.0.34 compatible)" (according to PHPInfo)
ImageMagick 6.6.1-0

On the hosting service I have
Ghostscript 8.15.2
GD Version "bundled (2.0.34 compatible)" (according to PHPInfo)
ImageMagick 6.4.8

In other words the working version is earlier than the ones where I have problems....

joel_guesclin’s picture

I was going crazy... using the png fix had worked on my Mac, then when I uploaded everything to my hosting service I was not seeing the images any more.
In desperation I tried changing the file upload method from public to private, and now it works! At last!!
At least up to a point... The files generated in the preset directory still have '.jpg' suffixes not '.png' ones. Which is weird.

anrikun’s picture

I don't understand why it works with you only when file upload method is changed to private.
The example site which URL is provided in this tutorial is using public upload method, not private one, and it works.

joel_guesclin’s picture

Actually, I think the problem was the existence of outdated .htaccess files, as described here - obviously a critical issue. But I only realised this afterwards. I imagine that changing the method to private somehow bypasses the bad .htaccess files, or else it was simply the fact the updating the file access method settings ALSO rebuilds the .htaccess file.

anrikun’s picture

Is your problem completely solved then?
If so, I will add this to the tutorial page.

joel_guesclin’s picture

I think my problem is completely solved (at least my site is working as I wanted!). Many thanks for your help and attention. The only surviving "oddity" is that:
a) The PNG files are being created with a JPG suffix
b) The URL to the image points to the file with a PDF suffix (apparently this is normal behaviour but it still seems to me a bit weird)
But I can live with that....

anrikun’s picture

Then it is not *completely* solved:
I don't understand why there's a JPG suffix.
Could you please post your full and final custom imagecache action code?

joel_guesclin’s picture

of my custom action preset:

$w = 190; // change to your preferred thumbnail width
if (!_imageapi_imagemagick_convert($image->source.'[0]', $image->source.'.png', array(0 => '-thumbnail '.$w))) return FALSE;
$img = imagecreatefrompng($image->source.'.png');
file_delete($image->source.'.png');
$image->source = $image->source.'.png';
$image->resource = $img;
$image->toolkit = 'imageapi_gd';
$image->info = array('extension' => 'png');
return TRUE;
anrikun’s picture

<?php
$image->source = $image->source.'.png';
?>

Remove it.

Then I think I found where the problem is.
In the patched imagecache.module around line 395, replace .jpg by .png in:

<?php
  $dst = imagecache_create_path($preset['presetname'], $path);
  if ($gs = in_array(strtolower(substr($dst, strrpos($dst, '.'))), array('.pdf'))) $dst .= '.jpg'; // Here replace '.jpg' by '.png'
  if (is_file($dst)) {
    imagecache_transfer($dst);
  }
?>

Tell me if it fully works then.

joel_guesclin’s picture

The 5th line was a sort of survival from my hacks trying to keep the png file. After doing the proposed changes it works. I presume what that means however is that you are required to convert the PDF to PNG and not JPEG?
But it works, and that's great - many thanks.

anrikun’s picture

So there's a limitation in my patch: whether output image is jpg or png is hard coded.
Need to find a way to remove this.

selinav’s picture

Hello,

I have followed your tutorial, I have not error message.
If I look on the generated code the img which is called is on pdf format. I've something like that

<img class="imagecache imagecache-parresia imagecache-default imagecache-parresia_default" title="" alt="" src="http://www.mysite.fr/sites/default/files/imagecache/parresia/parresia/parresia101.pdf">

If I try to reach the path, I have a blank page, if I change the extension in jpg or other I have an error page.

How to do to correctly generated the image?

How to see if I have the libraries on my server?

Thanks in advance.

timostegemann’s picture

Hi,

I had the same problem, that there were no images shown. I could solve it by setting the "download method" in the "file system" administration menu (admin/settings/file-system) from public to private.

I hope this helps.

selinav’s picture

Thanks for your advice however it doesn't work for me.

anrikun’s picture

Please visit the example page of this tutorial and tell me if you can see the thumbnail images.

selinav’s picture

It works, I see the image.

anrikun’s picture

Then it should work with your site too.
The fact that the image's file extension is PDF is normal.
You should be able to see it (like you can see it on the example page).
It you cannot, that means that something else is wrong with your config.
Please try again from the beginning.
Can you provide the URL of your page?

Could you please read and try comment-2947724.
Tell us if it works then.

augustynen’s picture

in my rapport details I found this error:

The selected image handling toolkit imageapi_imagemagick can not correctly process imageapi_imagemagick_image_open.

I get the right HTML output but there doens't come up an image.
Nothing

In HTML I get this:

Only local images are allowed.

I can see the thums on the example page.
In my status rapport the error I get is this: 403 file is not an image

I'm working on this a day know, please someone help me !!!

joel_guesclin’s picture

One thing that bothers me about this procedure is that - if I have understood correctly how imagecache works - it systematically converts the files every time the file is viewed. Is this really necessary? Would it not be possible to check first to see if the image file exists, and if it does then just return a "true" value with the file source already in it. I find the page loads very long with my (admittedly rather complex perhaps) PDF's.

anrikun’s picture

No, imagecache does not convert the file every time but only the first time it is viewed.
The converted image is saved to sites/all/files/imagecache directory and stay there unless the original image is deleted or replaced.
Further accesses to this image will get the cached image without converting it again.
That is why it is called imagecache.

Walter Moar’s picture

Step 4 can be made much simpler using the following:

_imageapi_imagemagick_convert(
$image->source . '[0-1]',
$image->source . '0.png',
array(0 => '-thumbnail ' . $w . ' +append')

This will take the first two pages and append them left/right (use -append for above/below).

anrikun’s picture

Great info Walter, I didn't know this option!
I will test it and update the page.
Thank you!

newToo’s picture

I'm using this to combine two images instead of a pdf. It does combine two images but the left and right are the same image.

The source is a cck image field that allows multiple image uploads. I'd only be combining the first two images uploaded.

Any suggestions on what tweaks I would need to make to bring in the first 2 images from a cck image field?

Thank you!

joel_guesclin’s picture

I just had a bizarre issue with imagecache. I looked at page as anonymous user, and some of my images simply did not appear - apparently they were not being generated. Then I logged on as the admin user - and suddenly they appeared ok. Then I looked at page as anonymous user again, and the images were there. What could the problem be? I wondered whether it might be a problem of permissions in Drupal - what exactly are the permissions that need to be set in Drupal to allow an anonymous user to create and view the images? At the moment I have "view imagecache pdf_press" set for all user roles.

joel_guesclin’s picture

I've had no response to this - the problem still recurs intermittently. Maybe it could be something to do with caching (block or page cache?).

KhaledBlah’s picture

Thx a lot! It worked like a charm once I got imagecache working again! :) Would it be possible to incorporate that patch into imagecache so that it's not overwritten with a new version?

@all: if you do forget the patch above you might get a 403 forbidden message when trying to access the preset image.

thsutton’s picture

I used this as a basis for my own custom action using ImageMagick to pre-scale large images outside of Apache's memory space. I found that I had to rebuild all of the $image->info array so that further actions could be performed, but that was easy: http://passingcuriosity.com/2010/drupal-imagecache-imagemagick-gd/

joel_guesclin’s picture

My site was working happily with an older version, patched as per instructions: 6.x-2.x-dev (2009-Oct-09). I upgraded to the latest and recommended version (beta-10), and all of a sudden it no longer worked. The log showed a message like this: "403: File is not an image files/fr/pdf/F_Isme348.pdf".
I put back the old version of the module and it works again - so apparently the various patches and so on have damaged this functionality.

westbywest’s picture

I would be curious to read if anyone has been able to get something like this working in D7.

Wolfgang Reszel’s picture