moo-man / FVTT-DD-Import

Allows Importing Dungeondraft map files into FoundryVTT
MIT License
60 stars 28 forks source link

Generated Image Issues with Modified Pixels_Per_Grid Value #107

Closed gabrieljtaylor closed 2 years ago

gabrieljtaylor commented 2 years ago

Summary:

When generating the map image from the DD2VTT file in which the pixels_per_grid value has been changed, the resulting image does not honor the pixels_per_grid changed value. The result is also different for PNG output and Webp output, with each format displaying different issues.

Expected behavior:

Actual behavior:

Steps to Reproduce:

  1. Generate a DD2VTT file with a large pixels_per_grid value (such as 200 or 256)
  2. Modify the DD2VTT JSON to reduce the pixels_per_grid value to a more reasonable value (such as 100)
  3. Use the Universal Battlemap Importer to import the scene into Foundry twice, once with the "Convert to Webp" option selected and once with it deselected.
  4. Compare the details of the generated Webp and PNG image files on the server, both their dimensions and the image itself

Version Information:

What I've Done So Far:

I plan to fork the repo and play around with the image generation code to see if I can figure out the fix, but also, as mentioned above, I don't know Javascript very well, so I am not certain I will have success or efficiency. I'm filing this issue both for awareness and also in hope someone with more Javascript knowledge than me might realize an easy fix and knock it out.

gabrieljtaylor commented 2 years ago

I've managed to figure out a fix for both issues when combining multiple images together - by passing the desired height and width to the image2Canvas function, the generated image is the correct size, with the correct contents and proportions, both when converting to webp and when not converting. I'll submit a pull request with my changes later (once all of my changes are ready for testing), but the specific code changes are these:

Line 258 changes to:

            await DDImporter.image2Canvas(mycanvas, f, image_type, size.x, size.y)

The image2Canvas function changes to:

  static image2Canvas(canvas, file, extension, imagewidth, imageheight){
    return new Promise( function(resolve){
      var image = new Image();
      image.decoding = 'sync';
      image.addEventListener('load', function() {
          image.decode().then(() => {
            canvas.drawImage(image, file.pos_in_image.x, file.pos_in_image.y, imagewidth, imageheight);
            resolve()
          }).catch(e => {
            console.log("decode failed because of DOMException, lets try directly");
            console.log(e);
            canvas.drawImage(image, file.pos_in_image.x, file.pos_in_image.y, imagewidth, imageheight);
            resolve()
          });
      });
      image.src = "data:image/"+extension+";base64,"+file.image
    });
  }

Regarding single-file import, I don't have a solution yet. If I'm interpreting the code correctly, it seems that single-file import always uses the DecodeImage function, and I'm still learning how that works but it doesn't appear to use the canvas element and so doesn't have a means for resizing the image currently. I might be able to add a processing of the decoded image via canvas to perform a resize in the existing code, or I might try redirecting the single-file import through the image2Canvas method to see if that works and if any functionality is lost. More testing to come!