9

I'm trying to add a clipping path to a TIFF image. I made one TIFF file with GIMP that contains a clipping path and I can clip my image using it by

$img = new Imagick("./test.tiff");
$img->clipPathImage("#1", false);

But I would like to append clipping path info as coordinates like GIMP does into the image file itself so later another process can read it...

I've tried with ImagickDraw, pathStart... pathFinish but it draws something on image not as a path that I can see in GIMP like

enter image description here

Edit: Solutions in other languages are appreciated.

tanaydin
  • 5,171
  • 28
  • 45
  • I think you mean [setImageClipMask()](https://www.php.net/manual/en/imagick.setimageclipmask.php), it has an example. – KIKO Software Jun 06 '19 at 11:56
  • I've tried exactly the same code, but in the end, it generates a clipped image. Instead of writing path information in the file. – tanaydin Jun 06 '19 at 11:58
  • Yes, that's true. I did find [this](http://www.imagemagick.org/Usage/masking/#clip). I'm not sure but maybe that's also returned with [identifyFormat()](https://www.php.net/manual/en/imagick.identifyformat.php)? It's worth a try (I don't have a clipped TIFF at hand). – KIKO Software Jun 06 '19 at 12:09
  • I've also tried that but couldn't get desired output. with identify and append raw output optiomn i can see SVG definition of path but I cannot write on it. – tanaydin Jun 06 '19 at 12:26
  • I'm not sure I understand you, but if you use the command line option you can retrieve the output with [shell_exec()](https://www.php.net/manual/en/function.shell-exec.php). – KIKO Software Jun 06 '19 at 12:35
  • I can read that information with $output = $img->identifyFormat("%[8BIM:1999,2998:Path 1]"); But I would like to write it... I'm just trying to read it first for understanding. – tanaydin Jun 06 '19 at 12:41

3 Answers3

2

After posting the previous java based answer, I was wondering if it would be possible to script gimp in a way to do what we want. Turns out this is possible and quite easy!

First install the following gimp plugin wich loads the image, draws the path and then saves the image as tif. Copy it to your gimp plugins folder. On Mac this is ~/Library/Application Support/GIMP/2.10/plug-ins/addpath.py. Create the plug-ins folder if it doesn't exist yet. Also make sure the python file is executable by the user who runs gimp (chmod u+x addpath.py).

#!/usr/bin/env python

from gimpfu import pdb, main, register, PF_STRING

def add_path(infile, outfile):
    image = pdb.gimp_file_load(infile, 'image')
    vectors = pdb.gimp_vectors_new(image, 'clippath')
    w = image.width
    h = image.height
    path = [
        # The array of bezier points for the path.
        # You can modify this for your use-case.
        # This one draws a rectangle 10px from each side.
        # Format: control1-x, control1-y, center-x, center-y, control2-x, control2-y
        10, 10, 10, 10, 10, 10,
        w - 10, 10, w - 10, 10, w - 10, 10,
        w - 10, h - 10, w - 10, h - 10, w - 10, h - 10,
        10, h - 10, 10, h - 10, 10, h - 10
    ]
    pdb.gimp_vectors_stroke_new_from_points(vectors, 0, len(path), path, True)
    pdb.gimp_image_add_vectors(image, vectors, 0)
    drawable = pdb.gimp_image_get_active_layer(image)
    pdb.file_tiff_save(image, drawable, outfile, 'image.tif', 0)

args = [(PF_STRING, 'infile', 'GlobPattern', '*.*'), (PF_STRING, 'outfile', 'GlobPattern', '*.*')]
register('python-add-path', '', '', '', '', '', '', '', args, [], add_path)

main()

After that, you can start gimp without user interface in batch mode, executing the plugin.

gimp -i -b '(python-add-path RUN-NONINTERACTIVE "/absolute/path/to/your/input/file.png" "/absolute/path/to/the/tif/file.tif")' -b '(gimp-quit 0)'

Without the second -b '(gimp-quit 0)' gimp keeps running. You can also ask gimp to read the batch commands from stdin. That way it stays open and you can send new "add-path" commands to it simply by writing to stdin.

gimp -i -b -

Florian Gutmann
  • 2,666
  • 2
  • 20
  • 28
  • That is nice! I was thinking to write a gimp plug-in also so that will be a good starting point for my requirements. Thank you very much. – tanaydin Jun 17 '19 at 07:51
1

This answer is about how it could be done in Java. Unfortunately there is no 100% ready solution and some things you would need to implemented yourself.

The clipping path extension to TIFF is a proprietary extension from Adobe. Basically they use a custom TIFF tag (34377/Photoshop) to store a Photoshop path element along the original image data.

The TwelveMonkeys image library has an implementation for reading the photoshop path format, also directly from tiff Images.

Unfortunately it lacks support for writing the photoshop path data. This is the part that you would have to implement yourself. Here is the related code for reading the path data. The format is also quite well documented here. Depending on your use case you might not need to implement full path writing support, but only the parts you need.

Here is a good related post about writing multi-layered tiff images which contains information about how the final image can be constructed and written in Java.

Florian Gutmann
  • 2,666
  • 2
  • 20
  • 28
0

The TwelveMonkeys image library version 3.5 includes functionality for reading and writing Adobe Photoshop clipping paths (supporting PSD, JPEG and TIFF). Use class Paths as starting point.

Add this dependency to your Java project:

<dependency>
  <groupId>com.twelvemonkeys.imageio</groupId>
  <artifactId>imageio-clippath</artifactId>
  <version>${twelvemonkeys.version}</version> <!-- 3.5 for now -->
</dependency>
rmuller
  • 12,062
  • 4
  • 64
  • 92