docx icon indicating copy to clipboard operation
docx copied to clipboard

Allow to specify image fileName and emu dimensions

Open tripodsan opened this issue 4 years ago • 6 comments

  • allowing to specify the fileName would help reducing the document size if the same image is included several times
  • allowing to specify the transformation.emus separately would allow to better set the image dimensions irrespective of the pixels.

tripodsan avatar Mar 23 '21 06:03 tripodsan

currently, I need to hack it like this:

  const drawing = new Drawing(imageData, { floating: false });
  // hack to get document properties to set alt text
  if (node.title || node.alt) {
    const docProps = findXMLComponent(drawing, 'wp:inline/wp:docPr/_attr');
    if (docProps && docProps.root) {
      docProps.root.name = title || '';
      docProps.root.descr = alt;
    }
  }

  // create picture
  const pic = new ImageRun({
    data: data.buffer,
    transformation: data.dimensions,
  });
  // replace drawing with custom filename and emu dimensions
  const oldDrawing = findXMLComponent(pic, 'w:drawing');
  const idx = pic.root.indexOf(oldDrawing);
  if (idx >= 0) {
    pic.root.splice(idx, 1);
  }
  pic.root.push(drawing);
  pic.key = key;
  pic.imageData = imageData;

tripodsan avatar Mar 23 '21 07:03 tripodsan

allowing to specify the fileName would help reducing the document size if the same image is included several times

This one is done now!

allowing to specify the transformation.emus separately would allow to better set the image dimensions irrespective of the pixels.

Hmm not so sure, emu is is not as intuitive, and is just a scale factor of 9525, so maybe it isn't worth the effort

Can raise again if people have interest

dolanmiu avatar Jun 15 '22 01:06 dolanmiu

thank you.

Hmm not so sure, emu is is not as intuitive, and is just a scale factor of 9525, so maybe it isn't worth the effort

but you are already using emu for the floating offsets.

The problem I found is, that if I want to keep the information about the original dimensions of the image, but scale it differently, eg restricting the width/height of an image inside a table, I need to set the emus.

eg:

  let x = data.dimensions.width * 9525;
  let y = data.dimensions.height * 9525;
  const limits = ctx.tableAlign ? LIMITS_TABLE : LIMITS;
  if (x > limits.width) {
    y = Math.round((limits.width * y) / x);
    x = limits.width;
  }
  if (y > limits.height) {
    x = Math.round((limits.height * x) / y);
    y = limits.height;
  }

  const imageData = {
    stream: data.buffer,
    fileName: data.key,
    transformation: {
      pixels: {
        x: Math.round(data.dimensions.width),
        y: Math.round(data.dimensions.height),
      },
      emus: {
        x,
        y,
      },
    },
  };

and then create the Drawing and replace the image as described above.

tripodsan avatar Jun 15 '22 07:06 tripodsan

Ok, I see the issue, maybe changing the API to allow for both options is a good idea

dolanmiu avatar Jun 15 '22 12:06 dolanmiu

allowing to specify the fileName would help reducing the document size if the same image is included several times

This one is done now!

How it is done? Maybe I don't see something, but after some experiments and analysis of the ImageRun class, I see that file name is always randomly generated for each instance of ImageRun.

Simplest solution that I see is to add optional uniqueId to RegularImageOptions and SvgMediaOptions and use them when generating keys:

this.key = `${options.uniqueId || uniqueId()}.${options.type}`;
this.fallbackKey = `${options.fallback?.uniqueId || uniqueId()}.png`;

If this solution is acceptable, I can prepare a PR.


Edit:

Attaching minimal reproducible example: mre.txt

After running, we can see two png files.

kildom avatar Jan 24 '24 00:01 kildom