Blurred pdf with pdf.js library - javascript

I'm using pdf.js library to render my pdf file on canvas.
First I was searching a solution for rendering pdf with the size of canvas parent element.
I've found it and it works fine.
Then I solve the problem of rendering ALL pages at once.
Finally, my code now looks this way:
pdfjsLib.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjsLib.version}/pdf.worker.min.js`;
class PdfLoader {
currPage = 1;
numPages = -1;
doc = null;
constructor($container) {
this.$container = $container;
}
load(path) {
// reset when using more than once
this.currPage = 1;
this.promise = new Promise(resolve => this.promiseResolve = resolve);
this.$container.innerHTML = "";
pdfjsLib.getDocument(path).promise.then(pdf => {
this.doc = pdf;
this.numPages = pdf.numPages;
pdf.getPage(1).then(this._handlePage.bind(this));
});
return this;
}
_handlePage(page) {
let viewport = page.getViewport({scale: 1});
const scale = this.$container.clientWidth/viewport.width;
// const outputScale = window.devicePixelRatio || 1;
const outputScale = 1;
viewport = page.getViewport({scale});
const cnv = document.createElement("canvas");
const ctx = cnv.getContext("2d");
const width = Math.floor(viewport.width);
const height = Math.floor(viewport.height);
cnv.width = Math.floor(width * outputScale);
cnv.height = Math.floor(height * outputScale);
cnv.style.width = `${width}px`;
cnv.style.height = `${height}px`;
const transform = (outputScale !== 1) ? [outputScale, 0, 0, outputScale, 0, 0] : null;
page.render({
canvasContext: ctx,
transform: transform,
viewport: viewport,
});
this.$container.appendChild(cnv);
this.currPage++;
if (this.doc !== null && this.currPage <= this.numPages) {
this.doc.getPage(this.currPage).then(this._handlePage.bind(this));
} else {
this.promiseResolve();
}
}
}
const $pages = document.getElementById("pages");
const pdfLoader = new PdfLoader($pages);
pdfLoader.load("extendedReport.pdf").promise
.then(initReport);
let arrow = null;
function initReport() {
// my other stuff
}
And now my problem is that when viewing rendered pdf it looks like its quality is very low and text is blurred so the document is unreadable on mobile devices. I tried to change passed scale like they say on the internet, but that's not it. Could you help me, plz? What am I missing?

Related

Scroll Sequence with .png image work weird

So I working on my project and I want to make some section kind of Apple Scroll Sequence.
But when I convert the image sequence to .PNG, it's awful :(
So, here's the image lookalike when I scroll the section. It's like shadowing / emm I don't know what it is haha.
Here's my codes:
<div class="intermezo-sequence">
<div class="sticky-element">
<div class="sequence-element">
<canvas id="intermezo_canvas"></canvas>
</div>
</div>
</div>
const canvas = document.querySelector('#hero_canvas')
const ctx = canvas.getContext('2d')
const heroSequence = document.querySelector('.hero-sequence')
const images = []
var sequence1 = <?= json_encode($sequence1) ?>;
sequence1.sort();
const frameCount = sequence1.length; // biar dinamis total nya
const prepareImages = () => {
for (var i = 0; i < frameCount; i++) {
// console.log(sequence1[i]);
const image = new Image()
// image.src = `./assets/images/studycase/sequence/${i}.jpg`
canvas.width = 1928;
canvas.height = 1000;
image.src = sequence1[i];
images.push(image)
if (i === 0) {
images[i].onload = () => drawImage1(0)
}
}
}
const drawImage1 = frameIndex => {
ctx.drawImage(images[frameIndex], 0, 0)
}
prepareImages()
const heroSection = document.getElementById("heroSection");
window.addEventListener('scroll', () => {
const scrollTop = document.documentElement.scrollTop - heroSection.offsetTop
const maxScrollTop = heroSequence.scrollHeight - window.innerHeight
const scrollFraction = scrollTop / maxScrollTop
const frameIndex = Math.max(0, Math.min(frameCount - 1, Math.ceil(scrollFraction * frameCount)))
images[frameIndex].onload = () => drawImage1(frameIndex)
requestAnimationFrame(() => drawImage1(frameIndex))
})
Is there anything that I should add to the logic? Thanks!

Capture zoom out event in Cesium

I want to capture zoom out event as soon as user reduces the map size to an extent i have to change the Map image layer.
var viewer = new Cesium.Viewer("cesiumContainer");
var scene = viewer.scene;
var clock = viewer.clock;
var referenceFramePrimitive;
var camera = viewer.camera;
....
camera.changed.addEventListener(function()
{
var height = Cesium.Cartographic.fromCartesian(camera.position).height;
if(height<4251907)
{
var layers = viewer.imageryLayers;
var baseLayer = layers.get(0);
layers.remove(baseLayer);
layers.addImageryProvider(new Cesium.IonImageryProvider({ assetId: 3812, maximumLevel : 5 }));
}
console.log(height);
}.bind(camera));
Is there any way to achieve this.
Thanks
This is one of the very simple solutions.
const viewer = new Cesium.Viewer("cesiumContainer");
const camera = viewer.camera;
const scratchCartesian1 = new Cesium.Cartesian3();
const scratchCartesian2 = new Cesium.Cartesian3();
let startPos, endPos;
camera.moveStart.addEventListener(function () {
startPos = camera.positionWC.clone(scratchCartesian1);
});
camera.moveEnd.addEventListener(function () {
endPos = camera.positionWC.clone(scratchCartesian2);
const startHeight = Cesium.Cartographic.fromCartesian(startPos).height;
const endHeight = Cesium.Cartographic.fromCartesian(endPos).height;
if (startHeight > endHeight) {
console.log("zoom in");
} else {
console.log("zoom out");
}
});

Problem with adding multiple images to the elements (javascript loop Issue)

I would like to add multiple photos from the Array in this code to the elements, but it adds just one photo from the Array to the first Element.
I tried adding for loop, but I dont know where to start and where to end the loop. Could you please take a look to the code using the link (codepen)?
thank you
let zoomLevel = 1;
const images = [
{
thumb: 'http://localhost:8080/links/works/Print/001.webp',
hires: 'http://localhost:8080/links/works/Print/001.webp'
},
{
thumb: 'https://tasvir-graphic.de/links/works/digital/unterwelt.webp',
hires: 'https://tasvir-graphic.de/links/works/digital/unterwelt.webp'
}
]
// set to random image
let img = images[Math.floor(Math.random() * images.length)];
image.getElementsByTagName('a')[0].setAttribute('href', img.hires);
image.getElementsByTagName('img')[0].setAttribute('src', img.thumb);
const preloadImage = url => {
let img = new Image();
img.src = url;
}
preloadImage(img.hires);
const enterImage = function(e) {
zoom.classList.add('show', 'loading');
clearTimeout(clearSrc);
let posX, posY, touch = false;
if (e.touches) {
posX = e.touches[0].clientX;
posY = e.touches[0].clientY;
touch = true;
} else {
posX = e.clientX;
posY = e.clientY;
}
You can check this better using Codepen HERE.
const image = document.querySelectorAll('.image');
/* Store the number of all elements with css class 'image' */
let imageElementsCount = image.length;
for (index = 0; index < imageElementsCount; index++)
{
let arrayElementPos = Math.floor(Math.random() * images.length);
/* Receive the requested element from array with image objects */
let imageObject = images[arrayElementPos];
preloadImage(imageObject.hires);
/* Assign received image properties to your html element */
image[index].getElementsByTagName('a')[0].setAttribute('href', imageObject.hires);
image[index].getElementsByTagName('img')[0].setAttribute('src', imageObject.thumb);
image[index].addEventListener('mouseover', enterImage);
image[index].addEventListener('touchstart', enterImage);
image[index].addEventListener('mouseout', leaveImage);
image[index].addEventListener('touchend', leaveImage);
image[index].addEventListener('mousemove', move);
image[index].addEventListener('touchmove', move);
image[index].addEventListener('wheel', e =>
{
e.preventDefault();
e.deltaY > 0 ? zoomLevel-- : zoomLevel++;
if (zoomLevel < 1) zoomLevel = 1;
if (zoomLevel > 5) zoomLevel = 5;
console.log(`zoom level: ${zoomLevel}`);
zoom.style.transform = `scale(${zoomLevel})`;
});
}
The loop is working until all founded divs got an assignment.
ToDos:
Remove in line
const image = document.querySelectorAll('.image')[0];
the [0].
Next step: Take a look into the body of for loop. Remove your lines of code in your original code
Thank you #Reporter, but I've allready done this editing my code for two days. :)
const zoo = document.querySelectorAll('.zoom');
const zooImg = document.querySelectorAll('.zoom-image');
const pic = document.querySelectorAll(".image");
let clearSrc;
let zoomLevel = 1;
const digiImgs = [{
thumb: 'https://tasvir-graphic.de/links/works/digital/MuZe.webp',
hires: 'https://tasvir-graphic.de/links/works/digital/MuZe.webp'
},
{
thumb: 'https://tasvir-graphic.de/links/works/digital/unterwelt.webp',
hires: 'https://tasvir-graphic.de/links/works/digital/unterwelt.webp'
},
{
thumb: 'https://tasvir-graphic.de/links/works/digital/takeCare.webp',
hires: 'https://tasvir-graphic.de/links/works/digital/takeCare.webp'
},
]
// set to random image
for (var i = 0; i < pic.length; i++) {
let img = digiImgs[i];
pic[i].getElementsByTagName('a')[0].setAttribute('href', img.hires);
pic[i].getElementsByTagName('img')[0].setAttribute('src', img.thumb);
const preloadImage = url => {
let img = new Image();
img.src = url;
}
preloadImage(img.hires);
const enterImage = function (e) {
var zoo = this.parentNode.childNodes[3];
zoo.classList.add('show', 'loading');
clearTimeout(clearSrc);
let posX, posY, touch = false;
if (e.touches) {
posX = e.touches[0].clientX;
posY = e.touches[0].clientY;
touch = true;
} else {
posX = e.clientX;
posY = e.clientY;
}
touch
?
zoo.style.top = `${posY - zoo.offsetHeight / 1.25}px` :
zoo.style.top = `${posY - zoo.offsetHeight / 2}px`;
zoo.style.left = `${posX - zoo.offsetWidth / 2}px`;
let originalImage = this.getElementsByTagName('a')[0].getAttribute('href');
var zoImg = this.parentNode.childNodes[3].childNodes[1];
zoImg.setAttribute('src', originalImage);
// remove the loading class
zoImg.onload = function () {
setTimeout(() => {
zoo.classList.remove('loading');
}, 500);
}
}
const leaveImage = function () {
// remove scaling to prevent non-transition
var zoImg = this.parentNode.childNodes[3].childNodes[1];
var zoo = this.parentNode.childNodes[3];
zoo.style.transform = null;
zoomLevel = 1;
zoo.classList.remove('show');
clearSrc = setTimeout(() => {
zoImg.setAttribute('src', '');
}, 250);
}
const move = function (e) {
e.preventDefault();
var zoImg = this.parentNode.childNodes[3].childNodes[1];
var zoo = this.parentNode.childNodes[3];
let posX, posY, touch = false;
if (e.touches) {
posX = e.touches[0].clientX;
posY = e.touches[0].clientY;
touch = true;
} else {
posX = e.clientX;
posY = e.clientY;
}
// move the zoom a little bit up on mobile (because of your fat fingers :<)
touch ?
zoo.style.top = `${posY - zoo.offsetHeight / 1.25}px` :
zoo.style.top = `${posY - zoo.offsetHeight / 2}px`;
zoo.style.left = `${posX - zoo.offsetWidth / 2}px`;
let percX = (posX - this.offsetLeft) / this.offsetWidth,
percY = (posY - this.offsetTop) / this.offsetHeight;
let zoomLeft = -percX * zoImg.offsetWidth + (zoo.offsetWidth / 2),
zoomTop = -percY * zoImg.offsetHeight + (zoo.offsetHeight / 2);
zoImg.style.left = `${zoomLeft}px`;
zoImg.style.top = `${zoomTop}px`;
}
pic[i].addEventListener('mouseover', enterImage);
pic[i].addEventListener('touchstart', enterImage);
pic[i].addEventListener('mouseout', leaveImage);
pic[i].addEventListener('touchend', leaveImage);
pic[i].addEventListener('mousemove', move);
pic[i].addEventListener('touchmove', move);
pic[i].addEventListener('wheel', e => {
var zoo = e.target.parentNode.parentNode.parentNode.childNodes[3];
console.log(zoo);
e.preventDefault();
e.deltaY > 0 ? zoomLevel-- : zoomLevel++;
if (zoomLevel < 1) zoomLevel = 1;
if (zoomLevel > 3) zoomLevel = 3;
console.log(`zoom level: ${zoomLevel}`);
zoo.style.transform = `scale(${zoomLevel})`;
});
}
but there is a problem with the touch. When I touch using mobile, the photo works like a link and opens the photo. How to use preventDefault Touch?

Firefox extension not able to select all images may be due to Canvas fuction getImageData()

In the below code I have imported my machine learning model through function model_startup(). model_startup() is working fine. But after that, I am getting into function blockk(), through this function I am trying to select all images on website by document.getElementsByTagName('img') and do prediction through that image with the help of an imported model. But my problem is that my second function is not selecting all images on website and selecting only some number of starting images and after prediction on that some number of images it get stopped.
I am new to javascript and trying to implement it as a firefox extension. Please help me in this problem
console.log('STARTING UP')
const MODEL_PATH = 'mdl/model.json'
const IMAGE_SIZE = 64;
let model;
async function model_startup()
{
console.log('Launching TF.js!');
tf.ENV.set('WEBGL_PACK',false);
await tf.ready();
console.log('TensorflowJS backend is: '+tf.getBackend());
let url = browser.runtime.getURL(MODEL_PATH);
console.log('Loading model... '+url);
try
{
model = await tf.loadLayersModel(url);
}
catch(e)
{
console.log('Failed to load model! '+e);
}
console.log('Model: ' + model);
console.log('Warming up...');
let dummy_data = tf.zeros([1, IMAGE_SIZE, IMAGE_SIZE, 3]);
// dummy_data.print();
let warmup_result = model.predict(dummy_data);
console.log("finding type : $$$$$$$$ " + typeof warmup_result)
warmup_result.print();
warmup_result.dispose();
console.log('Ready to go!');
// blockk();
};
model_startup().then(blockk);
function blockk() {
const x = document.getElementsByTagName('img');
console.log("wn ############################## " + x.length);
let inferenceCanvas = document.createElement('canvas');
inferenceCanvas.width = 64;
inferenceCanvas.height = 64;
let inferenceCtx = inferenceCanvas.getContext('2d', { alpha: false});
inferenceCtx.imageSmoothingEnabled = true;
for(var i = 0; i < x.length; i++)
{
console.log('pixel kmvsl lsvn');
let img = x[i];
inferenceCtx.drawImage(img, 0, 0, img.width, img.height, 0, 0, 64, 64);
const rightSizeImageData = inferenceCtx.getImageData(0, 0, 64, 64); //write promise. It may work.
const rightSizeImageDataTF = tf.browser.fromPixels(rightSizeImageData);
const floatImg = rightSizeImageDataTF.toFloat();
console.log('predicting...');
let scaled = floatImg.div(tf.scalar(255));
let batched = tf.stack([scaled]);
let result = model.predict(batched);
const val = result.dataSync()[0];
console.log(val);
if (val > 0.4)
{
console.log("blocking" + i);
let h = img.height
let w = img.width
pth = img.src
x[i].setAttribute("src", "https://indianonlineseller.com/wp-content/uploads/2017/05/blocked-listing.png");
// x[i].setAttribute("onclick", ` this.src = '${pth}' `);
x[i].setAttribute("data-src", "https://indianonlineseller.com/wp-content/uploads/2017/05/blocked-listing.png");
x[i].height = h;
x[i].width = w;
console.log('blocked');
}
console.log("co ########################### " + x.length)
}
};
The line in my code which is causing problem is
const rightSizeImageData = inferenceCtx.getImageData(0, 0, 64, 64);
If I remove this code and other code related to this line and I run it then my code is able to select all the images on webpage. Can you tell me why this may be happening?

How to detect, that drawing a canvas object is finished?

I have following JS code (found here, on stackoverflow, and a little-bit modded), which resize image on client side using canvas.
function FileListItem(a) {
// Necesary to proper-work of CatchFile function (especially image-resizing).
// Code by Jimmy Wärting (https://github.com/jimmywarting)
a = [].slice.call(Array.isArray(a) ? a : arguments)
for (var c, b = c = a.length, d = !0; b-- && d;) d = a[b] instanceof File
if (!d) throw new TypeError('expected argument to FileList is File or array of File objects')
for (b = (new ClipboardEvent('')).clipboardData || new DataTransfer; c--;) b.items.add(a[c])
return b.files
}
function CatchFile(obj) {
// Based on ResizeImage function.
// Original code by Jimmy Wärting (https://github.com/jimmywarting)
var file = obj.files[0];
// Check that file is image (regex)
var imageReg = /[\/.](gif|jpg|jpeg|tiff|png|bmp)$/i;
if (!file) return
var uploadButtonsDiv = document.getElementById('upload_buttons_area');
// Check, that it is first uploaded file, or not
// If first, draw a div for showing status
var uploadStatusDiv = document.getElementById('upload_status_area');
if (!uploadStatusDiv) {
var uploadStatusDiv = document.createElement('div');
uploadStatusDiv.setAttribute('class', 'upload-status-area');
uploadStatusDiv.setAttribute('id', 'upload_status_area');
uploadButtonsDiv.parentNode.insertBefore(uploadStatusDiv, uploadButtonsDiv.nextSibling);
// Draw sub-div for each input field
var i;
for (i = 0; i < 3; i++) {
var uploadStatus = document.createElement('div');
uploadStatus.setAttribute('class', 'upload-status');
uploadStatus.setAttribute('id', ('upload_status_id_commentfile_set-' + i + '-file'));
uploadStatusDiv.append(uploadStatus);
}
}
var canvasDiv = document.getElementById('canvas-area');
var currField = document.getElementById(obj.id);
var currFieldLabel = document.getElementById(('label_' + obj.id));
// Main image-converting procedure
if (imageReg.test(file.name)) {
file.image().then(img => {
const canvas = document.createElement('canvas')
canvas.setAttribute('id', ('canvas_' + obj.id));
const ctx = canvas.getContext('2d')
const maxWidth = 1600
const maxHeight = 1200
// Calculate new size
const ratio = Math.min(maxWidth / img.width, maxHeight / img.height)
const width = img.width * ratio + .5|0
const height = img.height * ratio + .5|0
// Resize the canvas to the new dimensions
canvas.width = width
canvas.height = height
// Drawing canvas-object is necessary to proper-work
// on mobile browsers.
// In this case, canvas is inserted to hidden div (display: none)
ctx.drawImage(img, 0, 0, width, height)
canvasDiv.appendChild(canvas)
// Get the binary (aka blob)
canvas.toBlob(blob => {
const resizedFile = new File([blob], file.name, file)
const fileList = new FileListItem(resizedFile)
// Temporary remove event listener since
// assigning a new filelist to the input
// will trigger a new change event...
obj.onchange = null
obj.files = fileList
obj.onchange = CatchFile
}, 'image/jpeg', 0.70)
}
)
// If file is image, during conversion show status
function ShowConvertConfirmation() {
if (document.getElementById('canvas_' + obj.id)) {
document.getElementById(('upload_status_' + obj.id)).innerHTML =
'<font color="#4CAF50">Konwertowanie pliku ' + file.name + ' zakończone!</font>';
return true;
}
else {
document.getElementById(('upload_status_' + obj.id)).innerHTML =
'<font color="#4CAF50">Konwertowanie pliku ' + file.name + ' zakończone!</font>';
return false;
}
}
// Loop ShowConvertConfirmation function untill return true (file is converted)
var convertConfirmationLoop = setInterval(function() {
var isConfirmed = ShowConvertConfirmation();
if (!isConfirmed) {
ShowConvertConfirmation();
}
else {
// Break loop
clearInterval(convertConfirmationLoop);
}
}, 2000); // Check every 2000ms
}
// If file is not an image, show status with filename
else {
document.getElementById(('upload_status_' + obj.id)).innerHTML =
'<font color="#4CAF50">Dodano plik ' + file.name + '</font>';
//uploadStatusDiv.append(uploadStatus);
}
}
Canvas is drawn in hidden div:
<div id="canvas-area" style="overflow: hidden; height: 0;"></div>
I am only detect, that div canvas-area is presented and basing on this, JS append another div with status.
Unfortunatelly on some mobile devices (mid-range smartphones), message will be showed before finish of drawing (it is wrong). Due to this, some uploaded images are corrupted or stay in original size.
How to prevent this?
Everything that should happen after the image has loaded, should be executed within the then callback, or called from within it.
It is important to realise that the code that is not within that callback will execute immediately, well before the drawing has completed.

Categories

Resources