0
|
1 // This file is a part of the Relic Tools and is copyright 2006-2018 IBBoard.
|
|
2 //
|
|
3 // The file and the library/program it is in are licensed under the GNU GPL license, either version 3 of the License or (at your option) any later version. Please see COPYING for more information and the full license.
|
|
4 using System;
|
|
5 using System.IO;
|
|
6 using IBBoard.Graphics;
|
|
7 using IBBoard.Relic.RelicTools.Exceptions;
|
|
8
|
|
9 namespace IBBoard.Relic.RelicTools
|
|
10 {
|
|
11 /// <summary>
|
|
12 /// Summary description for ChunkyDataPTBD.
|
|
13 /// </summary>
|
|
14 public class ChunkyDataPTBD : ChunkyDataLayer
|
|
15 {
|
|
16 const float size_x = 64;
|
|
17 const float size_y = 64;
|
|
18 float x;
|
|
19 float y;
|
|
20
|
|
21 public ChunkyDataPTBD(int version_in, string name_in, byte[] innerData):base("PTBD", version_in, name_in)
|
|
22 {
|
|
23 x = BitConverter.ToSingle(innerData,0);
|
|
24 y = BitConverter.ToSingle(innerData,4);
|
|
25 }
|
|
26
|
|
27 public float Pos_x
|
|
28 {
|
|
29 get{ return x; }
|
|
30 }
|
|
31
|
|
32 public float Pos_y
|
|
33 {
|
|
34 get{ return y; }
|
|
35 }
|
|
36
|
|
37 public float Height
|
|
38 {
|
|
39 get{ return size_y; }
|
|
40 }
|
|
41
|
|
42 public float Width
|
|
43 {
|
|
44 get{ return size_x; }
|
|
45 }
|
|
46
|
|
47 public override void Save(DirectoryInfo dir, string fileBaseName)
|
|
48 {
|
|
49 int width = Info.Width;
|
|
50 int height = Info.Height;
|
|
51
|
|
52 float right = x+size_x;
|
|
53 float top = y+size_y;
|
|
54
|
|
55 if (((int)right)>width || ((int)top)>height)
|
|
56 {
|
|
57 throw new InvalidChunkException("Badge layer contains an invalid badge position");
|
|
58 }
|
|
59
|
|
60 //create the TGA
|
|
61 int fileLength = width*height;
|
|
62 byte [] file = new byte[fileLength];
|
|
63
|
|
64 int pos = 0;
|
|
65
|
|
66 for (int i = 0; i<height; i++)
|
|
67 {
|
|
68 for (int j = 0; j<width; j++)
|
|
69 {
|
|
70 if (x<=j && j<right && y<=i && i<top)
|
|
71 {
|
|
72 file[pos] = byte.MaxValue;
|
|
73 }
|
|
74 else
|
|
75 {
|
|
76 file[pos] = byte.MinValue;
|
|
77 }
|
|
78
|
|
79 pos++;
|
|
80 }
|
|
81 }
|
|
82
|
|
83 //save the TGA
|
|
84 FileStream str = new FileStream(dir.FullName.TrimEnd(Path.DirectorySeparatorChar)+Path.DirectorySeparatorChar+fileBaseName+"_Badge.tga", FileMode.Create);
|
|
85 BinaryWriter bw = new BinaryWriter(str);
|
|
86 bw.Write(TGA_Greyscale_Header_a);
|
|
87 bw.Write((ushort)width);
|
|
88 bw.Write((ushort)height);
|
|
89 bw.Write(TGA_Greyscale_Header_b);
|
|
90 bw.Write(file);
|
|
91 bw.Flush();
|
|
92 bw.Close();
|
|
93 }
|
|
94
|
|
95 public static ChunkyDataPTBD CreateFromTGA(int version, string name, byte[] tgaData)
|
|
96 {
|
|
97 //check image type code
|
|
98 if (tgaData[2]!=0x03)
|
|
99 {
|
|
100 bool worked = false;
|
|
101
|
|
102 if (tgaData[1] == 0x01 && tgaData[2] == 0x01)
|
|
103 {
|
|
104 tgaData = ImageConverter.ColourMapToGreyscale(tgaData);
|
|
105 worked = true;
|
|
106 }
|
|
107
|
|
108
|
|
109 if (!worked)
|
|
110 {
|
|
111 ImageConverter.MapEncStruct format = ImageConverter.getMapEncStruct(tgaData[2]);
|
|
112 throw new InvalidFileException("_badge.tga must be an unencoded unmapped monochrome Targa image.\r\n"+
|
|
113 " Image type: "+format.formatType+"\r\n"+
|
|
114 " Image encoded: "+((format.isEncoded)?"yes":"no")+"\r\n"+
|
|
115 " Colour mapped: "+((format.isMapped)?"yes":"no"));
|
|
116 }
|
|
117 }
|
|
118
|
|
119 //check colour depth
|
|
120 if (tgaData[16]!=0x08)
|
|
121 {
|
|
122 throw new InvalidFileException("_badge.tga must be an 8-bit Targa image. Image was "+tgaData[16]+"-bit.");
|
|
123 }
|
|
124
|
|
125 float pos_x = float.MinValue;
|
|
126 float pos_y = float.MinValue;
|
|
127 int width = (int)tgaData[12]+(((int)tgaData[13])<<8);
|
|
128 int height = (int)tgaData[14]+(((int)tgaData[15])<<8);
|
|
129 int currPos = 0;
|
|
130 int size_x_int = (int)size_x;
|
|
131
|
|
132 for (currPos = 18; currPos<tgaData.Length; currPos+=size_x_int)
|
|
133 {
|
|
134 //try to find our badge;
|
|
135 if (tgaData[currPos]==byte.MaxValue)
|
|
136 {
|
|
137 pos_y = (float)((currPos-18)/width);
|
|
138 pos_x = (float)(currPos-18-(pos_y*width));
|
|
139 break;
|
|
140 }
|
|
141 }
|
|
142
|
|
143 if (pos_y!=float.MinValue)
|
|
144 {
|
|
145 int maxPossibleEnd = currPos+width;
|
|
146 int extra = 0;
|
|
147
|
|
148 while (currPos<maxPossibleEnd && tgaData[currPos]==byte.MaxValue)
|
|
149 {
|
|
150 currPos++;
|
|
151 extra++;
|
|
152 }
|
|
153
|
|
154 //check where the left hand side should start
|
|
155 if (pos_x>0 && (tgaData[currPos-size_x_int]!=byte.MaxValue || tgaData[currPos-size_x_int-1]!=byte.MinValue))
|
|
156 {
|
|
157 throw new InvalidFileException("Badge is is not the correct width or is not a solid white square");
|
|
158 }
|
|
159 else
|
|
160 {
|
|
161 pos_x = pos_x+extra-size_x;
|
|
162 }
|
|
163
|
|
164 //and check for the top - not all of the block, just assume a left and bottom side are OK
|
|
165 int aboveTop = currPos-size_x_int+(width*(int)size_y);
|
|
166 for (int i = currPos-size_x_int; i<=aboveTop && i<tgaData.Length; i+= width)
|
|
167 {
|
|
168 if (tgaData[i]!=byte.MaxValue && i!=aboveTop)
|
|
169 {
|
|
170 throw new InvalidFileException("Badge area is too small. Badge must be 64px by 64px");
|
|
171 }
|
|
172 }
|
|
173
|
|
174 //if we got here, it's all OK
|
|
175
|
|
176 byte[] data = new byte[16];
|
|
177
|
|
178 BitConverter.GetBytes(pos_x).CopyTo(data, 0);
|
|
179 BitConverter.GetBytes(pos_y).CopyTo(data, 4);
|
|
180 BitConverter.GetBytes(size_x).CopyTo(data, 8);
|
|
181 BitConverter.GetBytes(size_y).CopyTo(data, 12);
|
|
182
|
|
183 return new ChunkyDataPTBD(version, name, data);
|
|
184 }
|
|
185 else
|
|
186 {
|
|
187 return null;
|
|
188 }
|
|
189 }
|
|
190
|
|
191 public override bool Savable
|
|
192 {
|
|
193 get
|
|
194 {
|
|
195 return true;
|
|
196 }
|
|
197 }
|
|
198
|
|
199 public override int DataLength
|
|
200 {
|
|
201 get
|
|
202 {
|
|
203 return 16;
|
|
204 }
|
|
205 }
|
|
206
|
|
207 public override byte[] GetDataBytes()
|
|
208 {
|
|
209 byte[] data = new byte[16];
|
|
210 BitConverter.GetBytes(x).CopyTo(data, 0);
|
|
211 BitConverter.GetBytes(y).CopyTo(data, 4);
|
|
212 BitConverter.GetBytes(size_x).CopyTo(data, 8);
|
|
213 BitConverter.GetBytes(size_y).CopyTo(data, 12);
|
|
214 return data;
|
|
215 }
|
|
216
|
|
217 public override string GetDisplayDetails()
|
|
218 {
|
|
219 return base.GetBaseDisplayDetails()+Environment.NewLine+
|
|
220 "------------"+Environment.NewLine+
|
|
221 "X:\t\t"+x+Environment.NewLine+
|
|
222 "Y:\t\t"+y+Environment.NewLine+
|
|
223 "Width:\t\t"+size_x+Environment.NewLine+
|
|
224 "Height:\t\t"+size_y;
|
|
225 }
|
|
226 }
|
|
227 } |