Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Image opacity option not working #175

Open
ytaborda17 opened this issue Mar 3, 2020 · 6 comments
Open

Image opacity option not working #175

ytaborda17 opened this issue Mar 3, 2020 · 6 comments
Assignees
Labels

Comments

@ytaborda17
Copy link

I tried to use the opacity option with an image and is not working, if you open the file image in node_modules, you can see option.opacity declared but never used, but the documentation says you can use that property, in resume: it's not working

pdf.image(path + fileName, 361, 326, { width: 600, height: 450, keepAspectRatio: true, opacity: 10, align: 'center center' });

@chunyenHuang
Copy link
Owner

It seems to me the range for opacity is 0.0 - 1.0

@ytaborda17
Copy link
Author

It doesn't matter the number you use in the option:

  • 0.8 / 0,8
  • 0.5 / 0,5
  • 1
  • 1505656565

It doesn't work, because the option is never used in the library, if you open the file /node_modules/hummus-recipe/lib/image.js you can se the option been declared, but is never used:

`/**

  • Place images to pdf

  • @name image

  • @function

  • @memberof Recipe

  • @param {string} imgSrc - The path for the image. [JPEG, PNG, TIFF]

  • @param {number} x - The coordinate x

  • @param {number} y - The coordinate y

  • @param {Object} [options] - The options

  • @param {number} [options.width] - The new width

  • @param {number} [options.height] - The new height

  • @param {number} [options.scale] - Scale the image from the original width and height.

  • @param {boolean} [options.keepAspectRatio=true] - Keep the aspect ratio.

  • @param {number} [options.opacity] - The opacity.

  • @param {string} [options.align] - 'center center'...
    */
    exports.image = function image(imgSrc, x, y, options = {}) {
    const { width, height, offsetX, offsetY } = this._getImgOffset(imgSrc, options);
    const imgOptions = {
    transformation: {
    fit: 'always',
    // proportional: true,
    width,
    height
    }
    };
    const { nx, ny } = this._calibrateCoordinate(x, y, offsetX, offsetY);

    const _options = this._getPathOptions(options, nx, ny);
    const gsId = _options.fillGsId;

    // See if this image has been seen already, so as to not duplicate it.
    let xObject = this.xObjects.find((element) => {
    return element.get('name') == imgSrc;
    });

    if (xObject) {
    _options.xObject = xObject;
    _options.ratio = [width / xObject.get('width'), height / xObject.get('height')];
    }

    this._drawObject(this, nx, ny, width, height, _options, (ctx, xObject) => {

     // Only new images visit here
     xObject.set('type', 'image');
     xObject.set('name', imgSrc);
     xObject.set('width', width);
     xObject.set('height', height);
    
     this.xObjects.push(xObject);
    
     ctx
         .gs(xObject.getGsName(gsId))
         .drawImage(0, 0, imgSrc, imgOptions);
    

    });

    return this;
    };

exports._getImgOffset = function _getImgOffset(imgSrc = '', options = {}) {
// set default to true
options.keepAspectRatio = (options.keepAspectRatio == void 0) ?
true : options.keepAspectRatio;
const dimensions = this.writer.getImageDimensions(imgSrc);
const ratio = dimensions.width / dimensions.height;

let width = dimensions.width;
let height = dimensions.height;
if (options.scale) {
    width = width * options.scale;
    height = height * options.scale;
} else
if (options.width && !options.height) {
    width = options.width;
    height = options.width / ratio;
} else
if (!options.width && options.height) {
    width = options.height * ratio;
    height = options.height;
} else
if (options.width && options.height) {
    if (!options.keepAspectRatio) {
        width = options.width;
        height = options.height;
    } else {
        // fit to the smaller
        if (options.width / ratio <= options.height) {
            width = options.width;
            height = options.width / ratio;
        } else {
            width = options.height * ratio;
            height = options.height;
        }
    }
}
let offsetX = 0;
let offsetY = -height;

if (options.align) {
    const alignments = options.align.split(' ');
    if (alignments[0]) {
        switch (alignments[0]) {
            case 'center':
                offsetX = -1 * width / 2;
                break;
            case 'right':
                offsetX = width / 2;
                break;
            default:
        }
    }
    if (alignments[1]) {
        switch (alignments[1]) {
            case 'center':
                offsetY = -1 * height / 2;
                break;
            case 'bottom':
                offsetY = height / 2;
                break;
            default:
        }
    }
}
return { width, height, offsetX, offsetY };

};`

@chunyenHuang
Copy link
Owner

It doesn't matter the number you use in the option:

@ytaborda17 Please don't be mad. It does not mean the opacity is not applied if you dont find it in the code. PDF operator does not have a field called opacity, instead it calls gs when writing context.
https://github.com/chunyenHuang/hummusRecipe/blob/master/lib/image.js#L53.

I just run the following test and it seems to me the opacity works as expected. Please see the attached screen shot.

const path = require('path');
const HummusRecipe = require('../lib');

describe('Modify', () => {
    const taskATP = 'Add transparent png';
    it(taskATP, (done) => {
        const src = path.join(__dirname, 'materials/test.pdf');
        const output = path.join(__dirname, `output/${taskATP}.pdf`);
        const wikiPng = path.join(__dirname, 'materials/wiki.png');

        const recipe = new HummusRecipe(src, output);
        recipe
            .editPage(1)
            .image(wikiPng, 'center', 'center', {
                width: 300,
                height: 300,
                align: 'center center',
                opacity: 0.5,
            })
            .endPage()
            .endPDF(done);
    });
});

Screen Shot 2020-03-03 at 6 58 58 PM

If you still can not make it work, please post your code so I can take a look for you.

@ytaborda17
Copy link
Author

ytaborda17 commented Mar 7, 2020

Ok, still not working, thanks any way, as you said, here is the code:

async function newPdf(data) {
  const order = Object.keys(data.cotizar.companias).sort();

  // client files + folder
  const fileName = data.quoteId + '.pdf';
  const folderName = data.nid + data.nid_dv;

  // pdf
  const origPath = PDF_PATH + 'base.pdf';
  const destPath = PDF_PATH + '/' + folderName + '/' + fileName;

  // logos
  const p = require('path')
  let logos = {
      path: p.join(__dirname, '../../shared/logos/'),
      files: {
          partner: data.user.partner.name
      }
  };

  common.createFolder(PDF_PATH + '/', folderName);

  return await new Promise((resolve, reject) => {
      const pdfDoc = new HummusRecipe(origPath, destPath);
      resolve(pdfDoc);
  }).then((page1header) => { // page1header
      page1header.editPage(1);
      if (data.user.partner.logo.indexOf('http') !== -1) {
          page1header.image(logos.path + logos.files.partner, 700, 32, {
              width: 100,
              height: 30,
              keepAspectRatio: true,
              align: 'center center'
          });
          // water mark
          page1header.image(logos.path + logos.files.partner, 361, 326, { // center: 371, 306,
              width: 600,
              height: 450,
              keepAspectRatio: true,
              opacity: 0.3,
              align: 'center center'
          });
      }
      page1header.text(data.form.date, 119, 40, { color: '#000000', size: 7 })
          .text('No: ' + data.quoteId, 665, 550, { color: '#000000', size: 7, bold: true })
          .text(data.form.name.toUpperCase(), 145, 63, { color: '#000000', size: 7 })
          .text(`${data.form.badge} ${data.form.cold}`, 370, 61, { color: '#000000', size: 7 })
          .text(common.currency(data.form.value, 0), 626, 83, { color: '#000000', size: 9, align: 'center', bold: true })

      return page1header;
  }).then((page2) => { // pag 2
      let x = 60;
      let y = 170;
      order.forEach(item => {
          if (item) {
            // ... print image and text an stuff
            // ... everything ok here
          }
      });
      page2.endPage().endPDF();
      return page2;
  }).then(() => { //Upload and save
      return {
          destPath: destPath,
          awsPath: 'path/' + folderName + '/' + fileName,
          quoteId: data.quoteId
      };
  }).catch(err => {
      throw new ErrorHandler(500, '--> Code not working U suck!', err);
  });

}

So, what I'm I doing wrong? Beacuse, with or without an opacity option, the image is printed but in full color.

I'm using Node 12.16.1, and before you say it, a downgrade is not a solution.

@chunyenHuang
Copy link
Owner

Oh I see the where the issue is.

          page1header.image(logos.path + logos.files.partner, 700, 32, {
              width: 100,
              height: 30,
              keepAspectRatio: true,
              align: 'center center'
          });
          // water mark
          page1header.image(logos.path + logos.files.partner, 361, 326, { // center: 371, 306,
              width: 600,
              height: 450,
              keepAspectRatio: true,
              opacity: 0.3,
              align: 'center center'
          });

You called .image twice with different opacity setups. It is a bug that the xObject is cached so the opacity is locked to the first image.

I can reproduce this bug with the following codes

const path = require('path');
const HummusRecipe = require('../lib');

describe('Modify', () => {
    const taskATP = 'Add transparent png';
    it(taskATP, (done) => {
        const src = path.join(__dirname, 'materials/test.pdf');
        const output = path.join(__dirname, `output/${taskATP}.pdf`);
        const wikiPng = path.join(__dirname, 'materials/wiki.png');

        const recipe = new HummusRecipe(src, output);
        recipe
            .editPage(1)
            .image(wikiPng, 'center', 50, {
                width: 300,
                height: 300,
                align: 'center center',
                opacity: 0.8,
            })
            .image(wikiPng, 'center', 'center', {
                width: 300,
                height: 300,
                align: 'center center',
                opacity: 0.1,
            })
            .endPage()
            .endPDF(done);
    });
});

@chunyenHuang chunyenHuang added bug Next Patch next patch version labels Mar 7, 2020
@chunyenHuang chunyenHuang self-assigned this Mar 7, 2020
chunyenHuang added a commit that referenced this issue Mar 7, 2020
@chunyenHuang
Copy link
Owner

Screen Shot 2020-03-06 at 9 45 24 PM

The new version should fix this issue for you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants