How to fade a background-image to transparency? - image

Here's a related image:
I want to achieve something like what's pictured on the right side of my image. But I also have a parent container that has a background image of its own, instead of a solid color.
Any advice?
EDIT: Forgot to add, cross-browser compatibility is important. (Or atleast Firefox).

I can only think of one pure CSS solution and it is simply insane.
Let's say your image has a width of 100px. You'll have to create a div that's 100px wide and give it 100 children that are each 1px wide, that each have the same background (positioned accordingly) and that each have an opacity from 0 (the first child) to .99 (the last child).
Personally, I think it's crazy and I'd never use this method.
Rory O'Kane came with a nice and clean solution and I also have another idea which involves JavaScript.
Basically, the idea is that you use a canvas element (support), draw your image on it, loop through its pixels and adjust the alpha for each.
demo
(scroll down to see the result)
Relevant HTML:
<div class='parent'>
<canvas id='c' width='575' height='431'></canvas>
</div>
Relevant CSS (setting the background image on the parent)
.parent {
background: url(parent-background.jpg);
}
JavaScript:
window.onload = function() {
var c = document.getElementById('c'),
ctxt = c.getContext('2d'),
img = new Image();
img.onload = function() {
ctxt.drawImage(img, 0, 0);
var imageData = ctxt.getImageData(0, 0, 575, 431);
for(var i = 0, n = imageData.data.length; i < n; i += 4) {
imageData.data[i + 3] = 255*((i/4)%575)/575;
}
ctxt.putImageData(imageData, 0, 0);
};
/* images drawn onto the canvas must be hosted on the same web server
with the same domain as the code executing it */
/* or they can be encoded like in the demo */
img.src = 'image-drawn-on-canvas.jpg';
};

check these out maybe helpful
DEMO 1
DEMO 2

Ignoring possible CSS-only methods, you can make the image a PNG with the transparent gradient built in to the image’s alpha channel. All browsers support PNG transparency, except for IE 6 and below. Here’s what your sample image would look like as a PNG with a transparent gradient (try putting this image against other backgrounds):
If the images are user-submitted so you can’t add the gradient ahead of time, you could create and store a gradient-added version of each image at the time that the user uploads them.

CSS only method:
https://gist.github.com/3750808

Related

Solving Overlapping Images when zooming in Codenameone

I have an imageviewer with a couple images, When i zoom in the first image and wanna see the right side of the image. The folowing image is overlapping the inzooming image. This is very annoying. Is there a way how i can set the zoom in image on the front.
How can i set the zoomed image always on front.
See picture https://i.stack.imgur.com/5f5JZ.jpg
My imageviewer is in a container
Image red ;
red = EncodedImage.create("/HW_Delfzijl_Waddenzee_Oost.jpg");
Image blue = Image.createImage(500, 500, 0xff0000ff);
Image red2 = Image.createImage(500, 500, 0xffff0000);
Image List1[]= new Image [3];
List1[0] = red;
List1[1] = blue;
List1[2] = red2;
iv = new ImageViewer();
iv.setWidth(500);
iv.setHeight(500);
iv.setImageList(new DefaultListModel<>(List1));
Container1 = BoxLayout.encloseY( Kaarten.AuvHW, AdvSpr,iv,
Up,progressbar);
I was able to reproduce this with the following code:
Form hi = new Form("ImageViewer", BoxLayout.y());
Image red = Image.createImage(2000, 800, 0xffff0000);
Image blue = Image.createImage(2000, 500, 0xff0000ff);
ImageViewer viewer = new ImageViewer();
viewer.setImageList(new DefaultListModel<>(red, blue));
hi.add(BoxLayout.encloseY(viewer, new Label("Dummy")));
hi.show();
The problem only happens if I stand on the blue image (the second one) scale it up and then try to move. It doesn't happen when moving from the red image to the blue.
I believe this is due to this method in the ImagaViewer code. Since background isn't painted the old image isn't cleaned up. We need to add a condition that disables that while dragging. I think changing the code in that method to this will fix the problem but it's a bit risky and might trigger flickering:
protected void paintBackground(Graphics g) {
// disable background painting for performance when zooming
if(imageDrawWidth < getWidth() || imageDrawHeight < getHeight() || panPositionX != 0) {
super.paintBackground(g);
}
}
I would suggest filing an issue so we can consider the options here as this isn't trivial. One partial workaround is to use:
viewer.setImageInitialPosition(ImageViewer.IMAGE_FILL);
Which minimizes the impact of the issue.

Is it possible to save a generated image in Codename One?

My question is related to this previous question. What I want to achieve is to stack images (they have transparency), write a string on top, and save the photomontage / photocollage with full resolution.
#Override
protected void beforeMain(Form f) {
Image photoBase = fetchResourceFile().getImage("Voiture_4_3.jpg");
Image watermark = fetchResourceFile().getImage("Watermark.png");
f.setLayout(new LayeredLayout());
final Label drawing = new Label();
f.addComponent(drawing);
// Image mutable dans laquelle on va dessiner (fond blanc)
Image mutableImage = Image.createImage(photoBase.getWidth(), photoBase.getHeight());
drawing.getUnselectedStyle().setBgImage(mutableImage);
drawing.getUnselectedStyle().setBackgroundType(Style.BACKGROUND_IMAGE_SCALED_FIT);
// Paint all the stuff
paints(mutableImage.getGraphics(), photoBase, watermark, photoBase.getWidth(), photoBase.getHeight());
// Save the collage
Image screenshot = Image.createImage(photoBase.getWidth(), photoBase.getHeight());
f.revalidate();
f.setVisible(true);
drawing.paintComponent(screenshot.getGraphics(), true);
String imageFile = FileSystemStorage.getInstance().getAppHomePath() + "screenshot.png";
try(OutputStream os = FileSystemStorage.getInstance().openOutputStream(imageFile)) {
ImageIO.getImageIO().save(screenshot, os, ImageIO.FORMAT_PNG, 1);
} catch(IOException err) {
err.printStackTrace();
}
}
public void paints(Graphics g, Image background, Image watermark, int width, int height) {
g.drawImage(background, 0, 0);
g.drawImage(watermark, 0, 0);
g.setColor(0xFF0000);
// Upper left corner
g.fillRect(0, 0, 10, 10);
// Lower right corner
g.setColor(0x00FF00);
g.fillRect(width - 10, height - 10, 10, 10);
g.setColor(0xFF0000);
Font f = Font.createTrueTypeFont("Geometos", "Geometos.ttf").derive(220, Font.STYLE_BOLD);
g.setFont(f);
// Draw a string right below the M from Mercedes on the car windscreen (measured in Gimp)
g.drawString("HelloWorld",
(int) (848 ),
(int) (610)
);
}
This is the saved screenshot I get if I use the Iphone6 skin (the payload image is smaller than the original one and is centered). If I use the Xoom skin this is what I get (the payload image is still smaller than the original image but it has moved to the left).
So to sum it all up : why is the saved screenshot with Xoom skin different from the one I get with Iphone skin ? Is there anyway to directly save the graphics on which I paint in the paints method so that the saved image would have the original dimensions ?
Thanks a lot to anyone that could help me :-)!
Cheers,
You can save an image in Codename one using the ImageIO class. Notice that you can draw a container hierarchy into a mutable image using the paintComponent(Graphics) method.
You can do both approaches with draw image on mutable or via layouts. Personally I always prefer layouts as I like the abstraction but I wouldn't say the mutable image approach is right/wrong.
Notice that if you change/repaint a lot then mutable images are slower (this will not be noticeable for regular code or on the simulator) as they are forced to use the software renderer and can't use the GPU fully.
In the previous question it seems you placed the image with a "FIT" style which naturally drew it smaller than the containing container and then drew the image on top of it manually... This is problematic.
One solution is to draw everything manually but then you will need to do the "fit" aspect of drawing yourself. If you use layouts you should position everything based on the layouts including your drawing/text.

EaselJS spritesheet animation makes background disappear

I am working on a game using EaselJS, and I am still trying the functions provided by this great library.
What I may need is Alphamaskfilter class & Spritesheet class.
Currently, I have a canvas like this:
<canvas id = 'container3' width = 320px; height = 480px;
style = 'outline: 2px solid; margin-right: 10px;float:left;'></canvas>
and in my script, I have draw a rect with blue color:
var ctx3 = document.getElementById('container3').getContext('2d');
ctx3.beginPath();
ctx3.rect(0,0,320,480);
ctx3.fillStyle = 'blue';
ctx3.fill();
So now I have a blue color 320*480 canvas. And now I have a sprite sheet to animate on it,
here is the sprite and code I wrote:
http://i.imgur.com/XumDvic.png
PS: the sprite frame is 200*200 FYI.
stage = new createjs.Stage(document.getElementById('container3'));
var test = new Image();
test.src = 'trans_blackball.png';
test.onload = function(){
var sprite = new createjs.SpriteSheet({
images: [test],
frames: {width: 200, height: 200},
animations: {
born: [0,3,0]
}
});
var animation = new createjs.BitmapAnimation(sprite);
animation.gotoAndPlay("born");
animation.x = 10;
animation.y = 10;
animation.currentFrame = 0;
stage.addChild(animation);
createjs.Ticker.addListener(window);
createjs.Ticker.useRAF = true;
createjs.Ticker.setFPS(10);
}
function tick(){
stage.update();
}
Okay, my question is: I expect an animation of an enlarging black circle on a blue background(rect), but what I got is firstly the canvas is blue, but for a certain mini-second after, the whole canvas became white, and the animation is running on the white background, what is the reason of this and how can I solve it?
Here is two points that may help:
I am working with chrome, and I check with F12 & console, the fillStyle of the canvas is still blue even it appears white after the sprite animation start
If I set the canvas background property to blue instead of drawing a blue rect on it, everything's fine!!
<canvas id = 'container3' width = 320px; height = 480px;
style = 'background: blue; outline: 2px solid; margin-right:
10px;float:left;'></canvas>
but clearly this is not what I want...
The problem can be solved as well by not using native canvas rect but use EaselJS's Shape to draw the rect:
var shape = new createjs.Shape();
shape.graphics.beginFill("#ff0000").drawRect(0, 0, 320, 480);
stage.addChild(shape);
But I still wanna know why the native rect drawing code is not working...
Please bare my bad english and thanks for reading and any attempt to help...I can elaborate more if there is anything unclear in the situation..thanks!
createjs.Stage.update() will clear the canvas-contents by default before rendering the new frame.
The reason for this is one the one hand the technical behaviour of canvas, the canvas is basically just an image of pixels, you cannot have real 'layers' and say "I just want to remove/update this one object" - you just can modify the flattened pixels of the frame or remove everything and redraw it(which is safer, easier to achieve, and actually fast enough performance-whise. And on the other hand, it makes sense to make consistent use of a framework like EaselJS, and not do some parts with the framework and some parts without it, this would result in a big mess at the end.
So, the right solution is to go with 3.
You can set myStage.autoClear = false; to prevent the Stage from autoClearing the canvas on every update() but I don't think this will suit your needs in this case.
I would recommend instead using the EaselJS Shape class to make your blue box. If it part of the EaselJS display list, it will be drawn with the other content.
javascript
var shape = new createjs.Shape();
shape.graphics.beginFill("blue").drawRect(0,0,320,480);
stage.addChild(shape);

Fade in image when adding it to HTML5 canvas - Processing time concern

I am using the HTML5 canvas to draw an organisational structure. Each node includes an image, the URL of which is obtained form a database. I have a little function that handles the loading of the image, and that adds it to the canvas once loaded. It looks like this (note that the important bit is the onload listener added to the image):
(function (i, ctx, DrawId) {
var img = new Image();
img.src = REPORT.Structures[i].Managers[j].Employee.PhotoUrl; //get URL from object constructed elsewhere
img.onload = function () { //attach onload event
ctx.drawImage(img, x, y, width, height);//draw image on the canvas. x, y width and height are calculated inside the onload, but I have removed the calculations to improve readability
}
}
})(i, ctx, REPORT.DrawId);
This works great, except that the images all pop into existence at random as they finish loading. It looks very untidy.
I am looking for a way to make this look smoother. My first instinct is to try and create a fade in effect, but I can't think of how to do this without redrawing the canvas over and over.
I have thought of trying something like this:
img.onload = function () {
var counter = 1;
var width = 30 * REPORT.ZoomLevel;
var height = 30 * REPORT.ZoomLevel;
function fadeInImage(ctx, img, x, y, width, height) {
ctx.globalAlpha = 0.1 * counter;
ctx.drawImage(img, x, y, width, height);
counter++;
if (counter == 10)
clearTimeout(fadeInImageTimeout);
console.log(counter);
}
var fadeInImageTimeout = setInterval(function () { fadeInImage(ctx, img, x, y, width, height); }, 100);
}
This works, but I am also worried that if it does, it will be too processing heavy.
Has anyone tried doing something like this? Any suggestions would be much appreciated.
PS:
I am currently considering only having one interval that draws all images. Each image will be pushed into an array, and all elements in the array will be drawn once all images are loaded. Will keep you updated.
PPS:
I have managed to get it working as I mentioned in the PS above. It does not seem to affect the performance though. I guess the lag I am still experiencing is related to the image loading time. I'll try and strip out the code into a bare bones version and post it here a bit later, but if anyone can see a flaw in my approach, please do not hesitate to point it out. Again, any suggestions would be greatly appreciated.

Draw Element's Contents onto a Canvas Element / Capture Website as image using (?) language

I asked a question on SO about compiling an image file from HTML. Michaël Witrant responded and told me about the canvas element and html5.
I'm looked on the net and SO, but i haven't found anything regarding drawing a misc element's contents onto a canvas. Is this possible?
For example, say i have a div with a background image. Is there a way to get this element and it's background image 'onto' the canvas? I ask because i found a script that allows one to save the canvas element as a PNG, but what i really want to do is save a collection of DOM elements as an image.
EDIT
It doesn't matter what language, if it could work, i'm willing to attempt it.
For the record, drawWindow only works in Firefox.
This code will only work locally and not on the internet, using drawWindow with an external element creates a security exception.
You'll have to provide us with a lot more context before we can answer anything else.
http://cutycapt.sourceforge.net/
CutyCapt is a command line utility that uses Webkit to render HTML into PNG, PDF, SVG, etc. You would need to interface with it somehow (such as a shell_exec in PHP), but it is pretty robust. Sites render exactly as they do in Webkit browsers.
I've not used CutyCapt specifically, but it came to me highly recommended. And I have used a similar product called WkHtmlToPdf, which has been awesome in my personal experience.
After many attempts using drawWindow parameters, that were drawing wrong parts or the element, I managed to do it with a two steps processing : first capture the whole page in a canvas, then draw a part of this canvas in another one.
This was done in a XUL extension. drawWindow will not work in other browsers, and may not work in a non-privileged context due to security reasons.
function nodeScreenshot(aSaveLocation, aFileName, aDocument, aCSSSelector) {
var doc = aDocument;
var win = doc.defaultView;
var body = doc.body;
var html = doc.documentElement;
var selection = aCSSSelector
? Array.prototype.slice.call(doc.querySelectorAll(aCSSSelector))
: [];
var coords = {
top: 0,
left: 0,
width: Math.max(body.scrollWidth, body.offsetWidth,
html.clientWidth, html.scrollWidth, html.offsetWidth),
height: Math.max(body.scrollHeight, body.offsetHeight,
html.clientHeight, html.scrollHeight, html.offsetHeight)
var canvas = document.createElement("canvas");
canvas.width = coords.width;
canvas.height = coords.height;
var context = canvas.getContext("2d");
// Draw the whole page
// coords.top and left are 0 here, I tried to pass the result of
// getBoundingClientRect() here but drawWindow was drawing another part,
// maybe because of a margin/padding/position ? Didn't solve it.
context.drawWindow(win, coords.top, coords.left,
coords.width, coords.height, 'rgb(255,255,255)');
if (selection.length) {
var nodeCoords = selection[0].getBoundingClientRect();
var tempCanvas = document.createElement("canvas");
var tempContext = tempCanvas.getContext("2d");
tempCanvas.width = nodeCoords.width;
tempCanvas.height = nodeCoords.height;
// Draw the node part from the whole page canvas into another canvas
// void ctx.drawImage(image, sx, sy, sLargeur, sHauteur,
dx, dy, dLargeur, dHauteur)
tempContext.drawImage(canvas,
nodeCoords.left, nodeCoords.top, nodeCoords.width, nodeCoords.height,
0, 0, nodeCoords.width, nodeCoords.height);
canvas = tempCanvas;
context = tempContext;
}
var dataURL = canvas.toDataURL('image/jpeg', 0.95);
return dataURL;
}

Resources