6 Replies Latest reply on Jul 3, 2009 6:02 AM by Vackar

    Lookup Table (LUT) Implementation

    Vackar

      Hi,

       

      I'm trying to implement a lookup table shader in PixelBender which essentially needs to read the input rgb values and substitute them for another set of RGB values based on a predefined lookup table.

       

      .i.e

       

      Source-Red    LookupValue

      1                         55    

      2                         45

      3                         45

      4                         89

      ...

      255                     66

       

      and the same kind of thing for blue and green channels.

       

      It would be great if I could contruct 3 arrays, and then for each channel just do

      dstPix.r = redArray[srcPix.r]

      dstPix.g = redArray[srcPix.g]

      dstPix.b = redArray[srcPix.b]

       

      But as far as I know there are no arrays in PixelBender.

       

      Anyone got any idea as to what the best approach to tackling this would be. So far the only solution I can think of is to construct 3 sets of if else blocks. But 3x255 checks per pixel is a crazy amount of processing, so any tips would be welcomed.

       

      Thanks,

      Vackar

        • 1. Re: Lookup Table (LUT) Implementation
          souldreamer

          You could try a 256x3 bitmap image with the values in it, and just sampleNearest(indexImage, float2(srcPix.r, 0)).r for red, sampleNearest(indexImage, float2(srcPix.g, 1)).g for green and sampleNearest(indexImage, float2(srcPix.b, 2)).b for blue. In shaders, when you have to use big arrays, you can just use a texture (it works even for unidimensional arrays, just use a Nx1 texture)

           

          See the attached kernel [okay, can't attach pbk files, so the source is below], just tie the first image to the source, and the second to something that looks like the attached png. The palette I included is something that almost inverts the image (doesn't quite, because it's a quick gradient in photoshop and I put in a bit too much black at the end, so the contrast will be a bit higher; just compare the resulting image to a negative image if you're curios about it)

           

           

          <languageVersion: 1.0;>
           
          kernel changePalette
          <   namespace : "";
              vendor : "seventh-shape.com";
              version : 1;
              description : "change the palette of the image"; >
          {
              input image4 src;
              input image4 src2; // new palette
              output float4 dst;
              
              void evaluatePixel() {
                  float4 inputColor = sampleNearest(src, outCoord());
                  dst.r = sampleNearest(src2, float2(inputColor.r * 255.0, 0.0)).r;
                  dst.g = sampleNearest(src2, float2(inputColor.g * 255.0, 1.0)).g;
                  dst.b = sampleNearest(src2, float2(inputColor.b * 255.0, 2.0)).b;
                  dst.a = inputColor.a;
              }
          }
          
          • 2. Re: Lookup Table (LUT) Implementation
            Vackar Level 2

            Hi Souldreamer.

             

            Sorry I was away for a few days so havne't had a chance to try this out. I'm back at work tomorrow and I'll let you know how it goes.

             

             

            Thanks for all your help,

            Vackar

            • 3. Re: Lookup Table (LUT) Implementation
              Vackar Level 2

              Thank you sooo much. This was exactly what I was looking for.

               

              Now I just need to import it into flex.

              • 4. Re: Lookup Table (LUT) Implementation
                Vackar Level 2

                OK, got this working in pixelbender with the correct LUT, but I'm having problems using it in Flex, I think it may be becasue I've defined two input images.

                 

                Anyone got an example of how to implement a shader in flex with two input images?

                 

                Vackar

                • 5. Re: Lookup Table (LUT) Implementation
                  souldreamer Level 1

                  You could try the bendpixels library at http://code.google.com/p/bendpixels/ or in the one of the Adobe MAX2008 videos (http://tv.adobe.com/#vi+f15383v1072) they show pixelbender/flex integration somewhere in the middle.

                  1 person found this helpful
                  • 6. Re: Lookup Table (LUT) Implementation
                    Vackar Level 2

                    HI,

                     

                    For anyone who's wondering I got this working uing the following implemenation

                    I've included my base classes as well for anyone else who's intrested.

                     

                     

                    BaseFilter

                    public class BaseFilter 
                        {
                            [Bindable]
                            public var filterName:String;
                            
                            public function BaseFilter()
                            {
                            }
                    
                        }
                    

                     

                    IFilter

                    public interface IFilter
                        {
                            //function applyFilter(imgObj:ImageWrapper, imgUI:Image):void;
                            function getFilters():Array;
                            
                        }
                    

                     

                    Lookup Filter Class

                    
                    public class LookupFilter extends BaseFilter implements IFilter
                        {
                            var lkpImage:Class;
                            var pixelBenderFile:Class;
                            
                            public function LookupFilter(pixelBenderFile:Class, lkpImage:Class, lookupName:String)
                            {
                                super();
                                this.lkpImage = lkpImage;
                                this.pixelBenderFile = pixelBenderFile;
                                this.filterName = lookupName;
                            }
                    
                    
                            public function getFilters():Array{
                    
                                var filter:Shader = new Shader(new pixelBenderFile());
                                filter.data.src2.input = new lkpImage().bitmapData;
                                
                                var shaderFilter:ShaderFilter = new ShaderFilter(filter);
                    
                                
                                var filtersArray:Array = new Array();
                                filtersArray.push(shaderFilter);
                                return filtersArray;
                            }
                    
                    
                    

                     

                     

                    Implementation

                     

                            [Embed(source="filters/LutFilter.pbj", mimeType="application/octet-stream")]
                            private var pixelBenderLutFilter:Class;    
                            
                            [Embed(source="filters/assist.jpg")]
                            private var assistColourMap:Class;    
                    
                    
                            [Embed(source="filters/jetblack.jpg")]
                         private var jetBlackColourMap:Class;     
                    
                    
                    
                            function init():void
                            {  
                                var greyScaleFilter:BaseFilter = new GrayScaleFilter();
                                var edgeDetectionFilter:BaseFilter = new EdgeDetectionFilter();
                                var embossingFilter:BaseFilter = new EmbossFilter();
                                var glowFilter:BaseFilter = new GlowingFilter();
                                var sharpeningFilter:BaseFilter = new SharpeningFilter();
                                var negativeImageFilter:BaseFilter = new NegativeImageFilter();
                                var blurringFilter:BaseFilter = new BlurringFilter();
                                var assistFilter:BaseFilter = new LookupFilter(pixelBenderLutFilter, assistColourMap, "Colour Map -> Assist");
                                var jetBlackFilter:BaseFilter = new LookupFilter(pixelBenderLutFilter, jetBlackColourMap, "Colour Map -> Jet Black");
                                
                                imageFilters.addItem(blurringFilter);
                                imageFilters.addItem(edgeDetectionFilter);
                                imageFilters.addItem(embossingFilter);
                                imageFilters.addItem(greyScaleFilter);
                                imageFilters.addItem(glowFilter);
                                imageFilters.addItem(sharpeningFilter);
                                imageFilters.addItem(negativeImageFilter);
                                imageFilters.addItem(assistFilter);
                                imageFilters.addItem(jetBlackFilter);
                            }
                    

                     

                    Red parts are the relevent parts of the implementation.

                     

                    Souldreamer - Thanks for all your help

                     

                    Vackar