Blurred vignette in pygame - pygame

I'm trying to make a pygame surface become blurred at the edges for a visual effect. The centre of the surface would remain unblurred. I found a way of blurring a pygame surface with transform.smoothscale, but it seems that this only works for a whole surface (Blurring in PyGame)
I've managed to make a script that blurs only the edges of the screen, but the transition to the blur is sharp and not smooth. Is having a smooth transition between blurred and not blurred. Is this something that is possible? Thanks

Well, it's been a few days and I finally managed to work out a solution:
def blur_surface(surf, amount, iterations):
for i in range(iterations):
surf = pygame.transform.smoothscale(surf, (display_width / amount,
display_height / amount))
surf = pygame.transform.smoothscale(surf, (display_width, display_height))
return surf
blursurf = display.copy()
blursurf = blur_surface(blursurf, 2, 3)
blursurf.blit(blur_image, (0, 0), special_flags=pygame.BLEND_RGBA_SUB)
display.blit(blursurf, (0, 0))
'blur_image' is an image of a circle that is black in the centre, and slowly fades to transparent at the edges (like this).
Here's how it works:
The surface that we want to blur is copied.
The entire copy is blurred.
The image of a faded circle is blitted onto the copy, but with a flag that makes pygame cut a hole out of the surface instead.
The new surface is blitted ontop of the original.
I hope this helps anyone who ends up with the same problem

Related

Make images larger in HTML with no blur

I have been messing around with some new ideas in Javascript, but I'm not very good at making extremely detailed images in Paint, Paint.NET, etc. The problem is when I have a 64 * 64 image or an 8 * 8 and I want it to display 640 * 640 or 16 * 16; the images get blurry. I've seen many other forums and things were people ask this question or a similar one, but I'm relatively new to this and don't want to make the image larger in photoshop or whatever. On a similar note, can I display only part of an image at one time but have a larger image than shown, so that I don't have to make multiple images of the same thing?
Maybe this CSS attribute on your img helps:
image-rendering: pixelated;
I found it in this blog post:
https://css-tricks.com/keep-pixelated-images-pixelated-as-they-scale/
The reason your images get blurry when enlarged is because it is a rasterised graphic (pixel based image) and not a vector graphic (path based image).
When you try to enlarge the rasterised image, the pixels expand in size too which leads to the lower quality/blurry result (also referred to as 'pixelation').
The difference between vector and raster graphics is that raster graphics are composed of pixels, while vector graphics are composed of paths.
Source: http://pc.net/helpcenter/answers/vector_and_raster_graphics
You can't make it bigger without the picture becoming blurry. You are using a raster image. A raster image is an image that is made up of pixels. a color is assigned to each individual pixel. If you enlarge the picture. Each pixel will just be scaled so that it takes up more space on the screen. This will cause the image to appear blurry.
Here's an example:
rrr
rbr
rrr
"r" is a red pixel and "b" is a blue pixel. The dimensions are 3*3.
If you try to make the dimensions larger than 3*3, lets say 6*6, this happens.:
rrrrrr
rrrrrr
rrbbrr
rrbbrr
rrrrrr
rrrrrr
With the image was enlarged, each pixel just became bigger. In the larger image, each 2*2 square was originally 1 pixel in the original image. Now with this example, the new image wasn't blurry because it was just a square. But if you have a more complex image, it becomes blurry.
To fix your problem, use a vector image. A vector image is different from a raster image. Instead of being made up of pixels, it is made of shapes and lines and stuff like that. Each shape has a width, height, x coordinate, and y coordinate. Some shapes have even more variables. Because of this, vector images can be zoomed in indefinitely without becoming blurry. Sometimes when you zoom in on a vector image the quality even becomes better!
Here's an example:
rrr
rbr
rrr
Again, "r" is a red pixel and "b" is a blue pixel. Let's say this image has a width of 500. But you are zoomed out so far that it appears as a 3*3 square on the screen. In the center of the image is a blue circle. Now it doesn't look like a circle because it only takes up one pixel on the screen. So it looks like square. The circle has a fixed radius. and it is located in the center of the image.
Let's zoom in:
rrrrr
rrbrr
rbbbr
rrbrr
rrrrr
The image still has dimensions of 500*500. It is just zoomed in farther so that it takes up 5*5 on the screen. But the circle looks less like a square and more like a cross. and a 3*3 cross looks more like a circle than a 1*1 square.
The farther you zoom in, the more the image will look like a circle. But since you are using a raster image, enlarging it will result in a blurry picture.
To fix your problem use vector images instead of raster images.
For any form of res-sizing images, you will need a Vector-formatted image.
Vector formats are of the following:
CGM
Gerber format (RS-274X)
SVG
Image File Formats - Wikipedia
Use vector based graphics (svg), not raster bitmaps (jpg, png, gif).
Good thing about SVG is you can add CSS and JS to interact with it in a webpage.
Check this article on how to interface with the SVG

Solid lines become dotted - flash 3d transform

I am trying to 3d transform a floor tile pattern in flash, But when i do so the tile lines become dotted (dashed) here is the screenshot
The best solution is as LDMS said, thickening your lines (even if it is an image), or if you can, enable Anti Aliasing (which i think is what smoothing does)
As for why this happens, this is due to texture sampling. You will probably see that if you move your camera around the gaps/dots in the lines move. Now without going into too many details these are the basics:
Close to your camera the amount of pixel from your image that fit into a pixel on your screen will be less then 1, meaning that one pixel from your image is bigger then an actual pixel on your screen, so it will just display that color from the image. But what happens, if your image is so far away that multiple pixels from your image are so small that they combined fit into one pixel on your screen? With smoothing and Anti Aliasing you run an algorithm to combine colors and get en estimated result. But if you do not do this it will have to pick a color, say we have 2 pixels of black (your line) and 2 of the red background for the same pixel on screen, it will (randomly or based on some variable) pick a color and display it without regard of the other colors.
This is why you sometimes see your line and sometimes the background.

Increasing the width of line drawn using Shape Renderer in LibGDX

I am drawing a line using Shape Renderer in LibGDX and i am using Orthographic Camera in my code, so to increase the width i used
camera = new OrthographicCamera();
int lineWidth = 8; // pixels
Gdx.gl10.glLineWidth(lineWidth / camera.zoom);
Now, I get a wider line. But the problem arises when the screen power goes off and then turns on, the line becomes the normal one again. How to keep the width constant?
ShapeRenderer has the method rectLine that is intended to be used to draw thick lines. It draws a rotated filled rectangle with the smaller opposite sides centered on the points passed to it (as coordinates or as Vector2 objects). The method has the parameter width to set the line width.
You can see the documentation here
Example:
shapeRenderer.rectLine(new Vector2(x1,y1),new Vector2(x2,y2),lineWidth);
As you can see here:
libgdx Shaperenderer line .. How to draw line with a specific width
And here:
Libgdx gl10.glLineWidth()
And here:
Why Libgdx Gdx.gl10.glLineWidth(width); does not react to change projection properities
Playing with the line width in the shaperenderer isn't the best way to do what you want to achieve.
Try using a 1x1 white TextureRegion (you can change the color the Batch draws it with later), and draw it with the width and height that you desire:
batch.draw(region, x, y, width, height);

Calculate the accurate x and y position of a div inside a rotated div

I've implemented a zoom and crop on the HTML5 Canvas. Zoom is actually increasing the height and width of the Canvas so that it looks zoomed. For crop, I wrote an algorithm to select a rectangular area using mouse and then crop it. Now, if I want to crop when the image is zoomed in or out, while selecting the crop area I have to consider the top and left position displacement caused due to the zoom , which works fine.
So I'm now implementing a rotate (using css3 transform: rotate). The problem is, when I rotate the image by a certain angle, the selection appears a little away from the actual mouse position. This used to happen for the zoom effect as well, but since I used to subtract the added left and top distance from the x and y position resp., I was able to draw the selection even when the image was zoomed. I don't understand how I should do it for a rotated image!
The following image might help you understand my problem a little more clearly:
There's a div around the canvas, reflecting the canvas. It'll have the same width, height, top, left properties as the canvas. This is done on purpose since I can't add the selection, which is absolute, as the child of the canvas. Now this cover, when selected in FireBug, still shows as a rectangle with increased width and height and changed top and left positions.
I understand I have to calculate the displacement like I'm already doing for zoom, but I don't know how to do it! I have spent a lot of time trying out stuff like Pythagoras algorithm and rotational matrix and blah blah!
Please help me out!
You can rotate each of the vertices using this function where "pnt" is a vertex, "pivot" is the point you're rotating around and "angle" is the angle in radians
function rotatePoint(pnt, pivot, angle){
var data = figureAngle(pivot, pnt),
theta = data.angle + angle,
rise = Math.sin(theta) * data.length,
run = Math.cos(theta) * data.length;
return {
x: pivot.x + run,
y: pivot.y + rise
}
}
function figureAngle(start, end){
var rise = (end.y - start.y),
run = (end.x - start.x),
length = Math.sqrt(Math.pow(rise, 2) + Math.pow(run, 2));
return {length: length, angle: Math.atan2(-rise, -run) + Math.PI};
}
Then your horizontal shift is going to be the smallest x of the 4 new vertices, and your vertical shift is going to be the smallest y.
EDIT: this assumes your top left coordinate is [0, 0] before you rotate. If not you need to subtract your starting coordinates from the results i.e. if your top-left corner starts at [50, 100], your horizontal shift would be xMin - 50, and your vertical would be yMin - 100

Collision box for AS3 + papervision3d + jiglib

I'm trying to recreate the "tutorial" explained on the site below. It's 5 dices bouncing around on the scene. But i'm stuck at the very beginning :)
papervision3d-jiglib-dice-demo
My problem is the bounding box. I want to create a box with a floor and 4 walls based on the size of the stage. I can get it the right size using zoom/focus on the camera. But the problem is the dices go through it.
How can i build 4 walls and make sure a dice doesnt go through it when i apply forces to it?
I tried the solution in the following source, but somehow the dices keep going through :(
throwing-dice-with-the-jiglib-physics-engine-and-away3d
Anybody knows how to do it? Or a better way to keep the dices on screen?
I solved the problem. Just to share with others who want to try the same:
Set camera zoom = 2
Set camera focus = distance / zoom
// now the scene width and height match the actual size of the stage.
add the planes for all sides and make sure you make the segments smaller then the dice size. (EG: dice size = 30; stage width = 300; segments = stage width/ dice size = 10).
make sure you ceil the results because segments require int
Ofcourse you can make it larger, but then it will be harder to render.
I made the height of the planes a little smaller then twice the dice size to make sure they never get on top of eachother.
And finally add a ceiling by placing another plane with small segments on top of the other planes