protected void SaveAsBmp(string path, Rectangle area, float normalization, float maxValue, DataProcessor.Abstract.DataStringProcessor processor, Behaviors.TileCreator.TileOutputType outputType, System.Drawing.Imaging.ColorPalette palette = null, Filters.ImageFilterProxy filter = null) { var destinationFileName = Path.ChangeExtension(path, ".bmp"); var padding = (area.Width % 4); padding = padding == 0 ? 0 : 4 - padding; //since bitmap width has to be multiple of 4 at all times, we have to add padding bytes var padBytes = new byte[padding]; int strDataLength = SourceFile.Width * SourceFile.Header.BytesPerSample; byte[] frameStrData = new byte[area.Width * SourceFile.Header.BytesPerSample]; float[] floatFrameStrData = new float[area.Width]; var bmpHeader = GetBitmapFileHeader(area.Width, area.Height, palette); using (var fr = System.IO.File.Open(SourceFile.Properties.FilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { using (var fw = System.IO.File.Open(destinationFileName, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite)) { long lineToStartSaving = (long)area.Y * (long)(SourceFile.Width * SourceFile.Header.BytesPerSample + SourceFile.Header.StrHeaderLength); long sampleToStartSaving = area.X * SourceFile.Header.BytesPerSample; long offset = lineToStartSaving + sampleToStartSaving; fr.Seek(SourceFile.Header.FileHeaderLength, SeekOrigin.Begin); fr.Seek(offset, SeekOrigin.Current); fw.Write(bmpHeader, 0, bmpHeader.Length); for (int i = 0; i < area.Height; i++) { OnProgressReport((int)((double)i / (double)area.Height * 100)); if (OnCancelWorker()) { fw.Flush(); return; } fr.Seek(SourceFile.Header.StrHeaderLength, SeekOrigin.Current); fr.Read(frameStrData, 0, frameStrData.Length); var processedData = processor.ProcessDataString(frameStrData); byte[] processedBytes = null; switch (outputType) { case Behaviors.TileCreator.TileOutputType.Linear: { processedBytes = processedData.AsParallel().Select(x => TileCreator.NormalizationHelpers.ToByteRange( TileCreator.NormalizationHelpers.GetLinearValue(x, normalization))).ToArray(); break; } case Behaviors.TileCreator.TileOutputType.Logarithmic: { processedBytes = processedData.AsParallel().Select(x => TileCreator.NormalizationHelpers.ToByteRange( TileCreator.NormalizationHelpers.GetLogarithmicValue(x, maxValue))).ToArray(); break; } case Behaviors.TileCreator.TileOutputType.LinearLogarithmic: { processedBytes = processedData.AsParallel().Select(x => TileCreator.NormalizationHelpers.ToByteRange( TileCreator.NormalizationHelpers.GetLinearLogarithmicValue(x, maxValue, normalization))).ToArray(); break; } default: break; } if (filter != null) { processedBytes = filter.Filter.ApplyFilters(processedBytes); } fw.Write(processedBytes, 0, floatFrameStrData.Length); fw.Write(padBytes, 0, padBytes.Length); fr.Seek(strDataLength - frameStrData.Length, SeekOrigin.Current); } } } }