GNOME Bugzilla – Bug 170608
Suggestion: Option for the Sum (Addition) of Alpha (Transparency, Opacity) Pixel Values
Last modified: 2008-01-15 12:50:04 UTC
I propose an option to allow alpha blending using the sum of alpha values for each pixel rather than rendering each layer on top of each other. In other words, suppose an image has 3 layers, and we are focusing on one pixel. The top-most layer is green with 50% opacity, the next is red with 40%, and the last is blue with 20%. The end result, if the top two-most layers have sum blending, will be a pixel that is 50% green, 40% red, 10% blue, and 100% opaque (when opacity exceeds 100% when summing, you truncate the percentage from the bottom layers). Details and Examples: The applications for this feature are numerous. To give just one example, imagine selecting a circle, and filling it green. Then, on another layer, you select the inverted selection (whole image except for circle), and fill it red. What currently happens is that your alpha values will be somewhere between 1/sqrt(2) (when both layers have 50% at that pixel) and 100% (when one layer has 100% and the other, necessarily, has 0%). With summation applied to the top layer, we will add these percentages, and so all pixels will have 100% opacity. This is probably desired in this case, and is mathematically sound: the sum of a region and the inverse of that region is the whole region. As for why I want it, I am an artist who likes cell shading. I would like to be able to be very precise with the paths tool. How it stands now, I have two options: either fill the evil areas will lines (compromizing my art), or do some layer hacking involving the following process, which can only be done at the end of the art creation process: Current workaround: For every layer, bottom to top: 1. Create a temporary layer that is the merged result of all the layers below the current layer 2. Aside, extract the masks from the alphas of the current layer and the newly created layer and use the Addition Blend Mode. 3. Use this as the new CurrentLayer mask. Discard the temporary layer. As you can see, doing this, though generating what I want, is a) long and b) unmodifiable, since it is a blatant workaround which no longer plays nicely with the GIMP.
I said above that the transparency range started at 1/sqrt(2), when I should have said 75%. I got my math wrong. Anyway, I revised what I wanted out of the GIMP and decided to create instead bug 170610, which suggests the possibility of applying a blend mode to masks.
*** Bug 170610 has been marked as a duplicate of this bug. ***
Check if what I describe in bug 161449 would help you. (That off course, as a GIMP feature, not only abstracted in GEGL). That however doesnṫ use the information on the layer masks, so youḋ need a worrking procedure to use the alpha channel of the layers instead of masks.
Joao: Thank you for your suggestion. However, I think that your solution is much too advanced for what I have in mind. At least, what I suggest (in bug 170610... I hope to soon make this bug a duplicate of that one and not the other way around) can probably be implemented very rapidly. Layer masks and layers are already very close in terms of implementation. All that is needed is a way to give the functionality of blending modes to masks as well. Though I haven't looked at the code yet, I imagine that this may be harder to do GUI-wise than in the library code itself, since the pixel-specific blending functions already exist. Perhaps I lack understanding of bug 161449. If, after what I have said, you think that your bug would benefit mine (usefulness with relation to this bug > effort required), please give me details of why you think so.
Well, I had taken a look into this part of the code. The matter is that when each layer pixel values get to the compositing engine , the mask is already applied. Forr all effects, at composite time, the pixel alpha value already includes the mask calculation. So there is another layer could get to know wich are the layer mask's values for another layer. Bug 161449, however, is a suggestion to GEGL - although it could be implemented into teh GIMP while the GEGL doesn't replace it's compositing core. It wopuld allow one to dinamically create blending functions. Fully customizable blending functions. Then you would be able to create whatever expression you would like to combine the alpha values of layers set to a certain custom mode. And I think it is more simple because it requires little change of the way GIMP currently works - it would be just one more compositing function among about 20 others. There would only need to be a device to feed it with the "bytecode" expressions it use, which could be something as simple as layer parasites edited by some plug-in.
Joao: I wouldn't be planning on effecting the layers themselves. Basically how it is now (at least in end-result) is: 1. Apply mask to alpha 1. Apply alpha to layer 2. Apply blending to layer What I want to do is, before the mask is applied, to ignore the layer itself and only apply blending between masks, and then use the resulting mask for step 1. This whole process is independant of the layer. Though I do see your idea is a good one, and can expand the horizons for GIMP developers, I would like my solution to be implemented ASAP. This bug doesn't depend on yours, and to make it depend would mean that I will need to wait a version or so more. I suggest one of three things. 1. Have your patch accepted, and get back to me, or 2. Include my functionality in your patch, and get back to me, or 3. Include my functionality in your patch, get it accepted, and close this bug. I think it is most likely that your bug and mine are completely seperate issues.
I have several comments: 1) The alternative you suggest in bug #170610 would be much harder to implement than adding alpha values would be. The GIMP process for combining layers is very heavily optimized for speed (even written in assembly code in some parts), and the changes you suggest there would rip them apart at the center. The changes are simple in concept, but not simple to implement in something so optimized. 2) In spite of having read your original description half-a-dozen times, I haven't managed to understand quite what problem you're trying to solve. It's probably my lack of visual imagination, but your description of your workflow just isn't getting through to me. 3) You should realize that, since we are all volunteers here, unless you persuade somebody to be very enthusiastic about your change, the only way to get it done in a hurry is to submit a patch for it yourself. 4) It doesn't matter which bug report is a duplicate of which, as far as concerns what solution gets implemented. It is easier to keep track if the shorter one is a duplicate of the longer, that's all. So let's keep the discussion here, without prejudice to the ultimate solution.
Michel: As Bill and I had put it, it is thought to make the chagnes you are asking. I am not quite sure I understood exactly the desired effect. However, by reading your work-around, it would be feasible to write a script that would produce a layer combined the away you want, or, just replace all masks (if that is feasible). I recognize the disavantadge of this in relation to combination modes - which work in real time. However, it is the solution I can think of on the moment. Can you run GIMp-Python scripts? If so, I will ask you to explain once more, with other words, what are you intending, and I will see if I can code the script for you.
Dear weskaggs: I am sorry if I left the impression that I was trying to force the issue (sorry for saying ASAP. I didn't actually MEAN ASAP as in a rush, but ASAP as in without any detours). I most certainly wasn't forcing the issue, and am eternally appreciative of any time anyone takes in reading this report or doing any work related to it. My responses to your points: > 1) The alternative you suggest in bug #170610 would be much harder to > implement than adding alpha values would be. [...] The changes are > simple in concept, but not simple to implement in something so > optimized. 1) I did not realize that was the case. I had imagined that it would be more likely to be the other way around, but since you know the code and I don't, I'm not going to contest what you say. > 2) In spite of having read your original description half-a-dozen > times, I haven't managed to understand quite what problem you're > trying to solve. It's probably my lack of visual imagination, but > your description of your workflow just isn't getting through to me. 2) You are correct in not understanding what I am saying. Indeed, after some fiddling, I found that the correct method to get what I desire is different than what I said above. So, in the example that will follow: - A/B is a Divide Blend (note that the order the Gimp does it is such that B has to be the above layer). - ^A means an inversion in color for A - layer0 is the bottom layer - layer1 is just above layer0 - maskN is the mask for layerN Knowing this, here is the equation, iterated from bottom-up: mask0 = mask0 / (^mask1) And after creating each new mask and applying it, merge layer0 with layer1 This is a super hack, but I had to prove that it COULD be done with the GIMP as it stands right now, just not easily, and it won't be recoverable, ie. you destroy all your layer information. In fact, the division algorithm does not perform perfectly right now, though I cannot guess why (probably some float errors somewhere where I can't think off the top of my head), but after all, my equation is GIMP independant math, and can be proofed :) The non-hacked version would, ideally, in the case where all layers were in "addition" mode, render pixels top to bottom INDEPENDENTY (that is, doing operations on individual layers rather than compounded layers), so that the end result of layers with 20%, 30% and 50% opacity will be a final surface that has no transparency (since you add the percentages), rather than 20%, 30%-(20%*30%), 50%-(30%*50%)-(20%*30%), which becomes 20%, 24% and 29%, leaving a remaining 27% transparency... I will attach a screenshot with details, in my next post. As for *why* I want this feature: Look at my next post with the screenshot. Can you not imagine an application to me not wanting cracks that seap through? I figure that has many applications, but if you can't think of any after looking at the screenshot, let me know, and I will rewrite a justification for the feature. 3) I understand. 4) Got it. I'm new to bugzilla, so I thought you were throwing away my other idea (which ultimately, seems not to be the solution anymore...) In fact, the more I think of it, the more I think Joao's proposal, modified for masks, can be applied here (as long as it can give me live results). --- In reply to Joao, I thank you very much for your offer! If you need any details beyond this new post, let me know. As I demonstrated, it can be done with The GIMP right now, but requires a lot of steps that can be grueling for a user. I am guessing that a script can make a good temporary solution for me. Anyway, don't feel obligated in any way to do me this favour, though I do appreciate the offer. As for GIMP-Python... I've never developed a script, but I do like Python, and whatever there is involved in getting GIMP-Python to work in GIMP-windows, I will do it.
Created attachment 38879 [details] Four screenshots merged, illustrating my proposal.
Comments on the subimages of the attachment, from left to right: 1) This is the image with the paths I created. I use paths since they are very precise, and can be turned into very precise selections and filled with solid colours. 2) This is the resulting image as The Gimp does it now. I should have zoomed so you could see the difference with image 3... 3) This is the resulting image using the hack process I described above, or using the non-hack process I suggest. You may not see the difference. Luckily, the difference can be shown thanks to image 4. 4) The fundamental difference between 2 (The GIMP) and 3 (my proposal). There is no seepage of black in 3, and 4, which is a difference between 2 and 3, shows just how much seepage there was.
I am going to close this as WONTFIX because the rationale is too hard to understand. With limited time and manpower available, it is unlikely that anybody is going to want to implement this unless a much crisper explanation of the reason for it exists. (Note that this has sat unconfirmed for a year and a half now.)
Ok, I will clarify: Right now, when you have two layers, you multiply the transparencies for every pixel. I would like it to instead add the opacities for every pixel. If the sum exceeds 100%, upper layers have priority over lower layers. The reason for this to exist is that if you have two layers constructed with paths and they share a side (look at the image attached, and you'll see there are three layers, each one sharing one side with each of the two others), any time two layers will share pixels, though they should come up to 100% the whole length of the shared side, that is not the case, resulting in awkward looking images. The worst case is if two layers cut a pixel perfectly in half, in which case the opacity will be 75% (Transparency: 50%*50%=25% -> Opacity: 75%) as opposed to 100% (Opacity: 50%+50%=100%).