Hi Mark,

As discussed previously, I encountered some problems with the anchor type using the HSSFWorkbook ... I now tried the XSSFWorkbook with the same code and, what a miracle, the anchor type works just as it should.

(I had a look at the XSSFPicture source after I wrote this e-mail, see results below...)

But now, I am facing another problem concerning the resize() method of the Picture object.

As long as the image is larger (i.e. higher) than the cell, the resize() works fine. But if the image fits into one cell, the effect of resize() is that the image is scaled differentyl in X and Y. Width is ok, but height seems to be just the default height of a row.

I am attaching the java test code to this e-mail.

What I want to achieve is that one image nicely fits into one cell. Therefore I am setting the cell width and estimating the cell height.

Is it a bug or did I miss anything?

######

After checking the sources of XSSFPicture, I think I found the cause of this behaviour. There is a bug if an image fits into one cell, the calculation of the dx2 and dy2 is wrong:

In the
  public XSSFClientAnchor getPreferredSize(double scale)
method, the remaining X (dx2) in the next column is caluclated as follows:

    if (w > scaledWidth) {
      double cw = getColumnWidthInPixels(col2 + 1);
      double delta = w - scaledWidth;
      dx2 = (int) (EMU_PER_PIXEL * (cw - delta));
    }

which will give wrong results, if the image does not touch the neighbouring column. I have added a test as follows:

    if (w > scaledWidth) {
      double cw = getColumnWidthInPixels(col2 + 1);
      double delta = w - scaledWidth;
      dx2 = (int) (EMU_PER_PIXEL * (cw - delta));
      // test single col:
      if (col2 == anchor.getCol1()) {
        dx2 = (int) (EMU_PER_PIXEL * scaledWidth);
      }
    }

which solves the problem. Same for the rows in the same method:

    if (h > scaledHeight) {
      double ch = getRowHeightInPixels(row2 + 1);
      double delta = h - scaledHeight;
      dy2 = (int) (EMU_PER_PIXEL * (ch - delta));
      // again test single row:
      if (row2 == anchor.getRow1()) {
        dy2 = (int) (EMU_PER_PIXEL * scaledHeight);
      }
    }


I am going to build the poi-ooxml library myself, although there is one import missing in the XWPFStyle class:

import org.openxmlformats.schemas.wordprocessingml.x2006.main.STStyleType;

I checked the poi-ooxml-schemas-3.7-20101029.jar and indeed this class is not there. Anyway, I am commenting out the two methods

  public void setType(STStyleType.Enum type)
and
  public STStyleType.Enum getType()

hoping it won't do too much harm.

Cheers,
Hannes

PS: I am sending this as CC to the dev-list as well.


Am 07.02.2011 18:00, schrieb Mark Beardsley:
Will have a look at the attached example when I can. Sadly, I am away from
home at the moment and stuck using a laptop that does not have POI, Java or
Excel on it unfortunately


--
GRID-IT Gesellschaft für angewandte Geoinformatik mbH
Dr. Hannes Kleindienst

Technikerstrasse 21a, A-6020 Innsbruck
web www.grid-it.at
tel +43-(0)512-507 4861

mobil +43-(0)676-4300399
fax +43-(0)512-5074869
mail [email protected]
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.imageio.ImageIO;
import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.ss.usermodel.Drawing;
import org.apache.poi.ss.usermodel.Picture;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

/**
 * @author Hannes Kleindienst
 */
public class POItest {


  public static void main(String[] args) throws Exception {
    /** XLS workbook */
    Workbook wb = new XSSFWorkbook();
    // create sheet
    Sheet sheet = wb.createSheet("Liste");
    // set width to 200px
    sheet.setColumnWidth(0, (int) (200 * 36.5));
    // add image
    POItest.setCell(wb, sheet, 1, 0, 200, new File("img1.jpg"), 
ClientAnchor.DONT_MOVE_AND_RESIZE);
    POItest.setCell(wb, sheet, 2, 0, 200, new File("img1.jpg"), 
ClientAnchor.MOVE_AND_RESIZE);
    POItest.setCell(wb, sheet, 3, 0, 200, new File("img1.jpg"), 
ClientAnchor.MOVE_DONT_RESIZE);

    // write output
    File outputfile = new File("poitest.xlsx");
    FileOutputStream fos = new FileOutputStream(outputfile);
    wb.write(fos);
    fos.close();
  }


  public static void setCell(Workbook wb, Sheet sheet, int row, int col, int 
width, File imagefile, int anchortype) {
    // check if the image file exists
    if (!imagefile.exists()  || !imagefile.isFile()) {
      return;
    }
    try {
      // get the image
      BufferedImage img = POItest.resizeImage(ImageIO.read(imagefile), width*2);
      // calculate and set height (width is 200px)
      int height = img.getHeight();
      // get or create row
      Row r = sheet.getRow(row);
      if (r == null) {
        r = sheet.createRow(row);
      }
      r.setHeightInPoints(0.5F * height * 0.75F + 1);

      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      ImageIO.write(img, "JPG", baos);
      int pictureIdx = wb.addPicture(baos.toByteArray(), 
Workbook.PICTURE_TYPE_JPEG);
      // Create the drawing patriarch. This is the top level container for all 
shapes.
      Drawing drawing = sheet.createDrawingPatriarch();
      CreationHelper helper = wb.getCreationHelper();
      // create anchor
      ClientAnchor anchor = helper.createClientAnchor();
      anchor.setCol1(col);
      anchor.setRow1(row);
      anchor.setAnchorType(anchortype);
      //subsequent call of Picture#resize() will operate relative to it
      Picture pict = drawing.createPicture(anchor, pictureIdx);
      //auto-size picture relative to its top-left corner
//      pict.resize(0.5);
      pict.resize(0.51);
//      pict.resize();

    } catch (IOException ex) {
      ex.printStackTrace();
    }
  }


  public static BufferedImage resizeImage(BufferedImage img, int newW) {
    // current dimensions
    int w = img.getWidth();
    int h = img.getHeight();
    // calc new h
    int newH = (int) (h * ((float) newW) / w);
    int type = img.getType();
    // render image
    BufferedImage resizedImage = new BufferedImage(newW, newH, 
BufferedImage.TYPE_INT_RGB);
    Graphics2D g = resizedImage.createGraphics();
    g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
            RenderingHints.VALUE_INTERPOLATION_BILINEAR);
    g.drawImage(img, 0, 0, newW, newH, 0, 0, w, h, null);
    g.dispose();
    // return result
    return resizedImage;
  }

}

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

Reply via email to