I'm experimenting with Google Cloud Vision API and trying to extract colors from an image. The problem occurs when I try to send a cropped image to the Vision API and I get an "Bad image data" error message back.
The Base64 I send to Vision API that getting the error is working when I send it to the client and creating an image or canvas.
The plain URL that is getting sent to the server through a request (req.headers.imageurl) is working when sent to the Vision API.
The images that is being created from the base64 from the server is fully functional when downloaded and uploaded to the "Test the api" at https://cloud.google.com/vision
Could it have something with some CrossOrigin problem? But then I don't get why I can't draw it to an canvas later on when sent to the client.
Thanks in advance for the help!
The function for requesting and sending the Vision API request out of the cropped image
// Imports the Google Cloud client library
const vision = require("@google-cloud/vision");
const client = new vision.ImageAnnotatorClient();
const fetch = require("../functions/Fetch");
const imageEdit = require("../functions/ImageEdit");
exports.colorDetection = async (req, res) => {
// Then you 'get' your image like so:
await fetch.getImage(req.headers.imageurl, async function (err, data) {
// Handle the error if there was an error getting the image.
if (err) {
throw new Error(err);
}
// Crop Image
const cropSettings = JSON.parse(req.headers.cropsettings);
const croppedImage = await imageEdit.CropImage(data, cropSettings);
const stringify = JSON.stringify(croppedImage);
const request = {
image: {
content: Buffer.from(croppedImage).toString("base64"),
},
};
// // Performs label detection on the image file
const [result] = await client.imageProperties(request);
console.log(result)
const colors = result.imagePropertiesAnnotation;
// const stringify = JSON.stringify(colors);
await res.json(stringify);
});
};
The crop image function
const { createCanvas, Image } = require("canvas");
exports.CropImage = (data, cropSettings) => {
"user strict";
// Settings
let cropLeft = cropSettings.startX,
cropTop = cropSettings.startY,
cropWidth = cropSettings.width,
cropHeight = cropSettings.height;
// Canvas
let resize_canvas = createCanvas(cropWidth / 2, cropHeight / 2);
//Image
let crop_img = new Image();
crop_img.src = `data:image/png;base64,${data.toString("base64")}`;
function Crop() {
const ctx = resize_canvas.getContext("2d");
ctx.drawImage(
crop_img,
cropLeft,
cropTop,
cropWidth * 2,
cropHeight * 2,
0,
0,
cropWidth,
cropHeight
);
}
if (crop_img && crop_img.complete) {
Crop();
try {
const base64Img = resize_canvas.toDataURL("image/png", 1.0);
return base64Img
} catch (e) {
console.log(e);
}
} else {
crop_img.onload = function () {
Crop();
try {
const base64Img = resize_canvas.toDataURL("image/png", 1.0);
return base64Img
} catch (e) {
console.log(e);
}
};
}
};
You can use my code given below. Basically you have to convert the image into base64 and remove 'data:image/png;base64' and pass the value into content key.
const getBase64FromUrl = async (url) => {
const data = await fetch(url);
const blob = await data.blob();
return new Promise((resolve) => {
const reader = new FileReader();
reader.readAsDataURL(blob);
reader.onloadend = () => {
const base64data = reader.result;
resolve(base64data);
};
});
};
const base64Image = getBase64FromUrl('url').split(',')[1]
image: {
content: base64Image.split(",")[1],
},
This should work perfectly!