OK - it's up to you all. If it's doing what you think it should, I'm fine with it.
On Mon, Jul 15, 2013 at 6:28 PM, Aivar Grislis <gris...@wisc.edu> wrote: > I believe ImageJ1 treats it [RGBCMY] as additive. Look at the sample > "Organ of Corti" -- the current behavior of ImageJ2 causes that sample to > appear the same as it does in IJ1. Before we added the bounds-checking > code, it erroneously wrapped pixel values. > > By not being additive I meant C is a secondary color composed of primaries > G & B, etc. In the sense of http://en.wikipedia.org/wiki/Additive_color . > > Okay, "Organ of Corti" uses RGBK (and K is even worse than my example of C > since it has all three RGB components not just G & B) and yet it works as > an image. It's useful because the areas lit up in each channel are fairly > distinct. If these areas overlapped the bounds-checking code would come > into play in the overlapping pixels and some highlights would get squashed > and some colors distorted (when one component is squashed but not the > others). But even if the code did a better job of combining the colors of > overlapping areas you'd still have visual ambiguity in these areas (since > eyes can't distinguish C from G + B). So now I'm thinking the code works > well as is. > > It was intended to be more general than only the cases Aivar mentioned, > and instead provided additive support for *any* color table per channel you > throw at it, the same as ImageJ1's CompositeImages do. > > Sure, it shouldn't crash and burn if you put Fire on one channel and Ice > on another but that's not usable visually unless the areas lit up in each > channel are distinct. If you have a lot of overlap and you want the colors > to add up meaningfully you're better off sticking with primary additive > colors for your channel LUTs. > > On 7/15/13 3:53 PM, Curtis Rueden wrote: > > Hi all, > > > the bigger issue is RGBCMY is not an additive color system. > > I believe ImageJ1 treats it as additive. Look at the sample "Organ of > Corti" -- the current behavior of ImageJ2 causes that sample to appear the > same as it does in IJ1. Before we added the bounds-checking code, it > erroneously wrapped pixel values. > > As for the alpha stuff, I will try to digest and reply soon but I am way > too tired at this moment. I just wanted to clarify why the code is the way > it is. It was intended to be more general than only the cases Aivar > mentioned, and instead provided additive support for *any* color table per > channel you throw at it, the same as ImageJ1's CompositeImages do. > > Regards, > Curtis > > > On Mon, Jul 15, 2013 at 3:46 PM, Aivar Grislis <gris...@wisc.edu> wrote: > >> I think CompositeXYProjector is meant to handle the following cases: >> >> 1) Rendering LUT images, a single converter is used. Grayscale images >> are included here. >> >> 2) Rendering RGB images, three converters are used. These use red-only, >> green-only, and blue-only LUTs. >> >> 3) I believe it's also intended to work with images with > 3 channels, >> using C, M, and Y for the excess channels. >> >> The existing code works well for cases 1 & 2. Case 3 adds the >> possibility of overflow, if your red converter gives you a value of 255 for >> the red component but your magenta converter adds another 255. Currently >> the code just limits the value to 255 in that case. Some sort of blending >> might work better here, but the bigger issue is RGBCMY is not an additive >> color system. If you see a cyan blotch you don't know if its in both the G >> & B channels or just the C channel. >> >> Aivar >> >> >> >> On 7/15/13 2:40 PM, Lee Kamentsky wrote: >> >> Thanks for answering Aivar, >> >> I think what your reply did for me is to have me take a step back and >> consider what we're modeling. If you look at my replies below, I think that >> the best solution is to use a model where the background is white and each >> successive layer filters out some of that background, like a gel. A layer >> attenuates the underlying layer by a fraction of (1 - alpha/255 * (1 - >> red/255)), resulting in no attenuation for 255 and attenuation of alpha/255 >> for zero. We can then use a red converter that returns a value of 255 for >> the blue and green channels and the model and math work correctly. >> >> On Mon, Jul 15, 2013 at 1:59 PM, Aivar Grislis <gris...@wisc.edu> wrote: >> >>> I have an ImgPlus backed by an RGB PlanarImg of UnsignedByteType and >>> ARGBType.alpha(value) is 255 for all of them, so aSum is 765. It would >>> appear that the correct solution would be to divide aSum by 3. >>> >>> Isn't it unusual to define an alpha for each color component, generally >>> you have a single A associated with a combined RGB? So averaging the three >>> alphas might make sense here, because I think they should all be the same >>> value. >>> >> I think you're right, the model always is that each pixel has an alpha >> value that applies to R, G and B. The image I was using was the Clown >> example image. DefaultDatasetView.initializeView constructs three >> RealLUTConverters for the projector, one for red, one for green and one for >> blue which sends you down this rabbit hole. >> >>> In addition, there's no scaling of the individual red, green and blue >>> values by their channel's alpha. If the input were two index-color images, >>> each of which had different alphas, the code should multiply the r, g and b >>> values by the alphas before summing and then divide by the total alpha in >>> the end. The alpha in this case *should* be the sum of alphas divided by >>> the number of channels. >>> >>> I think alpha processing is more cumulative, done layer by layer in some >>> defined layer order. For a given pixel say the current output pixel value >>> is ARGB1 and you are compositing a second image with value ARGB2 on top of >>> it: For the red channel the output color should be ((255 - alpha(ARGB2)) * >>> red(ARGB1) + alpha(ARGB2) * red(ARGB2)) / 255. The alpha of ARGB1 is not >>> involved. >>> >> I think that's a valid interpretation. I've always used (alpha(ARGB1) * >> red(ARGB1) + alpha(ARGB2) * red(ARGB2)) / (alpha(ARGB1) + alpha(ARGB2)) >> because I assumed the alpha indicated the >> strength of the blending of each source. In any case, the code as it >> stands doesn't do either of these. >> >>> >>> In other words, if you add a layer that is completely opaque you no >>> longer have to consider any of the colors or alpha values underneath it. >>> >> >>> I think the bigger issue here is this code is specifically designed to >>> composite red, green and blue image layers. It's a special case since for >>> a given pixel the red comes from the red layer, blue from blue layer, and >>> green from green layer. These layers shouldn't be completely opaque, since >>> the colors wouldn't combine at all then or completely transparent since >>> then they wouldn't contribute any color. I don't think transparency is >>> useful here. >>> >> So this is an argument for blending instead of layering - transparency >> would be useful if the images were blended and treated as if on a par with >> each other, allowing the user to emphasize one channel or the other. >> >>> >>> It's also possible that a multichannel image with > 3 channels is being >>> displayed with more color channels, namely cyan, magenta, and yellow. The >>> code here is designed to stop overflow, but I'm not convinced those >>> extended color channels would combine meaningfully. >>> >>> Aivar >>> >>> In addition, there's no scaling of the individual red, green and blue >>> values by their channel's alpha. If the input were two index-color images, >>> each of which had different alphas, the code should multiply the r, g and b >>> values by the alphas before summing and then divide by the total alpha in >>> the end. The alpha in this case *should* be the sum of alphas divided by >>> the number of channels. >>> >>> I think alpha processing is cumulative layer by layer. >>> >>> This brings up some interesting questions: >>> >>> 1) If the first, bottom-most layer is transparent, what color should >>> show through? Black, white? Or perhaps it's best to ignore this base >>> layer transparency. >>> >> Maybe the model should be that the background is white and successive >> layers are like gel filters on top. In that case, you'd have: >> red = (255 - alpha(ARGB2) *(255 - red(ARGB2))/255) * red(ARGB1) >> >> And maybe that points to what the true solution is. For the default, we >> could change things so that red channel would have blue = 255 and green = >> 255 and the first composition would change only the red channel. >> >>> >>> 2) If you wanted to composite several transparent images, how do you >>> calculate the transparency of the composite? I'm not sure this is >>> something we need to do. >>> >>> Aivar >>> >>> >>> On 7/15/13 10:31 AM, Lee Kamentsky wrote: >>> >>> Hi all, >>> I'm looking at the code for net.imglib2.display.CompositeXYProjector and >>> as I step through it, it's clear that the alpha calculation isn't being >>> handled correctly. Here's the code as it stands now, line 190 roughly: >>> >>> for ( int i = 0; i < size; i++ ) >>> { >>> sourceRandomAccess.setPosition( currentPositions[ i ], dimIndex ); >>> currentConverters[ i ].convert( sourceRandomAccess.get(), bi ); >>> // accumulate converted result >>> final int value = bi.get(); >>> final int a = ARGBType.alpha( value ); >>> final int r = ARGBType.red( value ); >>> final int g = ARGBType.green( value ); >>> final int b = ARGBType.blue( value ); >>> aSum += a; >>> rSum += r; >>> gSum += g; >>> bSum += b; >>> } >>> if ( aSum > 255 ) >>> aSum = 255; >>> if ( rSum > 255 ) >>> rSum = 255; >>> if ( gSum > 255 ) >>> gSum = 255; >>> if ( bSum > 255 ) >>> bSum = 255; >>> targetCursor.get().set( ARGBType.rgba( rSum, gSum, bSum, aSum ) ); >>> >>> I have an ImgPlus backed by an RGB PlanarImg of UnsignedByteType and >>> ARGBType.alpha(value) is 255 for all of them, so aSum is 765. It would >>> appear that the correct solution would be to divide aSum by 3. In addition, >>> there's no scaling of the individual red, green and blue values by their >>> channel's alpha. If the input were two index-color images, each of which >>> had different alphas, the code should multiply the r, g and b values by the >>> alphas before summing and then divide by the total alpha in the end. The >>> alpha in this case *should* be the sum of alphas divided by the number of >>> channels. >>> >>> However, I think the problem is deeper than that. For an RGB ImgPlus, >>> there are three LUTs and each of them has an alpha of 255, but that alpha >>> only applies to one of the colors in the LUT. When you're compositing >>> images and weighing them equally, if two are black and one is white, then >>> the result is 1/3 of the white intensity - if you translate that to red, >>> green and blue images, the resulting intensity will be 1/3 of that desired. >>> This might sound weird, but the only solution that works out mathematically >>> is for the defaultLUTs in the DefaultDatasetView to use color tables that >>> return values that are 3x those of ColorTables.RED, GREEN and BLUE. >>> Thinking about it, I'm afraid this *is* the correct model and each channel >>> really is 3x brighter than possible. >>> >>> It took me quite a bit of back and forth to come up with the above... >>> I hope you all understand what I'm saying and understand the problem and >>> counter-intuitive solution and have the patience to follow it. Dscho, if >>> you made it this far - you're the mathematician, what's your take? >>> >>> --Lee >>> >>> >>> _______________________________________________ >>> ImageJ-devel mailing >>> listImageJ-devel@imagej.nethttp://imagej.net/mailman/listinfo/imagej-devel >>> >>> >>> >>> _______________________________________________ >>> ImageJ-devel mailing list >>> ImageJ-devel@imagej.net >>> http://imagej.net/mailman/listinfo/imagej-devel >>> >>> >> >> >> _______________________________________________ >> ImageJ-devel mailing list >> ImageJ-devel@imagej.net >> http://imagej.net/mailman/listinfo/imagej-devel >> >> > >
_______________________________________________ ImageJ-devel mailing list ImageJ-devel@imagej.net http://imagej.net/mailman/listinfo/imagej-devel