├── docu
└── screenshot.png
├── App.config
├── Properties
├── Settings.settings
├── Settings.Designer.cs
├── AssemblyInfo.cs
├── Resources.Designer.cs
└── Resources.resx
├── Program.cs
├── README.md
├── Irbis-Format.sln
├── LICENSE
├── DirectBitmap.cs
├── Form1.cs
├── Logging.cs
├── Irbis-Format.csproj
├── StreamReader.cs
├── Form1.resx
├── BufferReader.cs
├── Form1.Designer.cs
├── IrbImg.cs
└── IrbFileReader.cs
/docu/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomsoftware/Irbis-File-Format/HEAD/docu/screenshot.png
--------------------------------------------------------------------------------
/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using System.Windows.Forms;
6 |
7 | namespace Irbis_Format
8 | {
9 | static class Program
10 | {
11 | ///
12 | /// Der Haupteinstiegspunkt für die Anwendung.
13 | ///
14 | [STAThread]
15 | static void Main()
16 | {
17 | Application.EnableVisualStyles();
18 | Application.SetCompatibleTextRenderingDefault(false);
19 | Application.Run(new Form1());
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Irbis-File-Format
2 | This Project demonstrates how to read the file format used by the software infratec IRBIS (*.irb) and there cameras to store
3 | thermographic Images.
4 |
5 | 
6 |
7 | Magic File Number:
8 |
9 | ```
10 | FF 49 52 42 00 49 52 42 41 43 53 IRB IRBACS
11 | ```
12 |
13 |
14 | Disclaim: infratec and IRBIS are registered Trademarks. I do not have any connections to infratec and this is just a hobby project.
15 |
16 | ## Absolute temperatures
17 | Be very careful if you want to measure absolute temperatures! More details can be found in my master thesis
18 | https://www.hmilch.net/h/master.html
19 | or on wikipedia
20 | https://en.wikipedia.org/wiki/Emissivity
21 |
22 | # Java-Version
23 | You can find a JAVA-Port at https://github.com/jonathanschilling/irb
24 |
--------------------------------------------------------------------------------
/Irbis-Format.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.25420.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Irbis-Format", "Irbis-Format.csproj", "{DDCDC4FC-A642-4B09-9F17-34CEA935504C}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {DDCDC4FC-A642-4B09-9F17-34CEA935504C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {DDCDC4FC-A642-4B09-9F17-34CEA935504C}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {DDCDC4FC-A642-4B09-9F17-34CEA935504C}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {DDCDC4FC-A642-4B09-9F17-34CEA935504C}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | EndGlobal
23 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Thomas Zeugner
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace Irbis_Format.Properties
12 | {
13 |
14 |
15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
18 | {
19 |
20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
21 |
22 | public static Settings Default
23 | {
24 | get
25 | {
26 | return defaultInstance;
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // Allgemeine Informationen über eine Assembly werden über die folgenden
6 | // Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
7 | // die einer Assembly zugeordnet sind.
8 | [assembly: AssemblyTitle("Irbis-Format")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Irbis-Format")]
13 | [assembly: AssemblyCopyright("Copyright © 2019")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar
18 | // für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von
19 | // COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen.
20 | [assembly: ComVisible(false)]
21 |
22 | // Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
23 | [assembly: Guid("ddcdc4fc-a642-4b09-9f17-34cea935504c")]
24 |
25 | // Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
26 | //
27 | // Hauptversion
28 | // Nebenversion
29 | // Buildnummer
30 | // Revision
31 | //
32 | // Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern
33 | // übernehmen, indem Sie "*" eingeben:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/DirectBitmap.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 | using System.Drawing.Imaging;
4 | using System.Runtime.InteropServices;
5 |
6 | namespace Irbis_Format
7 | {
8 | public class DirectBitmap : IDisposable
9 | {
10 | public Bitmap Bitmap { get; private set; }
11 | public Int32[] Bits { get; private set; }
12 | public bool Disposed { get; private set; }
13 | public int Height { get; private set; }
14 | public int Width { get; private set; }
15 |
16 | protected GCHandle BitsHandle { get; private set; }
17 |
18 | public DirectBitmap(int width, int height)
19 | {
20 | Width = width;
21 | Height = height;
22 | Bits = new int[width * height];
23 | BitsHandle = GCHandle.Alloc(Bits, GCHandleType.Pinned);
24 | Bitmap = new Bitmap(width, height, width * 4, PixelFormat.Format32bppPArgb, BitsHandle.AddrOfPinnedObject());
25 | }
26 |
27 | public void SetPixel(int x, int y, Color colour)
28 | {
29 | int index = x + (y * Width);
30 | int col = colour.ToArgb();
31 |
32 | Bits[index] = col;
33 | }
34 |
35 | public Color GetPixel(int x, int y)
36 | {
37 | int index = x + (y * Width);
38 | int col = Bits[index];
39 | Color result = Color.FromArgb(col);
40 |
41 | return result;
42 | }
43 |
44 | public void Dispose()
45 | {
46 | if (Disposed) return;
47 | Disposed = true;
48 | Bitmap.Dispose();
49 | BitsHandle.Free();
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Form1.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Windows.Forms;
10 |
11 | namespace Irbis_Format
12 | {
13 | public partial class Form1 : Form
14 | {
15 | private IrbImgFormat.IrbFileReader reader;
16 | private IrbImgFormat.IrbImg imgStream;
17 | private int frameIndex = 0;
18 |
19 | public Form1()
20 | {
21 | InitializeComponent();
22 | }
23 |
24 | private void button1_Click(object sender, EventArgs e)
25 | {
26 | reader = new IrbImgFormat.IrbFileReader(txtFileName.Text);
27 | imgStream = new IrbImgFormat.IrbImg(reader);
28 |
29 | lblTextInfo.Text = reader.GetTextInfo();
30 |
31 | labFrameCountNo.Text = reader.GetImageCount().ToString();
32 |
33 | ShowNextFrame();
34 | }
35 |
36 | private void ShowNextFrame()
37 | {
38 | lblFrameIndex.Text = frameIndex.ToString();
39 |
40 | if (!imgStream.ReadImage(frameIndex))
41 | {
42 | lblFrameIndex.Text = "eof";
43 | return;
44 | }
45 |
46 | frameIndex++;
47 |
48 | var img = imgStream.GetData();
49 | var w = imgStream.GetWidth();
50 | var h = imgStream.GetHeight();
51 | var dataSize = w * h;
52 |
53 | var maxValue = float.MinValue;
54 | var minValue = float.MaxValue;
55 |
56 | for (int i = 0; i < dataSize; i++)
57 | {
58 | maxValue = Math.Max(maxValue, img[i]);
59 | minValue = Math.Min(minValue, img[i]);
60 | }
61 |
62 | if (maxValue == minValue)
63 | {
64 | maxValue = minValue + 1;
65 | }
66 |
67 | lblMax.Text = maxValue.ToString();
68 | lblMin.Text = minValue.ToString();
69 |
70 | DirectBitmap bmp = new DirectBitmap(w, h);
71 |
72 | float scale = 255.0f / (maxValue - minValue);
73 |
74 | for (int i = 0; i < dataSize; i++)
75 | {
76 | var x = i % w;
77 | var y = i / w;
78 | var c = (int)((img[i] - minValue) * scale);
79 |
80 | bmp.SetPixel(x, y, Color.FromArgb(c, c, c));
81 | }
82 | picResult.Image = bmp.Bitmap;
83 | }
84 |
85 | private void button2_Click(object sender, EventArgs e)
86 | {
87 | ShowNextFrame();
88 | }
89 |
90 | private void Form1_Load(object sender, EventArgs e)
91 | {
92 | }
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/Logging.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace IrbImgFormat
4 | {
5 | public class Logging
6 | {
7 | private string m_className;
8 |
9 | //- main error handler
10 | private static Logging s_mainError;
11 |
12 |
13 | //-------------------------------------------------------//
14 | public enum enumErrorType
15 | {
16 | enumErrorType_error,
17 | enumErrorType_warning,
18 | enumErrorType_info
19 | }
20 |
21 |
22 | //-------------------------------------------------------//
23 | public Logging(string classStr = "")
24 | {
25 | m_className = classStr;
26 | }
27 |
28 | //-------------------------------------------------------//
29 | public bool addError(string errorStr, string info1 = null, string info2 = null, string info3 = null)
30 | {
31 | getMainInstance().addMSG(errorStr, enumErrorType.enumErrorType_error, m_className, info1, info2, info3);
32 | return false;
33 | }
34 |
35 | //-------------------------------------------------------//
36 | public bool addInfo(string errorStr, string info1 = null, string info2 = null, string info3 = null)
37 | {
38 | getMainInstance().addMSG(errorStr, enumErrorType.enumErrorType_info, m_className, info1, info2, info3);
39 | return false;
40 | }
41 |
42 | //-------------------------------------------------------//
43 | public bool addWarning(string errorStr, string info1 = null, string info2 = null, string info3 = null)
44 | {
45 | getMainInstance().addMSG(errorStr, enumErrorType.enumErrorType_warning, m_className, info1, info2, info3);
46 | return false;
47 | }
48 |
49 | //-------------------------------------------------------//
50 | public static void addAnonymousError(string errorStr, string className = "", string info1 = null, string info2 = null, string info3 = null)
51 | {
52 | getMainInstance().addMSG(errorStr, enumErrorType.enumErrorType_error, className, info1, info2, info3);
53 | }
54 |
55 | //-------------------------------------------------------//
56 | protected static Logging getMainInstance()
57 | {
58 | if (s_mainError == null) s_mainError = new Logging("");
59 |
60 | return s_mainError;
61 | }
62 |
63 |
64 |
65 |
66 | //-------------------------------------------------------//
67 | protected void addMSG(string errorStr, enumErrorType ErrorType, string classStr, string errorStr2 = null, string errorStr3 = null, string errorStr4 = null)
68 | {
69 | System.Diagnostics.Debug.WriteLine(classStr + " " + errorStr + " " + errorStr2);
70 |
71 | System.DateTime ErrorTimeStamp = System.DateTime.Now;
72 |
73 | System.Console.WriteLine(ErrorType + "/t" + ErrorTimeStamp + "/t" + errorStr + "/t" + classStr + "/t" + errorStr2 + "/t" + errorStr3 + "/t" + errorStr4);
74 |
75 | }
76 |
77 |
78 | }
79 |
80 | }
81 |
--------------------------------------------------------------------------------
/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // Dieser Code wurde von einem Tool generiert.
4 | // Laufzeitversion: 4.0.30319.42000
5 | //
6 | // Änderungen an dieser Datei können fehlerhaftes Verhalten verursachen und gehen verloren, wenn
7 | // der Code neu generiert wird.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace Irbis_Format.Properties
12 | {
13 |
14 |
15 | ///
16 | /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
17 | ///
18 | // Diese Klasse wurde von der StronglyTypedResourceBuilder-Klasse
19 | // über ein Tool wie ResGen oder Visual Studio automatisch generiert.
20 | // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen
21 | // mit der Option /str erneut aus, oder erstellen Sie Ihr VS-Projekt neu.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources
26 | {
27 |
28 | private static global::System.Resources.ResourceManager resourceMan;
29 |
30 | private static global::System.Globalization.CultureInfo resourceCulture;
31 |
32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
33 | internal Resources()
34 | {
35 | }
36 |
37 | ///
38 | /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird.
39 | ///
40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
41 | internal static global::System.Resources.ResourceManager ResourceManager
42 | {
43 | get
44 | {
45 | if ((resourceMan == null))
46 | {
47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Irbis_Format.Properties.Resources", typeof(Resources).Assembly);
48 | resourceMan = temp;
49 | }
50 | return resourceMan;
51 | }
52 | }
53 |
54 | ///
55 | /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle
56 | /// Ressourcenlookups, die diese stark typisierte Ressourcenklasse verwenden.
57 | ///
58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
59 | internal static global::System.Globalization.CultureInfo Culture
60 | {
61 | get
62 | {
63 | return resourceCulture;
64 | }
65 | set
66 | {
67 | resourceCulture = value;
68 | }
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/Irbis-Format.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {DDCDC4FC-A642-4B09-9F17-34CEA935504C}
8 | WinExe
9 | Properties
10 | Irbis_Format
11 | Irbis-Format
12 | v4.5.2
13 | 512
14 | true
15 |
16 |
17 | AnyCPU
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 |
26 |
27 | AnyCPU
28 | pdbonly
29 | true
30 | bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | Form
56 |
57 |
58 | Form1.cs
59 |
60 |
61 |
62 |
63 |
64 | Form1.cs
65 |
66 |
67 | ResXFileCodeGenerator
68 | Resources.Designer.cs
69 | Designer
70 |
71 |
72 | True
73 | Resources.resx
74 |
75 |
76 | SettingsSingleFileGenerator
77 | Settings.Designer.cs
78 |
79 |
80 | True
81 | Settings.settings
82 | True
83 |
84 |
85 |
86 |
87 |
88 |
89 |
96 |
--------------------------------------------------------------------------------
/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/StreamReader.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 |
4 |
5 | namespace IrbImgFormat
6 | {
7 | class StreamReader
8 | {
9 | private static Logging logging = new Logging("StreamReader");
10 | private BinaryReader m_reader;
11 | private bool m_eof;
12 |
13 | private int m_offset;
14 | private int m_blocklen;
15 | private string filename;
16 |
17 | public StreamReader(string filename)
18 | {
19 | this.m_eof = true;
20 | this.m_offset = 0;
21 |
22 | Open(filename);
23 | }
24 |
25 | ///
26 | /// return the filename of the stream
27 | ///
28 | ///
29 | public string GetFileName()
30 | {
31 | try
32 | {
33 | return System.IO.Path.GetFileName(filename);
34 | }
35 | catch (Exception)
36 | {
37 | return string.Empty;
38 | }
39 |
40 | }
41 |
42 |
43 | ///
44 | /// Open the stream
45 | ///
46 | ///
47 | private void Open(string filename)
48 | {
49 | this.filename = filename;
50 |
51 | //- Datei öffnen
52 | try
53 | {
54 | m_reader = new System.IO.BinaryReader(System.IO.File.Open(filename, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read));
55 |
56 | this.m_eof = false;
57 | m_blocklen = (int)m_reader.BaseStream.Length; //- Beschränkung auf max 2GB Dateigröße
58 | }
59 | catch (System.Exception ex)
60 | {
61 | logging.addError("IO.BinaryReader fail", ex.Message, filename);
62 | return;
63 | }
64 |
65 | }
66 |
67 |
68 | ///
69 | /// Close the stream
70 | ///
71 | public void Close()
72 | {
73 | if (m_reader != null) m_reader.Close();
74 | }
75 |
76 |
77 | ///
78 | /// is the stream pointer at the end of the file?
79 | ///
80 | public bool Eof
81 | {
82 | get
83 | {
84 | return ((m_reader == null) || (m_eof));
85 | }
86 | }
87 |
88 | ///
89 | /// Sets the stream read position
90 | ///
91 | ///
92 | public void SetOffset(int offset)
93 | {
94 | if ((offset < m_blocklen) && (offset >= 0))
95 | {
96 | m_offset = offset;
97 | m_reader.BaseStream.Seek(m_offset, System.IO.SeekOrigin.Begin);
98 | m_eof = false;
99 | }
100 | else
101 | {
102 | m_eof = true;
103 | if (offset < 0) m_offset = 0;
104 | if (offset >= m_blocklen) m_offset = m_blocklen;
105 | m_reader.BaseStream.Seek(m_offset, System.IO.SeekOrigin.Begin);
106 | }
107 | }
108 |
109 |
110 | ///
111 | /// Read length bytes from the stream
112 | ///
113 | public byte[] ReadByte(int length, int offset)
114 | {
115 | if (length < 0) length = 0;
116 | if (offset > -1)
117 | {
118 | m_reader.BaseStream.Seek(offset, System.IO.SeekOrigin.Begin);
119 | m_offset = offset;
120 | }
121 |
122 | byte[] dataArray = null;
123 |
124 |
125 | if (m_offset < m_blocklen)
126 | {
127 | if ((m_offset + length) > m_blocklen)
128 | {
129 | m_eof = true;
130 | length = m_blocklen - m_offset;
131 | }
132 |
133 | dataArray = new byte[length];
134 |
135 |
136 | try
137 | {
138 | length = m_reader.Read(dataArray, 0, length);
139 | }
140 | catch (Exception e)
141 | {
142 | logging.addError("readByte(): length: " + length + " / offset: " + offset + " - " + e.Message);
143 | length = 0;
144 | m_eof = true;
145 | }
146 |
147 | if (length != dataArray.Length) System.Array.Resize(ref dataArray, length);
148 | }
149 | else
150 | {
151 | if (length > 0)
152 | {
153 | logging.addWarning("ReadStr:EOF!");
154 | length = 0;
155 | }
156 |
157 | m_eof = true;
158 | }
159 |
160 |
161 | if (length > 0) m_offset = m_offset + length;
162 |
163 | return dataArray;
164 | }
165 |
166 |
167 | ///
168 | /// Read a string from the stream
169 | ///
170 | public string ReadStr(int length, int offset = -1)
171 | {
172 | string outVal = "";
173 |
174 | byte[] tmpData = this.ReadByte(length, offset);
175 |
176 | if (tmpData != null)
177 | {
178 | outVal = System.Text.Encoding.Default.GetString(tmpData);
179 | }
180 |
181 | return outVal;
182 | }
183 |
184 |
185 |
186 | ///
187 | /// Read big ending int from the stream
188 | ///
189 | public int ReadIntBE(int offset = -1)
190 | {
191 | byte[] tmpData = this.ReadByte(4, offset);
192 |
193 | if ((tmpData == null) || (tmpData.Length != 4))
194 | {
195 | return 0;
196 | }
197 |
198 | return (int)(tmpData[0] | (tmpData[1] << 8) | (tmpData[2] << 16) | (tmpData[3] << 24));
199 |
200 | }
201 |
202 |
203 | }
204 | }
205 |
--------------------------------------------------------------------------------
/Form1.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
--------------------------------------------------------------------------------
/BufferReader.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 |
4 | namespace IrbImgFormat
5 | {
6 | class BufferReader
7 | {
8 | private static Logging logging = new Logging("BufferReader");
9 |
10 | ///
11 | /// Union to cast a 4-byte int to a float
12 | ///
13 | [StructLayout(LayoutKind.Explicit)]
14 | private struct BinaryConvertIntToFloat
15 | {
16 | [FieldOffset(0)]
17 | public float toFloat;
18 | [FieldOffset(0)]
19 | public int toInt;
20 | }
21 |
22 |
23 |
24 | ///
25 | /// Union to cast a 8 byte long into a double
26 | ///
27 | [StructLayout(LayoutKind.Explicit)]
28 | private struct BinaryConvertLongToDouble
29 | {
30 | [FieldOffset(0)]
31 | public double toDouble;
32 | [FieldOffset(0)]
33 | public long toLong;
34 | }
35 |
36 |
37 | byte[] data;
38 | int offset = 0;
39 | int dataLength = 0;
40 |
41 | public BufferReader(byte[] data)
42 | {
43 | this.data = data;
44 | dataLength = (data != null) ? data.Length : 0;
45 | }
46 |
47 | ///
48 | /// is the buffer Pointer at the end of the buffer
49 | ///
50 | public bool Eof
51 | {
52 | get
53 | {
54 | return ((offset < 0) || (offset >= dataLength) || (data == null));
55 | }
56 | }
57 |
58 | ///
59 | /// Return the lenght of the buffer
60 | ///
61 | public int Length
62 | {
63 | get
64 | {
65 | return data.Length;
66 | }
67 | }
68 |
69 | ///
70 | /// Read a string from the the buffer
71 | ///
72 | public string ReadStr(int length, int offset)
73 | {
74 | if (length < 0) length = 0;
75 | if (offset > -1) this.offset = offset;
76 |
77 | string outVal = "";
78 |
79 |
80 | if (this.offset < dataLength)
81 | {
82 | if ((this.offset + length) > dataLength)
83 | {
84 | length = dataLength - this.offset;
85 | }
86 |
87 | outVal = System.Text.Encoding.Default.GetString(data, this.offset, length);
88 | }
89 | else
90 | {
91 | if (length > 0)
92 | {
93 | logging.addWarning("ReadStr:EOF!");
94 | length = 0;
95 | }
96 | }
97 |
98 |
99 | if (length > 0) this.offset = this.offset + length;
100 |
101 | return outVal;
102 | }
103 |
104 |
105 | ///
106 | /// read a NULL terminated string from buffer
107 | ///
108 | public string ReadNullTerminatedString(int offset, int size)
109 | {
110 | string s = this.ReadStr(size, offset);
111 |
112 | int pos = s.IndexOf('\0');
113 |
114 | if (pos > 0)
115 | {
116 | return s.Substring(0, pos);
117 | }
118 | return s;
119 | }
120 |
121 |
122 | ///
123 | /// Read 8 byte big ending long from buffer
124 | ///
125 | public long ReadLongBE(int offset = -1)
126 | {
127 | if (offset > -1) this.offset = offset;
128 |
129 | if (this.offset < dataLength)
130 | {
131 | if ((this.offset + 8) > dataLength)
132 | {
133 | this.offset = dataLength;
134 | return 0;
135 | }
136 |
137 |
138 | byte[] d = data;
139 | int i = this.offset;
140 |
141 | byte[] bytes = { d[i + 0], d[i + 1], d[i + 2], d[i + 3], d[i + 4], d[i + 5], d[i + 6], d[i + 7] };
142 |
143 | return BitConverter.ToInt64(bytes, 0);
144 | }
145 | return 0;
146 |
147 |
148 | }
149 |
150 | ///
151 | /// Read one byte from buffer
152 | ///
153 | public int ReadByte(int offset = -1)
154 | {
155 | if (offset > -1) this.offset = offset;
156 |
157 | if (this.offset >= dataLength)
158 | {
159 | return 0;
160 | }
161 |
162 | if ((this.offset + 1) > dataLength)
163 | {
164 | this.offset = dataLength;
165 | return 0;
166 | }
167 |
168 |
169 | var result = data[this.offset];
170 | this.offset++;
171 | return result;
172 |
173 |
174 | }
175 |
176 |
177 | ///
178 | /// Read big ending word (2 Bytes) from buffer
179 | ///
180 | ///
181 | ///
182 | public int ReadWordBE(int offset = -1)
183 | {
184 | if (offset > -1)
185 | {
186 | this.offset = offset;
187 | }
188 |
189 |
190 | if (this.offset >= dataLength)
191 | {
192 | return 0;
193 | }
194 |
195 | if ((this.offset + 2) > dataLength)
196 | {
197 | this.offset = dataLength;
198 | return 0;
199 | }
200 |
201 |
202 | var result = (int)data[this.offset] + (data[this.offset + 1] << 8);
203 |
204 | this.offset += 2;
205 | return result;
206 |
207 |
208 | }
209 |
210 |
211 |
212 | ///
213 | /// Read big-ending int from buffer
214 | ///
215 | public int ReadIntBE(int offset = -1)
216 | {
217 | if (offset > -1)
218 | {
219 | this.offset = offset;
220 | }
221 |
222 |
223 | if (this.offset >= dataLength)
224 | {
225 | return 0;
226 | }
227 |
228 | if ((this.offset + 4) > dataLength)
229 | {
230 | this.offset = dataLength;
231 | return 0;
232 | }
233 |
234 |
235 | var result = (int)data[this.offset] + (data[this.offset + 1] << 8) + (data[this.offset + 2] << 16) + (data[this.offset + 3] << 24);
236 |
237 | this.offset += 4;
238 | return result;
239 | }
240 |
241 |
242 | ///
243 | /// read double from buffer
244 | ///
245 | public double ReadDoubleBE(int length = 8, int offset = -1)
246 | {
247 | BinaryConvertLongToDouble converterLongDouble;
248 | converterLongDouble.toDouble = 0.0; /// need to be set to avoid compiler errors
249 |
250 | converterLongDouble.toLong = ReadLongBE(offset);
251 | return converterLongDouble.toDouble;
252 | }
253 |
254 |
255 | ///
256 | /// read float from buffer
257 | ///
258 | public float ReadSingleBE(int offset = -1)
259 | {
260 | BinaryConvertIntToFloat converterIntFloat;
261 | converterIntFloat.toFloat = 0.0f; /// need to be set to avoid compiler errors
262 |
263 | converterIntFloat.toInt = ReadIntBE(offset);
264 | return converterIntFloat.toFloat;
265 | }
266 |
267 | }
268 | }
269 |
--------------------------------------------------------------------------------
/Form1.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace Irbis_Format
2 | {
3 | partial class Form1
4 | {
5 | ///
6 | /// Erforderliche Designervariable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Verwendete Ressourcen bereinigen.
12 | ///
13 | /// True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Vom Windows Form-Designer generierter Code
24 |
25 | ///
26 | /// Erforderliche Methode für die Designerunterstützung.
27 | /// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | this.button1 = new System.Windows.Forms.Button();
32 | this.txtFileName = new System.Windows.Forms.TextBox();
33 | this.labFrameCount = new System.Windows.Forms.Label();
34 | this.labFrameCountNo = new System.Windows.Forms.Label();
35 | this.button2 = new System.Windows.Forms.Button();
36 | this.picResult = new System.Windows.Forms.PictureBox();
37 | this.lblMax = new System.Windows.Forms.Label();
38 | this.label2 = new System.Windows.Forms.Label();
39 | this.lblMin = new System.Windows.Forms.Label();
40 | this.label4 = new System.Windows.Forms.Label();
41 | this.lblTextInfo = new System.Windows.Forms.Label();
42 | this.label1 = new System.Windows.Forms.Label();
43 | this.lblFrameIndex = new System.Windows.Forms.Label();
44 | this.label5 = new System.Windows.Forms.Label();
45 | this.label3 = new System.Windows.Forms.Label();
46 | ((System.ComponentModel.ISupportInitialize)(this.picResult)).BeginInit();
47 | this.SuspendLayout();
48 | //
49 | // button1
50 | //
51 | this.button1.Location = new System.Drawing.Point(625, 11);
52 | this.button1.Name = "button1";
53 | this.button1.Size = new System.Drawing.Size(70, 45);
54 | this.button1.TabIndex = 0;
55 | this.button1.Text = "load";
56 | this.button1.UseVisualStyleBackColor = true;
57 | this.button1.Click += new System.EventHandler(this.button1_Click);
58 | //
59 | // txtFileName
60 | //
61 | this.txtFileName.Location = new System.Drawing.Point(12, 25);
62 | this.txtFileName.Name = "txtFileName";
63 | this.txtFileName.Size = new System.Drawing.Size(409, 20);
64 | this.txtFileName.TabIndex = 1;
65 | this.txtFileName.Text = "C:\\Irbis-Format\\start.irb";
66 | //
67 | // labFrameCount
68 | //
69 | this.labFrameCount.AutoSize = true;
70 | this.labFrameCount.Location = new System.Drawing.Point(506, 66);
71 | this.labFrameCount.Name = "labFrameCount";
72 | this.labFrameCount.Size = new System.Drawing.Size(69, 13);
73 | this.labFrameCount.TabIndex = 2;
74 | this.labFrameCount.Text = "Frame count:";
75 | //
76 | // labFrameCountNo
77 | //
78 | this.labFrameCountNo.AutoSize = true;
79 | this.labFrameCountNo.Location = new System.Drawing.Point(524, 79);
80 | this.labFrameCountNo.Name = "labFrameCountNo";
81 | this.labFrameCountNo.Size = new System.Drawing.Size(10, 13);
82 | this.labFrameCountNo.TabIndex = 3;
83 | this.labFrameCountNo.Text = "-";
84 | //
85 | // button2
86 | //
87 | this.button2.Location = new System.Drawing.Point(625, 62);
88 | this.button2.Name = "button2";
89 | this.button2.Size = new System.Drawing.Size(70, 45);
90 | this.button2.TabIndex = 4;
91 | this.button2.Text = "next frame";
92 | this.button2.UseVisualStyleBackColor = true;
93 | this.button2.Click += new System.EventHandler(this.button2_Click);
94 | //
95 | // picResult
96 | //
97 | this.picResult.Location = new System.Drawing.Point(127, 53);
98 | this.picResult.Name = "picResult";
99 | this.picResult.Size = new System.Drawing.Size(364, 271);
100 | this.picResult.TabIndex = 5;
101 | this.picResult.TabStop = false;
102 | //
103 | // lblMax
104 | //
105 | this.lblMax.AutoSize = true;
106 | this.lblMax.Location = new System.Drawing.Point(524, 158);
107 | this.lblMax.Name = "lblMax";
108 | this.lblMax.Size = new System.Drawing.Size(10, 13);
109 | this.lblMax.TabIndex = 7;
110 | this.lblMax.Text = "-";
111 | //
112 | // label2
113 | //
114 | this.label2.AutoSize = true;
115 | this.label2.Location = new System.Drawing.Point(506, 144);
116 | this.label2.Name = "label2";
117 | this.label2.Size = new System.Drawing.Size(58, 13);
118 | this.label2.TabIndex = 6;
119 | this.label2.Text = "max-value:";
120 | //
121 | // lblMin
122 | //
123 | this.lblMin.AutoSize = true;
124 | this.lblMin.Location = new System.Drawing.Point(524, 197);
125 | this.lblMin.Name = "lblMin";
126 | this.lblMin.Size = new System.Drawing.Size(10, 13);
127 | this.lblMin.TabIndex = 9;
128 | this.lblMin.Text = "-";
129 | //
130 | // label4
131 | //
132 | this.label4.AutoSize = true;
133 | this.label4.Location = new System.Drawing.Point(506, 184);
134 | this.label4.Name = "label4";
135 | this.label4.Size = new System.Drawing.Size(55, 13);
136 | this.label4.TabIndex = 8;
137 | this.label4.Text = "min-value:";
138 | //
139 | // lblTextInfo
140 | //
141 | this.lblTextInfo.AutoSize = true;
142 | this.lblTextInfo.Location = new System.Drawing.Point(12, 66);
143 | this.lblTextInfo.Name = "lblTextInfo";
144 | this.lblTextInfo.Size = new System.Drawing.Size(10, 13);
145 | this.lblTextInfo.TabIndex = 10;
146 | this.lblTextInfo.Text = "-";
147 | //
148 | // label1
149 | //
150 | this.label1.AutoSize = true;
151 | this.label1.Location = new System.Drawing.Point(0, 53);
152 | this.label1.Name = "label1";
153 | this.label1.Size = new System.Drawing.Size(31, 13);
154 | this.label1.TabIndex = 11;
155 | this.label1.Text = "Text:";
156 | //
157 | // lblFrameIndex
158 | //
159 | this.lblFrameIndex.AutoSize = true;
160 | this.lblFrameIndex.Location = new System.Drawing.Point(524, 119);
161 | this.lblFrameIndex.Name = "lblFrameIndex";
162 | this.lblFrameIndex.Size = new System.Drawing.Size(10, 13);
163 | this.lblFrameIndex.TabIndex = 13;
164 | this.lblFrameIndex.Text = "-";
165 | //
166 | // label5
167 | //
168 | this.label5.AutoSize = true;
169 | this.label5.Location = new System.Drawing.Point(506, 105);
170 | this.label5.Name = "label5";
171 | this.label5.Size = new System.Drawing.Size(67, 13);
172 | this.label5.TabIndex = 12;
173 | this.label5.Text = "Frame-index:";
174 | //
175 | // label3
176 | //
177 | this.label3.AutoSize = true;
178 | this.label3.Location = new System.Drawing.Point(0, 9);
179 | this.label3.Name = "label3";
180 | this.label3.Size = new System.Drawing.Size(41, 13);
181 | this.label3.TabIndex = 14;
182 | this.label3.Text = "Source";
183 | //
184 | // Form1
185 | //
186 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
187 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
188 | this.ClientSize = new System.Drawing.Size(707, 414);
189 | this.Controls.Add(this.label3);
190 | this.Controls.Add(this.lblFrameIndex);
191 | this.Controls.Add(this.label5);
192 | this.Controls.Add(this.label1);
193 | this.Controls.Add(this.lblTextInfo);
194 | this.Controls.Add(this.lblMin);
195 | this.Controls.Add(this.label4);
196 | this.Controls.Add(this.lblMax);
197 | this.Controls.Add(this.label2);
198 | this.Controls.Add(this.picResult);
199 | this.Controls.Add(this.button2);
200 | this.Controls.Add(this.labFrameCountNo);
201 | this.Controls.Add(this.labFrameCount);
202 | this.Controls.Add(this.txtFileName);
203 | this.Controls.Add(this.button1);
204 | this.Name = "Form1";
205 | this.Text = "IRBIS File Format";
206 | this.Load += new System.EventHandler(this.Form1_Load);
207 | ((System.ComponentModel.ISupportInitialize)(this.picResult)).EndInit();
208 | this.ResumeLayout(false);
209 | this.PerformLayout();
210 |
211 | }
212 |
213 | #endregion
214 |
215 | private System.Windows.Forms.Button button1;
216 | private System.Windows.Forms.TextBox txtFileName;
217 | private System.Windows.Forms.Label labFrameCount;
218 | private System.Windows.Forms.Label labFrameCountNo;
219 | private System.Windows.Forms.Button button2;
220 | private System.Windows.Forms.PictureBox picResult;
221 | private System.Windows.Forms.Label lblMax;
222 | private System.Windows.Forms.Label label2;
223 | private System.Windows.Forms.Label lblMin;
224 | private System.Windows.Forms.Label label4;
225 | private System.Windows.Forms.Label lblTextInfo;
226 | private System.Windows.Forms.Label label1;
227 | private System.Windows.Forms.Label lblFrameIndex;
228 | private System.Windows.Forms.Label label5;
229 | private System.Windows.Forms.Label label3;
230 | }
231 | }
232 |
233 |
--------------------------------------------------------------------------------
/IrbImg.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 |
4 |
5 | namespace IrbImgFormat
6 | {
7 | class IrbImg
8 | {
9 | private static Logging logging = new Logging("IrbImg");
10 |
11 |
12 | public double ShotRangeMin { get; protected set; }
13 | public double ShotRangeMax { get; protected set; }
14 | public double CalibRangeMin { get; protected set; }
15 | public double CalibRangeMax { get; protected set; }
16 |
17 |
18 | IrbFileReader reader;
19 |
20 | int BytePerPixel;
21 | int Compressed;
22 |
23 | float Emissivity;
24 |
25 | float EnvironmentalTemp;
26 | float Distanz;
27 |
28 | float PathTemperature;
29 | float CenterWavelength;
30 |
31 | float CalibRange_min;
32 | float CalibRange_max;
33 |
34 | float ShotRange_start_ERROR;
35 | float ShotRange_size;
36 |
37 | double TimeStamp_Raw;
38 | DateTime TimeStamp;
39 | DateTime TimeStampOffsetTime;
40 |
41 | int TimeStampOffsetMilliseconds;
42 | int TimeStampMilliseconds;
43 |
44 | string Device;
45 | string DeviceSerial;
46 | string Optics;
47 | string OpticsResolution;
48 | string OpticsText;
49 |
50 | public float[] Data;
51 |
52 |
53 | private int Width;
54 | private int Height;
55 |
56 |
57 |
58 | public IrbImg(IrbFileReader FileReader, int imageIndex = 0)
59 | {
60 | reader = FileReader;
61 | ReadImage(imageIndex);
62 | }
63 |
64 |
65 | ///
66 | /// Width of the image
67 | ///
68 | ///
69 | public int GetWidth()
70 | {
71 | return Width;
72 | }
73 |
74 | ///
75 | /// Height of the image
76 | ///
77 | public int GetHeight()
78 | {
79 | return Height;
80 | }
81 |
82 | ///
83 | /// Return the data of the image as float array
84 | ///
85 | ///
86 | public float[] GetData()
87 | {
88 | if (Data == null) logging.addError("getData() Accessing non initialised data!");
89 | return Data;
90 | }
91 |
92 |
93 | ///
94 | /// Read a image from the file
95 | ///
96 | public bool ReadImage(int imageIndex)
97 | {
98 | System.DateTime FrameTime = System.DateTime.Now;
99 |
100 |
101 | var reader = new BufferReader(this.reader.GetImageData(imageIndex));
102 |
103 | if (reader.Eof)
104 | {
105 | return false;
106 | }
107 |
108 | Width = 0;
109 | Height = 0;
110 |
111 |
112 | //- Image header
113 | BytePerPixel = reader.ReadWordBE();
114 | Compressed = reader.ReadWordBE();
115 | Width = reader.ReadWordBE();
116 | Height = reader.ReadWordBE();
117 |
118 |
119 | reader.ReadIntBE(); //-- don't know - alway 0
120 | reader.ReadWordBE(); //-- don't know - alway 0
121 |
122 | //- dont know why but it is alwasy the width -1
123 | if (reader.ReadWordBE() != (Width - 1))
124 | {
125 | logging.addError("??? value != (Height - 1)");
126 | }
127 |
128 |
129 | reader.ReadWordBE(); //-- don't know - alway 0
130 |
131 | //- dont know why but it is alwasy the height -1
132 | if (reader.ReadWordBE() != (Height - 1))
133 | {
134 | logging.addError("??? value != (Height - 1)");
135 | }
136 |
137 |
138 | reader.ReadWordBE(); //-- don't know - alway 0
139 | reader.ReadWordBE(); //-- don't know - alway 0
140 |
141 | Emissivity = reader.ReadSingleBE();
142 |
143 | Distanz = reader.ReadSingleBE();
144 |
145 | EnvironmentalTemp = reader.ReadSingleBE();
146 |
147 |
148 | reader.ReadWordBE(); //-- don't know - always 0
149 | reader.ReadWordBE(); //-- don't know - always 0
150 |
151 | PathTemperature = reader.ReadSingleBE();
152 |
153 | reader.ReadWordBE(); //-- don't know - always 0x65
154 | reader.ReadWordBE(); //-- don't know - always 0
155 |
156 |
157 | CenterWavelength = reader.ReadSingleBE();
158 |
159 |
160 | reader.ReadWordBE(); //-- don't know - always 0
161 | reader.ReadWordBE(); //-- don't know - always 0xH4080
162 | reader.ReadWordBE(); //-- don't know - always 0x9
163 | reader.ReadWordBE(); //-- don't know - always 0x101
164 |
165 |
166 | if ((Width > 10000) || (Height > 10000))
167 | {
168 | logging.addError("Defect Irbis Image File: Image Width(" + Width + ") or Height(" + Height + ") is out of range!");
169 | Width = 1;
170 | Height = 1;
171 | return false;
172 | }
173 |
174 | //- liest weitere Bildinforationen aus
175 | this.ReadFlags(reader, 1084);
176 |
177 | Data = ReadImageData(reader, 0x6C0, Width, Height, 60, Compressed);
178 |
179 |
180 |
181 | if (reader.Eof) logging.addError("end of file!");
182 |
183 | return true;
184 | }
185 |
186 |
187 | ///
188 | /// Read image flags from the file
189 | ///
190 | public void ReadFlags(BufferReader reader, int offset)
191 | {
192 | CalibRange_min = reader.ReadSingleBE(offset + 92);
193 | CalibRange_max = reader.ReadSingleBE(offset + 96);
194 |
195 |
196 | Device = reader.ReadNullTerminatedString(offset + 142, 12);
197 | DeviceSerial = reader.ReadNullTerminatedString(offset + 186, 16);
198 | Optics = reader.ReadNullTerminatedString(offset + 202, 32);
199 | OpticsResolution = reader.ReadNullTerminatedString(offset + 234, 32);
200 | OpticsText = reader.ReadNullTerminatedString(offset + 554, 48);
201 |
202 | ShotRange_start_ERROR = reader.ReadSingleBE(offset + 532);
203 | ShotRange_size = reader.ReadSingleBE(offset + 536);
204 |
205 |
206 | TimeStamp_Raw = reader.ReadDoubleBE(8, offset + 540);
207 | TimeStampMilliseconds = reader.ReadIntBE(offset + 548);
208 |
209 | TimeStamp = Double2DateTime(TimeStamp_Raw, TimeStampMilliseconds);
210 | }
211 |
212 |
213 |
214 |
215 | ///
216 | /// Read the compressing "pallet" from file
217 | ///
218 | private float[] ReadPallet(BufferReader reader, int offset)
219 | {
220 | float[] palette = new float[256];
221 |
222 | int pos = offset;
223 |
224 | for (int i = 0; i < 256; i++)
225 | {
226 | palette[i] = reader.ReadSingleBE(pos);
227 | pos += 4;
228 | }
229 |
230 | return palette;
231 | }
232 |
233 |
234 |
235 | ///
236 | /// Read the image data from file
237 | ///
238 | ///
239 | private float[] ReadImageData(BufferReader reader, int bindata_offset, int width, int height, int palette_offset, int useCompression)
240 | {
241 | int data_size = width * height; //- count of pixles
242 | bool useComp = (useCompression == 1);
243 |
244 | int pixelCount = data_size;
245 | float[] matrixData = new float[pixelCount];
246 |
247 | int matrixDataPos = 0;
248 |
249 | int v1_pos = bindata_offset;
250 | int v2_pos = v1_pos + width * height; //- used if data are compressed
251 |
252 | //byte data_v1 = &bindata[v1_pos];
253 | //unsigned char* data_v2 = &bindata[v2_pos];
254 |
255 | int v1 = 0;
256 | int v2 = 0;
257 |
258 |
259 | float[] Palette = ReadPallet(reader, palette_offset);
260 |
261 |
262 | int v2_count = 0;
263 | float v = 0;
264 | float f;
265 |
266 |
267 | if (!useComp)
268 | {
269 | for (int i = pixelCount; i > 0; i--)
270 | {
271 | //- read values
272 | v1 = reader.ReadByte(v1_pos);
273 | v1_pos++;
274 | v2 = reader.ReadByte(v1_pos);
275 | v1_pos++;
276 |
277 | f = (float)v1 * (1.0f / 256.0f);
278 |
279 | //- lineare interpolation
280 | v = Palette[v2 + 1] * f + Palette[v2] * (1.0f - f);
281 |
282 | if (v < 0) v = 0; //- oder 255
283 |
284 | matrixData[matrixDataPos] = v;
285 | matrixDataPos++;
286 | }
287 | }
288 | else
289 | {
290 | for (int i = pixelCount; i > 0; i--)
291 | {
292 | //- werte lesen
293 | if (v2_count-- < 1) //- ok... neuen wert für V2 lesen
294 | {
295 | v2_count = reader.ReadByte(v2_pos) - 1;
296 | v2_pos++;
297 |
298 | v2 = reader.ReadByte(v2_pos);
299 | v2_pos++;
300 | }
301 |
302 | v1 = reader.ReadByte(v1_pos);
303 | v1_pos++;
304 |
305 | f = (float)v1 * (1.0f / 256.0f);
306 |
307 | //- lineare interpolation
308 | v = Palette[v2 + 1] * f + Palette[v2] * (1.0f - f);
309 |
310 | if (v < 0) v = 0; //- oder 255
311 |
312 | matrixData[matrixDataPos] = v;
313 | matrixDataPos++;
314 | }
315 | }
316 |
317 | return matrixData;
318 |
319 | }
320 |
321 |
322 | ///
323 | /// convert a double value to a date time
324 | ///
325 | private System.DateTime Double2DateTime(double date, int Milliseconds = 0)
326 | {
327 | System.DateTime d = DateTime.FromOADate(date);
328 |
329 | //- calc the time from the Date + Milliseconds
330 | if ((TimeStampOffsetTime != DateTime.MinValue) && (Milliseconds > 0) && (Milliseconds > TimeStampOffsetMilliseconds) && (d >= TimeStampOffsetTime))
331 | {
332 | return TimeStampOffsetTime.AddMilliseconds(Milliseconds - TimeStampOffsetMilliseconds);
333 | }
334 | else
335 | {
336 | //- never set so save start-date/time
337 | TimeStampOffsetMilliseconds = Milliseconds;
338 | TimeStampOffsetTime = d;
339 | return d;
340 | }
341 |
342 | }
343 |
344 |
345 | }
346 | }
347 |
--------------------------------------------------------------------------------
/IrbFileReader.cs:
--------------------------------------------------------------------------------
1 | namespace IrbImgFormat
2 | {
3 | class IrbFileReader
4 | {
5 | public enum enumBlockType
6 | {
7 | enumBlockTypeUnknown = -1,
8 | enumBlockTypeEmpty = 0,
9 | enumBlockTypeImage = 1,
10 | enumBlockTypePreview = 2,
11 | enumBlockTypeTextInfo = 3,
12 | enumBlockTypeHeader = 4,
13 | enumBlockTypeAudio = 7
14 |
15 | };
16 |
17 | public enum enumFileType
18 | {
19 | enumFileTypeImage = 1,
20 | enumFileTypeSequenz = 2
21 | };
22 |
23 | private struct tyBlock
24 | {
25 | public enumBlockType BlockType;
26 | public int DWord2;
27 | public int FrameIndex;
28 | public int offset;
29 | public int size;
30 | public int DWord6;
31 | public int DWord7;
32 | public int DWord8;
33 | public int headerOffset;
34 | public int headerSize;
35 | public int imageOffset;
36 | public int imageSize;
37 | };
38 |
39 |
40 | private struct tyHead
41 | {
42 | public string MagicNumber;
43 | public string FileType;
44 | public string FileType2;
45 | public enumFileType FileType2enum;
46 |
47 | public int Flag1;
48 | public int FirstBlockCount;
49 |
50 | public int BlockOffset;
51 | public int BlockCount;
52 | public tyBlock[] Block;
53 | public int BlockCountMax;
54 | };
55 |
56 | private static Logging logging = new Logging("IrbFileReader");
57 |
58 |
59 | private tyHead Head;
60 |
61 | private StreamReader reader;
62 | private int m_imageCount;
63 |
64 |
65 |
66 | //-------------------------------------//
67 | public IrbFileReader(string filename)
68 | {
69 | this.m_imageCount = 0;
70 |
71 | reader = new StreamReader(filename);
72 |
73 |
74 | Head.MagicNumber = reader.ReadStr(5);
75 |
76 | //- ID
77 | if (string.Compare(Head.MagicNumber, "\xFFIRB\0") != 0) //-- soll "\xFF" "IRB" "\0" aber C schneidet das \0 weg!
78 | {
79 | logging.addError("Irb File - ''Magische Number'' wrong");
80 | return;
81 | }
82 |
83 | //- FileType
84 | Head.FileType = reader.ReadStr(8);
85 |
86 | if (string.Compare(Head.FileType, "IRBACS\0\0") != 0)
87 | {
88 | Head.FileType2enum = enumFileType.enumFileTypeImage;
89 | }
90 | else if (string.Compare(Head.FileType, "IRBIS 3\0") != 0)
91 | {
92 | Head.FileType2enum = enumFileType.enumFileTypeSequenz;
93 | }
94 | else
95 | {
96 | logging.addError("Unknown Irbis File Type");
97 | return;
98 | }
99 |
100 |
101 |
102 | Head.FileType2 = reader.ReadStr(8);
103 |
104 | Head.Flag1 = reader.ReadIntBE();
105 | Head.BlockOffset = reader.ReadIntBE(); //- starts at 0
106 | Head.FirstBlockCount = reader.ReadIntBE();
107 |
108 | Head.BlockCount = 0;
109 | this.AddHead(Head.BlockOffset, Head.FirstBlockCount);
110 |
111 | int i = 0;
112 | while (i < Head.BlockCount)
113 | {
114 | if (Head.Block[i].BlockType == enumBlockType.enumBlockTypeHeader)
115 | {
116 | this.AddHead(Head.Block[i].offset, 2);
117 | }
118 | i++;
119 | }
120 |
121 |
122 | }
123 |
124 | //-------------------------------------------------------//
125 | public void Close()
126 | {
127 | if (reader != null)
128 | {
129 | reader.Close();
130 | }
131 | }
132 |
133 |
134 |
135 | //-------------------------------------//
136 | private void AddHead(int offset, int count)
137 | {
138 | if ((Head.BlockCount + count) > Head.BlockCountMax)
139 | {
140 | Head.BlockCountMax = Head.BlockCountMax + count + 100;
141 |
142 | System.Array.Resize(ref Head.Block, Head.BlockCountMax);
143 | }
144 |
145 |
146 | reader.SetOffset(offset);
147 |
148 | if (reader.Eof) return;
149 |
150 |
151 | for (int i = 0; i < count; i++)
152 | {
153 | if (reader.Eof) return;
154 |
155 | SetHeadBlockVars(ref Head.Block[Head.BlockCount]);
156 |
157 | Head.BlockCount++;
158 | }
159 | }
160 |
161 |
162 | //-------------------------------------//
163 | private void SetHeadBlockVars(ref tyBlock block)
164 | {
165 | block.BlockType = (enumBlockType)reader.ReadIntBE();
166 |
167 | block.DWord2 = reader.ReadIntBE();
168 | block.FrameIndex = reader.ReadIntBE();
169 |
170 |
171 | block.offset = reader.ReadIntBE(); // starts at 0
172 |
173 | block.size = reader.ReadIntBE();
174 |
175 | //- head is wlways 0x6C0 Byte in lengtg
176 | block.headerSize = 0x6C0;
177 | if (block.headerSize > block.size) block.headerSize = block.size;
178 |
179 |
180 | block.headerOffset = 0;
181 |
182 | block.imageOffset = block.headerSize;
183 | block.imageSize = block.size - block.imageOffset;
184 |
185 |
186 |
187 | block.DWord6 = reader.ReadIntBE();
188 | block.DWord7 = reader.ReadIntBE();
189 | block.DWord8 = reader.ReadIntBE();
190 |
191 | if (block.BlockType == enumBlockType.enumBlockTypeImage)
192 | {
193 | this.m_imageCount++;
194 | }
195 | }
196 |
197 |
198 | //-------------------------------------//
199 | public int GetImageCount()
200 | {
201 | return this.m_imageCount;
202 | }
203 |
204 |
205 |
206 |
207 | //-------------------------------------//
208 | public int GetBlockCount()
209 | {
210 | return Head.BlockCount;
211 | }
212 |
213 |
214 | //-------------------------------------//
215 | public int GetBlockSize(int index)
216 | {
217 | if ((index >= 0) && (index < Head.BlockCount))
218 | {
219 | return Head.Block[index].size;
220 | }
221 | else
222 | {
223 | return 0;
224 | }
225 | }
226 |
227 |
228 | //-------------------------------------//
229 | public bool IsBlockImage(int index)
230 | {
231 | if ((index >= 0) && (index < Head.BlockCount))
232 | {
233 | return (Head.Block[index].BlockType == enumBlockType.enumBlockTypeImage);
234 | }
235 | else
236 | {
237 | return false;
238 | }
239 | }
240 |
241 |
242 | //-------------------------------------//
243 | public bool IsBlockTextInfo(int index)
244 | {
245 | if ((index >= 0) && (index < Head.BlockCount))
246 | {
247 | return (Head.Block[index].BlockType == enumBlockType.enumBlockTypeTextInfo);
248 | }
249 | else
250 | {
251 | return false;
252 | }
253 | }
254 |
255 |
256 | //-------------------------------------//
257 | public enumBlockType GetBlockType(int index)
258 | {
259 | if ((index >= 0) && (index < Head.BlockCount))
260 | {
261 | return Head.Block[index].BlockType;
262 | }
263 | else
264 | {
265 | return enumBlockType.enumBlockTypeUnknown;
266 | }
267 | }
268 |
269 |
270 |
271 | //-------------------------------------//
272 | public bool IsBlockPreview(int index)
273 | {
274 | if ((index >= 0) && (index < Head.BlockCount))
275 | {
276 | return (Head.Block[index].BlockType == enumBlockType.enumBlockTypePreview);
277 | }
278 | else
279 | {
280 | return false;
281 | }
282 | }
283 |
284 |
285 |
286 | ///
287 | /// Return the info text of this file
288 | ///
289 | public string GetTextInfo(int index = 0)
290 | {
291 | var blockIndex = FindBlockIndexByType(enumBlockType.enumBlockTypeTextInfo, index);
292 |
293 | if (blockIndex < 0)
294 | {
295 | return string.Empty;
296 | }
297 |
298 | tyBlock block = Head.Block[blockIndex];
299 |
300 | return reader.ReadStr(block.size, block.offset);
301 |
302 | }
303 |
304 |
305 |
306 | ///
307 | /// return the data of an image
308 | ///
309 | public byte[] GetImageData(int imageIndex)
310 | {
311 | int blockIndex = GetImageBlockIndex(imageIndex);
312 |
313 | if (blockIndex < 0)
314 | {
315 | logging.addError("getImageData(imageIndex) fail - ImageIndex: " + imageIndex + " not found");
316 | return null;
317 | }
318 |
319 | //- Header zurückgeben
320 | tyBlock block = Head.Block[blockIndex];
321 | return reader.ReadByte(block.size, block.offset);
322 | }
323 |
324 |
325 | ///
326 | /// Return the n-th index of a given data block type
327 | ///
328 | private int FindBlockIndexByType(enumBlockType type, int number)
329 | {
330 | if ((number < 0) || (number >= Head.BlockCount))
331 | {
332 | return -1;
333 | }
334 |
335 | for (int i = 0; i < Head.BlockCount; i++)
336 | {
337 | tyBlock block = Head.Block[i];
338 |
339 | //- find all images
340 | if (block.BlockType == type)
341 | {
342 | /// return image if
343 | number--;
344 | if (number < 0)
345 | {
346 | return i;
347 | }
348 | }
349 | }
350 |
351 | return -1;
352 |
353 | }
354 |
355 | ///
356 | /// Retrun the data block for a given image index
357 | ///
358 | private int GetImageBlockIndex(int imageIndex)
359 | {
360 | return FindBlockIndexByType(enumBlockType.enumBlockTypeImage, imageIndex);
361 | }
362 |
363 |
364 |
365 | ///
366 | /// Return the file offset for a given data block
367 | ///
368 | public int GetBlockOffset(int index)
369 | {
370 | if ((index >= 0) && (index < Head.BlockCount))
371 | {
372 | return Head.Block[index].offset;
373 | }
374 | else
375 | {
376 | return 0;
377 | }
378 |
379 | }
380 |
381 |
382 |
383 |
384 | }
385 | }
386 |
--------------------------------------------------------------------------------