Index: apps/gdalbuildvrt.cpp
===================================================================
--- apps/gdalbuildvrt.cpp	(revision 24486)
+++ apps/gdalbuildvrt.cpp	(working copy)
@@ -91,6 +91,7 @@
             "                    [-tr xres yres] [-tap] [-separate] [-allow_projection_difference] [-q]\n"
             "                    [-te xmin ymin xmax ymax] [-addalpha] [-hidenodata] \n"
             "                    [-srcnodata \"value [value...]\"] [-vrtnodata \"value [value...]\"] \n"
+            "                    [-lutin \"value [value...]\" -lutout \"value [value...]\"] \n"
             "                    [-input_file_list my_liste.txt] [-overwrite] output.vrt [gdalfile]*\n"
             "\n"
             "eg.\n"
@@ -108,6 +109,7 @@
             "  o If one GDAL dataset is made of several subdatasets and has 0 raster bands, its\n"
             "    datasets will be added to the VRT rather than the dataset itself.\n"
             "  o By default, only datasets of same projection and band characteristics may be added to the VRT.\n"
+            "  o lutin and lutout should have the same number of value\n"
             );
     exit( 1 );
 }
@@ -197,6 +199,8 @@
     int                 bHideNoData;
     char               *pszSrcNoData;
     char               *pszVRTNoData;
+    char               *pszVRTLutIn;
+    char               *pszVRTLutOut;
 
     /* Internal variables */
     char               *pszProjectionRef;
@@ -216,6 +220,10 @@
     int                 nVRTNoDataCount;
     int                 bHasRunBuild;
     int                 bHasDatasetMask;
+    int                 bAllowLUT;
+    int                 nLUTItemCount;
+    double             *padfLUTInputs;
+    double             *padfLUTOutputs;
 
     int         AnalyseRaster(GDALDatasetH hDS, const char* dsFileName,
                               DatasetProperty* psDatasetProperties);
@@ -232,7 +240,8 @@
                            double minX, double minY, double maxX, double maxY,
                            int bSeparate, int bAllowProjectionDifference,
                            int bAddAlpha, int bHideNoData,
-                           const char* pszSrcNoData, const char* pszVRTNoData);
+                           const char* pszSrcNoData, const char* pszVRTNoData,
+                           const char *pszVRTLutIn=NULL, const char *pszVRTLutOut=NULL );
 
                ~VRTBuilder();
 
@@ -252,7 +261,8 @@
                        double minX, double minY, double maxX, double maxY,
                        int bSeparate, int bAllowProjectionDifference,
                        int bAddAlpha, int bHideNoData,
-                       const char* pszSrcNoData, const char* pszVRTNoData)
+                       const char* pszSrcNoData, const char* pszVRTNoData,
+                       const char *pszVRTLutIn, const char *pszVRTLutOut)
 {
     this->pszOutputFilename = CPLStrdup(pszOutputFilename);
     this->nInputFiles = nInputFiles;
@@ -278,6 +288,8 @@
     this->bHideNoData = bHideNoData;
     this->pszSrcNoData = (pszSrcNoData) ? CPLStrdup(pszSrcNoData) : NULL;
     this->pszVRTNoData = (pszVRTNoData) ? CPLStrdup(pszVRTNoData) : NULL;
+    this->pszVRTLutIn = (pszVRTLutIn) ? CPLStrdup(pszVRTLutIn) : NULL;
+    this->pszVRTLutOut = (pszVRTLutOut) ? CPLStrdup(pszVRTLutOut) : NULL;
 
     bUserExtent = FALSE;
     pszProjectionRef = NULL;
@@ -296,6 +308,10 @@
     nVRTNoDataCount = 0;
     bHasRunBuild = FALSE;
     bHasDatasetMask = FALSE;
+    bAllowLUT = FALSE;
+    nLUTItemCount = 0;
+    padfLUTInputs = NULL;
+    padfLUTOutputs = NULL;
 }
 
 /************************************************************************/
@@ -307,6 +323,8 @@
     CPLFree(pszOutputFilename);
     CPLFree(pszSrcNoData);
     CPLFree(pszVRTNoData);
+    CPLFree(pszVRTLutIn);
+    CPLFree(pszVRTLutOut);
 
     int i;
     for(i=0;i<nInputFiles;i++)
@@ -338,6 +356,8 @@
     CPLFree(pszProjectionRef);
     CPLFree(padfSrcNoData);
     CPLFree(padfVRTNoData);
+    CPLFree(padfLUTInputs);
+    CPLFree(padfLUTOutputs);
 }
 
 /************************************************************************/
@@ -753,13 +773,14 @@
         if (bHideNoData)
             GDALSetMetadataItem(hVRTBand,"HideNoDataValue","1",NULL);
 
-        if (bAllowSrcNoData && psDatasetProperties->panHasNoData[0])
+        if ( (bAllowSrcNoData && psDatasetProperties->panHasNoData[0]) || bAllowLUT )
         {
             GDALSetRasterNoDataValue(hVRTBand, psDatasetProperties->padfNoDataValues[0]);
             VRTAddComplexSource(hVRTBand, GDALGetRasterBand((GDALDatasetH)hProxyDS, 1),
                             nSrcXOff, nSrcYOff, nSrcXSize, nSrcYSize,
                             nDstXOff, nDstYOff, nDstXSize, nDstYSize,
-                            0, 1, psDatasetProperties->padfNoDataValues[0]);
+                            0, 1, psDatasetProperties->padfNoDataValues[0],
+                            nLUTItemCount, padfLUTInputs, padfLUTOutputs);
         }
         else
             /* Place the raster band at the right position in the VRT */
@@ -858,11 +879,21 @@
                     (VRTSourcedRasterBandH)GDALGetRasterBand(hVRTDS, j + 1);
 
             /* Place the raster band at the right position in the VRT */
-            if (bAllowSrcNoData && psDatasetProperties->panHasNoData[j])
+            
+            double noDataValue = VRT_NODATA_UNSET;
+            if(bAllowSrcNoData && psDatasetProperties->panHasNoData[j])
+            {
+              noDataValue = psDatasetProperties->padfNoDataValues[j];
+            }
+            
+            if ( (bAllowSrcNoData && psDatasetProperties->panHasNoData[j]) || bAllowLUT )
+            {
                 VRTAddComplexSource(hVRTBand, GDALGetRasterBand((GDALDatasetH)hProxyDS, j + 1),
                                 nSrcXOff, nSrcYOff, nSrcXSize, nSrcYSize,
                                 nDstXOff, nDstYOff, nDstXSize, nDstYSize,
-                                0, 1, psDatasetProperties->padfNoDataValues[j]);
+                                0, 1, noDataValue,
+                                nLUTItemCount, padfLUTInputs, padfLUTOutputs);
+            }
             else
                 VRTAddSimpleSource(hVRTBand, GDALGetRasterBand((GDALDatasetH)hProxyDS, j + 1),
                                 nSrcXOff, nSrcYOff, nSrcXSize, nSrcYSize,
@@ -879,7 +910,7 @@
             VRTAddComplexSource(hVRTBand, GDALGetRasterBand((GDALDatasetH)hProxyDS, 1),
                                 nSrcXOff, nSrcYOff, nSrcXSize, nSrcYSize,
                                 nDstXOff, nDstYOff, nDstXSize, nDstYSize,
-                                255, 0, VRT_NODATA_UNSET);
+                                255, 0, VRT_NODATA_UNSET, 0, NULL, NULL);
         }
         else if (bHasDatasetMask)
         {
@@ -970,6 +1001,60 @@
         }
     }
 
+    int nLUT_in = 0;
+    if (pszVRTLutIn != NULL)
+    {
+        if ( !EQUAL(pszVRTLutIn, "none") )
+        {
+            bAllowLUT = TRUE;
+            char **papszTokens = CSLTokenizeString( pszVRTLutIn );
+            nLUT_in = CSLCount(papszTokens);
+            padfLUTInputs = (double *) CPLMalloc(sizeof(double) * nLUT_in);
+            for(i=0;i<nLUT_in;i++)
+                padfLUTInputs[i] = CPLAtofM(papszTokens[i]);
+            CSLDestroy(papszTokens);
+        }
+    }
+
+    int nLUT_out = 0;
+    if (pszVRTLutOut != NULL)
+    {
+        if ( !EQUAL(pszVRTLutOut, "none") )
+        {
+            bAllowLUT = TRUE;
+            char **papszTokens = CSLTokenizeString( pszVRTLutOut );
+            nLUT_out = CSLCount(papszTokens);
+            padfLUTOutputs = (double *) CPLMalloc(sizeof(double) * nLUT_out);
+            for(i=0;i<nLUT_out;i++)
+                padfLUTOutputs[i] = CPLAtofM(papszTokens[i]);
+            CSLDestroy(papszTokens);
+        }
+    }
+
+    if( bAllowLUT )
+    {
+      if( nLUT_in != nLUT_out ) //LUT error
+      {
+        bAllowLUT = FALSE;
+        if(padfLUTInputs)
+        {
+            CPLFree(padfLUTInputs);
+            padfLUTInputs = NULL;
+        }
+        if(padfLUTOutputs)
+        {
+            CPLFree(padfLUTOutputs);
+            padfLUTOutputs = NULL;
+        }
+        CPLError(CE_Warning, CPLE_IllegalArg,
+                    "Ignored LUT cause lutin and lutout don't have the same number of argument.");
+      }
+      else
+      {
+        nLUTItemCount = nLUT_in;
+      }
+    }
+
     int nCountValid = 0;
     for(i=0;i<nInputFiles;i++)
     {
@@ -1180,6 +1265,8 @@
     int bHideNoData = FALSE;
     const char* pszSrcNoData = NULL;
     const char* pszVRTNoData = NULL;
+    const char* pszLUTin = NULL;
+    const char* pszLUTout = NULL;
 
     /* Check strict compilation and runtime library version as we use C++ API */
     if (! GDAL_CHECK_VERSION(papszArgv[0]))
@@ -1284,6 +1371,14 @@
         {
             pszVRTNoData = papszArgv[++iArg];
         }
+        else if ( EQUAL(papszArgv[iArg],"-lutin") && iArg + 1 < nArgc)
+        {
+            pszLUTin = papszArgv[++iArg];
+        }
+        else if ( EQUAL(papszArgv[iArg],"-lutout") && iArg + 1 < nArgc)
+        {
+            pszLUTout = papszArgv[++iArg];
+        }
         else if ( papszArgv[iArg][0] == '-' )
         {
             printf("Unrecognized option : %s\n", papszArgv[iArg]);
@@ -1377,7 +1472,7 @@
     VRTBuilder oBuilder(pszOutputFilename, nInputFiles, ppszInputFilenames,
                         eStrategy, we_res, ns_res, bTargetAlignedPixels, xmin, ymin, xmax, ymax,
                         bSeparate, bAllowProjectionDifference, bAddAlpha, bHideNoData,
-                        pszSrcNoData, pszVRTNoData);
+                        pszSrcNoData, pszVRTNoData, pszLUTin, pszLUTout);
 
     oBuilder.Build(pfnProgress, NULL);
     
Index: frmts/vrt/gdal_vrt.h
===================================================================
--- frmts/vrt/gdal_vrt.h	(revision 24486)
+++ frmts/vrt/gdal_vrt.h	(working copy)
@@ -94,7 +94,8 @@
                                                 GDALRasterBandH, 
                                                 int, int, int, int,
                                                 int, int, int, int,
-                                                double, double, double );
+                                                double, double, double,
+                                                int, double*, double* );
 CPLErr CPL_DLL CPL_STDCALL VRTAddFuncSource( VRTSourcedRasterBandH,
                                              VRTImageReadFunc,
                                              void *, double );
Index: frmts/vrt/vrtdataset.h
===================================================================
--- frmts/vrt/vrtdataset.h	(revision 24486)
+++ frmts/vrt/vrtdataset.h	(working copy)
@@ -393,7 +393,10 @@
                                      double dfScaleOff=0.0, 
                                      double dfScaleRatio=1.0,
                                      double dfNoDataValue = VRT_NODATA_UNSET,
-                                     int nColorTableComponent = 0);
+                                     int nColorTableComponent = 0,
+                                     int nLUTItemCount = 0,
+                                     const double *padfLUTInputs = NULL,
+                                     const double *padfLUTOutputs = NULL );
 
     CPLErr         AddMaskBandSource( GDALRasterBand *poSrcBand,
                                       int nSrcXOff=-1, int nSrcYOff=-1,
@@ -647,14 +650,18 @@
     virtual const char* GetType() { return "ComplexSource"; }
 
     double  LookupValue( double dfInput );
+    
+    CPLErr  SetLUT( int nNewLUTItemCount, const double *padfNewLUTInputs, const double *padfNewLUTOutputs );
 
     int            bDoScaling;
     double         dfScaleOff;
     double         dfScaleRatio;
+    int            nColorTableComponent;
+
+protected:
     double         *padfLUTInputs;
     double         *padfLUTOutputs;
     int            nLUTItemCount;
-    int            nColorTableComponent;
 };
 
 /************************************************************************/
Index: frmts/vrt/vrtsourcedrasterband.cpp
===================================================================
--- frmts/vrt/vrtsourcedrasterband.cpp	(revision 24486)
+++ frmts/vrt/vrtsourcedrasterband.cpp	(working copy)
@@ -645,7 +645,10 @@
                                                double dfScaleOff,
                                                double dfScaleRatio,
                                                double dfNoDataValue,
-                                               int nColorTableComponent)
+                                               int nColorTableComponent,
+                                               int nLUTItemCount,
+                                               const double *padfLUTInputs,
+                                               const double *padfLUTOutputs )
 
 {
 /* -------------------------------------------------------------------- */
@@ -694,6 +697,8 @@
 
     poSource->nColorTableComponent = nColorTableComponent;
 
+    poSource->SetLUT( nLUTItemCount, padfLUTInputs, padfLUTOutputs );
+
 /* -------------------------------------------------------------------- */
 /*      If we can get the associated GDALDataset, add a reference to it.*/
 /* -------------------------------------------------------------------- */
@@ -722,7 +727,10 @@
                                         int nDstXSize, int nDstYSize,
                                         double dfScaleOff, 
                                         double dfScaleRatio,
-                                        double dfNoDataValue )
+                                        double dfNoDataValue,
+                                        int nLUTItemCount,
+                                        double *padfLUTInputs,
+                                        double *padfLUTOutputs )
 {
     VALIDATE_POINTER1( hVRTBand, "VRTAddComplexSource", CE_Failure );
 
@@ -733,7 +741,9 @@
                                             nDstXOff, nDstYOff, 
                                             nDstXSize, nDstYSize,
                                             dfScaleOff, dfScaleRatio,
-                                            dfNoDataValue );
+                                            dfNoDataValue, 0,
+                                            nLUTItemCount,
+                                            padfLUTInputs, padfLUTOutputs );
 }
 
 /************************************************************************/
Index: frmts/vrt/vrtsources.cpp
===================================================================
--- frmts/vrt/vrtsources.cpp	(revision 24486)
+++ frmts/vrt/vrtsources.cpp	(working copy)
@@ -1543,6 +1543,54 @@
 }
 
 /************************************************************************/
+/*                               SetLUT()                               */
+/************************************************************************/
+
+CPLErr VRTComplexSource::SetLUT( int nNewLUTItemCount, const double *padfNewLUTInputs, const double *padfNewLUTOutputs )
+{
+  if( nNewLUTItemCount < 0  )
+  {
+    CPLError( CE_Failure, CPLE_IllegalArg, 
+              "Illegal LUT size %d, can't be negatif", 
+              nNewLUTItemCount );
+    return CE_Failure;
+  }
+  if( nNewLUTItemCount!=0 && ( !padfNewLUTInputs || !padfNewLUTOutputs ) )
+  {
+    
+    CPLError( CE_Failure, CPLE_ObjectNull, 
+              "NULL LUT pointer" );
+    return CE_Failure;
+  }
+  
+  //Reset the LUT
+  if ( padfLUTInputs ) VSIFree( padfLUTInputs );
+  if ( padfLUTOutputs ) VSIFree( padfLUTOutputs );
+  
+  nLUTItemCount = nNewLUTItemCount;
+  
+  if( !nNewLUTItemCount )
+  {
+    padfLUTInputs = NULL;
+    padfLUTOutputs = NULL;
+  }
+  else
+  {
+    padfLUTInputs = (double *)
+        CPLMalloc( sizeof(double) * nNewLUTItemCount );
+    padfLUTOutputs = (double *)
+        CPLMalloc( sizeof(double) * nNewLUTItemCount );
+    
+    memcpy( padfLUTInputs, padfNewLUTInputs,
+            sizeof(double) * nNewLUTItemCount );
+    memcpy( padfLUTOutputs, padfNewLUTOutputs,
+            sizeof(double) * nNewLUTItemCount );
+  }
+  
+  return CE_None;
+}
+
+/************************************************************************/
 /* ==================================================================== */
 /*                          VRTFuncSource                               */
 /* ==================================================================== */
