I have an image plot where I'd like to use a single color map, but I want the transparency to depend on the X/Y pixel position. Right now, I can add varying transparencies to any color by making a custom ColorTab, but here the transparency depends on the z value in the image, not the x/y position. I basically want to use a pre-made color table, but be able to apply an arbitrary alpha map to the image. Is this possible? For full context, I'm looking at changes in fluorescence in a neuron, and I want areas of the neuron with strong signals to be opaque, and weaker signals to be less opaque, with zero signal being fully transparent. Thanks for any insight.
I have an image plot where I'd like to use a single color map, but I want the transparency to depend on the X/Y pixel position. Right now, I can add varying transparencies to any color by making a custom ColorTab, but here the transparency depends on the z value in the image, not the x/y position. I basically want to use a pre-made color table, but be able to apply an arbitrary alpha map to the image. Is this possible? For full context, I'm looking at changes in fluorescence in a neuron, and I want areas of the neuron with strong signals to be opaque, and weaker signals to be less opaque, with zero signal being fully transparent. Thanks for any insight.
I'm not sure whether you would like the transparency to depend on x/y position or on the value at each x/y position. I am guessing that it's the latter based on the goal you describe.
Here's one way to implement the latter using a color table wave. (The help mouse over Color Table Wave radio button in the Modify Image Appearance dialog box doesn't mention that a 4-column color wave can be used too, but it's clearer in the Modifyimage help file.
•make/o/n=(10,10) image; image = p; newimage/k=1 image //this is an example image; any image should work (though 3 color images might be a bit more complicated)
•colortab2wave red //this is an example color table, any color table should work
•variable minTransparency = 0,maxTransparency = -1 + 2^16//this could be altered to give the most desirable representation
•duplicate/o m_colors,image_colors; redimension/n=(-1,4) image_colors
•variable colorRows=dimsize(image_colors,0)
•image_colors[][3] = minTransparency + (maxTransparency - minTransparency)*(p/(colorRows-1))//this relation could also be altered, e.g., to logarithmic
•ModifyImage image ctab= {*,*,image_colors,0}
You can compute your own four-layer wave, making a "direct color" image. The first three layers specify RGB for the color to be displayed, and the fourth layer the transparency. All values in the range [0,65535], alpha=0 is fully transparent. You will need to come up with a way to map your signal strength to alpha value.
@aoa, I'm looking for the alpha value to depend on the X/Y position, not the value at that position.
@John, yeah I though about that - I guess the trick would be to maintain some ability to change the scaling or color range of the image after making it into an RGBA wave.
Ah, ok, I misunderstood. Is it that you want the fluorescence signal to mask (in a manner proportional to the intensity of fluorescence at each pixel) a second image (e.g., bright field, transillumination) of the same neuron?
Could you overlay the fluorescence image (the wave setting opacity) on top of the primary image? Then give that fluorescence image a custom RGBA color table wave that is white (or another color if preferred) but varies in opacity in inverse proportion to the fluorescence z values. Dimly fluorescent pixels will get masked towards white, brightly fluorescent pixels will show through.
•make/o/n=(100,100) nImage; nImage=enoise(1)//fake underlying image to test
•make/o/n=(100,100) mask;mask=0;mask[20,80][20,80] = 1//fake mask/fluorescene image to test
•newimage/k=1 nimage ; appendimage/t/l mask
•make/o/u/i/n=(2,4) transparency //custom RGBA color table wave
•transparency[][0,2] = -1 + 2^16//white overlay color
•transparency[0][3] = -1+2^16//smallest overlay z value results in fully opaque/white (underlying image will be white)
•transparency[1][3] = 0//largest z value results in fully transparent (underlying image will show through completely)
•ModifyImage mask ctab= {*,*,transparency,0}
@John, yeah I though about that - I guess the trick would be to maintain some ability to change the scaling or color range of the image after making it into an RGBA wave.
So the image may change during the lifetime of the image display? How are you setting the color right now? You can extract a color wave from our built-in color tables, then you would have to use that with suitable computation to select the appropriate color from the wave. If the original image data is a single-layer matrix wave, and you want color and alpha set according to the intensity of the original image data, you might do something along the lines of
WARNING: I haven't compiled that or tried it out...
If I thought it through correctly, that should give you alpha proportional to the original intensity, normalized to the range, and it should also pick out a color from M_colors that is also proportional to the intensity range.
If binary transparency is OK, make a floating-point overlay image with one layer and put NaNs where you want the background image to show through.
So the image may change during the lifetime of the image display?
Yes, so once it becomes an RGBA image, I'd like the flexibility to still change the scaling range on the colors as if it were a single layer matrix. I made a panel that seems to do the trick, it uses basically the code you suggested, but it also lets you input new min/max scaling values that just auto-rebuild the RGBA wave with the new scaling.
I am trying to do the same thing, but even simpler, with just a single transparency value for all colors, but the color scaling for the color index wave when I am done does not match the color scaling when using the same (non-transparent) color table.
The first attached image is the overlay with the non-transparent rainbow color table, which is fine aside from the lack of transparency.
To generate the transparent color index wave I did the following:
The second attached image is with the color index wave applied (the image underneath is grayscale). The colors don't match the color table version (e.g. the purple pixel is now yellow). I assume this is some data range issue, but if data max/min is not used to get the range what is used. There is also a non-transparent tan-colored bar across the bottom that I do not understand, but I could presumably crop that out with the Y-range if need be.
I should also mention I am doing this in the Igor 9 beta, but I don't think that is relevant.
Here's one way to implement the latter using a color table wave. (The help mouse over Color Table Wave radio button in the Modify Image Appearance dialog box doesn't mention that a 4-column color wave can be used too, but it's clearer in the
Modifyimage
help file.•colortab2wave red //this is an example color table, any color table should work
•variable minTransparency = 0,maxTransparency = -1 + 2^16 //this could be altered to give the most desirable representation
•duplicate/o m_colors,image_colors; redimension/n=(-1,4) image_colors
•variable colorRows=dimsize(image_colors,0)
•image_colors[][3] = minTransparency + (maxTransparency - minTransparency) *(p/(colorRows-1)) //this relation could also be altered, e.g., to logarithmic
•ModifyImage image ctab= {*,*,image_colors,0}
April 27, 2018 at 07:16 am - Permalink
John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
April 27, 2018 at 09:13 am - Permalink
@John, yeah I though about that - I guess the trick would be to maintain some ability to change the scaling or color range of the image after making it into an RGBA wave.
Thanks for the input.
April 27, 2018 at 10:49 am - Permalink
Could you overlay the fluorescence image (the wave setting opacity) on top of the primary image? Then give that fluorescence image a custom RGBA color table wave that is white (or another color if preferred) but varies in opacity in inverse proportion to the fluorescence z values. Dimly fluorescent pixels will get masked towards white, brightly fluorescent pixels will show through.
•make/o/n=(100,100) mask;mask=0;mask[20,80][20,80] = 1 //fake mask/fluorescene image to test
•newimage/k=1 nimage ; appendimage/t/l mask
•make/o/u/i/n=(2,4) transparency //custom RGBA color table wave
•transparency[][0,2] = -1 + 2^16 //white overlay color
•transparency[0][3] = -1+2^16 //smallest overlay z value results in fully opaque/white (underlying image will be white)
•transparency[1][3] = 0 //largest z value results in fully transparent (underlying image will show through completely)
•ModifyImage mask ctab= {*,*,transparency,0}
April 27, 2018 at 11:58 am - Permalink
So the image may change during the lifetime of the image display? How are you setting the color right now? You can extract a color wave from our built-in color tables, then you would have to use that with suitable computation to select the appropriate color from the wave. If the original image data is a single-layer matrix wave, and you want color and alpha set according to the intensity of the original image data, you might do something along the lines of
ColorTab2Wave rainbow // or whatever
WaveStats imagew
Variable numcolors = DimSize(M_colors, 0)
newimagew[][][0,2] = M_colors[numcolors*(imagew[p][q] - V_min)/(V_max-V_min)]
newimagew[][][3] = 65535*(imagew[p][q] - V_min)/(V_max-V_min)
WARNING: I haven't compiled that or tried it out...
If I thought it through correctly, that should give you alpha proportional to the original intensity, normalized to the range, and it should also pick out a color from M_colors that is also proportional to the intensity range.
If binary transparency is OK, make a floating-point overlay image with one layer and put NaNs where you want the background image to show through.
John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
April 27, 2018 at 04:21 pm - Permalink
Yes, so once it becomes an RGBA image, I'd like the flexibility to still change the scaling range on the colors as if it were a single layer matrix. I made a panel that seems to do the trick, it uses basically the code you suggested, but it also lets you input new min/max scaling values that just auto-rebuild the RGBA wave with the new scaling.
April 28, 2018 at 04:53 pm - Permalink
John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
April 30, 2018 at 12:25 pm - Permalink
I am trying to do the same thing, but even simpler, with just a single transparency value for all colors, but the color scaling for the color index wave when I am done does not match the color scaling when using the same (non-transparent) color table.
The first attached image is the overlay with the non-transparent rainbow color table, which is fine aside from the lack of transparency.
To generate the transparent color index wave I did the following:
The second attached image is with the color index wave applied (the image underneath is grayscale). The colors don't match the color table version (e.g. the purple pixel is now yellow). I assume this is some data range issue, but if data max/min is not used to get the range what is used. There is also a non-transparent tan-colored bar across the bottom that I do not understand, but I could presumably crop that out with the Y-range if need be.
I should also mention I am doing this in the Igor 9 beta, but I don't think that is relevant.
March 11, 2021 at 11:42 am - Permalink
Figured it out, posting this for anyone else who runs into this even though it is clearly explained in the manual under "indexed color details."
The wave scaling of the color index wave controls the displayed range.
i.e. this fixed it for me:
March 11, 2021 at 11:52 am - Permalink