Created attachment 33986 [details] test.png If I do the following: Workbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet(); byte[] imageBytes = org.apache.commons.io.IOUtils.toByteArray(new FileInputStream(test.png)); Drawing drawing = sheet.createDrawingPatriarch(); int pictureIdx = workbook.addPicture(imageBytes, Workbook.PICTURE_TYPE_PNG); CreationHelper helper = workbook.getCreationHelper(); ClientAnchor anchor = helper.createClientAnchor(); anchor.setCol1(0); // Not needed, but let's make sure we are in the upper left anchor.setRow1(0); // corner of the spreadsheet. Picture pict = drawing.createPicture(anchor, pictureIdx); anchor.pict.getPreferredSize(); //This will return 1 and 1 for col2/row2 pict.resize(0.75); //This will return 0 and 0 for col2/row2 int lastColumn = anchor.getCol2(); int lastRow = anchor.getRow2(); The last row and column are useful for placing other data below or beside the image. The byte array is used to get an image stored in memory and not on the file system. ImageUtils.setPreferredSize snippet for col2: // in pixel Dimension imgSize = getImageDimension(new ByteArrayInputStream(data.getData()), data.getPictureType()); // in emus Dimension anchorSize = ImageUtils.getDimensionFromAnchor(picture); final double scaledWidth = (scaleX == Double.MAX_VALUE) ? imgSize.getWidth() : anchorSize.getWidth()/EMU_PER_PIXEL * scaleX; final double scaledHeight = (scaleY == Double.MAX_VALUE) ? imgSize.getHeight() : anchorSize.getHeight()/EMU_PER_PIXEL * scaleY; double w = 0; int col2 = anchor.getCol1(); int dx2 = 0; //space in the leftmost cell w = sheet.getColumnWidthInPixels(col2++); if (isHSSF) { w *= 1d - anchor.getDx1()/1024d; } else { w -= anchor.getDx1()/(double)EMU_PER_PIXEL; } while(w < scaledWidth){ w += sheet.getColumnWidthInPixels(col2++); } if(w > scaledWidth) { //calculate dx2, offset in the rightmost cell double cw = sheet.getColumnWidthInPixels(--col2); double delta = w - scaledWidth; if (isHSSF) { dx2 = (int)((cw-delta)/cw*1024); } else { dx2 = (int)((cw-delta)*EMU_PER_PIXEL); } if (dx2 < 0) dx2 = 0; } anchor.setCol2(col2); anchor.setDx2(dx2); This is the snippet from XSSFPicture.getPreferredSize in 3.8: XSSFClientAnchor anchor = (XSSFClientAnchor)getAnchor(); XSSFPictureData data = getPictureData(); Dimension size = getImageDimension(data.getPackagePart(), data.getPictureType()); double scaledWidth = size.getWidth() * scale; double scaledHeight = size.getHeight() * scale; float w = 0; int col2 = anchor.getCol1(); int dx2 = 0; for (;;) { w += getColumnWidthInPixels(col2); if(w > scaledWidth) break; col2++; } if(w > scaledWidth) { double cw = getColumnWidthInPixels(col2 ); double delta = w - scaledWidth; dx2 = (int)(EMU_PER_PIXEL*(cw-delta)); } anchor.setCol2(col2); anchor.setDx2(dx2); double h = 0; int row2 = anchor.getRow1(); int dy2 = 0; for (;;) { h += getRowHeightInPixels(row2); if(h > scaledHeight) break; row2++; } if(h > scaledHeight) { double ch = getRowHeightInPixels(row2); double delta = h - scaledHeight; dy2 = (int)(EMU_PER_PIXEL*(ch-delta)); } anchor.setRow2(row2); anchor.setDy2(dy2); Also please note as you debug that the scaledWidth and scaledHeight in 3.14 end up being almost identical to the value returned from columnWidthInPixels. The columnWidthInPixels is ~6 pixels smaller that the 3.8 version. The 3.8 version increments the columns with a check of w against the number of pixels in the width of the picture. So you end up with an image that is always squeezed into a single cell.
You end up with a single cell in 3.14 and a correct image in 3.8.
I did some tests on my machine and found this worked as late as 3.10-FINAL, but was broken in the 3.11 release. Interestingly 3.11, 12, and 13 return col2 as 1 and row2 as 0. 3.14 has both col2 and row2 as 0.