It's better to work not with stream of PDXObjectImage but create new instance of PDXObjectImage and replace it in resources collection. It's more generic and universal way. Use getRGBImage() to convert PDXObjectImage to BufferedImage and constructor (PDPixelMap, PDJpeg etc) to convert edited result back to PDXObjectImage. Note you still have problems with JBIG2 and Jpeg2000 images due to bugs. Here is code example I use to find and convert all images in document:
// Recursive resource processor
// Here can be images inside in PDXObjectForm objects
protected static void processResources(PDResources resources, PDDocument doc, String filename) throws IllegalArgumentException, SecurityException, IOException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, JBIG2Exception, ColorSpaceException, ICCProfileException
{
if(resources == null) return;
Map<String, PDXObject> xObjects = resources.getXObjects();
if (xObjects == null) return;
// iterate by images
Iterator<String> imageIter = xObjects.keySet().iterator();
while (imageIter.hasNext())
{
String key = imageIter.next();
PDXObject o = xObjects.get(key);
if(o instanceof PDXObjectImage)
xObjects.put(key, processImage((PDXObjectImage) o /*, some additional parms... */));
if(o instanceof PDXObjectForm)
processResources(((PDXObjectForm) o).getResources(), doc, filename);
}
resources.setXObjects(xObjects);
}
Note resources.setXObjects() call at the end - without it changes you made in collection obtained by resources.getXObjects() will not be written back to document.