issue in image to PDF not working in react native - react-native

I am trying to generate PDF from image path in react native so i am using below plugin for that
https://www.npmjs.com/package/react-native-image-to-pdf/v/1.2.0
As per above doc i configure all the thing and below is my code
const myAsyncPDFFunction = async () => {
try {
console.log('Call a');
let path ='file:///Users/macminiharshalk/Library/Developer/CoreSimulator/Devices/FADDF530-05FD-4A0E-9E61-C6AEDB719955/data/Containers/Data/Application/37B8FE42-B23A-4018-865F-F57670B3411E/tmp/606C88B3-5759-4942-A544-1231A0C17532.jpg';
const options = {
imagePaths: [path],
name: 'PDFName',
maxSize: {
// optional maximum image dimension - larger images will be resized
width: 900,
height: Math.round(
(Dimensions.get('window').height / Dimensions.get('window').width) *
900,
),
},
quality: 0.7, // optional compression paramter
// targetPathRN: "/storage/emulated/0/Download/", // only for android version 9 and lower
//for versions higher than 9 it is stored in (Download/img-to-pdf/)
};
console.log("options-->", options);
const pdf = await RNImageToPdf.createPDFbyImages(options);
console.log('PDF URIs-->', pdf);
console.log(pdf.filePath);
} catch (e) {
console.log(e);
}
};
When i console log i can able to see pdf path as below
/Users/macminiharshalk/Library/Developer/CoreSimulator/Devices/FADDF530-05FD-4A0E-9E61-C6AEDB719955/data/Containers/Data/Application/37B8FE42-B23A-4018-865F-F57670B3411E/Documents/PDFName.pdf
When i console option parameter it is showing as below
{"imagePaths": ["file:///Users/macminiharshalk/Library/Developer/CoreSimulator/Devices/FADDF530-05FD-4A0E-9E61-C6AEDB719955/data/Containers/Data/Application/37B8FE42-B23A-4018-865F-F57670B3411E/tmp/606C88B3-5759-4942-A544-1231A0C17532.jpg"], "maxSize": {"height": 1948, "width": 900}, "name": "PDFName", "quality": 0.7}
But when i open PDF image is not copy it is blank PDF so any idea how can i show image in PDF ?

please try
const newPath = path.replace('file://', ​​'');

Related

ReferenceError: google is not defined | Google Charts in pdfkit

I was trying to render graph in pdf generated using pdfkit. I found this solution https://quickchart.io/documentation/google-charts-image-server/#example
const GoogleChartsNode = require('google-charts-node');
// Define your chart drawing function
function drawChart() {
const data = google.visualization.arrayToDataTable([
['City', '2010 Population',],
['New York City, NY', 8175000],
['Los Angeles, CA', 3792000],
['Chicago, IL', 2695000],
['Houston, TX', 2099000],
['Philadelphia, PA', 1526000]
]);
const options = {
title: 'Population of Largest U.S. Cities',
chartArea: {width: '50%'},
hAxis: {
title: 'Total Population',
minValue: 0
},
vAxis: {
title: 'City'
}
};
const chart = new google.visualization.BarChart(container);
chart.draw(data, options);
}
// Render the chart to image
const image = await GoogleChartsNode.render(drawChart);
This works fine and I got a generated graph in my pdf. So tried to give dynamic data into new function I written
function drawtIntelligenceBarchar(intelligence) {
console.log(intelligence)
try{
const data = google.visualization.arrayToDataTable([
['Intelligence', 'Intelligence Level',],
["Linguistic", intelligence["Linguistic"]],
["Logical", intelligence["Logical"]],
["Musical", intelligence["Musical"]],
["Visual-Spatial", intelligence["Visual-Spatial"]],
["Kinesthetic", intelligence["Kinesthetic"]],
["Intra-Personal", intelligence["Intra-Personal"]],
["Inter-Personal", intelligence["Inter-Personal"]],
["Naturalistic", intelligence["Naturalistic"]],
["Existential", intelligence["Existential"]]
]);
const options = {
title: 'Intelligence Graph',
chartArea: {width: '70%'},
hAxis: {
title: 'AVERAGE GOOD VERY GOOD EXCELLENT',
minValue: 0,
maxValue: 100,
},
vAxis: {
title: 'INTELLIGENCE TYPE'
}
};
const chart = new google.visualization.BarChart(container);
chart.draw(data, options);
} catch(error){
console.log(error);
}
}
const intelligenceGraph = await GoogleChartsNode.render(drawtIntelligenceBarchar(intelligence));
Then I got this error
ReferenceError: google is not defined
It will be awesome if you can help me on this.
I faced a similar issue a while ago, the thing here is that you have to consider that google charts is a library that is loaded when the page is rendered, meaning that in order to generate a pdf it should be already there before generating it.
The approach you can use is to use a headless browser to emulate that the page is open and then the dependencies are loaded so when you send the HTML to pdfkit it will contain everything you need to generate the pdf or you can use selenium to do something similar. The tricky part however is to adjust the window size to hold all the charts, but you can sort it out with some trials.
This is due to accessibility of variable intelligence inside child function from external function. There is a solution by quickcharts.io . Instead of using a function use const variable for write code in js string and pass.
const drawtIntelligenceBarchar = `
const data = new google.visualization.DataTable();
data.addColumn('string', 'Intelligence');
data.addColumn('number', 'Intelligence Level (%)');
data.addRows([
["Linguistic", ${intelligence["Linguistic"]}],
["Logical", ${intelligence["Logical"]}],
["Musical", ${intelligence["Musical"]}],
["Visual-Spatial", ${intelligence["Visual-Spatial"]}],
["Kinesthetic", ${intelligence["Kinesthetic"]}],
["Intra-Personal", ${intelligence["Intra-Personal"]}],
["Inter-Personal", ${intelligence["Inter-Personal"]}],
["Naturalistic", ${intelligence["Naturalistic"]}],
["Existential", ${intelligence["Existential"]}]
]);
const options = {
title: 'Intelligence Graph',
chartArea: {width: '50%'},
hAxis: {
title: 'AVERAGE GOOD VERY GOOD EXCELLENT',
minValue: 0,
maxValue: 100,
},
vAxis: {
title: 'INTELLIGENCE TYPE'
}
};
const chart = new google.visualization.BarChart(container);
chart.draw(data, options);`;
const intelligenceGraph = await GoogleChartsNode.render(drawtIntelligenceBarchar, {width: 500,
height: 300,});
doc.image(intelligenceGraph, 0, 0,)
For more information visit the source code documentation

React-Native-Camera get height and width from uri

I have an app, which takes a photo and add it to the pdf file. Problem is resizing. I can resize it with pixels, but that not keep the original ratio. I need original height and width for calculating the right size
Calculate: Divide height by width, example 1200/1600 = 0,75. Then we can resize pd image height 100px and width is 100 / 0,75.
Question is: How can I get the size of image (data.uri)?
My code:
takePicture = async() => {
if (this.camera) {
const options = { quality: 0.5, base64: true , fixOrientation: true}; // Option for wuality etc
const data = await this.camera.takePictureAsync(options); // Take the image
console.log(data.uri); // Prints image (data) address to console log
back(data.uri) // Go back to ReportFault page
}
};
let imgX = 297;
let imgY = 618;
page.drawImage(arr[i].path.substring(7),'jpg',{
x: imgX, // Position in pdf A4
y: imgY, // Position in pdf A4
width: 200,
height: 150,
})
you can use react native Image getSize method
try this
import { Image } from 'react-native';
.....
Image.getSize(uri, (width, height) => {
console.log(`The image dimensions are ${width}x${height}`);
}, (error) => {
console.error(`Couldn't get the image size: ${error.message}`);
});

Trying to load obj & mtl file with Three.js in React Native

Main objective : Load animated models exported from Maya into React Native app
Exported files : obj, mtl & png file
I have setup https://github.com/react-community/react-native-webgl in my React Native project and it is working properly.
Now, when I am trying to load the MTL file using the MTLLoader, I am getting following error:
Can't find variable: document
Apparently, the MTLLoader is calling TextureLoader which internally calls some load function which has 'document' reference. So what could be the solution to this ?
Here are the two files that I am using:
three.js
const THREE = require("three");
global.THREE = THREE;
if (!window.addEventListener)
window.addEventListener = () => { };
// require("three/examples/js/renderers/Projector");
require("three/examples/js/loaders/MTLLoader");
require("three/examples/js/loaders/OBJLoader");
export default THREE;
ThreeView.js
import React, { Component } from "react";
import { StyleSheet, View } from "react-native";
import { WebGLView } from "react-native-webgl";
import THREE from "./three";
import { image } from "src/res/image";
export default class ThreeView extends Component {
requestId: *;
componentWillUnmount() {
cancelAnimationFrame(this.requestId);
}
onContextCreate = (gl: WebGLRenderingContext) => {
const rngl = gl.getExtension("RN");
const { drawingBufferWidth: width, drawingBufferHeight: height } = gl;
const renderer = new THREE.WebGLRenderer({
canvas: {
width,
height,
style: {},
addEventListener: () => { },
removeEventListener: () => { },
clientHeight: height
},
context: gl
});
renderer.setSize(width, height);
renderer.setClearColor(0xffffff, 1);
let camera, scene;
let cube;
function init() {
camera = new THREE.PerspectiveCamera(75, width / height, 1, 1100);
camera.position.y = 150;
camera.position.z = 500;
scene = new THREE.Scene();
var mtlLoader = new THREE.MTLLoader();
mtlLoader.load('female-croupier-2013-03-26.mtl', function (materials) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials(materials);
objLoader.load('female-croupier-2013-03-26.obj', function (object) {
scene.add(object);
}, onLoading, onErrorLoading);
}, onLoading, onErrorLoading);
}
const onLoading = (xhr) => {
console.log((xhr.loaded / xhr.total * 100) + '% loaded');
};
const onErrorLoading = (error) => {
console.log('An error happened', error);
};
const animate = () => {
this.requestId = requestAnimationFrame(animate);
renderer.render(scene, camera);
// cube.rotation.y += 0.05;
gl.flush();
rngl.endFrame();
};
init();
animate();
};
render() {
return (
<View style={styles.container}>
<WebGLView
style={styles.webglView}
onContextCreate={this.onContextCreate}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center"
},
webglView: {
width: 300,
height: 300
}
});
This error is as others have said caused by threejs trying to use features from a browser which react-native does not have.
I've gotten so far as to be able to load the textures (which is the stage you're getting the error from) by monkey patching the texture loader to use the loader in react-native-webgl. Add this in your init function (right near the top preferably).
//make sure you have defined renderer and rngl
/*
const renderer = new THREE.WebGLRenderer(...)
const rngl = gl.getExtension("RN");
*/
const loadTexture = async function(url, onLoad, onProgress, onError) {
let textureObject = new THREE.Texture();
console.log("loading",url,'with fancy texture loader');
let properties = renderer.properties.get(textureObject);
var texture = await rngl.loadTexture({yflip: false, image: url});
/*
rngl.loadTexture({ image: url })
.then(({ texture }) => {
*/
console.log("Texture [" + url + "] Loaded!")
texture.needsUpdate = true;
properties.__webglTexture = texture;
properties.__webglInit = true;
console.log(texture);
if (onLoad !== undefined) {
//console.warn('loaded tex', texture);
onLoad(textureObject);
}
//});
return textureObject;
}
THREE.TextureLoader.prototype.load = loadTexture;
This solves the problem of loading textures and I can see them load in Charles but they still don't render on a model so I'm stuck past that point. Technically a correct answer but you'll be stuck as soon as you've implemented it. I'm hoping you can comment back and tell me you've gotten further.
I had a similar setup and encountered same issue. My option was to switch to JSONLoader which doesn’t need document to render in react-native. So, I just loaded my model in Blender with a three-js addon, then exported it as json. Just check out this process of adding a three-js adon to Blender
https://www.youtube.com/watch?v=mqjwgTAGQRY
All the best
this might get you closer:
The GLTF format supports embedding texture images (as base64). If your asset pipeline allows it, you could convert to GLTF and then load into three/react-native.
I had to provide some "window" polyfills for "decodeUriComponent" and "atob" because GLTFLoader uses FileLoader to parse the base64:
I've successfully loaded embedded buffers, but you'll need more polyfills to load textures. TextureLoader uses ImageLoader, which uses document.createElementNS
You are using the MTLLoader which uses TextureLoader, and the TextureLoader uses the ImageLoader.
The imageloader uses the document.createElementNS() function.
what i did to solve this was to directly call the THREEjs TextureLoader:
let texture = new THREE.Texture(
url //URL = a base 64 JPEG string in this case
);
(for the use of Texture check the Texture documentation)
Then i used the Image class from React native (instead of the THREEjs Image, which requires the DOM to be constructed) to give that to the Texture as a property:
import { Image } from 'react-native';
var img = new Image(128, 128);
img.src = url;
texture.normal = img;
And then finally map the texture over the target material:
const mat = new THREE.MeshPhongMaterial();
mat.map = texture;
In the react native documentation it will explain how the react native Image element can be used, it supports base64 encoded JPEG.
Maybe there's a way for you to single out the part where it calls for the TextureLoader and replace that part with this answer. Let me know how it works out.
side note, i havent tried to display this yet in my webGLView, but in the logs it looked like normal threejs objects, it's worth the try
Use TextureLoader from expo-three
import { TextureLoader } from "expo-three";
export function loadTexture(resource) {
if (textureCache[resource]) {
return textureCache[resource].clone();
}
const texture = new TextureLoader().load(resource);
texture.magFilter = NearestFilter;
texture.minFilter = NearestFilter;
textureCache[resource] = texture;
return texture;
}
Source: https://github.com/EvanBacon/Expo-Crossy-Road/blob/master/src/Node/Generic.js

Invalid imageTag error from ImageStore.getBase64ForTag

I am trying to get a base64 image from facebook profile picture.
getImageFromFacebook() {
const imageURL = this.props.userInfo.picture;
Image.getSize(imageURL, (width, height) => {
var imageSize = {width, height};
ImageEditor.cropImage(imageURL, imageSize, (imageURI) => {
console.log(imageURI);
ImageStore.getBase64ForTag(imageURI, (base64Data) => {
this.setState({pictureBase64: base64Data});
ImageStore.removeImageForTag(imageURI);
}, (reason) => console.log(reason) )
}, (reason) => console.log(reason) )
}, (reason) => console.log(reason))
}
I am following the steps described in this https://github.com/facebook/react-native/issues/1158:
Use Image.getSize(uri) to get the image dimensions.
Use ImageEditor.cropImage(uri, cropData) to store a copy of the image in the ImageStore (if you pass the width and height you got in step 1) then cropImage won't actually crop the image, although it may still make a copy of it.
Use ImageStore.getBase64ForTag(uri) to get the base64 data of the new image (pass the uri you got from the cropImage function, not the original).
Don't forget to call ImageStore.removeImageForTag(uri) once you're done to delete the copy.
Although the ImageEditor.cropImage returns a valid URI (rct-image-store://0), ImageStore.getBase64ForTag fails with a reason:
code: "ERCTERRORDOMAIN0",
domain: "RCTErrorDomain",
message: "Invalid imageTag: rct-image-store://0"
What am I doing wrong?
Found the error!
imageSize should be set like this:
var imageSize = {
size: {
width,
height
},
offset: {
x: 0,
y: 0,
},
};

How to edit PDF file which is exported with jspdf.min.js?

Don't know if the question is well put, but here is my problem: I managed to export my chart to PDF format using jspdf.min.js through this piece of code:
$("#generate").on("click", function (e) {
html2canvas($("#placeholder").get(0), {
onrendered: function (canvas) {
var imgData = canvas.toDataURL('image/png');
console.log('Report Image URL: ' + imgData);
var doc = new jsPDF('portrait');
doc.addImage(imgData, 'PNG', 10, 10, 190, 95);
doc.text("TEST TEXT");//I tried to add a text in PDF file,but didn't work
doc.save('sample-file.pdf');
}
});
});
Is there a way to add a title of my chart in the PDF file?
Try this example. Is a trick which might help you. Don't forget to update your options:
var options = {
canvas: true,
grid: {
margin: {
top:50
},
}
};