could you help me how can I get output (source of cropped image) via react-image-crop module?
Upload component looks like this:
class MyUpload extends Component {
constructor() {
super();
this.state = {
src: 'source-to-image',
crop: {
x: 10,
y: 10,
aspect: 9 / 16,
width: 100
}
}
}
onCropComplete = (crop, pixelCrop) => {
this.setState({
crop
})
};
render() {
return (
<ReactCrop
src={this.state.src}
onComplete={this.onCropComplete}
/>
);
} }
Method onCropComplete returns only coordinates, width and height of cropped image, not source. I would like to get blob file.
EDIT (working solution -- thanks for Mosè Raguzzini reply):
If someone has similiar problem, call getCropptedImg function from tutorial in your component and create url from returned Blob object, like this:
getCroppedImg(this.state.image, pixelCrop, 'preview.jpg')
.then((res) => {
const blobUrl = URL.createObjectURL(res);
console.log(blobUrl); // it returns cropped image in this shape of url: "blob:http://something..."
})
react-image-crop is not meant to be used to produce blobs, is only meant to crop images inline. Probably you need something like https://foliotek.github.io/Croppie/
UPDATE:
Check the section "What about showing the crop on the client?" at bottom of
https://www.npmjs.com/package/react-image-crop, the blob is available as hidden feature
/**
* #param {File} image - Image File Object
* #param {Object} pixelCrop - pixelCrop Object provided by react-image-crop
* #param {String} fileName - Name of the returned file in Promise
*/
function getCroppedImg(image, pixelCrop, fileName) {
const canvas = document.createElement('canvas');
canvas.width = pixelCrop.width;
canvas.height = pixelCrop.height;
const ctx = canvas.getContext('2d');
ctx.drawImage(
image,
pixelCrop.x,
pixelCrop.y,
pixelCrop.width,
pixelCrop.height,
0,
0,
pixelCrop.width,
pixelCrop.height
);
// As Base64 string
// const base64Image = canvas.toDataURL('image/jpeg');
// As a blob
return new Promise((resolve, reject) => {
canvas.toBlob(file => {
file.name = fileName;
resolve(file);
}, 'image/jpeg');
});
}
async test() {
const croppedImg = await getCroppedImg(image, pixelCrop, returnedFileName);
}
Related
I tried with this library: https://www.npmjs.com/package/convert-svg-to-png
But it reaise an error:
import { convert } from 'convert-svg-to-png'
useEffect(() => {
let png = convert('/iStock-1188768310.svg')
console.log(png)
})
Error: Module not found: Can't resolve 'fs'
Import trace for requested module:
./node_modules/tar-fs/index.js
./node_modules/puppeteer/lib/cjs/puppeteer/node/BrowserFetcher.js
./node_modules/puppeteer/lib/cjs/puppeteer/node/Puppeteer.js
./node_modules/puppeteer/lib/cjs/puppeteer/initialize-node.js
What do I wrong, or is it any more 'standard' way to do it? My goal is to use the image az an og:image. I heard SVG can not be used, this is why I try convert to PNG.
I tried this package also: https://github.com/canvg/canvg Like this:
const canvas = document.querySelector('canvas')
const ctx = canvas.getContext('2d')
v = await Canvg.from(ctx, './svgs/1.svg')
// Start SVG rendering with animations and mouse handling.
v.start()
But it also raise error:
TypeError: Cannot read properties of null (reading 'getContext')
24 | let cv = async () => {
25 | const canvas = document.querySelector('canvas')
> 26 | const ctx = canvas.getContext('2d')
| ^
27 |
28 | v = await Canvg.from(ctx, './sv
according to the library's npm page, the function you need to import is convertFile and not convert:
const { convertFile} = require('convert-svg-to-png');
The following code should work:
(async() => {
const inputFilePath = '/path/to/my-image.svg';
const outputFilePath = await convertFile(inputFilePath);
console.log(outputFilePath);
//=> "/path/to/my-image.png"
})();
The title says "A Node.js package for converting SVG to PNG using headless Chromium". You can only use it in nodejs not in client-side JavaScript. You may want to check this answer if you want to do it in the browser: Convert SVG to image (JPEG, PNG, etc.) in the browser.
Here you have an (client-side) example of how an SVG document can be loaded using fetch() (if the SVG is not already in the DOM), turned into a File object, drawn on a canvas and expoted as a PNG.
var svgcontainer, svg, canvas, ctx, output;
document.addEventListener('DOMContentLoaded', e => {
svgcontainer = document.getElementById('svgcontainer');
canvas = document.getElementById('canvas');
output = document.getElementById('output');
ctx = canvas.getContext('2d');
fetch('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8Y2lyY2xlIGN4PSI1MCIgY3k9IjUwIiByPSI1MCIgZmlsbD0ib3JhbmdlIiAvPgo8L3N2Zz4KCgo=').then(res => res.text()).then(text => {
let parser = new DOMParser();
let svgdoc = parser.parseFromString(text, "application/xml");
canvas.width = svgdoc.rootElement.getAttribute('width');
canvas.height = svgdoc.rootElement.getAttribute('height');
// append SVG to DOM
svgcontainer.innerHTML = svgdoc.rootElement.outerHTML;
svg = svgcontainer.querySelector('svg');
// create a File object
let file = new File([svgdoc.rootElement.outerHTML], 'svg.svg', {
type: "image/svg+xml"
});
// and a reader
let reader = new FileReader();
reader.addEventListener('load', e => {
/* create a new image assign the result of the filereader
to the image src */
let img = new Image();
// wait for it to got load
img.addEventListener('load', e => {
// update canvas with new image
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(e.target, 0, 0);
// create PNG image based on canvas
let img = new Image();
img.src = canvas.toDataURL("image/png");
output.append(img);
});
img.src = e.target.result;
});
// read the file as a data URL
reader.readAsDataURL(file);
});
});
<div style="display:flex">
SVG:
<div id="svgcontainer"></div>
Canvas: <canvas id="canvas" width="200" height="200"></canvas>
</div>
<p>Exported PNG:</p>
<div id="output"></div>
I trained my model with Google Teachable Machines (Image) and inclueded the model into my Ionic Angular app. I loaded the model successfully and used the camera preview for predicting the class which is shown in the image from the camera.
The picture which is displayed in the canvas changes properly but the predict()-method returns the same result for every call.
import * as tmImage from '#teachablemachine/image';
...
async startPrediction() {
this.model = await tmImage.load(this.modelURL, this.metadataURL);
this.maxPredictions = this.model.getTotalClasses();
console.log('classes: ' + this.maxPredictions); //works properly
requestAnimationFrame(() => {
this.loop();
});
}
async loop() {
const imageAsBase64 = await this.cameraPreview.takeSnapshot({ quality: 60 });
const canvas = document.getElementById('output') as HTMLImageElement;
//image changes properly, I checked it with a canvas output
canvas.src = 'data:image/jpeg;base64,' + imageAsBase64;
const prediction = await this.model.predict(canvas);
for (let i = 0; i < this.maxPredictions; i++) {
const classPrediction =
prediction[i].className + ': ' + prediction[i].probability.toFixed(2);
//probability doesn't change, even if I hold the camera close over a trained image
}
requestAnimationFrame(() => {
this.loop();
});
}
The prediction result is e.g.: class1 = 0.34, class2 = 0.66 but doesn't change.
I hope you could help me to find my bug, thanks in advance!
The image has probably not yet been loaded before you are calling the prediction model. It has been discussed here and there
function load(url){
return new Promise((resolve, reject) => {
canvas.src = url
canvas.onload = () => {
resolve(canvas)
}
})
}
await load(base64Data)
// then the image can be used for prediction
I have a little problem with cropping images in react native.
As you can see the example below
I want to crop the image inside the white rectangle, I don't know if I'm using the wrong formula or not
takePicture = async() => {
console.log("pic")
if (this.camera != null) {
const data = await this.camera.takePictureAsync();
/**
* Calcul
*/
const x_axis_scale = data.width / width
const y_axis_scale = data.height / height
var x_coord_int = 70 * x_axis_scale;
var y_coord_int = 120 * y_axis_scale;
var rect_width_int = 200 * x_axis_scale;
var rect_height_int = 70 * y_axis_scale
const res = await ImageEditor.cropImage(data.uri, {
offset: {x: x_coord_int, y: y_coord_int},
size: {
width:rect_width_int,
height: rect_height_int
}
})
this.setState({
imageCrop: res
})
}
};
It doesn'tt crop correcty.
Any help?
Sorry , i can't help about this issue . But there is a library react-native-image-crop-picker which can help with cropping issue . Hope this helps.
I've been tasked with testing some pretty heavy duty functions and unfortunately I have no idea where to start with this one.
The function in question is this one:
export async function getCroppedImg(imageSrc, pixelCrop) {
const image = await createImage(imageSrc);
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
// set width to double image size to allow for a safe area for the
// image to rotate in without being clipped by canvas context
canvas.width = image.width * 2;
canvas.height = image.height * 2;
// translate canvas context to a central location to allow rotating around the center.
ctx.translate(image.width, image.height);
ctx.translate(-image.width, -image.height);
// draw rotated image and store data.
ctx.drawImage(image, image.width / 2, image.height / 2);
const data = ctx.getImageData(0, 0, image.width * 2, image.height * 2);
// set canvas width to final desired crop size - this will clear existing context
canvas.width = pixelCrop.width;
canvas.height = pixelCrop.height;
// paste generated rotate image with correct offsets for x,y crop values.
ctx.putImageData(data, 0 - image.width / 2 - pixelCrop.x, 0 - image.height / 2 - pixelCrop.y);
// As Base64 string
// return canvas.toDataURL('image/jpeg');
// As a blob
const preview = new Promise(resolve => {
canvas.toBlob(file => {
resolve(URL.createObjectURL(file));
}, "image/jpeg");
});
const base64String = canvas.toDataURL();
return Promise.all([preview, base64String]);
}
The other function called in this one is the createImage function that looks like this:
export const createImage = url =>
new Promise((resolve, reject) => {
const image = new Image();
image.addEventListener("load", () => resolve(image));
image.addEventListener("error", error => reject(error));
image.setAttribute("crossOrigin", "anonymous"); // needed to avoid cross-origin issues on CodeSandbox
image.src = url;
});
This has already been tested to 100% coverage so I know I've got to mock it to test the getCroppedImage function but I haven't got a clue where to start with this one...
You can consider spying on createImage and mock the response as a resolved promise.
const spy = jest.spyOn(yourMockedModule, 'createImage').mockImplementation(() => Promise.resolve(....));
I am trying to load a flag (gif) texture to a sphere geometry in THREE.js, but the caveat is I am using React to do this.
const textureLoader = new THREE.TextureLoader();
const flag = getFlagForCountry(flags, x.id),
texture = textureLoader.load(require(`../assets/images/flags/${flag.name}.gif`));
const mat = new THREE.MeshLambertMaterial({
transparent: true,
opacity: .5,
map: texture
});
const sphere = new THREE.Mesh(new THREE.SphereGeometry(1, 10, 10), mat);
sphere.overdraw = true;
When I remove the map: texture property I am able to see the sphere in the scene, but then when I add back in the texture it is simply a black screen. I know the docs for TextureLoader say url is a string, but I am not getting any errors and in fact I am getting warnings that make it appear like something is working. Has anyone had success loading a texture onto a sphere using require() in React.
THREE.WebGLRenderer: image is not power of two (1181x788). Resized to 1024x512
<img crossorigin="anonymous" src="/static/media/Argentina.4c3ff3da.gif">
I would recommend passing the image path directly to the .load() method rather than passing it via require(). Also, I suggest using the TextureLoader callback, to ensure that your texture object is valid and fully loaded, before trying to make use of it.
You can make use of the callback in this way:
const textureLoader = new THREE.TextureLoader();
const flag = getFlagForCountry(flags, x.id)'
// Use the loaders callback
textureLoader.load(`../assets/images/flags/${flag.name}.gif`, function(texture) {
// The texture object has loaded and is now avalible to be used
const mat = new THREE.MeshLambertMaterial({
transparent: true,
opacity: .5,
map: texture
});
const sphere = new THREE.Mesh(new THREE.SphereGeometry(1, 10, 10), mat);
sphere.overdraw = true;
// Add sphere to your scene ... scene.add(sphere);
});
As a final note, consider adjusting your image filepath to an absolute path (by removing the ..) if your assets directory is located in the same directory that your webserver is running from.
Hope this helps!
import React, { Component } from "react";
import * as THREE from "three";
var earthMesh;
class ThreeScene extends Component {
componentDidMount() {
const width = this.mount.clientWidth;
const height = this.mount.clientHeight;
//ADD SCENE
this.scene = new THREE.Scene();
//ADD CAMERA
this.camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000);
this.camera.position.z = 8;
//ADD RENDERER
this.renderer = new THREE.WebGLRenderer({ antialias: true });
this.renderer.setClearColor("#263238");
this.renderer.setSize(width, height);
this.mount.appendChild(this.renderer.domElement);
//ADD CUBE
const geometry = new THREE.BoxGeometry(5, 5, 5);
const material = new THREE.MeshBasicMaterial({
color: "#0F0",
wireframe: true
});
this.cube = new THREE.Mesh(geometry, material);
this.scene.add(this.cube);
//Add SPHERE
//LOAD TEXTURE and on completion apply it on box
var loader = new THREE.TextureLoader();
loader.load(
"data:image/png;base64,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",
this.onLoad,
this.onProgress,
this.onError
);
//LIGHTS
var lights = [];
lights[0] = new THREE.PointLight(0x304ffe, 1, 0);
lights[1] = new THREE.PointLight(0xffffff, 1, 0);
lights[2] = new THREE.PointLight(0xffffff, 1, 0);
lights[0].position.set(0, 200, 0);
lights[1].position.set(100, 200, 100);
lights[2].position.set(-100, -200, -100);
this.scene.add(lights[0]);
this.scene.add(lights[1]);
this.scene.add(lights[2]);
}
componentWillUnmount() {
this.stop();
this.mount.removeChild(this.renderer.domElement);
}
start = () => {
if (!this.frameId) {
this.frameId = requestAnimationFrame(this.animate);
}
};
stop = () => {
cancelAnimationFrame(this.frameId);
};
animate = () => {
this.earthMesh.rotation.x += 0.01;
this.cube.rotation.y += 0.01;
this.renderScene();
this.frameId = window.requestAnimationFrame(this.animate);
};
renderScene = () => {
this.renderer.render(this.scene, this.camera);
};
onLoad = texture => {
var objGeometry = new THREE.SphereBufferGeometry(3, 35, 35);
var objMaterial = new THREE.MeshPhongMaterial({
map: texture,
shading: THREE.FlatShading
});
this.earthMesh = new THREE.Mesh(objGeometry, objMaterial);
this.scene.add(this.earthMesh);
this.renderScene();
//start animation
this.start();
};
onProgress = xhr => {
console.log((xhr.loaded / xhr.total) * 100 + "% loaded");
};
// Function called when download errors
onError = error => {
console.log("An error happened" + error);
};
render() {
return (
<div
style={{ width: "400px", height: "400px" }}
ref={mount => {
this.mount = mount;
}}
/>
);
}
}
export default ThreeScene;
https://codesandbox.io/embed/kw7l49nw1r