I am trying to get sketch effect and i have the imagemagick command line code as follows
convert 1.jpg -colorspace gray ( +clone -blur 0x8 \) +swap -compose divide -composite -linear-stretch 2%x20% cousincs.jpg
I am using gm module and I tried to extend gm,however it is not not accepting parenthesis, failing to recognize -linear-stretch resulting in two blurred images instead of one. I tried node-imagemagick native and wizardry but unable to achieve the desired functionality. Can anyone let me know how can I achieve this. Thanks in advance
Here is the code i tried with gm
var dir = __dirname + '/kar/';
var newName=uuid.v4()+".jpg";
imageMagick("2.jpg")
.clone()
.swap()
.compose('divide')
.composite()
.write(dir+newName, function(err,data){console.log("error is ",err)});
Here is the args.js
proto.clone = function clone () {
return this.out("\( +clone -blur 0x8\)");
}
proto.swap=function swap(){
return this.out("+swap");
}
proto.composite=function composite(){
return this.out("-composite -linear-stretch 2%x20%")
}
Related
I want to convert a picture in pure black and white(e.g. no grayscale) using Image crate, the result should be a picture with 0 and 255 RGB values.
Following the docs i've wrote the following:
let img = image::open("photo.jpg").unwrap(); // Load picture
let gray_img = img.grayscale(); // Convert it
// Access a random pixel value
let px = gray_img.get_pixel(0,0);
println!("{:?}", pixel.data); // Print RGB array
The problem here is that, whatever pixel i print, it gives me grayscale value.
So, is there a function to convert an image in pure black and white? Something like Pillow's convert function for Python?
Here's how you can first build a grayscale image then dither it to a Black and White one:
use image::{self, imageops::*};
let img = image::open("cat.jpeg").unwrap();
let mut img = img.grayscale();
let mut img = img.as_mut_luma8().unwrap();
dither(&mut img, &BiLevel);
img.save("cat.png").unwrap(); // this step is optional but convenient for testing
You should of course properly handle errors instead of just doing unwrap.
I am trying to add a label/annotation text (where the background colour of the text is transparent) to an existing image.
I have tried a couple of different approaches but I keep getting a black background colour.
If anyone could point me in the right direction, I would greatly appreciate it.
Attempt 1:
using (var images = new MagickImageCollection())
using (var img = new MagickImage(imgBytes))
{
img.Resize(imageDto.Width, imageDto.Height);
using (var imgText = new MagickImage(MagickColors.None, imageDto.Width, imageDto.Height))
{
var labelSettings = new MagickReadSettings()
{
BackgroundColor = MagickColors.None,
Font = "Arial",
FontPointsize = imageDto.FontSize,
FillColor = MagickColors.Blue,
BorderColor = MagickColors.None,
};
imgText.Read("label:" + imageDto.WatermarkText, labelSettings);
img.Composite(imgText, Gravity.South);
img.Write($"{Guid.NewGuid().ToString()}.png");
return img.ToBase64();
}
}
Attempt 2:
using (var img = new MagickImage(imgBytes))
{
img.Resize(imageDto.Width, imageDto.Height);
// Load the original image and add it to the collection.
images.Add(img);
// Text label watermark settings
var labelSettings = new MagickReadSettings()
{
BackgroundColor = new MagickColor(MagickColors.Transparent),
Font = "Arial",
FontPointsize = imageDto.FontSize,
FillColor = MagickColors.Blue
};
// Create the label image.
var label = new MagickImage($"label:{imageDto.WatermarkText}", labelSettings);
// Extent the width of the label to match the width of the original image.
label.Extent(img.Width, 0, Gravity.Center);
label.Transparent(MagickColors.Black);
// Add the label to the collection.
images.Add(label);
// Append the images to create the output image.
using (var result = images.AppendVertically())
{
result.Write($"{Guid.NewGuid().ToString()}.png");
return result.ToBase64();
}
}
Both attempts produce the same image with a black background (in the area where the text was added to the image)
.
Your first approach is probably the easiest one. But you should use the following overload instead: img.Composite(imgText, Gravity.South, CompositeOperator.Over); The default is CompositeOperator.In and that is not what you should use to get the label as an overlay.
In ImageMagick, you cannot draw transparency for text or background on an opaque image. So you have to draw a colored (black) rectangle, then flood fill it with transparency, then draw your colored text onto the transparent image. For example with your image:
convert image.png \
-draw "translate 250,250 fill black rectangle -50,-50 50,50 \
fill none matte 0,0 floodfill" \
-fill "rgba(255,0,0,1)" -pointsize 20 \
-gravity center -annotate +0+0 "TESTING" \
result.png
ADDITION:
If you only want the text, then leave out the background color and just write the text.
convert image.png \
-fill "red" -pointsize 20 \
-gravity center -annotate +0+0 "TESTING" \
result.png
I'm working with wand to basically do a frame-by-frame translation of a gif. I want to transpose an image into each frame of a gif, then save the output animated gif.
def placeImage(gif_name, image_name, save_location):
with Image(filename = gif_name) as gif:
with Image(filename = image_name) as image:
new_frames = []
for frame_orig in gif_new.sequence:
frame = frame_orig.clone()
with Drawing() as draw:
draw.composite(operator='src_over', left=20, top=20,
width=image.width, height=image.height, image=image)
draw(frame)
new_frames.append(frame)
So now I've got all of these frames (though they're not SingleImage objects, but Image objects) that I'd like to put back together and generate a new gif. Any advice?
I'd like to be able to do something like:
with gif.clone() as output:
output.sequence=new_frames
output.save(filename=save_location)
I just answered something very similar here: Resizing GIFs with Wand + ImageMagick
with Image() as dst_image:
with Image(filename=src_path) as src_image:
for frame in src_image.sequence:
frame.resize(x, y)
dst_image.sequence.append(frame)
dst_image.save(filename=dst_path)
Hope that helps!
When I try to use fraxel's answer on
http://stackoverflow.com/questions/10269099/pil-convert-gif-frames-to-jpg
on the image http://24.media.tumblr.com/fffcc2d8e980fbba4f87d51ed4916b87/tumblr_mh8uaqMo2I1rkp3avo2_250.gif
I get ok data for some, but then for some I get missing data it looks like, e.g.
Correct
Missing
To display these I use imagemagick's display foo* and then use space to move through the images ... is it possible imagemagick is reading them wrong?
Edit:
Even when using convert and then displaying via display foo* I get the following
Could this be a characteristic of the gif then?
If you can stick to ImageMagick then it is very simple to solve this:
convert input.gif -coalesce output.png
Otherwise, you will have to consider the different forms of how each GIF frame can be constructed. For this specific type of GIF, and also the other one shown in your other question, the following code works (note that in your earlier question, the accepted answer doesn't actually make all the split parts transparent -- at least with the latest released PIL):
import sys
from PIL import Image, ImageSequence
img = Image.open(sys.argv[1])
pal = img.getpalette()
prev = img.convert('RGBA')
prev_dispose = True
for i, frame in enumerate(ImageSequence.Iterator(img)):
dispose = frame.dispose
if frame.tile:
x0, y0, x1, y1 = frame.tile[0][1]
if not frame.palette.dirty:
frame.putpalette(pal)
frame = frame.crop((x0, y0, x1, y1))
bbox = (x0, y0, x1, y1)
else:
bbox = None
if dispose is None:
prev.paste(frame, bbox, frame.convert('RGBA'))
prev.save('foo%02d.png' % i)
prev_dispose = False
else:
if prev_dispose:
prev = Image.new('RGBA', img.size, (0, 0, 0, 0))
out = prev.copy()
out.paste(frame, bbox, frame.convert('RGBA'))
out.save('foo%02d.png' % i)
Ultimately you will have to recreate what -coalesce does, since it is likely that the code above may not work with certain GIF images.
You should try keeping the whole history of frames in "background", instead of :
background = Image.new("RGB", size, (255,255,255))
background.paste( lastframe )
background.paste( im2 )
Just create the "background" once before the loop, then only paste() frame on it, it should work.
It's question more about "know-how". I have a bunch of images of completely different sizes: one could be 360x360 and another 1200x800. And I would to make thumbnails for a webpage of exact size, for example 150x150. Because of different sizes I can't just use convert -resize or just crop it some way, I need both.
How would you solve this?
This question is quite old, but a current answer would be to use resize:
convert "input_filename" -resize '400x400!' "output_filename"
Note the exclamation point "!", which at least some shells require you to quote or escape to avoid history expansion.
Note that in requesting exact size, you may be asking for distortion.
You need a function that will calculate what the thumbnail sizes should be based on the source image width and height, and the max thumbnail width and height:
function setWidthHeight($srcWidth, $srcHeight, $maxWidth, $maxHeight){
$ret = array($srcWidth, $srcHeight);
$ratio = $srcWidth / $srcHeight;
if($srcWidth > $maxWidth || $srcHeight > $maxHeight){
$ret[0] = $maxWidth;
$ret[1] = $ret[0] / $ratio;
if($ret[1] > $maxHeight){
$ret[1] = $maxHeight;
$ret[0] = $maxHeight * $ratio;
}
}
$ret[0] = intval(ceil($ret[0]));
$ret[1] = intval(ceil($ret[1]));
return $ret;
}
You can then use whichever thumbnail image generating procedure you like imagecopyresampled(...) or the $imageMagick->thumbnailImage($newWidth, $newHeight);