0

I'm looking to convert a large directory of thumbnails.

Instead of using the PythonMagick wrapper I'd like to access the convert binary directly (I have a lot of flags, and think this would be more efficient for a large quantity of photos.)

Are there any working examples of using ImageMagick as a subprocess? Or, is there a better way to do this?

Specifically, I'm not sure how to start and end a Python subprocess from within a class. My class is called ThumbnailGenerator. I'm hoping to make something like this:

>> t = ThumbnailGenerator()
>> t.makeThumbSmall('/path/to/image.jpg')  
>> True
ensnare
  • 40,069
  • 64
  • 158
  • 224
  • It should be pretty easy to do using `subprocess.Popen` or `subprocess.call`. What does your commandline look like? – mgilson Aug 30 '12 at 19:45
  • It's not so much the command line I'm confused about, but how to start, stop, and call this kind of subprocess from within my class. I updated the question to be more specific. Thanks – ensnare Aug 30 '12 at 19:50
  • @ensnare: I 'm not aware of a way to run convert in batch mode, though I did not double check. Is this what you are aiming at? – Sven Marnach Aug 30 '12 at 19:53
  • @SvenMarnach Yes, or at least to keep the executable open so I can keep throwing convert strings to it. That would be more efficient, right? – ensnare Aug 30 '12 at 19:54
  • @ensnare: It is much more efficient for things like `exiftool`, where the overhead of starting the Perl interpreter is quite significant compared to the actual operation, which consists of only extracting the metadata. For `convert`, it's quite the opposite: The startup overhead is rather small, and the actual work more significant, so the percentage of the overhead is small. I would either use PythonMagick, PIL, or not bother about the overhead. (I've used the latter two approaches in the past.) – Sven Marnach Aug 30 '12 at 19:57

1 Answers1

4

Here's what I've used in a personal project:

def resize_image(input, output, size, quality=None, crop=False, force=False):
    """
    Invoke ImageMagick's `convert` utility to resize an image.

    Arguments:

        input - the path of the input file
        output - the path of the output file
        size - a size string in the format <width>x<height> 
        quality - a number indicating the JPEG quality (100 = best)
        crop - Boolean value indicating whether to crop the image
            to the given size instead of scaling it
        force - Boolean value indicating whether to overwrite the
            output image even if it exists
    """
    if (not force and os.path.exists(output) and
        os.path.getmtime(output) > os.path.getmtime(input)):
        return
    params = []
    if crop:
        params += ["-resize", size + "^"]
        params += ["-gravity", "Center", "-crop", size + "+0+0"]
    else:
        params += ["-resize", size]
    params += ["-unsharp", "0x0.4+0.6+0.008"]
    if quality is not None:
        params += ["-quality", str(quality)]
    subprocess.check_call(["convert", input] + params + [output])

This will start one process per conversion. If the source images aren't too small, the process startup overhead will be comparatively small.

Sven Marnach
  • 574,206
  • 118
  • 941
  • 841
  • Thanks a lot. Can you give me an example of how to use this function? I tried `resize_image('231072600062.png', 'Output.png', 350*460) ` – YasserKhalil Mar 25 '22 at 12:28
  • 1
    @YasserKhalil This function is a bit idiosyncratic, and probably needs some adaption to be useful for your use case. I added a docstring to make clearer what it does. The size should be a string, e.g. `"350x460"`. – Sven Marnach Mar 25 '22 at 12:53
  • Thanks a lot. I tried to test using this line `resize_image('Test1.jpg', 'Yasser.jpg', "100x100") ` but I got `subprocess.CalledProcessError: Command '['convert', 'Test1.jpg', '-resize', '100x100', '-unsharp', '0x0.4+0.6+0.008', 'Yasser.jpg']' returned non-zero exit status 4.` – YasserKhalil Mar 25 '22 at 12:58
  • 1
    @YasserKhalil The `convert` tool should show an error message when this happens. If you don't see the error message for some reason, try running the command line directly, i.e. run `convert Test1.jpg -resize 100x100 -unsharp 0x0.4+0.6+0.008 Yasser.jpg` in the shell. You will probably get some file access error, e.g. input file not found or permission denied. – Sven Marnach Mar 28 '22 at 09:11