twelvemonkeys

Read multiple paths using Twelve Monkeys library


I am trying to get paths from JPEG file using the code below

import com.twelvemonkeys.imageio.path.Paths;
...
Shape clip = Paths.readPath(stream);

It works but I always get the first path. Is there a way to get other paths if my JPEG has more than 1?

In ImageMagick, I am able to get other paths using:

identify -format '%[8BIM:1999,2998:#2]'

Solution

  • The high-level Paths class only has methods for getting the first path (with resource id 2000).

    However, the API should allow you to read all paths in a similar fashion, if you look at the code in the Paths class (the code below is adapted from the library).

    For JPEG, you will first need to locate the Photoshop resources in the file:

    Map<Integer, List<String>> segmentIdentifiers = singletonMap(JPEG.APP13, singletonList("Photoshop 3.0"));
    List<JPEGSegment> photoshop = JPEGSegmentUtil.readSegments(stream, segmentIdentifiers);
    
    if (!photoshop.isEmpty()) {
        InputStream data = null;
    
        for (JPEGSegment ps : photoshop) {
            data = data == null ? ps.data() : new SequenceInputStream(data, ps.data());
        }
    
        // data should now contain all Photoshop resources
    }
    
    

    You can probably do the above in different ways too, if you are familiar with how JPEGs are structured.

    Then, to parse the Photoshop resources and the path objects inside them:

    ImageInputStream stream = new MemoryCacheImageInputStream(data);
    Directory resourceBlocks = new PSDReader().read(stream);
    
    List<Path2D> paths = new ArrayList<>();
            
    for (Entry resourceBlock : resourceBlocks) {
        int identifier = (Integer) resourceBlock.getIdentifier();
    
        if (identifier >= PSD.RES_CLIPPING_PATH && identifier < PSD.RES_CLIPPING_PATH + 998) {
            paths.add(new AdobePathReader((byte[]) resourceBlock.getValue()).readPath());
        } 
    }
    
    

    It's possible to add a method to the Paths class that does the above and returns a list or array of Path2D objects, if you think that is useful. In that case, please open an issue in the Github issue tracker, and attach a small file with multiple paths. 😀