protected bool ReadImageInfoMain(BinaryReader br) { bool isComposite = false; // Read image type: UInt32 dword = br.ReadUInt32(); if (dword == 0x100) { isComposite = true; Trace.WriteLine("Found a composite image"); //Logger.LogMessage(MsgLevel.DEBUG, "Found a composite image"); Debug.WriteLine("Found a composite image"); dword = br.ReadUInt32(); } else if (dword == 0x0) { Trace.WriteLine(string.Format("Found end of composite image ({0})", _imageNumber)); // Logger.LogMessage(MsgLevel.DEBUG, string.Format("Found end of composite image ({0})", _imageNumber)); Debug.WriteLine(string.Format("Found end of composite image ({0})", _imageNumber)); _imageNumber = 0; return(false); } switch (dword) { case 0x01: _imageType = AoWImageType.Type01_Picture08_0x01; break; case 0x02: _imageType = AoWImageType.Type02_RLESprite08_0x02; break; case 0x03: _imageType = AoWImageType.Type03_Sprite08_0x03; break; case 0x10: _imageType = AoWImageType.Type16_Picture16_0x10; break; case 0x11: _imageType = AoWImageType.Type17_RLESprite16_0x11; break; case 0x12: _imageType = AoWImageType.Type18_TransparentRLESprite16_0x12; break; case 0x16: _imageType = AoWImageType.Type22_Sprite16_0x16; break; default: throw new Exception(string.Format("Found unsupported type of image (0x{0:X})", dword)); } // Read record format: byte subId = br.ReadByte(); switch (subId) { // convert subtype 1 to 2 case 1: _subType = AoWImageSubType.SubType02; break; case 2: _subType = AoWImageSubType.SubType02; break; case 3: _subType = AoWImageSubType.SubType03; break; default: throw new Exception(string.Format("Found unsupported subtype (0x{0:X}) of image {1}", subId, _imageNumber)); } // Read bitmap filename: dword = br.ReadUInt32(); StringBuilder strb = new StringBuilder(); for (UInt32 i = 0; i < dword; ++i) { strb.Append((char)br.ReadSByte()); } _name = strb.ToString(); // Read image size: _cX = br.ReadInt32(); _cY = br.ReadInt32(); // Read image offset: _xShift = br.ReadInt32(); _yShift = br.ReadInt32(); // Read instance number: _instanceNumber = br.ReadInt32(); /*Logger.LogMessage(MsgLevel.DEBUG, * string.Format("Image {0}({1}): '{2}', {3}, sub {4}, {5}x{6}", _imageNumber, _instanceNumber, _name, _imageType, subId, _cX, _cY));*/ Debug.WriteLine(string.Format("Image {0}({1}): '{2}', {3}, sub {4}, {5}x{6}", _imageNumber, _instanceNumber, _name, _imageType, subId, _cX, _cY)); // Read LoadMode byte: dword = br.ReadByte(); switch (dword) { case 0: _loadMode = AoWLoadMode.lmInstant; break; case 1: _loadMode = AoWLoadMode.lmWhenUsed; break; case 2: _loadMode = AoWLoadMode.lmOnDemand; break; case 3: _loadMode = AoWLoadMode.lmWhenReferenced; break; default: _loadMode = AoWLoadMode.lmWhenUsed; break; } // Read image data size: _imageDataSize = br.ReadInt32(); if (_imageDataSize < 0) { throw new Exception(string.Format("Invalid data size of image {0})", _imageNumber)); } // Read image data offset: // Not here if InfoByte is 1 if (subId != 1) { dword = br.ReadUInt32(); // I think I'll not use it } // Read image size again: dword = br.ReadUInt32(); //Debug.Assert((int)dword == _cX + _xShift); dword = br.ReadUInt32(); //Debug.Assert((int)dword == _cY + _yShift); if (Is8bpp()) { // Read unknownB byte: dword = br.ReadByte(); Trace.WriteLine(string.Format("unknownB (0x{0:X})of image {1}", dword, _imageNumber)); if (_subType == AoWImageSubType.SubType03) { // Read unknownC int: dword = br.ReadUInt32(); Trace.WriteLine(string.Format("unknownC (0x{0:X})of image {1}", dword, _imageNumber)); // Read unknownD int: dword = br.ReadUInt32(); Trace.WriteLine(string.Format("unknownD (0x{0:X})of image {1}", dword, _imageNumber)); } } else { if (_subType == AoWImageSubType.SubType03) { // Read drawMode: UInt32 drawMode = br.ReadUInt32(); // Read blendValue: _blendValue = br.ReadInt32(); UInt32 showMode = drawMode & 0x000000FF; UInt32 blendMode = (drawMode & 0x0000FF00) >> 8; switch (showMode) { case 0x0: _showMode = AoWShowMode.smOpaque; break; case 0x1: _showMode = AoWShowMode.smTransparent; break; case 0x2: _showMode = AoWShowMode.smBlended; break; default: throw new Exception(string.Format("Invalid ShowMode 0x{0:X} of image {1})", showMode, _imageNumber)); } switch (blendMode) { case 0x0: _blendMode = AoWBlendMode.bmUser; break; case 0x1: _blendMode = AoWBlendMode.bmAlpha; break; case 0x2: _blendMode = AoWBlendMode.bmBrighten; break; case 0x3: _blendMode = AoWBlendMode.bmIntensity; break; case 0x4: _blendMode = AoWBlendMode.bmShadow; break; case 0x5: _blendMode = AoWBlendMode.bmLinearAlpha; break; } } } if (Is8bpp()) { // Read palette index if (subId != 1) { _numPalette = br.ReadInt32(); } } else { // Read pixelFormat: dword = br.ReadUInt32(); if (dword != 0x56509310u) { throw new Exception(string.Format("Invalid PixelFormat 0x{0:X} of image {1})", dword, _imageNumber)); } } // See if there should be a bounding box present. switch (_imageType) { case AoWImageType.Type02_RLESprite08_0x02: case AoWImageType.Type03_Sprite08_0x03: case AoWImageType.Type17_RLESprite16_0x11: case AoWImageType.Type18_TransparentRLESprite16_0x12: case AoWImageType.Type22_Sprite16_0x16: { // Read bounding box: Int32 bbWidth = br.ReadInt32(); Int32 bbHeight = br.ReadInt32(); Int32 bbXOffset = br.ReadInt32(); Int32 bbYOffset = br.ReadInt32(); _boundingBox.Set(bbYOffset, bbXOffset, bbWidth + bbXOffset - 1, bbHeight + bbYOffset - 1); // Read background colour _originalBackgroundColour = br.ReadUInt32(); //RGB565 or index } break; } // See if there should be clip_x switch (_imageType) { case AoWImageType.Type02_RLESprite08_0x02: // Read clip_x, seem useless, set to 0 dword = br.ReadUInt32(); Trace.WriteLine(string.Format("clip_x (0x{0:X})of image {1}", dword, _imageNumber)); break; case AoWImageType.Type17_RLESprite16_0x11: case AoWImageType.Type18_TransparentRLESprite16_0x12: { dword = br.ReadUInt32(); switch (dword) { case 0: _clipXHack = AoWClipXHack.None; break; //case AoW1Constants.clip_X_Structure: _clipXHack = AoWClipXHack.AsStructure; break; //case AoW1Constants.clip_X_Mountain: _clipXHack = AoWClipXHack.AsMountain; break; case AoW1Constants.clip_X_Item: _clipXHack = AoWClipXHack.AsItem; break; case AoW1Constants.clip_X_ShieldsM: _clipXHack = AoWClipXHack.AsShieldsM; break; case AoW1Constants.clip_X_TCMap: _clipXHack = AoWClipXHack.AsTCMap; break; default: _clipXHack = AoWClipXHack.None; // Logger.LogMessage( MsgLevel.DEBUG, string.Format("unknown clip_x (0x{0:X8})of image {1}", dword, _imageNumber)); Debug.WriteLine(string.Format("unknown clip_x (0x{0:X8})of image {1}", dword, _imageNumber)); break; } } break; } // Read image data if subtype == 1 if (subId == 1) { List <ColorPalette> palettes = null; if (Is8bpp()) { // I think there should be the palette palettes = new List <ColorPalette>(); palettes.Add(AoW1Header.ReadPalette(br)); } ReadImageData(br, palettes); } if (isComposite) { // read composite images // read info data AoW1Bitmap elem = null; while (true) { elem = new AoW1Bitmap(); elem.ImageNumber = _imageNumber; if (!elem.ReadImageInfoMain(br)) { // End composite section Debug.Assert(elem.ImageNumber == 0); break; } _subImageList.Add(elem); } } return(true); } // end ReadImageInfo
public override bool OpenIlb(string fileName, List <AoWBitmap> imageList) { using (FileStream fs = File.OpenRead(fileName)) { BinaryReader br = new BinaryReader(fs); // first byte is the number of following word infos UInt32 wordFields = br.ReadByte(); // the format of this header is weird: // because the choose to use word, // they may be too little to store address offset so dwords may be required. // In this case wordFields is 0x8n, and an additional dword follows // to specify the number of dword*2 infos UInt32 dwordFields = 0; if (wordFields > 0x80) { wordFields -= 0x80; dwordFields = br.ReadUInt32(); } // the infos are made by two fields // 1 - an id // 2 - the offset you find their data AFTER this list of info SortedList <UInt32, UInt32> infoMap = new SortedList <UInt32, UInt32>(); // Store them in a container for (int i = 0; i < wordFields; ++i) { UInt32 id = br.ReadByte(); infoMap.Add(id, br.ReadByte()); } for (int i = 0; i < dwordFields; ++i) { UInt32 id = br.ReadUInt32(); infoMap.Add(id, br.ReadUInt32()); } /* * 0x0A ??? * 0x0B max number of elements - dword * 0x0C palettes - ? * 0x32+ image header - vary */ if (infoMap.ContainsKey(0x0A)) { UInt32 unknown = br.ReadUInt32(); infoMap.Remove(0x0A); } // read the max number of elements // The images may have discontinued id (i.e.: 0 - 1 -3 - 5) // so the length of the list that should contain them all // should be large to contains gap, // then the max is the following dword if (infoMap.ContainsKey(0x0B)) { UInt32 lastElemNumber = br.ReadUInt32(); infoMap.Remove(0x0B); } List <ColorPalette> palettes = new List <ColorPalette>(); if (infoMap.ContainsKey(0x0C)) { // read unknown data // For now I've no clue on meaning of interposed data, // but should be the palettes UInt32 unknownLength = infoMap.Values[1] - infoMap[0x0C]; br.ReadBytes(0x6); // seem useless UInt32 numPalette = br.ReadByte(); for (UInt32 i = 0; i < numPalette; ++i) { br.ReadBytes(0xF); // seem useless palettes.Add(AoW1Header.ReadPalette(br)); } infoMap.Remove(0x0C); } // read image headers AoWBitmap model = PersistentData.Data.AoW1Default; foreach (UInt32 id in infoMap.Keys) { AoWBitmap elem = new AoW2Bitmap(model); elem.ImageNumber = (int)(id - 0x32u); if (!elem.ReadImageInfo(br)) { Debug.Assert(false); } // be sure there is enough space while (elem.ImageNumber >= imageList.Count) { imageList.Add(null); } imageList[elem.ImageNumber] = elem; } // read image data long startOffset = br.BaseStream.Position; foreach (AoW2Bitmap elem in imageList) { if (elem != null) { if (br.BaseStream.Position != startOffset + (long)elem.ImageOffset) { br.BaseStream.Position = startOffset + (long)elem.ImageOffset; } elem.ReadImageData(br, palettes); } } // now convert to AoW1 Type for (int i = 0; i < imageList.Count; ++i) { AoW2Bitmap elem = (AoW2Bitmap)imageList[i]; if (elem != null) { // the copy constructor make all the works imageList[i] = new AoW1Bitmap(elem); elem.Dispose(); } } } return(true); } // end OpenIlb