https://bz.apache.org/bugzilla/show_bug.cgi?id=59753

            Bug ID: 59753
           Summary: The XSSFPicture.getPreferredSize returns incorrect
                    anchor col2 and row2 due to error in
                    ImageUtils.setPreferredSize
           Product: POI
           Version: 3.14-FINAL
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: major
          Priority: P2
         Component: XSSF
          Assignee: [email protected]
          Reporter: [email protected]

Created attachment 33986
  --> https://bz.apache.org/bugzilla/attachment.cgi?id=33986&action=edit
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 are receiving this mail because:
You are the assignee for the bug.

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to