private void hfzWriteTile(ref EndianBinaryWriter writer, HfzHeader fh, HfzTile tile) { List<float> pTileData = tile.tileData; Int32 i=0, TempInt, FirstVal; float f, HFmin, HFmax, VertScale, VertOffset; sbyte c; short s; UInt32 nx = fh.nx; UInt32 ny = fh.ny; UInt32 TileSize = fh.TileSize; float Precis = fh.Precis; // get min/max alt in block (used for vert scale) HFmin = 0; HFmax = 0; Epsilon epsilon = new Epsilon(1E-3); for (i = 0; i < pTileData.Count; i++) { // find max diff in line f = pTileData.ElementAt(i); if (i == 0) { HFmin = HFmax = f; } else { if (RealExtensions.LT(f, HFmin, epsilon)) { HFmin = f; } if (RealExtensions.GT(f, HFmax, epsilon)) { HFmax = f; } } } // number of int levels required for this block float BlockLevels = ((HFmax - HFmin) / Precis) + 1; // calc scale VertScale = (HFmax - HFmin) / BlockLevels; VertOffset = HFmin; if (RealExtensions.LE(VertScale, 0, epsilon)) { VertScale = 1.0f; // this is for niceness } writer.Write(VertScale); writer.Write(VertOffset); // determine number of blocks Int32 nBlocksX = ((int)fh.nx / fh.TileSize) - 1; // -1 due to index starting at 0 Int32 exBlocksX = -1; Int32 nBlocksY = ((int)fh.ny / fh.TileSize) - 1; // -1 due to index starting at 0 Int32 exBlocksY = -1; if (fh.nx % fh.TileSize > 0) { exBlocksX = nBlocksX + 1; } if (fh.ny % fh.TileSize > 0) { exBlocksY = nBlocksY + 1; } UInt32 rows = TileSize; if(tile.x != exBlocksX && tile.y == exBlocksY || tile.x == exBlocksX && tile.y == exBlocksY) { rows = (uint)(TileSize - (((exBlocksY+1) * TileSize) - ny)); } else if (tile.x == exBlocksX && tile.y != exBlocksY) { rows = calculateRows(tile, ny, TileSize, rows); } int rowCount = 0; int rowZeroElement = 0; try { for (rowCount = 0; rowCount < rows; rowCount++) { List<float> row = null; int range = calculateRange(tile, nx, TileSize); rowZeroElement = (int)(rowCount * range); row = pTileData.GetRange(rowZeroElement, range); f = row.ElementAt(0); FirstVal = Convert.ToInt32(Math.Truncate((f - VertOffset) / VertScale)); Int32 LastVal = FirstVal; // find max diff in line Int32 Diff; Int32 MaxDev = 0; List<Int32> pDiffBuf = new List<Int32>(); for (int rowElementCounter = 1; rowElementCounter < row.Count; rowElementCounter++) { // find max diff in line f = row.ElementAt(rowElementCounter); TempInt = Convert.ToInt32(Math.Truncate((f - VertOffset) / VertScale)); Diff = TempInt - LastVal; pDiffBuf.Add(Diff); LastVal = TempInt; MaxDev = MaxDev > Math.Abs(Diff) ? MaxDev : Math.Abs(Diff); } // should we use 8, 16 or 32 bit pixels? byte LineDepth = 4; if (MaxDev <= 127) { LineDepth = 1; } else if (MaxDev <= 32767) { LineDepth = 2; } writer.Write(LineDepth); writer.Write(FirstVal); for (int rowElementCounter = 0; rowElementCounter < pDiffBuf.Count; rowElementCounter++) { Diff = pDiffBuf.ElementAt(rowElementCounter); switch (LineDepth) { case 1: c = Convert.ToSByte(Diff); writer.Write(c); break; case 2: s = Convert.ToInt16(Diff); writer.Write(s); break; case 4: writer.Write(Diff); break; } } } } catch (Exception ex) { System.Console.WriteLine("Tile x :" + tile.x); System.Console.WriteLine("Tile y :" + tile.y); System.Console.WriteLine("Rows :" + rows); System.Console.WriteLine("RowCount :" + rowCount); System.Console.WriteLine("RowZeroElement :" + rowZeroElement); System.Console.WriteLine("exBlocksX :" + exBlocksX); System.Console.WriteLine("exBlocksY :" + exBlocksY); System.Console.WriteLine("pTileData count :" + pTileData.Count); throw ex; } }
private Dictionary<short, HfzTile> readTiles(HfzHeader header, EndianBinaryReader reader) { // I know this is offensive but after all the headaches this gave me IT'S STAYING IN ! Boolean extraTileBullshit = false; UInt32 nx = header.nx; UInt32 ny = header.ny; debugLine("nx " + nx); debugLine("ny " + ny); ushort TileSize = header.TileSize; // determine number of blocks UInt32 nBlocksX = nx / TileSize; UInt32 nBlocksY = ny / TileSize; if (nx % TileSize != 0) { nBlocksX++; extraTileBullshit = true; } if (ny % TileSize != 0) { nBlocksY++; extraTileBullshit = true; } debugLine("x: " + nBlocksX + ", y: " + nBlocksY + ", extraTileBullshit: " + extraTileBullshit); short nTile = 0; Dictionary<short, HfzTile> tiles = new Dictionary<short, HfzTile>(); for (UInt32 yAxis = 0; yAxis < nBlocksY; yAxis++) { for (UInt32 xAxis = 0; xAxis < nBlocksX; xAxis++) { tiles.Add(nTile, hfzReadTile(reader, header, xAxis, yAxis, extraTileBullshit)); nTile++; } } return tiles; }
private void hfzWriteHeader(ref EndianBinaryWriter writer, HfzHeader fh) { // copy header into buffer writer.Write(Util.StringToByteArray("HF2", 4)); writer.Write(fh.FileVersionNo); writer.Write(fh.nx); writer.Write(fh.ny); writer.Write(fh.TileSize); writer.Write(fh.Precis); writer.Write(fh.HorizScale); writer.Write(fh.countExtLength()); // put extended header into a buffer hfzHeader_EncodeExtHeaderBuf(fh, ref writer); }
private HfzTile hfzReadTile(EndianBinaryReader reader, HfzHeader fh, UInt32 TileX, UInt32 TileY, Boolean extraPixelBullshit) { debugLine("TileX: "+ TileX +", TileY: " + TileY); List<float> pTileData = new List<float>(); UInt32 i = 0, j = 0; UInt32 TileSize = fh.TileSize; UInt32 mapWidth = fh.nx; UInt32 mapHeight = fh.ny; UInt32 Rows = TileSize; UInt32 RowSize = TileSize-1; if (extraPixelBullshit) { Epsilon e = new Epsilon(1E-3); if (RealExtensions.EQ(TileX, (mapWidth / TileSize), e)) { debugLine("Entering X on " + TileX + "," + TileY); debugLine("result: " + (TileSize - (((TileX + 1) * TileSize) - mapWidth))); Rows = TileSize; RowSize = (TileSize - (((TileX + 1) * TileSize) - mapWidth)) - 1; } if (RealExtensions.EQ(TileY, (mapHeight / TileSize), e)) { debugLine("Entering Y on " + TileX + "," + TileY); debugLine("result: " + (TileSize - (((TileY + 1) * TileSize) - mapHeight))); Rows = TileSize - (((TileY + 1) * TileSize) - mapHeight); RowSize = TileSize - 1; } if (RealExtensions.EQ(TileX, (mapWidth / TileSize), e) && RealExtensions.EQ(TileY, (mapHeight / TileSize), e)) { debugLine("Entering X,Y on " + TileX + "," + TileY); debugLine("result: " + (TileSize - (((TileY + 1) * TileSize) - mapHeight))); debugLine("result: " + ((TileSize - (((TileX + 1) * TileSize) - mapWidth)) - 1)); Rows = TileSize - (((TileY + 1) * TileSize) - mapHeight); RowSize = (TileSize - (((TileX + 1) * TileSize) - mapWidth)) - 1; } } // read vert offset and sale byte LineDepth = 0; Int32 FirstVal = 0; int tileValues = 0; int firstValues = 0; try { float VertScale = reader.ReadSingle(); float VertOffset = reader.ReadSingle(); for (j = 0; j < Rows; j++) { LineDepth = reader.ReadByte(); // 1, 2, or 4 debugLine("Linedepth " + LineDepth); FirstVal = reader.ReadInt32(); debugLine("FirstVal " + FirstVal); tileValues++; firstValues++; float pixelValue = (float)FirstVal * VertScale + VertOffset; // set first pixel pTileData.Add(pixelValue); debugLine("FirstValue: " + pixelValue); Int32 LastVal = FirstVal; Int32 li; for (i = 0; i < RowSize; i++) { switch (LineDepth) { case 1: sbyte bvalue = reader.ReadSByte(); li = (Int32)bvalue; break; case 2: short svalue = reader.ReadInt16(); li = (Int32)svalue; break; default: li = reader.ReadInt32(); break; } pixelValue = (float)(li + LastVal) * VertScale + VertOffset; LastVal = li + LastVal; pTileData.Add(pixelValue); tileValues++; debugLine("v: " + pixelValue); } } debugLine("TileValues: " + tileValues); debugLine("FirstValues: " + firstValues); } catch (Exception) { System.Console.WriteLine("TileSize: " + TileSize); System.Console.WriteLine("x: " + TileX); System.Console.WriteLine("y: " + TileY); System.Console.WriteLine("j: " + j); System.Console.WriteLine("i: " + i); System.Console.WriteLine("LineDepth: " + LineDepth); System.Console.WriteLine("FirstVal: " + FirstVal); throw; } debugLine("total tilevalues " + tileValues); debugLine("total firstvalues " + firstValues); return new HfzTile(TileX, TileY, RowSize+1, Rows, pTileData); }
private HfzHeader hfzReadHeader(EndianBinaryReader reader) { HfzHeader fh = new HfzHeader(); string heading = UTF8Encoding.UTF8.GetString(reader.ReadBytes(4)); if (heading.Equals("HF2")) { throw new Exception("Invalid file format heading HF2 not found"); } ushort fileVersion = reader.ReadUInt16(); fh.FileVersionNo = fileVersion; UInt32 nx = reader.ReadUInt32(); fh.nx = nx; UInt32 ny = reader.ReadUInt32(); fh.ny = ny; ushort tileSize = reader.ReadUInt16(); fh.TileSize = tileSize; float Precis = reader.ReadSingle(); fh.Precis = Precis; float HorizScale = reader.ReadSingle(); fh.HorizScale = HorizScale; UInt32 ExtHeaderLength = reader.ReadUInt32(); fh.ExtHeaderLength = ExtHeaderLength; if (ExtHeaderLength > 0) { fh = decodeExtHeaderBuf(fh, reader); } return fh; }
private void hfzHeader_EncodeExtHeaderBuf(HfzHeader fh, ref EndianBinaryWriter writer) { if (fh.nExtHeaderBlocks == 0) { return; } if (fh.countExtLength() == 0) { // can't have zero length throw new Exception("Can't have a extended header of zero size"); } HfzExtHeaderBlock pBlock; for (int i = 0; i < fh.nExtHeaderBlocks; i++) { pBlock = fh.pExtHeaderBlocks.ElementAt(i); writer.Write(Util.StringToByteArray(pBlock.BlockType, 4)); writer.Write(Util.StringToByteArray(pBlock.BlockName, 16)); writer.Write(pBlock.BlockLength); if (pBlock.BlockLength > 0) { writer.Write(pBlock.pBlockData); } } }
private HfzHeader decodeExtHeaderBuf(HfzHeader fh, EndianBinaryReader reader) { if (fh.ExtHeaderLength == 0) { return fh; } fh.nExtHeaderBlocks = 0; fh.pExtHeaderBlocks = new List<HfzExtHeaderBlock>(); // read once to determine number of blocks bool DoneFlag = false; int offset = 0; do { if (offset == fh.ExtHeaderLength) { DoneFlag = true; } else if (fh.ExtHeaderLength - offset < 24) { // not enough for a complete header throw new Exception("Not enough bytes for a full extended header found. Header size: " + fh.ExtHeaderLength); } else { string blockType = UTF8Encoding.UTF8.GetString(reader.ReadBytes(4)); string blockName = UTF8Encoding.UTF8.GetString(reader.ReadBytes(16)); UInt32 blockLength = reader.ReadUInt32(); byte[] data = reader.ReadBytes((int)blockLength); HfzExtHeaderBlock block = new HfzExtHeaderBlock(blockType, blockName, blockLength, data); fh.pExtHeaderBlocks.Add(block); fh.nExtHeaderBlocks = fh.nExtHeaderBlocks + 1; offset = offset + 24 + (int)block.BlockLength; } } while (!DoneFlag); return fh; }