Bug 52209

Summary: XSLF: Cannot add more than 9 images to a group or slide
Product: POI Reporter: Mike Lundin <mike>
Component: XSLFAssignee: POI Developers List <dev>
Status: RESOLVED FIXED    
Severity: normal    
Priority: P2    
Version: 3.8-dev   
Target Milestone: ---   
Hardware: PC   
OS: All   

Description Mike Lundin 2011-11-18 15:20:42 UTC
I'm hitting an issue with inserting multiple images (more than 10) to either a group or a slide. I've written the following test case that fails and shows the problem:

public void testCreateMultiplePictures() throws IOException {
        XMLSlideShow ppt = new XMLSlideShow();
        XSLFSlide slide = ppt.createSlide();
        XSLFGroupShape group1 = slide.createGroup();
        
        for (int i = 0; i < 20; i++) {
            byte[] data1 = new byte[]{1, 2, (byte)(i/8)};
            int elementIndex = ppt.addPicture(data1, XSLFPictureData.PICTURE_TYPE_PNG);
            XSLFPictureShape picture = group1.createPicture(elementIndex);
            assertEquals("image" + (elementIndex + 1) + ".png", picture.getPictureData().getFileName());
        }
    }

I can fix it, but I don't like the way I fixed it. What I'm finding is that in the OPCPackage.getPartsByName method, the resulting list comes back in alphabetically sorted name order (not index order). So, once you have an image called image10.png, it shows up in the resulting list at a different index and throws everything off. A hack that made things work was to modify the createPicture function in both XSLFGroupShape and XSLFSheet, to look like the following (this is from the XSLFGroupShape): 

public XSLFPictureShape createPicture(int pictureIndex){

        List<PackagePart>  pics = _sheet.getPackagePart().getPackage()
                .getPartsByName(Pattern.compile("/ppt/media/image" + (pictureIndex + 1) + ".*?"));
        
        PackagePart pic = pics.get(0);
        PackageRelationship rel = _sheet.getPackagePart().addRelationship(
                pic.getPartName(), TargetMode.INTERNAL, XSLFRelation.IMAGES.getRelation());

        XSLFPictureShape sh = getDrawing().createPicture(rel.getId());
        sh.resize();
        _shapes.add(sh);
        return sh;
    }

I received the following message from Yegor Kozlov after posting my findings in the users forum:

I confirmed the bug in trunk. Can you please create a new bug in Bugzilla so that we have a record of it.

Your solution might be a good idea. We have a convention that the image number is a part of the image name and can rely on it.

Actually, this bug is a consequence of the API design. In HSLF we refer to images by index and this is how the .ppt format does it - images are stored globally and all objects refer to them by index. All the OOXML-based formats are different - picture is a part of the OPC package and you refer to it by its relationshipId which is a string, so a better version of XSLF would use string (relId) instead of an integer . The main reason we use an integer id is compatibility with HSLF. XSLF and HSLF will eventually converge into a common
Presentation API and basic operations should have similar semantics.

Yegor
Comment 1 Yegor Kozlov 2011-11-19 12:30:44 UTC
Fixed in r1203969, junit added

Yegor