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); //} }
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); }
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)); }
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); } }
// 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)); }