Find file format of loaded bitmap with SkiaSharp? - skiasharp

I'm trying to figure out the format of an image that is loaded by an array of bytes into an SKBitmap. I'd just like to know if it is a JPEG or PNG, etc.
// Was the decoding done by a JPEG decoder or PNG or?
var bitmap = SKBitmap.Decode(buffer);
Is this possible?

I would have a look at SKCodec.
https://learn.microsoft.com/dotnet/api/skiasharp.skcodec
That doesn't even load the actual image data out the box - just the headers. The way, you don't use stacks of memory when reading the file type.
To read the type, use the EncodedFormat property:
https://learn.microsoft.com/dotnet/api/skiasharp.skcodec.encodedformat
using var codec = SKCodec.Create(...);
var format = codec.EncodedFormat;

Related

Swift 4: help decoding a JSON that contains an encoded image using base64

I'm a Swift (and programming) newb, fair warning.
I'm working on an app that is used to track scavenger hunt bonuses. I want to use a JSON file to contain all the bonus data, including a sample image. I see how to encode the image into base64 outside the program, then I can add it into my JSON as a string. Where I'm not certain is what to do with this? From searching I see you would use something like:
class func convertBase64ToImage(imageString: String) -> UIImage {
let imageData = Data(base64Encoded: imageString, options: Data.Base64DecodingOptions.ignoreUnknownCharacters)!
return UIImage(data: imageData)!
}
But I'm not certain if that would simply display said image, or if I need to save that and then call it somehow. The goal is to simply view the image (it is used for reference by the person taking a picture with their placard in the shot).
(I haven't implemented this in code yet, I'm still researching how to do it)
Your code works fine. You can test it out in a Playground easily enough. I used https://www.base64-image.de to Base64 encode a small PNG file and generate a string which I ran through your function. It worked fine.
To answer your direct question, UIImage is simply an image which you can display to the user as follows:
Create a view controller. Add a UIImageView to the view controller and wire up an outlet for it with a suitable name (for example, bonusImageView).
Call your function within the view controller to load the image into the image view.
bonusImageView.image = convertBase64ToImage(imageString: imageString)
Where imageString is the Base64-encoded string you obtained from your JSON.
Whether or not you choose to store the imageString first is up to you. It's not necessary to store it if all you want to do is retrieve it from a server and display it on demand.

Images downloaded from s3, how to save them

After downloading an image from s3, I get a bunch of bits inside the 'Body'. Previously, I was encoding such bits into base64 and displaying them directly in a <img> tag.
But now, I want to save them into a "real" file (.jpg/png) in the filesystem (android/iOS) then give the path to a html (background) tag.
(will it work?)
Do I still need to convert the bunch of bits I got from S3 into base64 then save it or is there a more straightforward way ?
You can use the plugin cordova-plugin-file for saving file locally to your filesystem.
Like this
var url = url;
var targetPath = cordova.file.externalDataDirectory + NAME;
//alert(targetPath);
var trustHosts = true;
var options = {};
$cordovaFileTransfer.download(url, targetPath, options, trustHosts)
I think you can give the local file address to img src..

Send opencv Mat image through Qt websocket to HTML client

I'm trying to write an application in c++ using Qt 5.7, basically it should be a websocket server, using qwebsocket for this, capable to send an image elaborated with opencv to an HTML client. What I'm trying to do is encode the image in base64, transmit and on the client put the encoded string in the src of an image tag.
Just to test, I can send/receive text messages correctly, so the websocket architecture is working, but I have some problems with images. This is my code snippets:
Server
cv::Mat imgIn;
imgIn = cv::imread("/home/me/color.png",CV_LOAD_IMAGE_COLOR);
QByteArray Img((char*)(imgIn.data),imgIn.total()*imgIn.elemSize());
QByteArray Img64 = Img.toBase64();
pClient->sendBinaryMessage(Img64);
Client
<img id="ItemPreview" src="" style="border:5px solid black" />
....
websocket.binaryType = "arraybuffer";
websocket.onmessage = function (evt) {
console.log( "Message received :", evt.data );
document.getElementById("ItemPreview").src = "data:image/png;base64," + evt.data;
};
I think most of the problems are in the Server, because the base64 sequence I got from the image is different from the one I can get from online converter image/base64.
On the client I receive this error in the console and nothing is showed:
data:image/png;base64,[object ArrayBuffer]:1 GET
data:image/png;base64,[object ArrayBuffer] net::ERR_INVALID_URL
Any hints?
SOLUTION
Thanks to the suggestions, I can provide the working code:
Server
imgIn = cv::imread("/home/me/color.png", CV_LOAD_IMAGE_UNCHANGED);
std::vector<uchar> buffer;
cv::imencode(".png",imgIn,buffer);
std::string s = base64_encode(buffer.data(),buffer.size());
pClient->sendTextMessage(QString::fromStdString(s));
Client
Removed this line:
websocket.binaryType = "arraybuffer";
The base64 encoding in the server is done using this code:
Encode/Decode base64
This line in the server:
imgIn = cv::imread("/home/me/color.png",CV_LOAD_IMAGE_COLOR);
decodes a PNG formatted image, and places it in memory as load of pixel data (plus possibly some row padding, which you don't take account of, see below). That's what you're base64 encoding.
This line in the client:
document.getElementById("ItemPreview").src = "data:image/png;base64," + evt.data;
is expecting a PNG image, but that isn't what you're sending; you've just pushed out a load of raw pixel data, with no dimensions or stride or format information or anything else.
If your client wants a PNG, you're going to have to use something like imencode to write PNG data to a memory buffer, and base64 encode that instead.
One other important thing to note is that decoded images may have row padding... a few bytes on the end of each row for memory alignment purposes. Therefore, the actual length of each image row may exceed the width of the image multiplied by the size of the each pixel in bytes. That means that this operation:
QByteArray Img((char*)(imgIn.data),imgIn.total()*imgIn.elemSize());
may not, in fact, wrap the entire image buffer in your QByteArray. There are various ways to check the stride/step of an image, but you'd best read the cv::Mat docs as it isn't worth me repeating them all here. This only matters if you're doing raw byte-level image manipulation, like you are here. If you use imencode, you don't need to worry about this.

Image conversion and view in Chrome browser

I have a bytearray of a tiff image. When I convert into the same format, image opens. But when I convert it into jpg, it doesn't (in Chrome, but works in IE).
PS: I want to directly convert the bytearray to show image dynamically as per my requirement.
ByteArrayOutputStream bOutStream = new ByteArrayOutputStream();
bOutStream = < ... Tiff image Stream Received from my API Call... >
byte[] chqImage = bOutStream.toByteArray();
response.setContentType("image/jpeg");
BufferedOutputStream output = null;
output = new BufferedOutputStream(response.getOutputStream());
output.write( bOutStream.toByteArray());
output.flush();
You're going to need to actually translate the image itself from TIFF to JPEG. To do that, I recommend reviewing the ImageIO library in Java.
I feel like the javadoc for that library is pretty straightforward, so you should be OK there.

Export google doc to PNG and send it on email script

I need a simple way to export - saveAs or getAs, a google document to PNG or JPG and send it on email.
I was able to get it as pdf with 'application/pdf' with this: Class Blob
But wasn't able to use 'image/png' with the same code. The code I use to get .pdf is:
var pdf = DriveApp.getFileById("docID").getAs("application/pdf");
Should I change the code to function for PNG?
The documentation says:
For most blobs, 'application/pdf' is the only valid option. For images in BMP, GIF, JPEG, or PNG format, any of 'image/bmp', 'image/gif', 'image/jpeg', or 'image/png' are also valid.
A Google Document is not an image, so the only type offered is PDF.
What you can do is to save any images embedded in a document as PNG, like this.
var doc = DocumentApp.openByUrl('...');
var image = doc.getBody().getImages()[0]; // first image in document
var file = DriveApp.createFile(image.getBlob().setName('my image.png'));