Ejemplo n.º 1
0
        protected virtual void GetPreview(Dataset dataset, Size size, Graphics g,
                                          Envelope displayBbox, ProjectionInfo mapProjection, Map map)
#endif
        {

            if (!NeedRotation(dataset))
            {
                GetNonRotatedPreview(dataset, size, g, displayBbox, mapProjection);
                return;
            }

            var geoTransform = new GeoTransform(dataset);
            
            Bitmap bitmap = null;
            var bitmapTL = new Point();

            //Coordinate imageTL = new Coordinate(), imageBR = new Coordinate();
            //int bitmapWidth, bitmapHeight;
            var bitmapSize = new Size();

            const int pixelSize = 3; //Format24bppRgb = byte[b,g,r] 

            if (dataset != null)
            {
                //check if image is in bounding box
                if ((displayBbox.MinX > _envelope.MaxX) || (displayBbox.MaxX < _envelope.MinX)
                    || (displayBbox.MaxY < _envelope.MinY) || (displayBbox.MinY > _envelope.MaxY))
                    return;

                // init histo
                Histogram = new List<int[]>();
                for (int i = 0; i < Bands + 1; i++)
                    Histogram.Add(new int[256]);

                // bounds of section of image to be displayed
                //var left = Math.Max(displayBbox.MinX, _envelope.MinX);
                //var top = Math.Min(displayBbox.MaxY, _envelope.MaxY);
                //var right = Math.Min(displayBbox.MaxX, _envelope.MaxX);
                //var bottom = Math.Max(displayBbox.MinY, _envelope.MinY);

                var trueImageBbox = displayBbox.Intersection(_envelope);

                // put display bounds into current projection
                Envelope shownImageBbox;
                if (Transform != null)
                {
#if !DotSpatialProjections
                    Transform.MathTransform.Invert();
                    shownImageBbox = GeometryTransform.TransformBox(trueImageBbox, Transform.MathTransform);
                    Transform.MathTransform.Invert();
#else
                    shownImageBbox = GeometryTransform.TransformBox(trueImageBbox, _transform.Source, _transform.Target);
#endif
                }
                else
                {
                    shownImageBbox = trueImageBbox;
                }

                // find min/max x and y pixels needed from image
                var g2i = geoTransform.GroundToImage(shownImageBbox).Intersection(new Envelope(0, _imageSize.Width, 0, _imageSize.Height));
                var gdalImageRect = ToRectangle(g2i);
                var displayImageSize = gdalImageRect.Size;

                //// find ground coordinates of image pixels
                //var groundBR = geoTransform.ImageToGround(imageBR);
                //var groundTL = geoTransform.ImageToGround(imageTL);

                // convert ground coordinates to map coordinates to figure out where to place the bitmap
                var bitmapBR = new Point((int)map.WorldToImage(trueImageBbox.BottomRight()).X + 1,
                                         (int)map.WorldToImage(trueImageBbox.BottomRight()).Y + 1);
                bitmapTL = new Point((int)map.WorldToImage(trueImageBbox.TopLeft()).X,
                                     (int)map.WorldToImage(trueImageBbox.TopLeft()).Y);

                bitmapSize.Width = bitmapBR.X - bitmapTL.X;
                bitmapSize.Height = bitmapBR.Y - bitmapTL.Y;

                // check to see if image is on its side
                if (bitmapSize.Width > bitmapSize.Height && displayImageSize.Width < displayImageSize.Height)
                {
                    displayImageSize.Width = bitmapSize.Height;
                    displayImageSize.Height = bitmapSize.Width;
                }
                else
                {
                    displayImageSize.Width = bitmapSize.Width;
                    displayImageSize.Height = bitmapSize.Height;
                }

                // scale
                var bitScalar = GetBitScalar();

                // 0 pixels in length or height, nothing to display
                if (bitmapSize.Width < 1 || bitmapSize.Height < 1)
                    return;

                //initialize bitmap
                BitmapData bitmapData;
                bitmap = InitializeBitmap(bitmapSize, PixelFormat.Format24bppRgb, out bitmapData);
                
                /*
                bitmap = new Bitmap(bitmapLength, bitmapHeight, PixelFormat.Format24bppRgb);
                BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmapLength, bitmapHeight),
                                                        ImageLockMode.ReadWrite, bitmap.PixelFormat);
                 */
                try
                {
                    unsafe
                    {
                        var cr = _noDataInitColor.R;
                        var cg = _noDataInitColor.G;
                        var cb = _noDataInitColor.B;

                        /* functionality moved to InitializeBitmap
                        // turn everything to _noDataInitColor, so we can make fill transparent

                        for (int y = 0; y < bitmapHeight; y++)
                        {
                            byte* brow = (byte*)bitmapData.Scan0 + (y * bitmapData.Stride);
                            for (int x = 0; x < bitmapLength; x++)
                            {
                                Int32 offsetX = x * 3;
                                brow[offsetX++] = cb;
                                brow[offsetX++] = cg;
                                brow[offsetX] = cr;
                            }
                        }
                        */


                        // create 3 dimensional buffer [band][x pixel][y pixel]
                        //var tempBuffer = new double[Bands][];
                        var buffer = new double[Bands][][];
                        for (int i = 0; i < Bands; i++)
                        {
                            buffer[i] = new double[displayImageSize.Width][];
                            for (var j = 0; j < displayImageSize.Width; j++)
                                buffer[i][j] = new double[displayImageSize.Height];
                        }

                        //Band[] band = new Band[Bands];
                        var ch = new int[Bands];

                        //
                        var noDataValues = new Double[Bands];
                        var scales = new Double[Bands];
                        ColorTable colorTable = null;

                        var imageRect = gdalImageRect;

                        ColorBlend colorBlend = null;
                        var intermediateValue = new double[Bands];

                        // get data from image
                        for (var i = 0; i < Bands; i++)
                        {
                            using (var band = dataset.GetRasterBand(i + 1))
                            {
                                int hasVal;

                                //get nodata value if present
                                band.GetNoDataValue(out noDataValues[i], out hasVal);
                                if (hasVal == 0) noDataValues[i] = Double.NaN;
                                
                                //Get the scale value if present
                                band.GetScale(out scales[i], out hasVal);
                                if (hasVal == 0) scales[i] = 1.0;

                                switch (band.GetRasterColorInterpretation())
                                {
                                    case ColorInterp.GCI_BlueBand:
                                        ch[i] = 0;
                                        break;
                                    case ColorInterp.GCI_GreenBand:
                                        ch[i] = 1;
                                        break;
                                    case ColorInterp.GCI_RedBand:
                                        ch[i] = 2;
                                        break;
                                    case ColorInterp.GCI_Undefined:
                                        if (Bands > 1)
                                            ch[i] = 3; // infrared
                                        else
                                        {
                                            ch[i] = 4;
                                            colorBlend = GetColorBlend(band);
                                            intermediateValue = new Double[3];
                                        }
                                        break;
                                    case ColorInterp.GCI_GrayIndex:
                                        ch[i] = 0;
                                        break;
                                    case ColorInterp.GCI_PaletteIndex:
                                        if (colorTable != null)
                                        {
                                            //this should not happen
                                            colorTable.Dispose();
                                        }
                                        colorTable = band.GetRasterColorTable();
                                        ch[i] = 5;
                                        intermediateValue = new Double[3];
                                        break;
                                    default:
                                        ch[i] = -1;
                                        break;
                                }
                            }
                        }

                        // store these values to keep from having to make slow method calls
                        var bitmapTLX = bitmapTL.X;
                        var bitmapTLY = bitmapTL.Y;
                        double imageTop = g2i.MinY;
                        double imageLeft = g2i.MinX;
                        double dblMapPixelWidth = map.PixelWidth;
                        double dblMapPixelHeight = map.PixelHeight;
                        double dblMapMinX = map.Envelope.MinX;
                        double dblMapMaxY = map.Envelope.MaxY;

                        // get inverse values
                        var geoTop = geoTransform.Inverse[3];
                        var geoLeft = geoTransform.Inverse[0];
                        var geoHorzPixRes = geoTransform.Inverse[1];
                        var geoVertPixRes = geoTransform.Inverse[5];
                        var geoXRot = geoTransform.Inverse[2];
                        var geoYRot = geoTransform.Inverse[4];

                        var dblXScale = (g2i.Width) / (displayImageSize.Width - 1);
                        var dblYScale = (g2i.Height) / (displayImageSize.Height - 1);

                        // get inverse transform  
                        // NOTE: calling transform.MathTransform.Inverse() once and storing it
                        // is much faster than having to call every time it is needed
#if !DotSpatialProjections
                        IMathTransform inverseTransform = null;
                        if (Transform != null)
                            inverseTransform = Transform.MathTransform.Inverse();
#endif

                        var rowsRead = 0;
                        var displayImageStep = displayImageSize.Height;
                        while (rowsRead < displayImageSize.Height)
                        {
                            var rowsToRead = displayImageStep;
                            if (rowsRead + rowsToRead > displayImageSize.Height)
                                rowsToRead = displayImageSize.Height - rowsRead;

                            var tempBuffer = new double[displayImageSize.Width * rowsToRead];
                            for (var i = 0; i < Bands; i++)
                            {
                                // read the buffer
                                using (var band = dataset.GetRasterBand(i + 1))
                                {
                                    band.ReadRaster(imageRect.Left, imageRect.Top,
                                                    imageRect.Width, imageRect.Height,
                                                    tempBuffer, displayImageSize.Width, rowsToRead, 0, 0);
                                }

                                // parse temp buffer into the image x y value buffer
                                long pos = 0;
                                var newRowsRead = rowsRead + rowsToRead;
                                for (var y = rowsRead; y < newRowsRead; y++)
                                {
                                    for (var x = 0; x < displayImageSize.Width; x++)
                                    {
                                        buffer[i][x][y] = tempBuffer[pos++];
                                    }
                                }
                            }
                            rowsRead = rowsRead + rowsToRead;

                            for (var pixY = 0d; pixY < bitmapBR.Y - bitmapTL.Y; pixY++)
                            {
                                var row = (byte*) bitmapData.Scan0 + ((int) Math.Round(pixY)*bitmapData.Stride);

                                for (var pixX = 0; pixX < bitmapBR.X - bitmapTL.X; pixX++)
                                {
                                    // same as Map.ImageToGround(), but much faster using stored values...rather than called each time
                                    var gndX = dblMapMinX + (pixX + bitmapTLX)*dblMapPixelWidth;
                                    var gndY = dblMapMaxY - (pixY + bitmapTLY)*dblMapPixelHeight;

                                    // transform ground point if needed
                                    if (Transform != null)
                                    {
#if !DotSpatialProjections
                                        var dblPoint = inverseTransform.Transform(new[] {gndX, gndY});
#else
                                    dblPoint = new double[] { GndX, GndY };
                                    Reproject.ReprojectPoints(dblPoint, null, _transform.Source, _transform.Target, 0, 1);
#endif
                                        gndX = dblPoint[0];
                                        gndY = dblPoint[1];
                                    }

                                    // same as GeoTransform.GroundToImage(), but much faster using stored values...
                                    var imageCoord = new Coordinate(
                                        geoLeft + geoHorzPixRes*gndX + geoXRot*gndY,
                                        geoTop + geoYRot*gndX + geoVertPixRes*gndY);

                                    if (!g2i.Contains(imageCoord)) 
                                        continue;

                                    var imagePt = new Point((int)((imageCoord.X - imageLeft) / dblXScale),
                                                            (int)((imageCoord.Y - imageTop) / dblYScale));

                                    // Apply color correction
                                    for (var i = 0; i < Bands; i++)
                                    {
                                        intermediateValue[i] = buffer[i][imagePt.X][imagePt.Y];

                                        // apply scale
                                        intermediateValue[i] *= scales[i];

                                        double spotVal;
                                        var imageVal = spotVal = intermediateValue[i] = intermediateValue[i]/bitScalar;

                                        if (ch[i] == 4)
                                        {
                                            if (imageVal != noDataValues[i])
                                            {
                                                var color = colorBlend.GetColor(Convert.ToSingle(imageVal));
                                                intermediateValue[0] = color.B;
                                                intermediateValue[1] = color.G;
                                                intermediateValue[2] = color.R;
                                                //intVal[3] = ce.c4;
                                            }
                                            else
                                            {
                                                intermediateValue[0] = cb;
                                                intermediateValue[1] = cg;
                                                intermediateValue[2] = cr;
                                            }
                                        }

                                        else if (ch[i] == 5 && colorTable != null)
                                        {
                                            if (imageVal != noDataValues[i])
                                            {
                                                using (var ce = colorTable.GetColorEntry(Convert.ToInt32(imageVal)))
                                                {
                                                    intermediateValue[0] = ce.c3;
                                                    intermediateValue[1] = ce.c2;
                                                    intermediateValue[2] = ce.c1;
                                                    //intVal[3] = ce.c4;
                                                }

                                            }
                                            else
                                            {
                                                intermediateValue[0] = cb;
                                                intermediateValue[1] = cg;
                                                intermediateValue[2] = cr;
                                            }
                                        }

                                        else
                                        {

                                            if (ColorCorrect)
                                            {
                                                intermediateValue[i] = ApplyColorCorrection(imageVal, spotVal, ch[i],
                                                                                            gndX,
                                                                                            gndY);

                                                // if pixel is within ground boundary, add its value to the histogram
                                                if (ch[i] != -1 && intermediateValue[i] > 0 &&
                                                    (HistoBounds.Bottom >= (int) gndY) &&
                                                    HistoBounds.Top <= (int) gndY &&
                                                    HistoBounds.Left <= (int) gndX && HistoBounds.Right >= (int) gndX)
                                                {
                                                    Histogram[ch[i]][(int) intermediateValue[i]]++;
                                                }
                                            }

                                            if (intermediateValue[i] > 255)
                                                intermediateValue[i] = 255;
                                        }
                                    }

                                    // luminosity
                                    if (Bands >= 3)
                                        Histogram[Bands][
                                            (int)
                                            (intermediateValue[2]*0.2126 + intermediateValue[1]*0.7152 +
                                             intermediateValue[0]*0.0722)]
                                            ++;

                                    WritePixel(pixX, intermediateValue, pixelSize, ch, row);
                                }
                            }
                        }

                        if (colorTable != null)
                        {
                            colorTable.Dispose();
                        }
                    }
                }

                finally
                {
                    bitmap.UnlockBits(bitmapData);
                }
            }

            //using (var ia = new ImageAttributes())
            //{
            //    var colorMap = new[]
            //        {
            //            new ColorMap {OldColor = _noDataInitColor, NewColor = Color.Transparent},
            //            new ColorMap {OldColor = TransparentColor, NewColor = Color.Transparent}
            //        }; 
            //    
            //    ia.SetRemapTable(colorMap, ColorAdjustType.Bitmap);
                bitmap.MakeTransparent(_noDataInitColor);
                if (TransparentColor != Color.Empty)
                    bitmap.MakeTransparent(TransparentColor);
                g.DrawImage(bitmap, bitmapTL);
            //}
        }
Ejemplo n.º 2
0
        private void ExecuteIntersectionQuery(Coordinate pt, FeatureDataSet ds)
        {

            if (CoordinateTransformation != null)
            {
#if !DotSpatialProjections
                if (ReverseCoordinateTransformation != null)
                {
                    pt = GeometryTransform.TransformCoordinate(pt, ReverseCoordinateTransformation.MathTransform);
                }
                else
                {
                    CoordinateTransformation.MathTransform.Invert();
                    pt = GeometryTransform.TransformCoordinate(pt, CoordinateTransformation.MathTransform);
                    CoordinateTransformation.MathTransform.Invert();
                }
#else
                pt = GeometryTransform.TransformCoordinate(pt, 
                    CoordinateTransformation.Target, 
                    CoordinateTransformation.Source);
#endif
            }
            
            //Setup resulting Table
            var dt = new FeatureDataTable();
            dt.Columns.Add("Ordinate X", typeof(Double));
            dt.Columns.Add("Ordinate Y", typeof(Double));
            for (int i = 1; i <= Bands; i++)
                dt.Columns.Add(string.Format("Value Band {0}", i), typeof(Double));

            //Get location on raster
            Double[] buffer = new double[1];
            Int32[] bandMap = new int[Bands];
            for (int i = 1; i <= Bands; i++) bandMap[i - 1] = i;

            var geoTransform = new GeoTransform(_gdalDataset);
            var imgPt = geoTransform.GroundToImage(pt);
            Int32 x = Convert.ToInt32(imgPt.X);
            Int32 y = Convert.ToInt32(imgPt.Y);

            //Test if raster ordinates are within bounds
            if (x < 0) return;
            if (y < 0) return;
            if (x >= _imageSize.Width) return;
            if (y >= _imageSize.Height) return;

            //Create new row, add ordinates and location geometry
            FeatureDataRow dr = dt.NewRow();
            dr.Geometry = Factory.CreatePoint(pt);
            dr[0] = pt.X;
            dr[1] = pt.Y;

            //Add data from raster
            for (int i = 1; i <= Bands; i++)
            {
                Band band = _gdalDataset.GetRasterBand(i);
                //DataType dtype = band.DataType;
                CPLErr res = band.ReadRaster(x, y, 1, 1, buffer, 1, 1, 0, 0);
                if (res == CPLErr.CE_None)
                {
                    dr[1 + i] = buffer[0];
                }
                else
                {
                    dr[1 + i] = Double.NaN;
                }
            }
            //Add new row to table
            dt.Rows.Add(dr);

            //Add table to dataset
            ds.Tables.Add(dt);
        }
Ejemplo n.º 3
0
        protected virtual void GetPreview(Dataset dataset, Size size, Graphics g,
                                          BoundingBox displayBbox, ProjectionInfo mapProjection, Map map)
#endif
        {
            double[] geoTrans = new double[6];
            _gdalDataset.GetGeoTransform(geoTrans);

            // not rotated, use faster display method
            if ((!_useRotation ||
                 (geoTrans[1] == 1 && geoTrans[2] == 0 && geoTrans[4] == 0 && Math.Abs(geoTrans[5]) == 1))
                && !_haveSpot && _transform == null)
            {
                GetNonRotatedPreview(dataset, size, g, displayBbox, mapProjection);
                return;
            }
            // not rotated, but has spot...need default rotation
            else if ((geoTrans[0] == 0 && geoTrans[3] == 0) && _haveSpot)
                geoTrans = new[] { 999.5, 1, 0, 1000.5, 0, -1 };

            _geoTransform = new GeoTransform(geoTrans);
            double DsWidth = _imagesize.Width;
            double DsHeight = _imagesize.Height;
            double left, top, right, bottom;
            double GndX = 0, GndY = 0, ImgX = 0, ImgY = 0, PixX, PixY;
            double[] intVal = new double[Bands];
            double imageVal = 0, SpotVal = 0;
            double bitScalar = 1.0;
            Bitmap bitmap = null;
            Point bitmapTL = new Point(), bitmapBR = new Point();
            Geometries.Point imageTL = new Geometries.Point(), imageBR = new Geometries.Point();
            BoundingBox shownImageBbox, trueImageBbox;
            int bitmapLength, bitmapHeight;
            int displayImageLength, displayImageHeight;

            int iPixelSize = 3; //Format24bppRgb = byte[b,g,r] 

            if (dataset != null)
            {
                //check if image is in bounding box
                if ((displayBbox.Left > _envelope.Right) || (displayBbox.Right < _envelope.Left)
                    || (displayBbox.Top < _envelope.Bottom) || (displayBbox.Bottom > _envelope.Top))
                    return;

                // init histo
                _histogram = new List<int[]>();
                for (int i = 0; i < _lbands + 1; i++)
                    _histogram.Add(new int[256]);

                // bounds of section of image to be displayed
                left = Math.Max(displayBbox.Left, _envelope.Left);
                top = Math.Min(displayBbox.Top, _envelope.Top);
                right = Math.Min(displayBbox.Right, _envelope.Right);
                bottom = Math.Max(displayBbox.Bottom, _envelope.Bottom);

                trueImageBbox = new BoundingBox(left, bottom, right, top);

                // put display bounds into current projection
                if (_transform != null)
                {
#if !DotSpatialProjections
                    _transform.MathTransform.Invert();
                    shownImageBbox = GeometryTransform.TransformBox(trueImageBbox, _transform.MathTransform);
                    _transform.MathTransform.Invert();
#else
                    shownImageBbox = GeometryTransform.TransformBox(trueImageBbox, _transform.Source, _transform.Target);
#endif
                }
                else
                    shownImageBbox = trueImageBbox;

                // find min/max x and y pixels needed from image
                imageBR.X =
                    (int)
                    (Math.Max(_geoTransform.GroundToImage(shownImageBbox.TopLeft).X,
                              Math.Max(_geoTransform.GroundToImage(shownImageBbox.TopRight).X,
                                       Math.Max(_geoTransform.GroundToImage(shownImageBbox.BottomLeft).X,
                                                _geoTransform.GroundToImage(shownImageBbox.BottomRight).X))) + 1);
                imageBR.Y =
                    (int)
                    (Math.Max(_geoTransform.GroundToImage(shownImageBbox.TopLeft).Y,
                              Math.Max(_geoTransform.GroundToImage(shownImageBbox.TopRight).Y,
                                       Math.Max(_geoTransform.GroundToImage(shownImageBbox.BottomLeft).Y,
                                                _geoTransform.GroundToImage(shownImageBbox.BottomRight).Y))) + 1);
                imageTL.X =
                    (int)
                    Math.Min(_geoTransform.GroundToImage(shownImageBbox.TopLeft).X,
                             Math.Min(_geoTransform.GroundToImage(shownImageBbox.TopRight).X,
                                      Math.Min(_geoTransform.GroundToImage(shownImageBbox.BottomLeft).X,
                                               _geoTransform.GroundToImage(shownImageBbox.BottomRight).X)));
                imageTL.Y =
                    (int)
                    Math.Min(_geoTransform.GroundToImage(shownImageBbox.TopLeft).Y,
                             Math.Min(_geoTransform.GroundToImage(shownImageBbox.TopRight).Y,
                                      Math.Min(_geoTransform.GroundToImage(shownImageBbox.BottomLeft).Y,
                                               _geoTransform.GroundToImage(shownImageBbox.BottomRight).Y)));

                // stay within image
                if (imageBR.X > _imagesize.Width)
                    imageBR.X = _imagesize.Width;
                if (imageBR.Y > _imagesize.Height)
                    imageBR.Y = _imagesize.Height;
                if (imageTL.Y < 0)
                    imageTL.Y = 0;
                if (imageTL.X < 0)
                    imageTL.X = 0;

                displayImageLength = (int)(imageBR.X - imageTL.X);
                displayImageHeight = (int)(imageBR.Y - imageTL.Y);

                // find ground coordinates of image pixels
                Geometries.Point groundBR = _geoTransform.ImageToGround(imageBR);
                Geometries.Point groundTL = _geoTransform.ImageToGround(imageTL);

                // convert ground coordinates to map coordinates to figure out where to place the bitmap
                bitmapBR = new Point((int)map.WorldToImage(trueImageBbox.BottomRight).X + 1,
                                     (int)map.WorldToImage(trueImageBbox.BottomRight).Y + 1);
                bitmapTL = new Point((int)map.WorldToImage(trueImageBbox.TopLeft).X,
                                     (int)map.WorldToImage(trueImageBbox.TopLeft).Y);

                bitmapLength = bitmapBR.X - bitmapTL.X;
                bitmapHeight = bitmapBR.Y - bitmapTL.Y;

                // check to see if image is on its side
                if (bitmapLength > bitmapHeight && displayImageLength < displayImageHeight)
                {
                    displayImageLength = bitmapHeight;
                    displayImageHeight = bitmapLength;
                }
                else
                {
                    displayImageLength = bitmapLength;
                    displayImageHeight = bitmapHeight;
                }

                // scale
                if (_bitDepth == 12)
                    bitScalar = 16.0;
                else if (_bitDepth == 16)
                    bitScalar = 256.0;
                else if (_bitDepth == 32)
                    bitScalar = 16777216.0;

                // 0 pixels in length or height, nothing to display
                if (bitmapLength < 1 || bitmapHeight < 1)
                    return;

                //initialize bitmap
                bitmap = new Bitmap(bitmapLength, bitmapHeight, PixelFormat.Format24bppRgb);
                BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmapLength, bitmapHeight),
                                                        ImageLockMode.ReadWrite, bitmap.PixelFormat);

                try
                {
                    unsafe
                    {
                        // turn everything to _noDataInitColor, so we can make fill transparent
                        byte cr = _noDataInitColor.R;
                        byte cg = _noDataInitColor.G;
                        byte cb = _noDataInitColor.B;

                        for (int y = 0; y < bitmapHeight; y++)
                        {
                            byte* brow = (byte*)bitmapData.Scan0 + (y * bitmapData.Stride);
                            for (int x = 0; x < bitmapLength; x++)
                            {
                                Int32 offsetX = x * 3;
                                brow[offsetX++] = cb;
                                brow[offsetX++] = cg;
                                brow[offsetX] = cr;
                            }
                        }

                        // create 3 dimensional buffer [band][x pixel][y pixel]
                        double[][] tempBuffer = new double[Bands][];
                        double[][][] buffer = new double[Bands][][];
                        for (int i = 0; i < Bands; i++)
                        {
                            buffer[i] = new double[displayImageLength][];
                            for (int j = 0; j < displayImageLength; j++)
                                buffer[i][j] = new double[displayImageHeight];
                        }

                        Band[] band = new Band[Bands];
                        int[] ch = new int[Bands];

                        //
                        Double[] noDataValues = new Double[Bands];
                        Double[] scales = new Double[Bands];
                        ColorTable colorTable = null;


                        // get data from image
                        for (int i = 0; i < Bands; i++)
                        {
                            tempBuffer[i] = new double[displayImageLength * displayImageHeight];
                            band[i] = dataset.GetRasterBand(i + 1);

                            //get nodata value if present
                            Int32 hasVal = 0;
                            band[i].GetNoDataValue(out noDataValues[i], out hasVal);
                            if (hasVal == 0) noDataValues[i] = Double.NaN;
                            band[i].GetScale(out scales[i], out hasVal);
                            if (hasVal == 0) scales[i] = 1.0;

                            band[i].ReadRaster(
                                (int)imageTL.X,
                                (int)imageTL.Y,
                                (int)(imageBR.X - imageTL.X),
                                (int)(imageBR.Y - imageTL.Y),
                                tempBuffer[i], displayImageLength, displayImageHeight, 0, 0);

                            // parse temp buffer into the image x y value buffer
                            long pos = 0;
                            for (int y = 0; y < displayImageHeight; y++)
                            {
                                for (int x = 0; x < displayImageLength; x++, pos++)
                                    buffer[i][x][y] = tempBuffer[i][pos];
                            }

                            if (band[i].GetRasterColorInterpretation() == ColorInterp.GCI_BlueBand) ch[i] = 0;
                            else if (band[i].GetRasterColorInterpretation() == ColorInterp.GCI_GreenBand) ch[i] = 1;
                            else if (band[i].GetRasterColorInterpretation() == ColorInterp.GCI_RedBand) ch[i] = 2;
                            else if (band[i].GetRasterColorInterpretation() == ColorInterp.GCI_Undefined)
                            {
                                if (Bands > 1)
                                    ch[i] = 3; // infrared
                                else
                                {
                                    ch[i] = 4;
                                    if (_colorBlend == null)
                                    {
                                        Double dblMin, dblMax;
                                        band[i].GetMinimum(out dblMin, out hasVal);
                                        if (hasVal == 0) dblMin = Double.NaN;
                                        band[i].GetMaximum(out dblMax, out hasVal);
                                        if (hasVal == 0) dblMax = double.NaN;
                                        if (Double.IsNaN(dblMin) || Double.IsNaN(dblMax))
                                        {
                                            double dblMean, dblStdDev;
                                            band[i].GetStatistics(0, 1, out dblMin, out dblMax, out dblMean, out dblStdDev);
                                            //double dblRange = dblMax - dblMin;
                                            //dblMin -= 0.1*dblRange;
                                            //dblMax += 0.1*dblRange;
                                        }
                                        Single[] minmax = new float[] { Convert.ToSingle(dblMin), 0.5f * Convert.ToSingle(dblMin + dblMax), Convert.ToSingle(dblMax) };
                                        Color[] colors = new Color[] { Color.Blue, Color.Yellow, Color.Red };
                                        _colorBlend = new ColorBlend(colors, minmax);
                                    }
                                    intVal = new Double[3];
                                }
                            }
                            else if (band[i].GetRasterColorInterpretation() == ColorInterp.GCI_GrayIndex) ch[i] = 0;
                            else if (band[i].GetRasterColorInterpretation() == ColorInterp.GCI_PaletteIndex)
                            {
                                colorTable = band[i].GetRasterColorTable();
                                ch[i] = 5;
                                intVal = new Double[3];
                            }
                            else ch[i] = -1;
                        }

                        // store these values to keep from having to make slow method calls
                        int bitmapTLX = bitmapTL.X;
                        int bitmapTLY = bitmapTL.Y;
                        double imageTop = imageTL.Y;
                        double imageLeft = imageTL.X;
                        double dblMapPixelWidth = map.PixelWidth;
                        double dblMapPixelHeight = map.PixelHeight;
                        double dblMapMinX = map.Envelope.Min.X;
                        double dblMapMaxY = map.Envelope.Max.Y;
                        double geoTop, geoLeft, geoHorzPixRes, geoVertPixRes, geoXRot, geoYRot;

                        // get inverse values
                        geoTop = _geoTransform.Inverse[3];
                        geoLeft = _geoTransform.Inverse[0];
                        geoHorzPixRes = _geoTransform.Inverse[1];
                        geoVertPixRes = _geoTransform.Inverse[5];
                        geoXRot = _geoTransform.Inverse[2];
                        geoYRot = _geoTransform.Inverse[4];

                        double dblXScale = (imageBR.X - imageTL.X) / (displayImageLength - 1);
                        double dblYScale = (imageBR.Y - imageTL.Y) / (displayImageHeight - 1);
                        double[] dblPoint;

                        // get inverse transform  
                        // NOTE: calling transform.MathTransform.Inverse() once and storing it
                        // is much faster than having to call every time it is needed
#if !DotSpatialProjections
                        IMathTransform inverseTransform = null;
                        if (_transform != null)
                            inverseTransform = _transform.MathTransform.Inverse();
#endif

                        for (PixY = 0; PixY < bitmapBR.Y - bitmapTL.Y; PixY++)
                        {
                            byte* row = (byte*)bitmapData.Scan0 + ((int)Math.Round(PixY) * bitmapData.Stride);

                            for (PixX = 0; PixX < bitmapBR.X - bitmapTL.X; PixX++)
                            {
                                // same as Map.ImageToGround(), but much faster using stored values...rather than called each time
                                GndX = dblMapMinX + (PixX + bitmapTLX) * dblMapPixelWidth;
                                GndY = dblMapMaxY - (PixY + bitmapTLY) * dblMapPixelHeight;

                                // transform ground point if needed
                                if (_transform != null)
                                {
#if !DotSpatialProjections
                                    dblPoint = inverseTransform.Transform(new[] { GndX, GndY });
#else
                                    dblPoint = new double[] { GndX, GndY };
                                    Reproject.ReprojectPoints(dblPoint, null, _transform.Source, _transform.Target, 0, 1);
#endif
                                    GndX = dblPoint[0];
                                    GndY = dblPoint[1];
                                }

                                // same as GeoTransform.GroundToImage(), but much faster using stored values...
                                ImgX = (geoLeft + geoHorzPixRes * GndX + geoXRot * GndY);
                                ImgY = (geoTop + geoYRot * GndX + geoVertPixRes * GndY);

                                if (ImgX < imageTL.X || ImgX > imageBR.X || ImgY < imageTL.Y || ImgY > imageBR.Y)
                                    continue;

                                // color correction
                                for (int i = 0; i < Bands; i++)
                                {
                                    intVal[i] =
                                        buffer[i][(int)((ImgX - imageLeft) / dblXScale)][
                                            (int)((ImgY - imageTop) / dblYScale)];

                                    imageVal = SpotVal = intVal[i] = intVal[i] / bitScalar;
                                    if (ch[i] == 4)
                                    {
                                        if (imageVal != noDataValues[i])
                                        {
                                            Color color = _colorBlend.GetColor(Convert.ToSingle(imageVal));
                                            intVal[0] = color.B;
                                            intVal[1] = color.G;
                                            intVal[2] = color.R;
                                            //intVal[3] = ce.c4;
                                        }
                                        else
                                        {
                                            intVal[0] = cb;
                                            intVal[1] = cg;
                                            intVal[2] = cr;
                                        }
                                    }

                                    else if (ch[i] == 5 && colorTable != null)
                                    {
                                        if (imageVal != noDataValues[i])
                                        {
                                            ColorEntry ce = colorTable.GetColorEntry(Convert.ToInt32(imageVal));
                                            intVal[0] = ce.c3;
                                            intVal[1] = ce.c2;
                                            intVal[2] = ce.c1;
                                            //intVal[3] = ce.c4;
                                        }
                                        else
                                        {
                                            intVal[0] = cb;
                                            intVal[1] = cg;
                                            intVal[2] = cr;
                                        }
                                    }

                                    else
                                    {

                                        if (_colorCorrect)
                                        {
                                            intVal[i] = ApplyColorCorrection(imageVal, SpotVal, ch[i], GndX, GndY);

                                            // if pixel is within ground boundary, add its value to the histogram
                                            if (ch[i] != -1 && intVal[i] > 0 && (_histoBounds.Bottom >= (int)GndY) &&
                                                _histoBounds.Top <= (int)GndY &&
                                                _histoBounds.Left <= (int)GndX && _histoBounds.Right >= (int)GndX)
                                            {
                                                _histogram[ch[i]][(int)intVal[i]]++;
                                            }
                                        }

                                        if (intVal[i] > 255)
                                            intVal[i] = 255;
                                    }
                                }

                                // luminosity
                                if (_lbands >= 3)
                                    _histogram[_lbands][(int)(intVal[2] * 0.2126 + intVal[1] * 0.7152 + intVal[0] * 0.0722)]
                                        ++;

                                WritePixel(PixX, intVal, iPixelSize, ch, row);
                            }
                        }
                    }
                }

                finally
                {
                    bitmap.UnlockBits(bitmapData);
                }
            }
            bitmap.MakeTransparent(_noDataInitColor);
            if (_transparentColor != Color.Empty)
                bitmap.MakeTransparent(_transparentColor);
            g.DrawImage(bitmap, new Point(bitmapTL.X, bitmapTL.Y));
        }
Ejemplo n.º 4
0
        protected virtual void GetPreview(Dataset dataset, Size size, Graphics g,
                                          Envelope displayBbox, ProjectionInfo mapProjection, Map map)
#endif
        {
            DateTime drawStart = DateTime.Now;
            double totalReadDataTime = 0;
            double totalTimeSetPixel = 0;

            if (!NeedRotation(dataset))
            {
                GetNonRotatedPreview(dataset, size, g, displayBbox, mapProjection);
                return;
            }

            var geoTransform = new GeoTransform(dataset);
            
            Bitmap bitmap = null;
            var bitmapTl = new Point();
            var bitmapSize = new Size();

            const int pixelSize = 3; //Format24bppRgb = byte[b,g,r] 

            if (dataset != null)
            {
                //check if image is in bounding box
                if ((displayBbox.MinX > _envelope.MaxX) || (displayBbox.MaxX < _envelope.MinX)
                    || (displayBbox.MaxY < _envelope.MinY) || (displayBbox.MinY > _envelope.MaxY))
                    return;

                // init histo
                Histogram = new List<int[]>();
                for (int i = 0; i < Bands + 1; i++)
                    Histogram.Add(new int[256]);

                var trueImageBbox = displayBbox.Intersection(_envelope);

                // put display bounds into current projection
                Envelope shownImageBbox = trueImageBbox;
#if !DotSpatialProjections
                if (ReverseCoordinateTransformation != null)
                {
                    shownImageBbox = GeometryTransform.TransformBox(trueImageBbox, ReverseCoordinateTransformation.MathTransform);
                }
#else
                if (CoordinateTransformation != null)
                {
                    shownImageBbox = GeometryTransform.TransformBox(trueImageBbox,
                        CoordinateTransformation.Target, CoordinateTransformation.Source);
                }
#endif

                // find min/max x and y pixels needed from image
                var g2I = geoTransform.GroundToImage(shownImageBbox).Intersection(new Envelope(0, _imageSize.Width, 0, _imageSize.Height));
                var gdalImageRect = ToRectangle(g2I);
                var displayImageSize = gdalImageRect.Size;

                // convert ground coordinates to map coordinates to figure out where to place the bitmap
                var bitmapBr = new Point((int)map.WorldToImage(trueImageBbox.BottomRight()).X + 1,
                                         (int)map.WorldToImage(trueImageBbox.BottomRight()).Y + 1);
                bitmapTl = new Point((int)map.WorldToImage(trueImageBbox.TopLeft()).X,
                                     (int)map.WorldToImage(trueImageBbox.TopLeft()).Y);

                bitmapSize.Width = bitmapBr.X - bitmapTl.X;
                bitmapSize.Height = bitmapBr.Y - bitmapTl.Y;

                // check to see if image is on its side
                if (bitmapSize.Width > bitmapSize.Height && displayImageSize.Width < displayImageSize.Height)
                {
                    displayImageSize.Width = bitmapSize.Height;
                    displayImageSize.Height = bitmapSize.Width;
                }
                else
                {
                    displayImageSize.Width = bitmapSize.Width;
                    displayImageSize.Height = bitmapSize.Height;
                }

                // scale
                var bitScalar = GetBitScalar();

                // 0 pixels in length or height, nothing to display
                if (bitmapSize.Width < 1 || bitmapSize.Height < 1)
                    return;

                //initialize bitmap
                BitmapData bitmapData;
                bitmap = InitializeBitmap(bitmapSize, PixelFormat.Format24bppRgb, out bitmapData);
                
                try
                {
                    unsafe
                    {
                        var cr = _noDataInitColor.R;
                        var cg = _noDataInitColor.G;
                        var cb = _noDataInitColor.B;


                        // create 3 dimensional buffer [band][x pixel][y pixel]
                        var buffer = new double[Bands][][];
                        for (int i = 0; i < Bands; i++)
                        {
                            buffer[i] = new double[displayImageSize.Width][];
                            for (var j = 0; j < displayImageSize.Width; j++)
                                buffer[i][j] = new double[displayImageSize.Height];
                        }

                        var ch = new int[Bands];

                        var noDataValues = new Double[Bands];
                        var scales = new Double[Bands];
                        ColorTable colorTable = null;
                        short[][] colorTableCache = null;

                        var imageRect = gdalImageRect;

                        ColorBlend colorBlend = null;
                        var intermediateValue = new double[Bands];

                        // get data from image
                        for (var i = 0; i < Bands; i++)
                        {
                            using (var band = dataset.GetRasterBand(i + 1))
                            {
                                int hasVal;

                                //get nodata value if present
                                band.GetNoDataValue(out noDataValues[i], out hasVal);
                                if (hasVal == 0) noDataValues[i] = Double.NaN;
                                
                                //Get the scale value if present
                                band.GetScale(out scales[i], out hasVal);
                                if (hasVal == 0) scales[i] = 1.0;

                                switch (band.GetRasterColorInterpretation())
                                {
                                    case ColorInterp.GCI_BlueBand:
                                        ch[i] = 0;
                                        break;
                                    case ColorInterp.GCI_GreenBand:
                                        ch[i] = 1;
                                        break;
                                    case ColorInterp.GCI_RedBand:
                                        ch[i] = 2;
                                        break;
                                    case ColorInterp.GCI_Undefined:
                                        if (Bands > 1)
                                            ch[i] = 3; // infrared
                                        else
                                        {
                                            ch[i] = 4;
                                            colorBlend = GetColorBlend(band);
                                            intermediateValue = new Double[3];
                                        }
                                        break;
                                    case ColorInterp.GCI_GrayIndex:
                                        ch[i] = 0;
                                        break;
                                    case ColorInterp.GCI_PaletteIndex:
                                        if (colorTable != null)
                                        {
                                            //this should not happen
                                            colorTable.Dispose();
                                        }
                                        colorTable = band.GetRasterColorTable();

                                        int numColors = colorTable.GetCount();
                                        colorTableCache = new short[numColors][];
                                        for (int col = 0; col < numColors; col++)
                                        {
                                            using (var colEntry = colorTable.GetColorEntry(col))
                                            {
                                                colorTableCache[col] = new short[]{
                                                    colEntry.c1, colEntry.c2, colEntry.c3
                                                };
                                            }
                                        }

                                        ch[i] = 5;
                                        intermediateValue = new Double[3];
                                        break;
                                    default:
                                        ch[i] = -1;
                                        break;
                                }
                            }
                        }

                        // store these values to keep from having to make slow method calls
                        var bitmapTlx = bitmapTl.X;
                        var bitmapTly = bitmapTl.Y;
                        double imageTop = g2I.MinY;
                        double imageLeft = g2I.MinX;
                        double dblMapPixelWidth = map.PixelWidth;
                        double dblMapPixelHeight = map.PixelHeight;
                        double dblMapMinX = map.Envelope.MinX;
                        double dblMapMaxY = map.Envelope.MaxY;

                        // get inverse values
                        var geoTop = geoTransform.Inverse[3];
                        var geoLeft = geoTransform.Inverse[0];
                        var geoHorzPixRes = geoTransform.Inverse[1];
                        var geoVertPixRes = geoTransform.Inverse[5];
                        var geoXRot = geoTransform.Inverse[2];
                        var geoYRot = geoTransform.Inverse[4];

                        var dblXScale = (g2I.Width) / (displayImageSize.Width - 1);
                        var dblYScale = (g2I.Height) / (displayImageSize.Height - 1);

                        // get inverse transform  
                        // NOTE: calling transform.MathTransform.Inverse() once and storing it
                        // is much faster than having to call every time it is needed
#if !DotSpatialProjections
                        IMathTransform inverseTransform = null;
                        if (ReverseCoordinateTransformation != null)
                            inverseTransform = ReverseCoordinateTransformation.MathTransform;
#else
                        DotSpatial.Projections.ICoordinateTransformation inverseTransform = null;
                        if (CoordinateTransformation != null)
                        {
                            inverseTransform = new DotSpatial.Projections.CoordinateTransformation { Source = CoordinateTransformation.Target, Target = CoordinateTransformation.Source };
                        }
#endif

                        var rowsRead = 0;
                        var displayImageStep = displayImageSize.Height;
                        while (rowsRead < displayImageStep)
                        {
                            var rowsToRead = displayImageStep;
                            if (rowsRead + rowsToRead > displayImageStep)
                                rowsToRead = displayImageStep - rowsRead;

                            var tempBuffer = new double[displayImageSize.Width * rowsToRead];
                            for (var i = 0; i < Bands; i++)
                            {
                                // read the buffer
                                using (var band = dataset.GetRasterBand(i + 1))
                                {
                                    DateTime start = DateTime.Now;
                                    band.ReadRaster(imageRect.Left, imageRect.Top,
                                                    imageRect.Width, imageRect.Height,
                                                    tempBuffer, displayImageSize.Width, rowsToRead, 0, 0);

                                    if (_logger.IsDebugEnabled)
                                    {
                                        TimeSpan took = DateTime.Now - start;
                                        totalReadDataTime += took.TotalMilliseconds;
                                    }
                                }

                                // parse temp buffer into the image x y value buffer
                                long pos = 0;
                                var newRowsRead = rowsRead + rowsToRead;
                                for (var y = rowsRead; y < newRowsRead; y++)
                                {
                                    for (var x = 0; x < displayImageSize.Width; x++)
                                    {
                                        buffer[i][x][y] = tempBuffer[pos++];
                                    }
                                }
                            }
                            rowsRead = rowsRead + rowsToRead;

                            for (var pixY = 0d; pixY < bitmapBr.Y - bitmapTl.Y; pixY++)
                            {
                                var row = (byte*) bitmapData.Scan0 + ((int) Math.Round(pixY)*bitmapData.Stride);

                                for (var pixX = 0; pixX < bitmapBr.X - bitmapTl.X; pixX++)
                                {
                                    // same as Map.ImageToGround(), but much faster using stored values...rather than called each time
                                    var gndX = dblMapMinX + (pixX + bitmapTlx)*dblMapPixelWidth;
                                    var gndY = dblMapMaxY - (pixY + bitmapTly)*dblMapPixelHeight;

                                    // transform ground point if needed
                                    if (inverseTransform != null)
                                    {
#if !DotSpatialProjections
                                        var dblPoint = inverseTransform.Transform(new[] {gndX, gndY});
#else
                                    var dblPoint = new double[] { gndX, gndY };
                                    Reproject.ReprojectPoints(dblPoint, null, inverseTransform.Source, inverseTransform.Target, 0, 1);
#endif
                                        gndX = dblPoint[0];
                                        gndY = dblPoint[1];
                                    }

                                    // same as GeoTransform.GroundToImage(), but much faster using stored values...
                                    var imageCoord = new Coordinate(
                                        geoLeft + geoHorzPixRes*gndX + geoXRot*gndY,
                                        geoTop + geoYRot*gndX + geoVertPixRes*gndY);

                                    if (!g2I.Contains(imageCoord)) 
                                        continue;

                                    var imagePt = new Point((int)((imageCoord.X - imageLeft) / dblXScale),
                                                            (int)((imageCoord.Y - imageTop) / dblYScale));

                                    // Apply color correction
                                    for (var i = 0; i < Bands; i++)
                                    {
                                        intermediateValue[i] = buffer[i][imagePt.X][imagePt.Y];

                                        // apply scale
                                        intermediateValue[i] *= scales[i];

                                        double spotVal;
                                        var imageVal = spotVal = intermediateValue[i] = intermediateValue[i]/bitScalar;

                                        if (ch[i] == 4)
                                        {
                                            if (!DoublesAreEqual(imageVal,noDataValues[i]))
                                            {
                                                var color = colorBlend.GetColor(Convert.ToSingle(imageVal));
                                                intermediateValue[0] = color.B;
                                                intermediateValue[1] = color.G;
                                                intermediateValue[2] = color.R;
                                                //intVal[3] = ce.c4;
                                            }
                                            else
                                            {
                                                intermediateValue[0] = cb;
                                                intermediateValue[1] = cg;
                                                intermediateValue[2] = cr;
                                            }
                                        }

                                        else if (ch[i] == 5 && colorTable != null)
                                        {
                                            if (double.IsNaN(noDataValues[i]) || !DoublesAreEqual(imageVal, noDataValues[i]))
                                            {
                                                var ce = colorTableCache[Convert.ToInt32(imageVal)];

                                                intermediateValue[0] = ce[2];
                                                intermediateValue[1] = ce[1];
                                                intermediateValue[2] = ce[0];
                                            }
                                            else
                                            {
                                                intermediateValue[0] = cb;
                                                intermediateValue[1] = cg;
                                                intermediateValue[2] = cr;
                                            }
                                        }

                                        else
                                        {
                                            if (ColorCorrect)
                                            {
                                                intermediateValue[i] = ApplyColorCorrection(imageVal, spotVal, ch[i],
                                                                                            gndX,
                                                                                            gndY);

                                                // if pixel is within ground boundary, add its value to the histogram
                                                if (ch[i] != -1 && intermediateValue[i] > 0 &&
                                                    (HistoBounds.Bottom >= (int) gndY) &&
                                                    HistoBounds.Top <= (int) gndY &&
                                                    HistoBounds.Left <= (int) gndX && HistoBounds.Right >= (int) gndX)
                                                {
                                                    Histogram[ch[i]][(int) intermediateValue[i]]++;
                                                }
                                            }

                                            if (intermediateValue[i] > 255)
                                                intermediateValue[i] = 255;
                                        }
                                    }

                                    // luminosity
                                    if (Bands >= 3)
                                        Histogram[Bands][
                                            (int)
                                            (intermediateValue[2]*0.2126 + intermediateValue[1]*0.7152 +
                                             intermediateValue[0]*0.0722)]
                                            ++;

                                    DateTime writeStart = DateTime.MinValue;
                                    if (_logger.IsDebugEnabled)
                                        writeStart = DateTime.Now;
                                    WritePixel(pixX, intermediateValue, pixelSize, ch, row);
                                    if (_logger.IsDebugEnabled)
                                    {
                                        TimeSpan took = DateTime.Now - writeStart;
                                        totalTimeSetPixel += took.TotalMilliseconds;
                                    }
                                }
                            }
                        }

                        if (colorTable != null)
                        {
                            colorTable.Dispose();
                        }
                    }
                }

                finally
                {
                    bitmap.UnlockBits(bitmapData);
                }
            }

            
            DateTime drawGdiStart = DateTime.Now;
                bitmap.MakeTransparent(_noDataInitColor);
                if (TransparentColor != Color.Empty)
                    bitmap.MakeTransparent(TransparentColor);
                g.DrawImage(bitmap, bitmapTl);
            
            if (_logger.IsDebugEnabled)
            {
                TimeSpan took = DateTime.Now - drawStart;
                TimeSpan drawGdiTook = DateTime.Now - drawGdiStart;
                _logger.DebugFormat("Draw GdalImage in {0}ms, readTime: {1}, setPixelTime: {2}, drawTime: {3}", took.TotalMilliseconds, totalReadDataTime,
                    totalTimeSetPixel, drawGdiTook.TotalMilliseconds);
            }
        }
Ejemplo n.º 5
0
        // add image pixels to the map
        protected virtual void GetPreview(Dataset dataset, System.Drawing.Size size, System.Drawing.Graphics g,
                                            BoundingBox displayBbox, ICoordinateSystem mapProjection, Map map)
        {
            double[] geoTrans = new double[6];
            _GdalDataset.GetGeoTransform(geoTrans);

            // not rotated, use faster display method
            if ((!_useRotation || (geoTrans[1] == 1 && geoTrans[2] == 0 && geoTrans[4] == 0 && Math.Abs(geoTrans[5]) == 1))
                && !_haveSpot && _transform == null)
            {
                GetNonRotatedPreview(dataset, size, g, displayBbox, mapProjection);
                return;
            }
            // not rotated, but has spot...need default rotation
            else if ((geoTrans[0] == 0 && geoTrans[3] == 0) && _haveSpot)
                geoTrans = new double[] { 999.5, 1, 0, 1000.5, 0, -1 };

            GT = new GeoTransform(geoTrans);
            double DsWidth = _imagesize.Width;
            double DsHeight = _imagesize.Height;
            double left, top, right, bottom;
            double GndX = 0, GndY = 0, ImgX = 0, ImgY = 0, PixX, PixY;
            double[] intVal = new double[Bands];
            double imageVal = 0, SpotVal = 0;
            double bitScalar = 1.0;
            Bitmap bitmap = null;
            GdiPoint bitmapTL = new GdiPoint(), bitmapBR = new GdiPoint();
            SMPoint imageTL = new SMPoint(), imageBR = new SMPoint();
            BoundingBox shownImageBbox, trueImageBbox;
            int bitmapLength, bitmapHeight;
            int displayImageLength, displayImageHeight;

            int iPixelSize = 3; //Format24bppRgb = byte[b,g,r] 

            if (dataset != null)
            {
                //check if image is in bounding box
                if ((displayBbox.Left > _Envelope.Right) || (displayBbox.Right < _Envelope.Left)
                    || (displayBbox.Top < _Envelope.Bottom) || (displayBbox.Bottom > _Envelope.Top))
                    return;

                // init histo
                _histogram = new List<int[]>();
                for (int i = 0; i < _lbands + 1; i++)
                    _histogram.Add(new int[256]);

                // bounds of section of image to be displayed
                left = Math.Max(displayBbox.Left, _Envelope.Left);
                top = Math.Min(displayBbox.Top, _Envelope.Top);
                right = Math.Min(displayBbox.Right, _Envelope.Right);
                bottom = Math.Max(displayBbox.Bottom, _Envelope.Bottom);

                trueImageBbox = new BoundingBox(left, bottom, right, top);

                // put display bounds into current projection
                if (_transform != null)
                    shownImageBbox = GeometryTransform.TransformBox(trueImageBbox, _transform.MathTransform.Inverse());
                else
                    shownImageBbox = trueImageBbox;

                // find min/max x and y pixels needed from image
                imageBR.X = (int)(Math.Max(GT.GroundToImage(shownImageBbox.TopLeft).X, Math.Max(GT.GroundToImage(shownImageBbox.TopRight).X,
                    Math.Max(GT.GroundToImage(shownImageBbox.BottomLeft).X, GT.GroundToImage(shownImageBbox.BottomRight).X))) + 1);
                imageBR.Y = (int)(Math.Max(GT.GroundToImage(shownImageBbox.TopLeft).Y, Math.Max(GT.GroundToImage(shownImageBbox.TopRight).Y,
                    Math.Max(GT.GroundToImage(shownImageBbox.BottomLeft).Y, GT.GroundToImage(shownImageBbox.BottomRight).Y))) + 1);
                imageTL.X = (int)Math.Min(GT.GroundToImage(shownImageBbox.TopLeft).X, Math.Min(GT.GroundToImage(shownImageBbox.TopRight).X,
                    Math.Min(GT.GroundToImage(shownImageBbox.BottomLeft).X, GT.GroundToImage(shownImageBbox.BottomRight).X)));
                imageTL.Y = (int)Math.Min(GT.GroundToImage(shownImageBbox.TopLeft).Y, Math.Min(GT.GroundToImage(shownImageBbox.TopRight).Y,
                    Math.Min(GT.GroundToImage(shownImageBbox.BottomLeft).Y, GT.GroundToImage(shownImageBbox.BottomRight).Y)));

                // stay within image
                if (imageBR.X > _imagesize.Width)
                    imageBR.X = _imagesize.Width;
                if (imageBR.Y > _imagesize.Height)
                    imageBR.Y = _imagesize.Height;
                if (imageTL.Y < 0)
                    imageTL.Y = 0;
                if (imageTL.X < 0)
                    imageTL.X = 0;

                displayImageLength = (int)(imageBR.X - imageTL.X);
                displayImageHeight = (int)(imageBR.Y - imageTL.Y);

                // find ground coordinates of image pixels
                SMPoint groundBR = GT.ImageToGround(imageBR);
                SMPoint groundTL = GT.ImageToGround(imageTL);

                // convert ground coordinates to map coordinates to figure out where to place the bitmap
                bitmapBR = new GdiPoint((int)map.WorldToImage(trueImageBbox.BottomRight).X + 1, (int)map.WorldToImage(trueImageBbox.BottomRight).Y + 1);
                bitmapTL = new GdiPoint((int)map.WorldToImage(trueImageBbox.TopLeft).X, (int)map.WorldToImage(trueImageBbox.TopLeft).Y);

                bitmapLength = bitmapBR.X - bitmapTL.X;
                bitmapHeight = bitmapBR.Y - bitmapTL.Y;

                // check to see if image is on its side
                if (bitmapLength > bitmapHeight && displayImageLength < displayImageHeight)
                {
                    displayImageLength = bitmapHeight;
                    displayImageHeight = bitmapLength;
                }
                else
                {
                    displayImageLength = bitmapLength;
                    displayImageHeight = bitmapHeight;
                }

                // scale
                if (_bitDepth == 12)
                    bitScalar = 16.0;
                else if (_bitDepth == 16)
                    bitScalar = 256.0;
                else if (_bitDepth == 32)
                    bitScalar = 16777216.0;

                // 0 pixels in length or height, nothing to display
                if (bitmapLength < 1 || bitmapHeight < 1)
                    return;

                //initialize bitmap
                bitmap = new Bitmap(bitmapLength, bitmapHeight, PixelFormat.Format24bppRgb);
                BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmapLength, bitmapHeight), ImageLockMode.ReadWrite, bitmap.PixelFormat);

                try
                {
                    unsafe
                    {
                        // turn everything yellow, so we can make fill transparent
                        for (int y = 0; y < bitmapHeight; y++)
                        {
                            byte* brow = (byte*)bitmapData.Scan0 + (y * bitmapData.Stride);
                            for (int x = 0; x < bitmapLength; x++)
                            {
                                brow[x * 3 + 0] = 0;
                                brow[x * 3 + 1] = 255;
                                brow[x * 3 + 2] = 255;
                            }
                        }

                        // create 3 dimensional buffer [band][x pixel][y pixel]
                        double[][] tempBuffer = new double[Bands][];
                        double[][][] buffer = new double[Bands][][];
                        for (int i = 0; i < Bands; i++)
                        {
                            buffer[i] = new double[displayImageLength][];
                            for (int j = 0; j < displayImageLength; j++)
                                buffer[i][j] = new double[displayImageHeight];
                        }

                        Band[] band = new Band[Bands];
                        int[] ch = new int[Bands];

                        // get data from image
                        for (int i = 0; i < Bands; i++)
                        {
                            tempBuffer[i] = new double[displayImageLength * displayImageHeight];
                            band[i] = dataset.GetRasterBand(i + 1);

                            band[i].ReadRaster(
                                (int)imageTL.X,
                                (int)imageTL.Y,
                                (int)(imageBR.X - imageTL.X),
                                (int)(imageBR.Y - imageTL.Y),
                                tempBuffer[i], displayImageLength, displayImageHeight, 0, 0);

                            // parse temp buffer into the image x y value buffer
                            long pos = 0;
                            for (int y = 0; y < displayImageHeight; y++)
                            {
                                for (int x = 0; x < displayImageLength; x++, pos++)
                                    buffer[i][x][y] = tempBuffer[i][pos];
                            }

                            if (band[i].GetRasterColorInterpretation() == ColorInterp.GCI_BlueBand) ch[i] = 0;
                            else if (band[i].GetRasterColorInterpretation() == ColorInterp.GCI_GreenBand) ch[i] = 1;
                            else if (band[i].GetRasterColorInterpretation() == ColorInterp.GCI_RedBand) ch[i] = 2;
                            else if (band[i].GetRasterColorInterpretation() == ColorInterp.GCI_Undefined) ch[i] = 3;     // infrared
                            else if (band[i].GetRasterColorInterpretation() == ColorInterp.GCI_GrayIndex) ch[i] = 0;
                            else ch[i] = -1;
                        }

                        // store these values to keep from having to make slow method calls
                        int bitmapTLX = bitmapTL.X;
                        int bitmapTLY = bitmapTL.Y;
                        double imageTop = imageTL.Y;
                        double imageLeft = imageTL.X;
                        double dblMapPixelWidth = map.PixelWidth;
                        double dblMapPixelHeight = map.PixelHeight;
                        double dblMapMinX = map.Envelope.Min.X;
                        double dblMapMaxY = map.Envelope.Max.Y;
                        double geoTop, geoLeft, geoHorzPixRes, geoVertPixRes, geoXRot, geoYRot;

                        // get inverse values
                        geoTop = GT.Inverse[3];
                        geoLeft = GT.Inverse[0];
                        geoHorzPixRes = GT.Inverse[1];
                        geoVertPixRes = GT.Inverse[5];
                        geoXRot = GT.Inverse[2];
                        geoYRot = GT.Inverse[4];

                        double dblXScale = (imageBR.X - imageTL.X) / (displayImageLength - 1);
                        double dblYScale = (imageBR.Y - imageTL.Y) / (displayImageHeight - 1);
                        double[] dblPoint;

                        // get inverse transform  
                        // NOTE: calling transform.MathTransform.Inverse() once and storing it
                        // is much faster than having to call every time it is needed
                        IMathTransform inverseTransform = null;
                        if (_transform != null)
                            inverseTransform = _transform.MathTransform.Inverse();

                        for (PixY = 0; PixY < bitmapBR.Y - bitmapTL.Y; PixY++)
                        {
                            byte* row = (byte*)bitmapData.Scan0 + ((int)Math.Round(PixY) * bitmapData.Stride);

                            for (PixX = 0; PixX < bitmapBR.X - bitmapTL.X; PixX++)
                            {
                                // same as Map.ImageToGround(), but much faster using stored values...rather than called each time
                                GndX = dblMapMinX + (PixX + (double)bitmapTLX) * dblMapPixelWidth;
                                GndY = dblMapMaxY - (PixY + (double)bitmapTLY) * dblMapPixelHeight;

                                // transform ground point if needed
                                if (_transform != null)
                                {
                                    dblPoint = inverseTransform.Transform(new double[] { GndX, GndY });
                                    GndX = dblPoint[0];
                                    GndY = dblPoint[1];
                                }

                                // same as GeoTransform.GroundToImage(), but much faster using stored values...
                                ImgX = (geoLeft + geoHorzPixRes * GndX + geoXRot * GndY);
                                ImgY = (geoTop + geoYRot * GndX + geoVertPixRes * GndY);

                                if (ImgX < imageTL.X || ImgX > imageBR.X || ImgY < imageTL.Y || ImgY > imageBR.Y)
                                    continue;

                                // color correction
                                for (int i = 0; i < Bands; i++)
                                {
                                    intVal[i] = buffer[i][(int)((ImgX - imageLeft) / dblXScale)][(int)((ImgY - imageTop) / dblYScale)];

                                    imageVal = SpotVal = intVal[i] = intVal[i] / bitScalar;

                                    if (_colorCorrect)
                                    {
                                        intVal[i] = ApplyColorCorrection(imageVal, SpotVal, ch[i], GndX, GndY);

                                        // if pixel is within ground boundary, add its value to the histogram
                                        if (ch[i] != -1 && intVal[i] > 0 && (_histoBounds.Bottom >= (int)GndY) && _histoBounds.Top <= (int)GndY &&
                                            _histoBounds.Left <= (int)GndX && _histoBounds.Right >= (int)GndX)
                                        {
                                            _histogram[ch[i]][(int)intVal[i]]++;
                                        }
                                    }

                                    if (intVal[i] > 255)
                                        intVal[i] = 255;
                                }

                                // luminosity
                                if (_lbands >= 3)
                                    _histogram[_lbands][(int)(intVal[2] * 0.2126 + intVal[1] * 0.7152 + intVal[0] * 0.0722)]++;

                                WritePixel(PixX, intVal, iPixelSize, ch, row);
                            }
                        }
                    }
                }

                finally
                {
                    bitmap.UnlockBits(bitmapData);
                }
            }
            bitmap.MakeTransparent(Color.Yellow);
            if (_transparentColor != Color.Empty)
                bitmap.MakeTransparent(_transparentColor);
            g.DrawImage(bitmap, new System.Drawing.Point(bitmapTL.X, bitmapTL.Y));
        }