How would I programmatically crop an image to a non-rectangular shape? - php

I want to crop a rectangular image to a non-rectangular shape. I realize that if you take that completely literally, it's not possible. What I want to end up with is image X, cropped to shape Y, on a transparent background.
Let's say for example that I want to take a picture of the Idaho flag and crop it to the shape of the state of Idaho. I imagine I would do something like this:
Create an image that has opaque pixels for the shape of Idaho, transparent pixels everywhere else
Read and store some kind of bitmap for this Idaho state image
For each opaque pixel location in the Idaho state image, copy the corresponding pixel from the Idaho state flag image and place it on a blank, transparent canvas
Step 1 would obviously be done manually, but the rest would be done programatically. I think I have the right idea in general but I don't know how I'd approach the specifics. Can anyone point me in the right direction?
As far as implementation technology goes, I'm a PHP guy, so using gdLibrary or something that works with PHP would probably be the best way for me to go.

I would think it would be much easier to do by simply adding a bitmask or alpha channel. In that case you would use a negative mask image of your shape and then simply apply it to he regular image as a mask and then save out in a transparent format. Ive never actually done this with GD or ImageMagick but i would think its available as Jerry suggests.
Acutally here is a blog post form a similar SO question that might help: http://about.phalacee.com/geek/creating-mask-layers-using-php-gd

The usual way to do something like this would be to use white (all 1's) and black (all 0's) for your outline instead of transparent and opaque. Then you AND that image with the image you're trying to crop. The result is 0's where the outline image had 0's, and the other image where the outline had 1's.
You may also need to invert your outline image, and AND the inverted version with the background image. Then you OR the background image with the foreground image to produce a composite of the foreground image in the shape of Idaho (to use your example) and the background image everywhere else.
Depending on the capabilities of the library you're using, there's a good chance that kind of capability is directly available though. Just for example, Windows has this capability in the MaskBlt function.

In php using ImageMagick is probably your best bet:
$source = IMagick("sourcefile");
$mask = IMagick("maskfile");
$mask->adaptiveResizeImage($source->getImageWidth(), $source->getImageHeight(), true);
$source->compositeImage($mask, imagick::COMPOSITE_MULTIPLY, 0, 0);
$source->writeImage("newfile");
$source->clear();
$source->destroy();
sourcefile must be the source image as you like, maskfile must be a mask file that has the alpha channel set correctly for the shape you want.

Related

Replacing detected object in a frame with an image.(imageProcessing)

Overview:
I am working on a video creation project. The technology I am using are: imageMagick, php, ffmpeg.
Current Status:
Currently the project is able to create videos using images and texts and few basic transitions. The way I am doing it is using imagemagick to create gif using input images(with transition effects in them) and then converting all gifs to videos and atlast concatenating the video together.
Next Move (My question):
I am now set to take it to the next level. So, what I am having is a video(1920x1080) with some white frames(1280x720) that keeps shifting in each frame. I want to replace those white frames appearing in some frames of the video with some images(1280x720) that I wish to use. Please see the image here and you will get an idea: These are just two frames from my video. If you can see carefully the images are shifting(white space is not constant).
Expectation:
So, I want to fill those white space with one of my own image. If the case would have been for only one frame I could have used ffmpeg to overlay image on the exact width and height. But here the white space is not fixed and keeps shifting in all the frames and there are a lot of frames. So, I am looking for something like opencv or some other technology that can be used for object detection in a video or in a set of frames and replace the detected area with some other image.
I just need a kick. So, if anyone has already worked on something like this just suggest me what technology can I use. Thanks in advance.
It all depends on exactly what you can assume :
If you can safely assume that your rectangle's boundary is never occluded (hidden) somehow, you can try finding the edges in your image (like OpenCV's Canny edge) and then look for rectangular shape (corners forming a warped rectangle, or the very popular Hough Lines).
If the rectangle you're looking for is always white, you can threshold the image in a colorspace like HSV to look for maximum value (the V in HSV ~ brightness) then rectangular shape search in a binary image.
If your corners are occluded sometimes you'll have to do some tweaking with your image, like morphological operations ("grow and contract" binary thresholded image), then Hough Lines could do the trick.
Note that this answer assumes that once you know where the rectangle is, "you're done", and you just have to overwrite the rectangle with custom content.
I also do not check for any time-continuity : you video frame might jump around based on the frame-by-frame appearance of rectangle. You'd have to include some knowledge about previous positions.

Convert white parts in image to transparent to simulate printing

I am currently developing an AJAX application using PHP and Javascript that allows people to upload images that will be printed on foil. Since I will be using a standard CMYK printer, it won't print any white parts, but rather just leave those spots blank - a thing that usually does not make a difference on white paper, but here it does, since I'm printing on foil. It gets more complicated when you consider that a grey dot will become semi-transparent black, and I'm not even talking of colors yet.
Yet I would like to create a PNG file with an alpha channel that will simulate the printing process, so I can give a preview of how the printed foil would look when being hold against different backgrounds.
Now I do understand the basic theory of subtractive and additive color models and also of RGBA and CMYK, but then again it's only the basics and here I'm kind of at a loss of how to proceed. I guess in theory you would convert every pixel into CMYK and interpret each channel as a scale from transparent to color instead of from white to color, but how would you translate that back into RGBA?
The nicest thing would, of course, be if ImageMagick would provide such a feature .... does it, or do I have to loop through the pixels manually? If the latter, how would I do the calculations?
I don't know if this has been an issue before. I couldn't find anything on either Stackoverflow or Google, but maybe I just missed the right keywords. Any further reading, food for thoughts or hyperlinks with a note "we discussed this a million times, idiot!" would be warmly welcome.
Thanks
What you basically want is to add an alpha channel to the uploaded image and create a PNG file.
The alpha channel should represent the opacity of the printed color. To generate it, you have several options:
Take a copy of the image, convert it to grayscale, invert it and use it as alpha channel.
Create an alpha channel compute the alpha value of each pixel derived from the original image as: alpha = 1.0 - min(red, green, blue) (use 255 instead of 1.0 depending on whether you're using integer or floating point numbers).
Convert the original image to CMYK (using a color profile and not the poor formulas youn find all over the internet) and use it as the basis to create the alpha channel for the original RGB image: alpha = max(cyan, magenta, yellow, black).
Come up with an even better formula to compute the transparency of each pixel such as: alpha = min(0.2 * cyan + 0.5 * magenta + 0.1 * yellow + 0.7 * black, 1.0)
The last one is just a guess of the relative opacity of each color. You can certainly improve it.

HTML5 Canvas Re-Colorize Images *Before* Rendering

I have an image which is essentially a star-burst effect. The color of the star-burst is white, and the background is transparent (PNG w/ Alpha). I randomly generate these star-bursts onto an HTML5 canvas at random locations, and at the same time, generate random Hue, Saturation, and Light (HSL) values. These could be RGB values, if this simplifies things.
The goal is to re-colorize the PNG for display on the HTML5 canvas based on the randomly generated HLS values before rendering it to the canvas.
I've read some other posts on StackOverflow and other sites, but the only solutions I've seen involve rendering it to the canvas, grabbing the coordinates for where the image is displaying, and modify the color on a pixel-by-pixel basis. In theory this could work, however some of the images may overlap slightly. Also if there is a background already present, then from what I understand, the background's color would also be modified which isn't much of a solutions for me either.
If this is out of the realm of what Canvases are capable of, as a fallback I suppose I would be okay with having images dynamically re-colored via PHP using GD2 or Imagick, or via the command-line via Gimp, ImageMagick or some other image library...
Thanks much!
-- OUTCOME --
Special thanks to #jing3142 for initial suggestion of off-screen canvas rendering, and #Jarrod for providing the vital piece I was missing: globalCompositeOperation = "source-in"
Here is a working implementation of the concept: http://jsfiddle.net/fwtW2/2/
Works in:
Chrome
Firefox
IE 9 (haven't tested other versions)
How about a second canvas that has the size of the image, place the image on that canvas, re-colour as required, extract re-coloured image and place at random on main canvas, re-colour image on second canvas using new HSL values, extract and randomly place on main canvas and repeat?
This may help as well https://developer.mozilla.org/en-US/docs/HTML/Canvas/Pixel_manipulation_with_canvas
I'm pretty sure you can just use the source-in globalCompositeOperation opertaion? No need to get all hardcore and crazy with vector images.
This code is where the magic happens:
var color = 'red';
ctx.fillStyle = color;
ctx.globalCompositeOperation = "source-in";
But yOu'd need to re-draw this to an offscreen canvas: You can do that like so
createBuffer = function(sizeW, sizeH)
{
buffer = document.createElement('buffer');
bufferCtx = buffer.getContext('2d');
buffer.width = sizeW;
buffer.height = sizeH;
}
then just draw your image to the offscreen canvas and apply the global composition.
Here’s how to easily recolor your starbursts just before rendering on canvas
Convert your starburst.png into a vector path! (I know, you will have to drag out Gimp/Illustrator for this one time—but it’s worth it!)
Starburst paths can have fills and the fills can be solid colors or even gradients—as fancy, random recoloring as you need!
Starburst paths can scale without the pixilation of raster images like .png’s.
Starburst paths can rotate to show diversity in your bursts--and even skew to represent a bit of 3d motion.
If you want to get fancy, you can even create “glowing” bursts by using shadows and blurs.
Starburst paths are faster to render than .png images—especially if you need to manipulate each .png before drawing.

Possible to blend an image into a color? (Left, right, bottom)

Is it possible to blend the left, right and bottom sides of an image into a color?
Lets say, I want the image to be blended into the color "#F0F0F0". I want the image to appear as an actual part of the background, so I thought it would look cool if it was blended in.
If this is just for a webpage this is possible using basic HTML+CSS. Just like you said, you could use a PNG as a layover (via a carefully positioned <div>) on your background.
Otherwise, look into the ImageMagick Libraries for PHP, as they'll let you programmatically create a blended image like you describe. (Imagick::colorizeImage)
You can do this by using an image-manipulation library like ImageMagick or GD. I found this page where the author uses a gradient to perform blending using GD.
You can also try using Imagick::colorizeimage
UPDATE
Based on your screenshot, I don't see why you couldn't do what you wanted to with just straight HTML+CSS. You can either use a transparent PNG or you can use -moz-opacity, opacity or filter:alpha in your CSS (Cross-browser Transparency via CSS).
You would have to manipulate the pixeldata of the image to achieve this but once you have that covered its not really a problem. Take the color value of the pixel and blend it with your blendcolor. There are some pretty standard maths that can do it fairly well such as this algorithm value1 + (value2 - value1) * amount often used in pixelshaders when doing multi-texturing.
As others have said image libraries for php such as GD helps out with the data manipulation of the image as you won't have to decode and encode it yourself
I don't know what you need exactly, but using a semi-transparent png as an overlay you can do a lot as well without the need to manipulate your original images.
i suggest you use verot's upload php class. It contains all currently available serverside manipulation functions dealing with image (rotate, tint, frame color, background color, etc.).
See this sample code:
$foo->image_resize = true;
$foo->image_ratio_fill = 'R';
$foo->image_y = 150;
$foo->image_x = 100;
$foo->image_background_color = '#FF00FF';
$foo->image_rotate = '90';

PHP - Mask polygon over image

Hi Everyone (this is my first post),
I am trying to figure a way of cropping a polygon out of an image. I have been reading other similar code. It seems that most code is based around the following process:
Resize the image to fit the width and height of the polygon shape,
Create a blank image of an unusual colour the same size,
Overlay transparent pixels in the shape of the polygon,
Overlay that on to the resized image
Set the unusual colour to be transparent...
My problem is I do not want the code to be reliant on the unusual colour not being in the original image. Does anyone have a better method or some code which I can use to check if the unusual colour is in the image.
On a side note once I have cropped them I am looking to add a border only around the top and the left sides of the shape and three pixels in the corners to achieve a rounded corner effect... if anyone has any ideas about that then please also post.
If you draw the polygon in black-white (and brey values between) on a different image (called mask), you can use applyMask of the WideImage library.
See:
- http://wideimage.sourceforge.net/
- http://wideimage.sourceforge.net/wp-content/current/demo/index.php?demo=applyMask&output=preset%20for%20demo&colors=255&dither=&match_palette=
an alternative way would be to cut the big image in 4 parts ...
a top part,
left side and right side that are the parts on the left and right of the image afte the mask
and bottom part
and recompose them.
But that would require a bit of code and calculations.

Categories