public static void Reduce(FileMetadata metadata, Stream input, Stream output, int desiredPoints) { // s = scaler to solve for // d = desired points // (x / s) * (y / s) == d // so... // s = (sqrt(x) * sqrt(y))/sqrt(d) float scaler = (float)((Math.Sqrt(metadata.Height) * Math.Sqrt(metadata.Width)) / Math.Sqrt(desiredPoints)); int newHeight = (int)Math.Floor(metadata.Height / scaler); int newWidth = (int)Math.Floor(metadata.Width / scaler); float[,] originalMatrix = new float[metadata.Width, metadata.Height]; float[,] newMatrix = new float[newWidth, newHeight]; using (BinaryReader reader = new BinaryReader(input)) { for (int y = 0; y < metadata.Height; y++) { for (int x = 0; x < metadata.Width; x++) { switch (metadata.BitsPerSample) { case 32: originalMatrix[x, y] = reader.ReadSingle(); break; case 16: originalMatrix[x, y] = reader.ReadUInt16(); break; } } } } float noDataValue = float.Parse(metadata.NoDataValue); using (BinaryWriter writer = new BinaryWriter(output)) { for (int y = 0; y < newHeight; y++) { for (int x = 0; x < newWidth; x++) { float value = originalMatrix[(int)(x * scaler), (int)(y * scaler)]; if (value != noDataValue) value /= scaler; writer.Write(value); } } } metadata.Width = newWidth; metadata.Height = newHeight; metadata.PixelScaleX *= scaler; metadata.PixelScaleY *= scaler; }
public static void Reduce(FileMetadata metadata, float[,] input, Stream output, int desiredPoints) { // s = scaler to solve for // d = desired points // (x / s) * (y / s) == d // so... // s = (sqrt(x) * sqrt(y))/sqrt(d) float scaler = (float)((Math.Sqrt(metadata.Height) * Math.Sqrt(metadata.Width)) / Math.Sqrt(desiredPoints)); int newHeight = (int)Math.Floor(metadata.Height / scaler); int newWidth = (int)Math.Floor(metadata.Width / scaler); float[,] newMatrix = new float[newWidth, newHeight]; float noDataValue = float.Parse(metadata.NoDataValue); using (BinaryWriter writer = new BinaryWriter(output)) { for (int y = 0; y < newHeight; y++) { for (int x = 0; x < newWidth; x++) { float value = input[(int)(x * scaler), (int)(y * scaler)]; //if (value != noDataValue) // value /= scaler; writer.Write(value); } } } metadata.Width = newWidth; metadata.Height = newHeight; metadata.PixelScaleX *= scaler; metadata.PixelScaleY *= scaler; }
private void WriteBinary(string inputFilename, Stream output, string bitmapFilename, FileMetadata metadata) { float min = float.MaxValue; float max = float.MinValue; float range; float[,] data = new float[metadata.Width, metadata.Height]; for (int i = 0; i < metadata.Height; i++) { byte[] buffer = new byte[metadata.Width * metadata.BitsPerSample / 8]; _tiff.ReadScanline(buffer, i); for (int p = 0; p < metadata.Width; p++) { var heightValue = BitConverter.ToSingle(buffer, p * metadata.BitsPerSample / 8); data[p, i] = heightValue; if (heightValue != -10000) { min = Math.Min(min, heightValue); max = Math.Max(max, heightValue); } } output.Write(buffer, 0, metadata.Width * metadata.BitsPerSample / 8); } // compute range of heights so we can normalize the values for the grayscale bmp range = max - min; if (!string.IsNullOrEmpty(bitmapFilename)) { DiagnosticUtils.OutputDebugBitmap(data, min, max, bitmapFilename, -10000); } }
private float[,] WriteBinary(string inputFilename, string bitmapFilename, FileMetadata metadata) { float min = float.MaxValue; float max = float.MinValue; float range; int width, height, increment; if (metadata.Width > 0x1fff || metadata.Height > 0x1fff) { width = metadata.Width / 2; height = metadata.Height / 2; increment = 2; } else { width = metadata.Width; height = metadata.Height; increment = 1; } float[,] data = new float[width, height]; for (int i = 0; i <= metadata.Height - increment; i += increment) { byte[] buffer = new byte[metadata.Width * metadata.BitsPerSample / 8]; _tiff.ReadScanline(buffer, i); for (int p = 0; p <= metadata.Width - increment; p += increment) { var heightValue = BitConverter.ToSingle(buffer, p * metadata.BitsPerSample / 8); data[p/increment, i/increment] = heightValue; if (heightValue != -10000) { min = Math.Min(min, heightValue); max = Math.Max(max, heightValue); } } //output.Write(buffer, 0, metadata.Width * metadata.BitsPerSample / 8); } // compute range of heights so we can normalize the values for the grayscale bmp range = max - min; if (!string.IsNullOrEmpty(bitmapFilename)) { DiagnosticUtils.OutputDebugBitmap(data, min, max, bitmapFilename, -10000); } metadata.Width /= increment; metadata.Height /= increment; metadata.PixelScaleX *= increment; metadata.PixelScaleY *= increment; return data; }
private FileMetadata ParseMetadata(string filename) { FileMetadata metadata = new FileMetadata(); _tiff = Tiff.Open(filename, "r"); metadata.Height = _tiff.GetField(TiffTag.IMAGELENGTH)[0].ToInt(); metadata.Width = _tiff.GetField(TiffTag.IMAGEWIDTH)[0].ToInt(); FieldValue[] modelPixelScaleTag = _tiff.GetField((TiffTag)33550); FieldValue[] modelTiepointTag = _tiff.GetField((TiffTag)33922); byte[] modelPixelScale = modelPixelScaleTag[1].GetBytes(); metadata.PixelScaleX = BitConverter.ToDouble(modelPixelScale, 0); metadata.PixelScaleY = BitConverter.ToDouble(modelPixelScale, 8); // Ignores first set of model points (3 bytes) and assumes they are 0's... byte[] modelTransformation = modelTiepointTag[1].GetBytes(); metadata.OriginLongitude = BitConverter.ToDouble(modelTransformation, 24); metadata.OriginLatitude = BitConverter.ToDouble(modelTransformation, 32); // Grab some raster metadata metadata.BitsPerSample = _tiff.GetField(TiffTag.BITSPERSAMPLE)[0].ToInt(); // Add other information about the data metadata.SampleFormat = "Single"; // TODO: Read this from tiff metadata or determine after parsing metadata.NoDataValue = "-10000"; metadata.WorldUnits = "meter"; return metadata; }
private static FileMetadata ParseMetadata(string filename, string outputFile, string outputBitmap, int targetPixelWidth) { FileMetadata metadata = new FileMetadata(); Obj obj = new Obj(); obj.LoadObj(filename); metadata.BitsPerSample = BITS_PER_SAMPLE; metadata.SampleFormat = "Single"; double pointsPerPixel = obj.Size.XSize / targetPixelWidth; metadata.Height = (int)(Math.Ceiling(obj.Size.YSize / pointsPerPixel)) + 1; metadata.Width = (int)(Math.Ceiling(obj.Size.XSize / pointsPerPixel)) + 1; metadata.PixelScaleX = pointsPerPixel; metadata.PixelScaleY = pointsPerPixel; float[,] heights = new float[metadata.Height, metadata.Width]; bool[,] dataPresent = new bool[metadata.Height, metadata.Width]; metadata.OriginLatitude = obj.Size.XMin; metadata.OriginLongitude = obj.Size.YMax; metadata.WorldUnits = "meters"; float minHeight = float.MaxValue; float maxHeight = float.MinValue; for (int y = 0; y < metadata.Height; y++) { var row = obj.VertexList.Where(v => (int)(Math.Floor((v.Y - obj.Size.YMin) / pointsPerPixel)) == y); var rowCols = row.GroupBy(r => (int)(Math.Floor((r.X - obj.Size.XMin) / pointsPerPixel))).OrderBy(rc => rc.Key); int x = 0; foreach (var rowcol in rowCols) { while (rowcol.Key > x) { heights[y, x] = -1; x++; } heights[y, x] = (float)rowcol.Average(v => v.Z); if (heights[y, x] > maxHeight) { maxHeight = heights[y, x]; } if (heights[y, x] < minHeight) { minHeight = heights[y, x]; } dataPresent[y, x] = true; x++; } while (x < metadata.Width) { heights[y, x] = -1; x++; } } bool dataMissing = true; int maxCount = 8; while (dataMissing) { dataMissing = false; bool dataFound = false; for (int i = 0; i < dataPresent.GetLength(0); i++) { for (int j = 0; j < dataPresent.GetLength(1); j++) { if (!dataPresent[i, j]) { var sum = 0.0f; var count = 0; bool firstRow = i == 0; bool lastRow = i == dataPresent.GetLength(0) - 1; bool firstCol = j == 0; bool lastCol = j == dataPresent.GetLength(1) - 1; // up left if (!firstRow && !firstCol && dataPresent[i - 1, j - 1]) { sum += heights[i - 1, j - 1]; count++; } // up center if (!firstRow && dataPresent[i - 1, j]) { sum += heights[i - 1, j]; count++; } // up right if (!firstRow && !lastCol && dataPresent[i - 1, j + 1]) { sum += heights[i - 1, j + 1]; count++; } // center left if (!firstCol && dataPresent[i, j - 1]) { sum += heights[i, j - 1]; count++; } // center right if (!lastCol && dataPresent[i, j + 1]) { sum += heights[i, j + 1]; count++; } // down left if (!lastRow && !firstCol && dataPresent[i + 1, j - 1]) { sum += heights[i + 1, j - 1]; count++; } // down center if (!lastRow && dataPresent[i + 1, j]) { sum += heights[i + 1, j]; count++; } // down right if (!lastRow && !lastCol && dataPresent[i + 1, j + 1]) { sum += heights[i + 1, j + 1]; count++; } if (count >= maxCount) { dataPresent[i, j] = true; heights[i, j] = sum / count; dataFound = true; } else { dataMissing = true; } } } } if (dataMissing && !dataFound) { maxCount--; } } if (!string.IsNullOrEmpty(outputBitmap)) { DiagnosticUtils.OutputDebugBitmap(heights, minHeight, maxHeight, outputBitmap); } if (!string.IsNullOrEmpty(outputFile)) { using (var stream = File.OpenWrite(outputFile)) { foreach (var height in heights) { byte[] bytesToWrite = BitConverter.GetBytes(height); stream.Write(bytesToWrite, 0, bytesToWrite.Length); } } } return metadata; }