I am generating html pages with Google chart by domtoimage and jsPDF library. But its generated PDF document looks little bit blurry on Acrobat Reader and fine on Google Chrome. I've tried to printing it and result was so blurry. How to increase quality of PDF?
Code that generates PDF:
function makePDF(a, fname){
var key;
var doc = new jsPDF('l', 'mm', 'a5', true);
for(key in a){
doc.addImage(a[key],'PNG',0,0*key,210,148);
if(a.length - 1 === key*1){
}else{
doc.addPage();
}
}
doc.save(fname + ".pdf");
$(".www").css("margin","auto");
a = null;
isdone = true;
ngViewLoader(false);
}
Code that converts DOM Element to image:
function build_image(dis){
domtoimage.toPng(dis).then(function(dataUrl){
a.push(dataUrl);
arr_index++;
if(index === a.length){
makePDF(a, fname);
}else{
if(arr_index > 13){
return false;
}
build_image(arr_dis[arr_index]);
}
}).catch(function (error) {
console.error('oops, something went wrong!', error);
});
}
#Rozig
Try using the following code below instead:
domtoimage.toJpeg(dis, {
quality: 1.0
})
The JPEG full quality is better compared to the PNG output. But depending on how big your image is being rendered, it still won't be completely look sharp.
Related
I have very little experience with C#/Asp.net/Razor HTML. I'm trying to change the webcam feature on a web app from using the old jQuery webcam (with flash) project to the jhuckaby/webcamjs (on Github) project. I think the problem right now is that the base64 image isn't saving right. I see in the below code something about String_To_Bytes2. What exactly does that do and do you have any ideas on how I could adjust it to take the input base64 image data from the JavaScript side to be saved in a directory folder?
C#:
public ActionResult Capture(int id)
{
var uniqueFileName = id + ".png";
var uploads = Path.Combine(hostingEnvironment.WebRootPath, "images/photos/");
var path = Path.Combine(uploads, uniqueFileName);
var stream = Request.Body;
string dump;
using (var reader = new StreamReader(stream))
dump = reader.ReadToEnd();
if (System.IO.File.Exists(path))
{
System.IO.File.Delete(path);
System.IO.File.WriteAllBytes(path, String_To_Bytes2(dump));
}
else System.IO.File.WriteAllBytes(path, String_To_Bytes2(dump));
return RedirectToAction("ServiceHistory", new { Id = id });
}
private byte[] String_To_Bytes2(string strInput)
{
int numBytes = (strInput.Length) / 2;
byte[] bytes = new byte[numBytes];
for (int x = 0; x < numBytes; ++x)
{
bytes[x] = Convert.ToByte(strInput.Substring(x * 2, 2), 16);
}
return bytes;
}
JavaScript (with a bit of Razor HTML)
<script>
Webcam.set({
width: 320,
height: 240,
image_format: 'jpeg',
//enable_flash: false,
jpeg_quality: 80
});
Webcam.attach('#Camera');
</script>
<script>
function configure() {
Webcam.set({
width: 320,
height: 240,
image_format: 'jpeg',
//enable_flash: false,
jpeg_quality: 80
});
Webcam.attach('#Camera');
}
// preload shutter audio clip
var shutter = new Audio();
shutter.autoplay = false;
shutter.src = navigator.userAgent.match(/Firefox/) ? '#Url.Content("~/shutter.ogg")' : '#Url.Content("~/shutter.mp3")';
function take_snapshot() {
// play sound effect
shutter.play();
// take snapshot and get image data
Webcam.snap(function (data_uri) {
// display results in page
document.querySelector('#Camera').innerHTML =
'<img id="imageprev" src="' + data_uri + '"/>';
});
//Webcam.reset();
}
function saveSnap() {
// Get base64 value from <img id='imageprev'> source
var base64image = document.getElementById("imageprev").src;
Webcam.upload(base64image, '#Url.Action("Capture", "Guest", new { Id = #Model.Id })', function (code, text) {
console.log('Save successfully');
console.log('The server responded with a' +' '+ code);
// document.querySelector('#save-btn').style.border = "4px solid green";
configure();
});
}
</script>
Any ideas or explanation would be greatly appreciated. I'm a noob and I feel like I'm so close to getting it to work.
So far, I've tested and I can send the base64 image data to console with console.log and it does indeed generate the image.
It also saves a PNG file in the folder directory, but it's 0kb so something isn't right on the C# side I think.
Again, any assistance would be amazing! Let me know if you need more information.
I have a django app where users would print some pages which include images as a part of Data processing.
I tried jsPDF but it didn't render my images and I ended up with just text
$(document).ready(function() {
$("#pdfDownloader").click(function() {
var doc = new jsPDF('p', 'pt', 'a4', true);
doc.fromHTML($('#renderMe').get(0), 15, 15, {
'width': 500
}, function (dispose) {
doc.save('thisMotion.pdf');
});
});
})
This was my code and it didn't render the images so do I need to change anything?
is using a Django view would solve this and is there any alternatives to xhtml2pdf as with this I need to include my CSS in the HTML file ?
fromHTML is used to get text from the HTML to form a PDF. Try using html2canvas js library instead.
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.5.0-beta4/html2canvas.min.js"></script>
You can create a canvas image and add it to the PDF with code like this,
$(document).ready(function() {
$("#pdfDownloader").click(function() {
html2canvas($("#renderMe")).then(canvas => {
const contentDataURL = canvas.toDataURL('image/png')
let pdf = new jspdf('p', 'pt', 'a4', true); // A4 size page of PDF
var positionX = 0;
var positionY = 0;
pdf.addImage(contentDataURL, 'PNG', positionY, positionY, undefined, undefined)
pdf.save('thisMotion.pdf'); // Generated PDF
});
});
})
This will get you a PDF just like the HTML rendered on screen.
I asked a previous question here about saving canvas to png. It works great when I save to png except on problem: the background is transparent, and I want it to be white.
My first idea was to try using JPG encoding and it would automatically add a background in -- I was right! But it added a black background in.
Now unfortunately I don't seem to have control of the production of the canvas, so I can't just add a white background to it. I looked up documentation on canvas and can't just add white to the background of it apparently - if I can just add a white background to a canvas, please tell me, as that will solve my problem.
So the only other solution is to somehow take my PNG-encoded stream from the code below and replace transparency with white. If it can be done inside of a png instead of jpg, I'm fine with that. If it can only be done on a jpg, I'm fine with that too. Any solution to get a white background on this image.
function saveCanvasAsImage(canvasElement) {
var Imaging = Windows.Graphics.Imaging;
var picker = new Windows.Storage.Pickers.FileSavePicker();
picker.suggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.picturesLibrary;
// picker.fileTypeChoices.insert("JPEG file", [".jpg"]);
picker.fileTypeChoices.insert("PNG file", [".png"]);
var fileStream, decoder, encoding, pixels = null;
var encoderIds = {
'.png': Imaging.BitmapEncoder.pngEncoderId,
'.jpg': Imaging.BitmapEncoder.jpegEncoderId
}
var encoderId = encoderIds['.jpg'];
var blob = canvasElement.msToBlob();
return Imaging.BitmapDecoder.createAsync(Imaging.BitmapDecoder.pngDecoderId,
blob.msDetachStream())
.then(function (dc) {
decoder = dc;
return picker.pickSaveFileAsync();
}).then(function (file) {
if (file) {
encoderId = encoderIds[file.fileType];
return file.openAsync(Windows.Storage.FileAccessMode.readWrite);
} else {
return WinJS.Promise.wrapError("No file selected");
}
}).then(function(stream) {
fileStream = stream;
var transform = new Windows.Graphics.Imaging.BitmapTransform();
return decoder.getPixelDataAsync(
decoder.bitmapPixelFormat,
decoder.bitmapAlphaMode,
transform,
Windows.Graphics.Imaging.ExifOrientationMode.respectExifOrientation,
Windows.Graphics.Imaging.ColorManagementMode.colorManageToSRgb
);
}).then(function (pixelProvider) {
pixels = pixelProvider.detachPixelData();
return Imaging.BitmapEncoder.createAsync(encoderId, fileStream);
}).then(function (encoder) {
encoding = decoder;
//Set the pixel data--assume "encoding" object has options from elsewhere
encoder.setPixelData(encoding.bitmapPixelFormat, encoding.bitmapAlphaMode,
encoding.pixelWidth, encoding.pixelHeight, encoding.dpiX, encoding.dpiY,
pixels);
//Go do the encoding
return encoder.flushAsync();
}).done(function () {
//Make sure to do this at the end
fileStream.close();
}, function () {
//Empty error handler (do nothing if the user canceled the picker
});
}
I need some help with the following problem, when I get a pdf with images on Chrome and FireFox I can get a good résult, jsPDF put on it some blur but I can live with it.
Result on Chrome
In other hand, on IE 10,11 and Edge the result is the following:
Result on IE
If you notice we can see something on pictures but almost is black.
Those are charts from highcharts and I convert svg to canvas.
I put some snippets but I can send to email the whole example:
var doc = new jsPDF('p', 'pt', 'a4', true);
var centered_x = (doc.internal.pageSize.width / 2) - ((context.destWidth / 2) * 0.75);
imgData_1 = atob(imgData_1);
doc.addImage(imgData_1, 'png', centered_x, 50);
data.datauri = context.browserSupportDownload && doc.output('datauristring');
data.blob = context.browserSupportBlob && doc.output('blob');
I call the function download to send the stream to the browser and its definition is like that:
var download = function(highChartsObject, context, data) {
if (!data || (!data.content && !(data.datauri || data.blob))) {
throw new Error("Something went wrong while exporting the chart");
}
if (context.browserSupportDownload && (data.datauri || data.content)) {
a = document.createElement('a');
a.href = data.datauri || ('data:' + context.type + ';base64,' + window.btoa(unescape(encodeURIComponent(data.content))));
a.download = 'result_good.pdf';
document.body.appendChild(a);
a.click();
a.remove();
}
else if (context.browserSupportBlob && (data.blob || data.content)) {
blobObject = data.blob || new Blob([data.content], { type: context.type });
window.navigator.msSaveOrOpenBlob(blobObject, 'IE_CASE.pdf');
}
else {
//window.open(data);
window.navigator.msSaveOrOpenBlob(blobObject, 'IE_CASE.pdf');
}
};
Thanks in advance.
Try changing the background color of the image using canvas or svg.
https://github.com/MrRio/jsPDF/issues/247
Straight to point. I want to set the limit of the width and height of the image when user upload an image using plupload.
Letsay:
if
width: 1000px
height: 1000px
else
you must upload image with at least width:1000px and height:1000px
// $(".form").validator();
$(function() {
if($("#uploader").length > 0) {
var uploader = new plupload.Uploader({
runtimes : 'html5,flash,silverlight',
browse_button : 'pickfile',
container : 'uploader',
max_file_size : '10mb',
url : 'design.php?do=upload&ajax=1',
multiple_queues: false,
file_data_name: 'design',
flash_swf_url : www + '/js/plupload.flash.swf',
silverlight_xap_url : www + '/js/plupload.silverlight.xap',
filters : [
{title : "Image files", extensions : "jpg,gif,png,jpeg,bmp"}
]
});
$('#uploadfiles').click(function(e) {
if($("#uploader select[name=category]").val() == "") {
$("#uploader select[name=category]").next('.error-required').show();
return false;
}
uploader.start();
e.preventDefault();
});
uploader.init();
So, is this possible?
You can easily write a filter for plupload.
Here is filter for min required width.
Add bellow code to your script. (Just copy)
plupload.addFileFilter('min_width', function(maxwidth, file, cb) {
var self = this, img = new o.Image();
function finalize(result) {
// cleanup
img.destroy();
img = null;
// if rule has been violated in one way or another, trigger an error
if (!result) {
self.trigger('Error', {
code : plupload.IMAGE_DIMENSIONS_ERROR,
message : "Image width should be more than " + maxwidth + " pixels.",
file : file
});
}
cb(result);
}
img.onload = function() {
// check if resolution cap is not exceeded
finalize(img.width >= maxwidth);
};
img.onerror = function() {
finalize(false);
};
img.load(file.getSource());
});
And add this filter to your upload script.
filters : {
min_width: 700,
},
Plupload doesn't support this itself (although it has been requested). There are probably a couple of reasons for this, firstly because you just can't get the image dimensions before upload in IE (you can in some other browsers) and secondly, whilst that would work for some browsers using the using the HTML4/5 methods, I am not sure that the Flash/Silverlight etc. methods would also be able to reliably determine dimensions.
If you were happy with limited browser, HTML4/5 methods only you should hook into the "FilesAdded" event e.g.
uploader.bind('FilesAdded', function(up, files) {
//Get src of each file, create image, remove from file list if too big
});
I recently wanted to do the same thing, and was able to achieve it the way Thom was suggesting. He was correct on it's limitation though; if you want to add this, it will only work in modern browsers and not in the flash or silverlight runtimes. This is not a huge issue, as my non-html5 users will just get an error after upload, rather than before.
I initialized a total image count variable to keep track of the images placed on the page. Also a vairable to store photos we want to delete after we read them all.
var total_image_count = 0;
var files_to_remove = [];
Then I read the pending files with FileReader(), place them on the page, and get their width
init:{
FilesAdded: function(up, files) {
if (uploader.runtime == "html5"){
files = jQuery("#"+uploader.id+"_html5")[0].files
console.log(files);
for (i in files){
//create image tag for the file we are uploading
jQuery("<img />").attr("id","image-"+total_image_count).appendTo("#upload-container");
reader_arr[total_image_count] = new FileReader();
//create listener to place the data in the newly created
//image tag when FileReader fully loads image.
reader_arr[total_image_count].onload = function(total_image_count) {
return function(e){
var img = $("#image-"+total_image_count);
img.attr('src', e.target.result);
if ($(img)[0].naturalWidth < 1000){
files_to_remove.push(files[i]); //remove them after we finish reading in all the files
//This is where you would append an error to the DOM if you wanted.
console.log("Error. File must be at least 1000px");
}
}
}(total_image_count);
reader_arr[total_image_count].readAsDataURL(files[i]);
total_image_count++;
}
for (i in files_to_remove){
uploader.removeFile(files_to_remove[i]);
}
}
}
}
As a side note, I was wanting to show image thumbnails anyway, so this method works great for me. I have not figured out how to get an image's width without first appending it to the DOM.
Sources:
Thumbnail an image before upload:
https://stackoverflow.com/a/4459419/686440
Accessing image's natural width:
https://stackoverflow.com/a/1093414/686440
to access width and heigth without thumbnail an image you can do this:
uploader.bind('FilesAdded', function(up, files) {
files = jQuery("#"+uploader.id+"_html5").get(0).files;
jQuery.each(files, function(i, file) {
var reader = new FileReader();
reader.onload = (function(e) {
var image = new Image();
image.src = e.target.result;
image.onload = function() {
// access image size here using this.width and this.height
}
};
});
reader.readAsDataURL(file);
}
}