1 module converter; 2 3 //import imageformats; 4 5 import PixelPerfectEngine.graphics.bitmap; 6 import PixelPerfectEngine.extbmp.extbmp; 7 import PixelPerfectEngine.system.exc; 8 import PixelPerfectEngine.system.etc; 9 import PixelPerfectEngine.map.mapload; 10 11 //import derelict.freeimage.freeimage; 12 //import derelict.freeimage.functions; 13 //import derelict.freeimage.types; 14 15 import std.stdio; 16 import std.path; 17 import std.bitmanip; 18 import std.conv; 19 20 /*Bitmap32Bit import32BitBitmapFromFile(string filename){ 21 22 FREE_IMAGE_FORMAT format; 23 switch(filename[filename.length-3..filename.length]){ 24 case "png": format = FIF_PNG; break; 25 case "tga": format = FIF_TARGA; break; 26 case "bmp": format = FIF_BMP; break; 27 default: break; 28 } 29 30 const char* fn = std.string.toStringz(filename); 31 FIBITMAP* source = FreeImage_Load(format, fn); 32 int iX = FreeImage_GetWidth(source), iY = FreeImage_GetHeight(source); 33 Bitmap32Bit result = new Bitmap32Bit(iX,iY); 34 switch(FreeImage_GetBPP(source)){ 35 case 32: 36 for(int y; y < iY; y++){ 37 for(int x; x < iX; x++){ 38 RGBQUAD c; FreeImage_GetPixelColor(source, x, iY - 1 - y, &c); 39 result.writePixel(x,y,c.rgbRed,c.rgbGreen,c.rgbBlue,c.rgbReserved); 40 //writeln(c.rgbRed,',',c.rgbGreen,',',c.rgbBlue,',',c.rgbReserved,','); 41 } 42 } 43 break; 44 default: 45 for(int y; y < iY; y++){ 46 for(int x; x < iX; x++){ 47 RGBQUAD c; FreeImage_GetPixelColor(source, x, iY - 1 - y, &c); 48 result.writePixel(x,y,c.rgbRed,c.rgbGreen,c.rgbBlue,255); 49 //writeln(c.rgbRed,',',c.rgbGreen,',',c.rgbBlue,',',c.rgbReserved,','); 50 } 51 } 52 break; 53 } 54 55 return result; 56 }*/ 57 58 enum NumberingStyle{ 59 DECIMAL = 0, 60 OCTAL = 1, 61 HEXADECIMAL = 2, 62 CHAR = 3, 63 WCHAR = 4 64 } 65 66 class ImportData{ 67 string[] ID; 68 string bitdepth, format; 69 int x, y, IDpos; 70 ushort paletteOffset; 71 NamingConvention nc; 72 this(string[] ID, string bitdepth, int x, int y, ushort paletteOffset){ 73 this.ID = ID; 74 this.bitdepth = bitdepth; 75 this.x = x; 76 this.y = y; 77 this.paletteOffset = paletteOffset; 78 //this.numOfDigits = numOfDigits; 79 } 80 this(NamingConvention nc, string bitdepth, int x, int y, ushort paletteOffset){ 81 this.nc = nc; 82 this.bitdepth = bitdepth; 83 this.x = x; 84 this.y = y; 85 this.paletteOffset = paletteOffset; 86 //this.numOfDigits = numOfDigits; 87 } 88 string getNextID(){ 89 if(nc is null){ 90 string result = ID[IDpos]; 91 IDpos++; 92 return result; 93 }else{ 94 string result = nc.wordA; 95 switch(nc.incrStyle){ 96 case NumberingStyle.OCTAL: result ~= intToOct(IDpos+nc.startingPoint,nc.format); break; 97 case NumberingStyle.HEXADECIMAL: result ~= intToHex(IDpos+nc.startingPoint,nc.format); break; 98 default: result ~= to!string(IDpos+nc.startingPoint); break; 99 } 100 IDpos++; 101 result ~= nc.wordB; 102 return result; 103 } 104 } 105 bool isMulti(){ 106 if(x > 0 && y > 0) return true; 107 return false; 108 } 109 110 } 111 112 class NamingConvention{ 113 string wordA, wordB; 114 NumberingStyle incrStyle; 115 int startingPoint, format; 116 this(string wordA, string wordB, NumberingStyle incrStyle, int startingPoint, int format){ 117 this.wordA = wordA; 118 this.wordB = wordB; 119 this.incrStyle = incrStyle; 120 this.startingPoint = startingPoint; 121 this.format = format; 122 } 123 } 124 125 public class BitmapInfo{ 126 int width, height; 127 public this(){ 128 129 } 130 } 131 132 public BitmapInfo getBitmapInfo(string path){ 133 import std..string; 134 /*FREE_IMAGE_FORMAT format; 135 switch(extension(path)){ 136 case ".png": format = FIF_PNG; break; 137 case ".tga": format = FIF_TARGA; break; 138 case ".bmp": format = FIF_BMP; break; 139 default: break; 140 } 141 const char* fn = std.string.toStringz(path); 142 FIBITMAP* source = FreeImage_Load(format, fn); 143 BitmapInfo bi = new BitmapInfo; 144 bi.width = FreeImage_GetWidth(source); 145 bi.height = FreeImage_GetHeight(source); 146 if(source) 147 FreeImage_Unload(source); 148 return bi;*/ 149 throw new Exception("Function unimplemented!"); 150 } 151 152 public void importDirectlyToXMP(string path, string palette, ExtendibleBitmap target, ImportData id){ 153 /*import std.string; 154 FREE_IMAGE_FORMAT format; 155 switch(extension(path)){ 156 case ".png": format = FIF_PNG; break; 157 case ".tga": format = FIF_TARGA; break; 158 case ".bmp": format = FIF_BMP; break; 159 default: break; 160 } 161 const char* fn = std.string.toStringz(path); 162 FIBITMAP* source = FreeImage_Load(format, fn); 163 int iX = FreeImage_GetWidth(source), iY = FreeImage_GetHeight(source); 164 ubyte[] raw; ushort[] raw16; 165 switch(id.bitdepth){ 166 case "1bit": 167 BitArray ba = BitArray(cast(void[])raw, 0); 168 ba.length(iX * iY); 169 for(int y; y < iY; y++){ 170 for(int x; x < iX; x++){ 171 ubyte c; FreeImage_GetPixelIndex(source, x, iY - 1 - y, &c); 172 if(c != 0){ 173 ba[x + (iX * y)] = true; 174 } 175 } 176 } 177 break; 178 case "16bit": 179 for(int y; y < iY; y++){ 180 for(int x; x < iX; x++){ 181 ubyte c; FreeImage_GetPixelIndex(source, x, iY - 1 - y, &c); 182 raw16 ~= to!ushort(id.paletteOffset + c); 183 } 184 } 185 break; 186 default: 187 switch(FreeImage_GetBPP(source)){ 188 case 1,2,4,8: 189 for(int y; y < iY; y++){ 190 for(int x; x < iX; x++){ 191 ubyte c; FreeImage_GetPixelIndex(source, x, iY - 1 - y, &c); 192 raw ~= c; 193 } 194 } 195 break; 196 case 32: 197 for(int y; y < iY; y++){ 198 for(int x; x < iX; x++){ 199 RGBQUAD c; FreeImage_GetPixelColor(source, x, iY - 1 - y, &c); 200 //result.writePixel(x,y,c.rgbRed,c.rgbGreen,c.rgbBlue,c.rgbReserved); 201 //writeln(c.rgbRed,',',c.rgbGreen,',',c.rgbBlue,',',c.rgbReserved,','); 202 raw ~= [c.rgbRed,c.rgbGreen,c.rgbBlue,c.rgbReserved]; 203 } 204 } 205 break; 206 default: 207 for(int y; y < iY; y++){ 208 for(int x; x < iX; x++){ 209 RGBQUAD c; FreeImage_GetPixelColor(source, x, iY - 1 - y, &c); 210 //result.writePixel(x,y,c.rgbRed,c.rgbGreen,c.rgbBlue,255); 211 //writeln(c.rgbRed,',',c.rgbGreen,',',c.rgbBlue,',',c.rgbReserved,','); 212 raw ~= [c.rgbRed,c.rgbGreen,c.rgbBlue,255]; 213 } 214 } 215 break; 216 } 217 break; 218 } 219 if(id.isMulti){ 220 if(iX%id.x > 0 || iY%id.y > 0){ 221 throw new BitmapFormatException("Incorrect sizes for slicing!"); 222 } 223 if(id.bitdepth == "16bit"){ 224 //target.addBitmap(raw16,id.x,id.y,id.bitdepth,id.ID[0]); 225 for(int jY; jY < iY / id.y; jY++){ 226 for(int jX; jX < iX / id.x; jX++){ 227 ushort[] raw2; 228 for(int y; y < id.y; y++){ 229 int from = ((jY * id.y * iX) + (y * iX) + (jX * id.x)), t = from + id.x; 230 raw2 ~= raw16[from..t]; 231 } 232 target.addBitmap(raw2,id.x,id.y,id.bitdepth,id.getNextID(),id.format,palette); 233 //si++; 234 } 235 } 236 }else{ 237 int pitch = 1; 238 if(id.bitdepth == "32bit")pitch = 4; 239 for(int jY; jY < iY / id.y; jY++){ 240 for(int jX; jX < iX / id.x; jX++){ 241 ubyte[] raw2; 242 for(int y; y < id.y; y++){ 243 int from = pitch * ((jY * id.y * iX) + (y * iX) + (jX * id.x)), t = from + (id.x * pitch); 244 raw2~= raw[from..t]; 245 } 246 target.addBitmap(raw2,id.x,id.y,id.bitdepth,id.getNextID(),id.format,palette); 247 //si++; 248 } 249 } 250 251 } 252 }else{ 253 if(id.bitdepth == "16bit"){ 254 target.addBitmap(raw16,iX,iY,id.bitdepth,id.ID[0]); 255 }else{ 256 target.addBitmap(raw,iX,iY,id.bitdepth,id.ID[0],id.format); 257 } 258 } 259 if(source) 260 FreeImage_Unload(source);*/ 261 throw new Exception("XMP is being deprecated. Please use different graphics format."); 262 } 263 264 public void importPaletteDirectlyToXMP(string path, ExtendibleBitmap target, string paletteID, ushort offset = 0){ 265 import std..string; 266 /*FREE_IMAGE_FORMAT format; 267 switch(extension(path)){ 268 case ".png": format = FIF_PNG; break; 269 case ".tga": format = FIF_TARGA; break; 270 case ".bmp": format = FIF_BMP; break; 271 default: break; 272 } 273 const char* fn = std.string.toStringz(path); 274 FIBITMAP* source = FreeImage_Load(format, fn); 275 uint bitdepth = FreeImage_GetBPP(source); 276 277 ubyte[] palette; 278 switch(bitdepth){ 279 case 4: palette.length = 64; break; 280 case 8: palette.length = 1024; break; 281 default: break; 282 } 283 RGBQUAD* colors = FreeImage_GetPalette(source); 284 //RGBQUAD.sizeof; 285 palette[0] = 0; 286 palette[1] = colors.rgbRed; 287 palette[2] = colors.rgbGreen; 288 palette[3] = colors.rgbBlue; 289 for(int i = 4; i < palette.length; i+=4){ 290 colors++; 291 palette[i] = 255; 292 palette[i + 1] = colors.rgbRed; 293 palette[i + 2] = colors.rgbGreen; 294 palette[i + 3] = colors.rgbBlue; 295 296 } 297 target.addPalette(cast(void[])palette, paletteID); 298 if(source) 299 FreeImage_Unload(source);*/ 300 throw new Exception("XMP is being deprecated. Please use different graphics format."); 301 } 302 303 public Bitmap32Bit getBitmapPreview(ExtendibleBitmap xmp, string ID){ 304 Bitmap32Bit result; 305 switch(xmp.getBitDepth(ID)){ 306 case "32bit": 307 result = new Bitmap32Bit(cast(Color[])xmp.getBitmap(ID),xmp.getXsize(ID),xmp.getYsize(ID)); 308 break; 309 case "16bit": 310 ushort[] raw = xmp.get16bitBitmap(ID); 311 Color[] clut = cast(Color[])xmp.getPalette(xmp.getPaletteMode(ID)); 312 Color[] res2; 313 foreach(c; raw){ 314 res2 ~= clut[c]; 315 } 316 result = new Bitmap32Bit(res2,xmp.getXsize(ID),xmp.getYsize(ID)); 317 break; 318 case "8bit": 319 ubyte[] raw = xmp.get8bitBitmap(ID); 320 Color[] clut = cast(Color[])xmp.getPalette(xmp.getPaletteMode(ID)); 321 Color[] res2; 322 foreach(c; raw){ 323 res2 ~= clut[c]; 324 } 325 result = new Bitmap32Bit(res2,xmp.getXsize(ID),xmp.getYsize(ID)); 326 break; 327 default: break; 328 } 329 return result; 330 } 331 332 public void autoloadFromXMP(string filename, ExtendibleMap map, int layerNum){ 333 ExtendibleBitmap xmpFile = new ExtendibleBitmap(filename); 334 map.addFileToTileSource(layerNum, filename); 335 for(int i ; i < xmpFile.bitmapID.length ; i++){ 336 try{ 337 if(xmpFile.bitmapID[i].length <= 4){ 338 throw new Exception(""); 339 } 340 wchar ID = to!wchar(parseHex(xmpFile.bitmapID[i][0..4])); 341 string descr = xmpFile.bitmapID[i].length > 5 ? xmpFile.bitmapID[i][5..xmpFile.bitmapID[i].length] : ""; 342 map.addTileToTileSource(layerNum, ID, descr, xmpFile.bitmapID[i], filename); 343 }catch(Exception e){ 344 writeln("Bitmap \'"~xmpFile.bitmapID[i]~"\' does not follow the format xxxx\\{description} and will be skipped."); 345 } 346 } 347 } 348 349 enum LookupMethod : uint{ 350 NearestValue = 1, 351 Dithering = 2 352 }