2

I am trying to make a canvas application and i get success. I just stuck in print image that is output of canvas. Size of image is too small to print enough.

Following is flow of application:

  1. Upload image and draw to the canvas.
  2. Do some operations like zoom, move and rotating on split canvas.
  3. I have successfully generated single images from those splits
  4. And I have export base64 from canvas to printing process.

Problem is here when I export data from canvas it's small image, even if I do some Imagick stuff to resize image quality of final image is not near to print on poster.

JavaScript:

function draw() {
  var Activecanvas = document.getElementsByClassName("cf-photoframe-active");
  var canvas = Activecanvas[0];
  var ctx = canvas.getContext('2d');
  var ActiveCanvasId = canvas.getAttribute("id");
  var img = canvasDetail[ActiveCanvasId].selectedImage;
  var imageX = canvasDetail[ActiveCanvasId].imageX;
  var imageY = canvasDetail[ActiveCanvasId].imageY;
  var resize = resizeDetail[ActiveCanvasId].resize;
  var rotate = rotateDetail[ActiveCanvasId].rotate;
  //if(resize)
  $j("#resize").slider({
    value: resize,
    min: -300,
    max: 300,
    step: 1,
  });
  $j("#rotat").slider({
    value: rotate,
    min: -180,
    max: 180,
    step: 1,
  });
  if (img != '') {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.save();
    var im_width = parseInt(img.width + $j("#resize").slider('value'));
    var im_height = parseInt(img.height + $j("#resize").slider('value'));

    var maxWidth = canvas.width; // Max width for the image
    var maxHeight = canvas.height;


    var iswidthMax = 0;
    var imageOrgWidth = img.width;
    var imageOrgHeight = img.height;
    if (maxWidth < maxHeight) {
      iswidthMax = 1;
    } else if (maxWidth == maxHeight) {
      iswidthMax = 2;
    }

    if (iswidthMax == 1) {
      maxWidth = (maxHeight * imageOrgWidth) / imageOrgHeight;

    } else if (iswidthMax == 0) {
      maxHeight = (maxWidth * imageOrgHeight) / imageOrgWidth;
    } else if (iswidthMax == 2) {
      if (img.width > img.height) {
        maxWidth = (maxHeight * imageOrgWidth) / imageOrgHeight;
      } else {
        maxHeight = (maxWidth * imageOrgHeight) / imageOrgWidth;
      }
    }

    var resizeVal = $j("#resize").slider('value');
    var nw = maxWidth + resizeVal;
    var resizeValHeight = maxHeight * resizeVal / maxWidth;
    var nh = maxHeight + resizeValHeight;

    ctx.translate(imageX, imageY);
    ctx.rotate(rotate * Math.PI / 180);
    ctx.translate(-nw / 2, -nh / 2);
    ctx.drawImage(img, 0, 0, nw, nh);
    ctx.setTransform(1, 0, 0, 1, 0, 0);
    ctx.restore();
  }
}
chudasamachirag
  • 317
  • 5
  • 14
  • Ensure that you set the size (width/height) of your canvas before you draw to it. It should be the size required prior to your drawing operations. You need to post some of the code that you're using. – ManoDestra Jun 21 '16 at 14:32
  • i already set size(width/height) as HTML inline attributes. and here i am put **Draw** function – chudasamachirag Jun 21 '16 at 14:40
  • 1
    No, that's no use. You need to set the width and height via JavaScript e.g. `canvas.width = img.width; canvas.height = img.height;` The dimensions of the element are different from the dimensions of the internal data. If you don't set it manually, you will get the default internal dimensions. See here, especially the accepted answer: http://stackoverflow.com/questions/4938346/canvas-width-and-height-in-html5 – ManoDestra Jun 21 '16 at 14:40
  • if i do assign image size to canvas size then split image and move image on canvas is not work. they get failed. so to over come this problem i just make image small size and perform all other operation. – chudasamachirag Jun 21 '16 at 14:46
  • Which is why you get a decreased size of canvas in your data output. You can't scale an image down, then back up again and expect it to look good. The canvas needs to be the size that you expect when you output the data from it otherwise it will be small and blurry when resized. – ManoDestra Jun 21 '16 at 14:48
  • as per my application user add images in 5mb - 20mb. if i don't decreased size of canvas, split image and rotate is not work. i tried to google split image and other operation with large image file on canvas but i don't get any solution. – chudasamachirag Jun 21 '16 at 14:57
  • Well, if you split the image into multiple canvases for editing, then simply copy the content of the ImageData of each smaller canvas to an invisible larger canvas and output the data from that full size canvas. – ManoDestra Jun 21 '16 at 14:58
  • Ok let me try that one and get back to you. – chudasamachirag Jun 21 '16 at 15:04
  • Yes, canvas resolution is about 96 and print resolution is 300 -- print requires many more pixels for clarity. If re-rendering to poster size with ImageMagick is not working then you must make the canvas bigger so you can feed ImageMagick more pixels to work with. Maybe use 2 canvases: one huge canvas for the poster and one `context.scale`-ed down canvas for the user to see / work on. – markE Jun 21 '16 at 16:35
  • https://stackoverflow.com/questions/17025603/what-is-the-best-practice-to-export-canvas-with-high-quality-images/17035046#17035046 –  Jun 21 '16 at 22:13
  • https://stackoverflow.com/questions/19754961/print-canvas-contents/19756491#19756491 –  Jun 21 '16 at 22:14

1 Answers1

1

If you have smaller canvas elements for editing, then you will have to recombine the data from those smaller canvas elements into a canvas element which is the full size and output the data from that element.

For simplicity's sake, let's say that you have cut the image into four quadrants and drawn to four canvas elements canvas[0] - canvas[3] for editing. You would then need to recombine them into one larger canvas doing something like the following...

var imgData = [];
for (var i = 0; i < 4; i++) {
    var tmpCtx = canvas[i].getContext('2d');
    imgData[i] = tmpCtx.getImageData(0, 0, canvas[i].width, canvas[i].height);
}

var fullSizeCanvas = document.createElement('canvas');
fullSizeCanvas.width = img.width * 2;
fullSizeCanvas.height = img.height * 2;

var fullCtx = fullSizeCanvas.getContext('2d');
fullCtx.putImageData(imgData[0], 0, 0);
fullCtx.putImageData(imgData[1], img.width, 0);
fullCtx.putImageData(imgData[2], 0, img.height);
fullCtx.putImageData(imgData[3], img.width, img.height);

var data = fullSizeCanvas.toDataURL();
ManoDestra
  • 6,325
  • 6
  • 26
  • 50
  • Thanks @ManoDestra, i follow your second comment. assign image height and width to canvas and that works for me. http://stackoverflow.com/questions/4938346/canvas-width-and-height-in-html5 – chudasamachirag Jun 22 '16 at 13:22
  • Yes, exactly. Whatever size of canvas you require to be output as data, is what you need to ultimately draw to in your final operation. You can cut up your image into smaller canvases initially for editing, but you need to draw back to a master image for export at some point, either after every zoom, or at the end. Good luck! – ManoDestra Jun 22 '16 at 13:33