Getting alpha channel/opacity working for lighting - java

I have two pixel arrays, foreground and lighting. When I draw a white radial gradient (blurry circle) onto the lighting array, I want it to make the foreground visible - much like a torch in terraria/starbound. However, I also want to be able to mix different colors of lighting, rather than be stuck with black to white.
So how do I manipulate the pixel arrays so that they 'multiply' (I believe it's called)? Or is there an easier way using RGBA which I have not been able to get to work (flickering black on white or image getting ever more posterized)?
So far most responses regarding alpha channels / opacity have been using libraries from java which for this project I want to refrain from using.
Any help much appreciated!

If you want to know how the blending modes (such as "multiply") work in image editing programs on the pixel-value level, read this: How does photoshop blend two images together?.
Note that if you want to make the image lighter, you need a mode like "screen", because "multiply" makes it darker.

Related

How to automatically blend images to create realistic composites (java)

I have two images - background & foreground, having different lighting conditions and colour tones. Each of them contains a person. Also i have an alpha mask for the person in foreground image. I want to blend the person (cropped out using mask) from the foreground with the background image so that the final image looks as if the person in the foreground was standing next to person in background(i.e realistic composite blending).I already have the segmentation mask and i'am able to get the cropped out person from foreground image.It looks like we need to ensure proper illumination, saturation and colour matching to obtain a natural blended feel.It seems, we can easily do that using photoshop manually(link1,link2). How can achieve similar results programmatically, given two random background and foreground images with person?
The following are the approaches i tried; but each of them have certain issues and works only with certain types of images.
1.OpenCV Seamless clone - Works pretty well for plane and similar contrast images.Issues:- heavy, smudging, cannot be generalised for all types of images.
2.Photorealistic style transfer - Works great; but its heavy, needs special training and works only with few class of images. Still artefacts may be present.
3.Fast Color Transfer (pyimagesearch)- Works for plane background. Background color averaging causes colours to be spill over to image roi and thus loses its natural feel.
Also tried normal alpha blending, laplacian blending, histogram matching etc. Additionally, experimented with techniques like CLAHE, gamma correction, histogram equalisation, edge blending etc to adjust and improve the output of blending. Unfortunately, none of these combinations gave the desired result.(NB:-The output should not ideally look as if a layer is stacked or pasted on top of background image).i.e we need a seamless natural blend.
Is this possible only using some AI models or is there any light weight methods for performing automatic image composting in java, using some standard libraries (should work adaptively for any two images in general)?
We are trying to achieve something similar to the following methods:-
https://people.csail.mit.edu/yichangshih/portrait_web/
https://arxiv.org/abs/1709.09828
https://www.cs.cornell.edu/~kb/publications/egsr18_harmonization.pdf
Finally found the answer..Here is the caffe implementaion of Deep Color Harmoniation: https://github.com/wasidennis/DeepHarmonization. It seems to a light weight network and works pretty fast. Still trying to figure out how to convert the same to a mobile friendly format like tensorflow lite ...
Hope it helps somebody ...

Transparency when using ‘drawPixel’ on Pixmap?

Background
I am creating an application where I manually lay out a texture atlas. The whole point is that the image itself isn’t supposed to be transparent—it has a consistent background color that is then supposed to be removed in the code.
The problem I’m having is that I can’t seem to be able to remove pixels—make them transparent—from the Pixmap I’m working on. I’ve made sure to use RGBA_8888 for my Pixmap’s Format, which is sure to support transparency.
Problem
Here’s the piece of code I’m having trouble with:
pixmap.drawPixel(x, y, 0x00000000);
Quite obviously, 0x00000000 would be zero—even if converted from hex to base ten—seriously, it’s the same number!
From my observations, I’ve noticed that the drawPixel method draws a pixel onto the current one. What I want is for it to become transparent. Using the aforementioned piece of code, it draws transparency onto something that isn’t transparent—ending up changing nothing. As if you add nothing to something, the something remains.
Research
As usual, I’ve done some research on my own. Here on Stackoverflow I haven’t managed to find anything of use. The only things I know is the things mentioned above that I’ve managed to find out by observing the Pixmap and its drawPixel method.
Moreover
Perhaps someone can point me in the right direction as to how you’d make a pixel of a Pixmap transparent?
As you already discovered, you can't draw a blended transparent pixel over the existing pixel, because you can't see anything. So first you need to disable Pixmap blending.
Pixmap.setBlending(Pixmap.Blending.None); // before you start drawing pixels.
pixmap.drawPixel(x, y, 0x00000000);
// And all pixels you want to draw
Pixmap.setBlending(Pixmap.Blending.SourceOver); // if you want to go back to blending
If you want to maintain the RGB of the existing pixel, you have to get the current pixel color and manually black out the alpha component only:
pixmap.drawPixel(x, y, pixmap.getPixel(x, y) & 0xffffff00);

opengl / JOGL - best way to draw textures

I thought about the best way to draw a picture in OpenGL / JOGL.
I currently program a Game and it is my goal to save the information about a picture in a text file instead of saving the picture.
My idea was to program a method that saves every pixel information (RGB) at the position of X and Y.
Then I draw every pixel and it is finished.
What you think about that idea?
You should simply use TextureIO to make a texture from your picture and use this texture with 4 vertices that have some texture coordinates while drawing. glReadPixels() is very slow, reading each pixel of a picture would take a lot of time, saving its content as a text file would require a lot of memory (saving it as a compressed image in a loss-less format like PNG might be worth a try), drawing each pixel one by one would be a lot slower than drawing a texture. derhass is right. You could vectorize your picture (make a SVG from it) but you would have to rasterize it after or you would have to implement some rendering of vectorized contents and it would be probably slower than using a texture. I'm not sure you really need an offscreen buffer.
I had a similar problem when I began working on my first person shooter. I wasn't using JOGL at the very beginning, I reused the source code of someone else, it relied on software rendering in an image, it was very slow. Then, I used JOGL to draw each pixel one by one instead of using Java2D, it was about 4 times faster on my machine but still very slow for me. At the end, I had to redesign the whole rendering to use OpenGL for what it is for as derhass would say, I used triangles, quads and textures. The performance became acceptable and this is what you should do, use OpenGL to draw primitives and clarify what you're trying to achieve so that we can help you a bit better.

How to draw a fading, dissolving color at Java?

I would like to create a fading color effect, something like a cloud. A transition between
two Color. I found a link. But, at this topic, the writer define an bitmap pixel by pixel. Is there an other way to do this, like a fadingDrawable class? Or this is the most effective way of fading?
Without knowing what specific libraries you're using, I can't be too specific, but as far as I know:
Most graphics libraries include some gradient functionality - this will probably be relatively fast.
And if they don't, I can't see any way to do it other than drawing the gradient pixel by pixel

Using a semi transparent texture to "mask" out a part of the background

I am attempting to create a "hole in the fog" effect. I have a background grid image, overlapped onto that I have a "fog" texture that I use to show that certain areas are not in view. I am attempting to cut a chunk out of "fog" that will show the area that is currently in view. I am trying to "mask" a part of the fog off the screen.
I made some images to help explain what I am after:
Background:
"Mask Image" (The full transparency has to be on the inside and not the outer rim for what I am going to use it for):
Fog (Sorry, hard to see.. Mostly Transparent):
What I want as a final Product:
I have tried:
Stencil-Buffer: I got this fully working except for one fact... I wasn't able to figure out how to retain the fading transparency of the "mask" image.
glBlendFunc: I have tried many different version of the parameters and many other methods with it (glColorMask, glBlendEquation, glBlendFuncSeparate) I started by using some parameter that I found on this website: here. I used the "glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);" as this seemed to be what I was looking for but... This is what ended up happening as a result: (Its hard to tell what is happening here but... There is fog covering the grid in the background. Though, the mask is just ending up as an fully opaque black blob when its supposed to be a transparent part in the fog.
Some previous code:
glEnable(GL_BLEND); // This is not really called here... It is called on the init function of the program as it is needed all the way through the rendering cycle.
renderFogTexture(delta, 0.55f); // This renders the fog texture over the background the 0.55f is the transparency of the image.
glBlendFunc(GL_ZERO, GL11.GL_ONE_MINUS_SRC_ALPHA); // This is the one I tried from one of the many website I have been to today.
renderFogCircles(delta); // This just draws one (or more) of the mask images to remove the fog in key places.
(I would have posted more code but after I tried many things I started removing some old code as it was getting very cluttered (I "backed them up" in block comments))
This is doable, provided that you're not doing anything with the alpha of the framebuffer currently.
Step 1: Make sure that the alpha of the framebuffer is cleared to zero. So your glClearColor call needs to set the alpha to zero. Then call glClear as normal.
Step 2: Draw the mask image before you draw the "fog". As Tim said, once you blend with your fog, you can't undo that. So you need the mask data there first.
However, you also need to render the mask specially. You only want the mask to modify the framebuffer's alpha. You don't want it to mess with the RGB color. To do that, use this function: glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE). This turns off writes to the RGB part of the color; thus, only the alpha will be modified.
Your mask texture seems to have zero where it is visible and one where it isn't. However, the algorithm needs the opposite, so you should either fix your texture or use a glTexEnv mode that will effectively flip the alpha.
After this step, your framebuffer should have an alpha of 0 where we want to see the fog, and an alpha of 1 where we don't.
Also, don't forget to undo the glColorMask call after rendering the mask. You need to get those colors back.
Step 3: Render the fog. That's easy enough; to make the masking work, you need a special blend mode. Like this one:
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFuncSeparate(GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA, GL_ZERO, GL_ONE);
The separation between the RGB and A blend portions is important. You don't want to change the framebuffer's alpha (just in case you want to render more than one layer of fog).
And you're done.
The approach you're currently taking will not work, as once you draw the fog over the whole screen, there's no way to 'erase' it.
If you're using fixed pipeline:
You can use multitexturing (glTexEnv) with fixed pipeline to combine the fog and circle textures in a single pass. This function is probably kind of confusing if you haven't used it before, you'll probably have to spend some time studying the man page. You'll do something like bind fog to glActiveTexture 0, and mask to glActiveTexture 1, enable multitexturing, and then combine them with glTexEnv. I don't remember exactly the right parameters for this.
If you're using shaders:
Use a multitexturing shader where you multiply the fog alpha with the circle texture (to zero out the alpha in the circle region), and then blend this combined texture into the background in a single pass. This is probably a more conceptually easy approach, but not sure if you're using shaders.
I'm not sure there's a way you can do this where you draw the fog and the mask in separate passes, as they both have their own alpha values, it will be difficult to combine them to get the right color result.

Categories

Resources