I would like to generate a thumbnail image from a .dcm file (Dicom) in node.js.
So far I've found a node modules called dicom-parser that extracts the metadata from a dcm file.
My test case :
var dicom = require('dicom-parser');
var fs = require('fs');
var dicomFileAsBuffer = fs.readFileSync('./FullPano.dcm');
var dataSet = dicom.parseDicom(dicomFileAsBuffer);
var pixelData = new Uint8Array(dataSet.byteArray.buffer,
dataSet.elements.x00880200.items[0].dataSet.elements.x7fe00010.dataOffset,
dataSet.elements.x00880200.items[0].dataSet.elements.x7fe00010.length);
fs.writeFileSync('test5.jpg', pixelData); // <----- not working :'(
To help you help me debug, here is the dataSet.elements.x00880200 object :
But the pixelData stored in the tag x00880200 -> x7fe00010 is not in a standard format, either jpeg, jpg, png... The idea here is to get the thumbnail of a dcm image directly from a file, on the fly, server-side in nodejs.
From the dicom doc (see below), the tag 0088,0200 holds the data for the icon, aka thumbnail.
Icon Image Sequence
(0088,0200)
3
This icon image is representative of the Image.
Only a single Item is permitted in this Sequence.
I've come around the cornerstone libs : cornerstone-js and wado-image-loader. But neither are working in a node.js environment (made an issue about that). These libs can generate the "main" image of a dcm, but only once the dcm file is loaded on the cliend-side, in js. My requirement is to do that in nodejs, for the icon/thumbnail.
If you are trying to save the image icon as a JPG, that may be your issue:
Only monochrome and palette color images shall be used. Samples per Pixel (0028,0002) shall have a Value of 1, Photometric Interpretation (0028,0004) shall have a Value of either MONOCHROME 1, MONOCHROME 2 or PALETTE COLOR, Planar Configuration (0028,0006) shall not be present.source
I'm not familiar with node.js, but the data in the Icon Image Sequence may not be appropriate for that call.
Note also that you are getting an optional, small, thumbnail of the image, not the actual image data, which can be found in the Pixel Data attribute (7FE0,0010).
A bit late but, if you are still looking for an answer, you can use dcmjs-imaging (full disclosure, I am the author). The library implements a DICOM image and overlay rendering pipeline, for Node.js and browser.
The library supports uncompressed data but also, optionally, decodes all major transfer syntaxes using a native WebAssembly module.
Given that you have already fetched the the DICOM bytes in an ArrayBuffer, you can use the following Node.js example to render the image in an RGBA pixel ArrayBuffer.
// Import objects
const dcmjsImaging = require('dcmjs-imaging');
const { DicomImage, NativePixelDecoder } = dcmjsImaging;
// Optionally register native decoders WebAssembly.
// If native decoders are not registered, only
// uncompressed syntaxes would be able to be rendered.
await NativePixelDecoder.initializeAsync();
// Create an ArrayBuffer with the contents of the DICOM P10 byte stream.
const image = new DicomImage(arrayBuffer);
// Render image.
const renderingResult = image.render();
// Rendered pixels in an RGBA ArrayBuffer.
const renderedPixels = renderingResult.pixels;
// Rendered width.
const width = renderingResult.width;
// Rendered height.
const height = renderingResult.height;
Related
I'm working with Etsy api uploading images like this example, and it requires the images be in binary format. Here is how I'm getting the image binary data:
async function getImageBinary(url) {
const imageUrlData = await fetch(url);
const buffer = await imageUrlData.buffer();
return buffer.toString("binary");
}
However Etsy says it is not a valid image file. How can I get the image in the correct format, or make it in a valid binary format?
Read this for a working example of Etsy API
https://github.com/etsy/open-api/issues/233#issuecomment-927191647
Etsy API is buggy and has an inconsistent guide. You might think of using 'binary' encoding for the buffer because the docs saying that the data type is string but you actually don't need to. Just put the default encoding.
Also currently there is a bug for image upload, try to remove the Content-type header. Better read the link above
I want to compress an image using Sharp image processing library, pass it through an external quant library and then get the sharp metadata for it. I want to do this to actually overlay the compressed image size onto the image (during development only).
For a WEBP this is easy because everything is in the sharp pipeline.
// specify the compression
myImage.webp({ quality: 80 });
// actually compress it
var tempBuffer = await myImage.toBuffer({ resolveWithObject: true});
// create a new sharp object to read the metadata
var compressedImage = sharp(tempBuffer.data);
// Image data is now available in
console.log(compressedImage.info.size / 1024);
But when using the quant library I'm piping it into a third party library and so it's no longer a sharp object. I need to get the raw buffer out again in the most efficient way. I'm new to Node.js and don't know how to do this.
resizedImage.png()
.pipe(new quant(['--quality=50-70', '--speed', '1', '-']));
Do I need to use something like https://www.npmjs.com/package/stream-to-array ?
That seems crazy to me! Am I missing something?
Figured it out. You can just pipe it back into sharp()like this:
resizedImage.png()
.pipe(new quant(['--quality=50-70', '--speed', '1', '-']))
.pipe(sharp());
Then you can call metadata() or further resizing etc. (not that you'd normally do that!)
How can i generate an image of a string that has:
a size in px
embossed effect of the letters in the image
a font
a color
and other less important stuff that i think i can figure out once i achieve whats above like:
rotation of text
drop shadow
basically the user will send a request on how he wants his image to be.
but when i receive the request how should i make use of nodejs to render a png or a base64 url to send it back to the user. is there any libraries or way to achieve this.
i did some previous research and it doesn't seem like there is a frameworks that helps render text with a font and text style like emboss
You can try node canvas implementation: https://github.com/Automattic/node-canvas
Basically you can "draw" anything you want like if you'd be using browser js canvas, but some things may be different
Update - This will cover updating attributes of an image, not pulling text from image and updating that - you may need an image analysis library for that
Use the sharp library to manipulate the image as desired. https://github.com/lovell/sharp
http://sharp.dimens.io/en/stable/
A simple example that resizes (docs will show how to make the changes you want outside of this):
const request = require('request').defaults({ encoding: null });
request.get(imgUrl, params, function (err, res, body) {
sharp(body)
.resize(params.width, params.height)
.toFormat('jpeg')
.toBuffer()
.then((outputBuffer) => {
// outputBuffer contains JPEG image data no wider than params.width and no higher
// than params.height while maintaining quality of image.
let output = "data:" + res.headers["content-type"] + ";base64," + new Buffer(outputBuffer).toString('base64');
return output;
});
The output here will be the base64 image
For a project I need to to parse an Adobe Photoshop PSD file, programatically find and replace an image layer and then save it back to a PSD file and/or export it as PNG (or JPEG). I do not have a lot of experience with Adobe Photoshop but I think these types of layers are called 'smart layers'.
The use case:
Render mockup preview image
User uploads image to Node HTTP server
Replace layer in PSD with
uploaded image (image fill layer)
Render as PNG/JPEG and write to HTTP response
The replacement layer is 3d skewed over x and y for a mockup template. I have included an image to illustrate what this means. Additional mockup templates will be created in the future which is why I think labeling the replacement layer with a constant value is the way to implement this.
The template file:
The uploaded image:
The final rendered image
I don't need help with the HTTP server/authentication etc, that part is trivial. I am only looking for a method to replace the image layer.
The PSD files are/will be custom made for this particular project. To identify the right layer to replace based on the layer name (label) is an acceptable implementation.
I have had a look at several NPM packages to do this job but was not able to get a functioning prototype. This package seems the most promising.
https://www.npmjs.com/package/psd
I currently have the following code:
/* mockup.js */
var PSD = require('psd')
var psd = PSD.fromFile("mockup.psd")
var fs = require('fs')
psd.parse()
/* For easier reference */
var replacementLayer, file, fileBuffer
let tree = psd.tree()
let layers = tree.layer.node._children
for(let layer of layers) {
/* i named the layer 'replacementLayer' */
if(layer.name == 'replacementLayer') {
replacementLayer = layer
file = replacementLayer.layer.file
fileBuffer = replacementLayer.layer.file.data
}
}
/* replacementLayer = instanceof Layer
file = instanceof File with a property 'data' (data is a buffer)
fileBuffer = instanceof Buffer */
I tried various ways of opening an image file and replacing the replacementLayer in the PSD but I can't get it to work. Simply overwriting the property with a new Buffer object is not enough.
Saving the image as a PNG is as simple as
psd.image.saveAsPng('./output.png')
Ideally, the image that is used to replace the replacementLayer should 'fill' to the width and height of the layer.
Any ideas?
ag-psd can handle this, but the saved PSD does not render the outermost layer
When creating a SVG image you have to set width,height and position otherwise it will not be rendered.
How do I read them from the original image?
Using Dart I first load the html image and after it's loaded I get the size and then define the SVG image and use the info I got before. This is a bit cumbersome and I wondered if there is another way.
The dart code looks like this:
ImageElement img = new ImageElement(src:'2.jpg'); //401x600
img.onLoad.listen((e) {
svg.ImageElement image = new svg.ImageElement();
image.setAttribute('x', '0');
image.setAttribute('y', '0');
image.setAttribute('width', img.width.toString());
image.setAttribute('height', img.height.toString());
image.getNamespacedAttributes('http://www.w3.org/1999/xlink')['href'] = '2.jpg';
});
There seems not to be a more convenient method (also not in JavaScript except when you use jQuery or another framework that includes methods for this).
Just create a method yourself and reuse that method for each image you load.