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 = 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; //// 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 (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 < 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 (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 (!DoublesAreEqual(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); //} }
// gets transform between raster's native projection and the map projection private void GetTransform(ProjectionInfo mapProjection) { if (mapProjection == null || string.IsNullOrEmpty(Projection)) { CoordinateTransformation = (ICoordinateTransformation)null; return; } // get our two projections var srcCoord = ProjectionInfo.FromEsriString(Projection); var tgtCoord = mapProjection; // raster and map are in same projection, no need to transform if (srcCoord.Matches(tgtCoord)) { CoordinateTransformation = (ICoordinateTransformation)null; return; } // create transform CoordinateTransformation = new DotSpatial.Projections.CoordinateTransformation {Source = srcCoord, Target = tgtCoord}; }