How to convert png pure black & white (no greyscale) with Sharp.js - node.js

I need to convert a png with color into a png that is only black and white. I'm currently processing images Sharp.js. But I haven't been able to find a way to generate a monochromatic image.
I found a greyscale option.
const sharp = require('sharp');
sharp('color-image.png')
.toGreyscale()
.toFile('b-w-image.png')
.then(() => {
console.log('Huzzah!')
});
But this doesn't work for my needs. I'm looking for a pure black and white image with no shades of grey.
I haven't found anything in the documentation that allows you to specify the level of greyscale to allow for only a B/W image.
Is there a method available that converts the image into pure black and white?

This will get you an image with two colors. Increase the contrast using the linear option.
const sharp = require('sharp');
sharp('ben.png')
.greyscale() // make it greyscale
.linear(1.5, 0) // increase the contrast
.png({colors:2}) // reduce image to two colors
.toFile('b-w-image.png')
.then(() => {
console.log('Huzzah!')
});

Related

SwiftUI tint for image but preserving Black and White

I need to shift the color in an image, e.g. from gray to green. But only the parts that are not white and/or black...
For UIKit I had a handy extension:
// colorize image with given tint color
// this is similar to Photoshop's "Color" layer blend mode
// this is perfect for non-greyscale source images, and images that have both highlights and shadows that should be preserved
// white will stay white and black will stay black as the lightness of the image is preserved
func tint(tintColor: UIColor) -> UIImage {
return modifiedImage { context, rect in
// draw black background - workaround to preserve color of partially transparent pixels
context.setBlendMode(.normal)
UIColor.black.setFill()
context.fill(rect)
// draw original image
context.setBlendMode(.normal)
context.draw(self.cgImage!, in: rect)
// tint image (loosing alpha) - the luminosity of the original image is preserved
context.setBlendMode(.color)
tintColor.setFill()
context.fill(rect)
// mask by alpha values of original image
context.setBlendMode(.destinationIn)
context.draw(self.cgImage!, in: rect)
}
}
is there any way to generate the same functionality with the tint options in SwiftUI?
".colorMultiply" colors white as well.
".saturation(0.5)" directly generates a grayscale image.
You can continue to use your extension, like
var body: some View {
Image(uiImage: UIImage(named: "some")!.tint(tintColor: UIColor.red))
}
I was looking for the wrong keyword.
The actually way to do this in SwiftUI is hueRotation!
It only works with coloured images and not with grayscale images though.
See example below:
Color.blue
.hueRotation(.degrees(-45.0))

Can fabric.js parse raster graphic to "real" svg?

I have a question/problem with fabric.js - in my code the user can upload a picture, with filters he can convert it to a black/white image. When I export the picture with canvas.toSVG(); it exports a svg image, but it is no real vector graphic - it loses quality when scaling up.
function handleImage(e) {
var reader = new FileReader();
reader.onload = function (event) {
var img = new Image();
img.onload = function () {
var imgInstance = new fabric.Image(img, {
scaleX: 0.7,
scaleY: 0.7
})
canvas.add(imgInstance);
}
img.src = event.target.result;
} reader.readAsDataURL(e.target.files[0]);}
$('saveBtn').onclick = function() {
var filedata= canvas.toSVG(); // the SVG file is now in filedata
var locfile = new Blob([filedata], {type: "image/svg+xml;charset=utf-8"});
var locfilesrc = URL.createObjectURL(locfile);//mylocfile);
var dwn = document.getElementById('dwn');
dwn.innerHTML = "<a href=" + locfilesrc + " download='mysvg.svg'>Download</a>";}
What am I doing wrong?
There is no easy way to "parse" raster graphics to a vector image. Vector graphics include information for how to draw an image, while raster images only include the pixel data for how an image appears at a given size and resolution. That's enough for many purposes, but it means that while it's easy to go from vector to raster (just execute the instructions), it's not easy to go from raster to vector.
It is possible to "trace" the edges of a raster image to obtain vectors that can approximate the raster: in other words, a set of vector instructions that, for that particular resolution and depth, yields an image that is the same as the original raster (or something very like it). But there is no guarantee that these actually correspond in any way to the original vectors (if there are any original vectors at all). Usually there is no correspondence, in fact, unless your tracing algorithm is very specialized: for example, tracing images of a font to make a vector copy of that font. Because they don't correspond, there's no guarantee that the image will scale up the way you want it to: it'll scale, but things may enlarge in strange ways.
It is possible to implement tracing algorithms in JavaScript, by drawing the image into a <canvas> element, using getImageData() to grab the pixel information from that, and performing your operations on the pixel information. Doing this, though, is beyond the scope of this question.

MagickWand: transparent SVG part rendered as white background

I am trying to read SVG images using ImageMagick (6.8.8-7) and get valid transparent pixels.
The code below is working well with PNG format, but for SVG i can only have some white background.
So i tried to add MagickSetBackgroundColor, and MagickSetImageBackgroundColor with some merging layers but i still can't make it works.
Below an extract from the PoC:
MagickWandGenesis();
m_wand = NewMagickWand();
MagickReadImage(m_wand, file_name);
hasAlfa = MagickGetImageAlphaChannel(m_wand);
fprintf(stderr, "alpha channel detection: %d\n", hasAlfa);
if (hasAlfa == MagickTrue) {
PixelWand *color;
MagickWand *new_wand;
imagedata = malloc(w*h*4);
color = NewPixelWand();
PixelSetColor(color, "none");
MagickSetBackgroundColor(m_wand, color);
MagickSetImageBackgroundColor(m_wand, color);
new_wand = MagickMergeImageLayers(m_wand, MergeLayer);
DestroyMagickWand(m_wand);
m_wand = new_wand;
mrc = MagickExportImagePixels(m_wand, 0, 0, (size_t)w, (size_t)h, "RGBA", CharPixel, imagedata);
fprintf(stderr, "R:%d G:%d B:%d A:%d\nR:%d G:%d B:%d A:%d\n", imagedata[0], imagedata[1], imagedata[2], imagedata[3], imagedata[4], imagedata[5], imagedata[6], imagedata[7]);
}
Result using a PNG image:
size: 9 x 11
alpha channel detection: 1
R:0 G:0 B:0 A:0
R:0 G:0 B:0 A:0
Result using a SVG image:
size: 640 x 1000
alpha channel detection: 1
R:255 G:255 B:255 A:255
R:255 G:255 B:255 A:255
Any clues ?
I hope, I understood your question. To convert transparence from svg to png a pixel has to be defined as transparent.
You can define transparency in svg using "opacity", but in svg transparency is only given for next layer (not alpha-layer, that shines through all objects like in alpha).
If you want alpha transparency on an png, it's really the best way to define (i.e. white), and set that to alpha transperency

How to create a `pixelized' SVG image from a bitmap?

I have a 16x16 bitmap and want to create an SVG that contains 16x16 squares with the colors of the pixels of the image. Is there an easy way to achieve this?
My current thoughts go into the direction of using Python and PIL to read the bitmap image and dynamically create an SVG image file with the corresponding objects. But this feels a little clumsy and like reinventing the wheel.
Is there a better way to do this?
If you don't need the output to be SVG, I would suggest using an HTML5 Canvas where you can sample the pixels of the image client-side (using getImageData() on the context) and then draw your own up-scaled image. Or, if you need SVG, you could still use Canvas for the image sampling and then use procedurally-created <rect/> elements in SVG for each pixel.
I've written an example using just HTML Canvas so you can see how to do this. In short:
function drawPixelated(img,context,zoom,x,y){
if (!zoom) zoom=4; if (!x) x=0; if (!y) y=0;
if (!img.id) img.id = "__img"+(drawPixelated.lastImageId++);
var idata = drawPixelated.idataById[img.id];
if (!idata){
var ctx = document.createElement('canvas').getContext('2d');
ctx.width = img.width;
ctx.height = img.height;
ctx.drawImage(img,0,0);
idata = drawPixelated.idataById[img.id] = ctx.getImageData(0,0,img.width,img.height).data;
}
for (var x2=0;x2<img.width;++x2){
for (var y2=0;y2<img.height;++y2){
var i=(y2*img.width+x2)*4;
var r=idata[i ];
var g=idata[i+1];
var b=idata[i+2];
var a=idata[i+3];
context.fillStyle = "rgba("+r+","+g+","+b+","+(a/255)+")";
context.fillRect(x+x2*zoom, y+y2*zoom, zoom, zoom);
}
}
};
drawPixelated.idataById={};
drawPixelated.lastImageId=0;
If you really need SVG involved, I'd be happy to write an example that dynamically generated that.
Edit: OK, I've created an SVG version just for fun and practice. :)
As an aside (from an initial misreading of your question) this demo file from ASVG3 their old SVG Examples Page shows how to use some complex compositing of many different effects to create pixelation on arbitrary vector data. Unfortunately the demo does not load in Chrome, having been hardwired to require the (now-discontinued) Adobe SVG Viewer.

Opencv: Converting hue image to RGB image

I am trying to show the hue component of the image from my webcam. I have split apart the image into the hue component but I can't figure out how to show the hue component as the pure colors. For example if one pixel of the image was B=189 G=60 R=60 then in HSV, H=0. I don't want the draw image to be the the gray values of hue but the RGB equivalent of the hue or H=0 -> B=0 G=0 R=255
IplImage *image, *imageHSV, *imageHue;
image = cvQueryFrame(capture); //image from webcam
imageHSV = cvCreateImage( cvGetSize(image), IPL_DEPTH_8U, 3 );
imageHue = cvCreateImage( cvGetSize(image), IPL_DEPTH_8U, 1 );
cvCvtColor( image, imageHSV, CV_BGR2HSV );
cvSplit( imageHSV, imageHue, 0, 0, 0 );
I have a feeling there is a simple solution so any help is appreciated.
If I understand you correctly, you want to "correctly" visualize just the Hue component. You can create another imageSat and imageVal, one-channel each and filled with 255 (maximum). Then cvMerge your imageHue with the other two, to create a new HSV image, and convert that back to RGB/BGR for final display.

Resources