PerlTk canvas + pixel manipulation - perltk

I'm having some problems understanding how the image types in PerlTk work.
I basically want a way to create an "empty" image (for example fully white) and then manipulate the pixel data. I need to able to change a pixel to black or white.
I've tried a few approaches but non of them seem to work. Documentation seems to be pretty scarce and very old. This is closest I've got.
#args name, width, height, data
my $bitmap = $mw->DefineBitmap('cells', 1, 1, pack("b1", "1"));
#args x-pos, y-pos, bitmap-name
$canvas->createBitmap(0, 0, -bitmap => 'cells');
Another idea I had was to use a Photo element but I couldn't find any documentation on how to create one with the "-data" option.
Any help is appreciated.

Use the put() method if you have to set single pixels. Here's a complete example:
use Tk;
my $mw = tkinit;
my $p = $mw->Photo(-width => 100, height => 100);
my $l = $mw->Label(-image => $p, -border => 0)->pack;
for (0..99) {
$p->put("#000000", -to => $_,$_);
$p->put("#000000", -to => 100-$_,$_);
}
MainLoop;

Related

Stitch multiple pngs with Jimp

I need to stitch multiple pngs into a long png, and I believe I can use Jimp's blit method:
// blit the image with another Jimp image at x, y, optionally cropped.
image.blit( src, x, y, [srcx, srcy, srcw, srch] );
My question is, how do I loop along all the pngs and make the current png attach to the end of the previous one? For example, they are all in a same folder with file names like img-1, img-2 ... img-10. And their sizes are not necessarily the same. This is what I have in mind, any suggestions would be greatly appreciated!
// This is dummy code
const bg = white_background
bg.width = Math.max(img-1...img-10 width)
bg.height = sum(img-1...img-10 height)
for (let i=0;i<imgs.length;i++) {
if(i=0) bg.blit(img, 0, 0)
else bg.blit(img, imgs[i-1].width, imgs[i-1].height)
}

OpenCV Seamless Cloning shift position after finish the process

I am trying to used the seamsless cloning to blend to image together.
but I notice that after using the seamsless clone function the area in the
mask that I want to transfer is shift upward. So I have a question that
is this a normal behaviour of the seamsless clone function or it is a bug
on my implementation.
Here are the Source photo
Here are the destination photo
Here are the result photo
I encountered similar situation. Moreover, like #JoshuaCWebDeveloper noted, this shift disappeared when all one mask is used. Nevertheless, I got a fix for this. What I did is this. I cropped valid mask (non-zero sub-section) out using cv2.boundingRect. So my source image and mask image are reduced to a smaller size, while center is now calculated from boundingRect outputs (Since reference point is marked on destination image). This way, error got solved/shift got ridden.
(Based on the answer posted by Fractalic Forieu) You can achieve the same result without reducing the image size.
Instead of using the image center:
center = (width // 2, height // 2)
poissonImage = cv2.seamlessClone(srcImage, dstImage, maskImage, center)
use the center of the bounding rect:
monoMaskImage = cv2.split(maskImage)[0] # reducing the mask to a monochrome
br = cv2.boundingRect(monoMaskImage) # bounding rect (x,y,width,height)
centerOfBR = (br[0] + br[2] // 2, br[1] + br[3] // 2)
poissonImage = cv2.seamlessClone(srcImage, dstImage, maskImage, centerOfBR )

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.

Poor quality jpeg resize on GD library use. Wrong steps?

So I have the following script to resize an incoming jpg and save it to the server in a new size. The created jpg file has terrible quality, even when I am making the quality 90 on the imagejpeg. I am wondering if I am messing it up earlier in my efforts.
// Get new sizes
list($width, $height) = getimagesize($filename);
$percentW=298/$width;
$newwidth = $width * $percentW;
$newheight = $height * $percentW;
// Creating a blank canvas to put the new file. Is this an extra step?
$thumb = imagecreatetruecolor($newwidth, $newheight);
$source = imagecreatefromjpeg($filename);
// Now I create the resized photo with the needed width and height on the blank canvas with the source file resized
imagecopyresampled($thumb, $source, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
// Output to server, define 90% quality. My guess is the quality is destroyed before now.
imagejpeg($thumb,"../../uploads/buckets/" . $_POST["bucket"] . "/" .$fileNameBucket,90);
imagedestroy($thumb);
Am I messing up the quality before I even output the file to the server? Should I use resample instead of resize? I am stuck with using the GD library so ImageMagick is not an option. Thanks.

How to display vertical text (90 degree rotated) in all browsers?

How can I display vertical text (90 degree rotated) in all browsers?
(source: sun.com)
The problem is independent from the server side language. If it's not a problem when the vertically rendered text isn't text anymore but an image, choose the solution provided by tharkun. Otherwise, there are ways to do it in the presentation layer.
First, there's (at the moment) an IE-only solution, which is part of the CSS3 standard. You can check it live.
p {
writing-mode: tb-rl;
}
The CSS3 text module also specify some properties for text orientation.
Other guys do it with SVG.
I don't think you can rotate text with PHP/HTML/CSS. But you can create an image with GD containing vertical text.
Example:
header ("Content-type: image/png");
// imagecreate (x width, y width)
$img_handle = #imagecreatetruecolor (15, 220) or die ("Cannot Create image");
// ImageColorAllocate (image, red, green, blue)
$back_color = ImageColorAllocate ($img_handle, 0, 0, 0);
$txt_color = ImageColorAllocate ($img_handle, 255, 255, 255);
ImageStringUp ($img_handle, 2, 1, 215, $_GET['text'], $txt_color);
ImagePng ($img_handle);
ImageDestroy($img_handle);
function verticletext($string)
{
$tlen = strlen($string);
for($i=0;$i<$tlen;$i++)
{
$vtext .= substr($string,$i,1)."<br />";
}
return $vtext;
}
there you go no echo
Text rotation is also possible with other browsers.
CSS:
/*Safari*/
-webkit-transform: rotate(-90deg);
/*Firefox*/
-moz-transform: rotate(-90deg);
/*Opera*/
-o-transform: rotate(-90deg);
/*IE*/
writing-mode: tb-rl;
filter: flipV flipH;
I use the function below if table header rows are too long. It's quite useful because it's easy to use, fast and you don't have to calculate text height & width. Those css-gimmicks just don't work.
#######################################################
# convert text to image and embed it to html
# uses /tmp as a cache to make it faster
# usage: print imagetext("Hello my friend");
# Created by Ville Jungman, GPL-licenced, donated by www.varuste.net
function imagetext($text,$size = 10,$color = array(253,128,46)){
$dir = "/tmp/tekstit";
$filename = "$dir/" . base64_encode($text);
if(!file_exists($filename)){
$font = "/usr/share/fonts/truetype/freefont/FreeSans.ttf";
$box = imagettfbbox($size,90,$font,$text);
$w = -$box[4] - 1;
$h = -$box[3];
$im = imagecreatetruecolor($w,$h);
$white = imagecolorallocate($im,$color[1],$color[2],$color[3]);
$black = imagecolorallocate($im, 0x00, 0x00, 0x00);
imagecolortransparent($im,$white);
imagefilledrectangle($im, 0, 0, $size, 99, $white);
imagettftext($im,$size,90,$size,$h,$black,$font,$text);
#mkdir($dir);
imagepng($im,$filename);
imagedestroy($im);
}
$data = base64_encode(file_get_contents($filename));
return "<img src='data:image/png;base64,$data'>";
}
This thread suggests that you can write text to an image and then rotate the image.
It appears to be possible with IE but not with other browsers so it might be one of those little win for IE6 =)
imagettftext oughta do the trick.
As far as I know it's not possible to get vertical text with CSS, so that means that the rotated text has to be in an image. It's very straightforward to generate with PHP's' libgd interface to output an image file.
Note however that this means using one script to produce the image, and another to produce the surrounding web page. You can't generally (inline data: URI's notwithstanding) have one script produce more than one page component.
Use raphaeljs
It works on IE 6 also
http://raphaeljs.com/text-rotation.html
function verticletext($string)
{
$tlen = strlen($string);
for($i=0;$i<$tlen;$i++)
{
echo substr($string,$i,1)."<br />";
}
}

Resources