Added support for Boom colormaps

This commit is contained in:
codeimp 2009-05-12 09:50:08 +00:00
parent 63c22e5d2d
commit 16dfffb068
24 changed files with 828 additions and 35 deletions

View file

@ -152,6 +152,16 @@ flats
}
}
// Colormap sources
colormaps
{
standard1
{
start = "C_START";
end = "C_END";
}
}
/*
GAME DETECT PATTERN

View file

@ -147,6 +147,16 @@ flats
}
}
// Colormap sources
colormaps
{
standard1
{
start = "C_START";
end = "C_END";
}
}
/*
GAME DETECT PATTERN

View file

@ -152,6 +152,16 @@ flats
}
}
// Colormap sources
colormaps
{
standard1
{
start = "C_START";
end = "C_END";
}
}
/*
GAME DETECT PATTERN

View file

@ -147,6 +147,16 @@ flats
}
}
// Colormap sources
colormaps
{
standard1
{
start = "C_START";
end = "C_END";
}
}
/*
GAME DETECT PATTERN

View file

@ -147,6 +147,16 @@ flats
}
}
// Colormap sources
colormaps
{
standard1
{
start = "C_START";
end = "C_END";
}
}
/*
GAME DETECT PATTERN

View file

@ -155,6 +155,16 @@ flats
}
}
// Colormap sources
colormaps
{
standard1
{
start = "C_START";
end = "C_END";
}
}
/*
GAME DETECT PATTERN

View file

@ -166,6 +166,16 @@ flats
}
}
// Colormap sources
colormaps
{
standard1
{
start = "C_START";
end = "C_END";
}
}
/*
GAME DETECT PATTERN

View file

@ -155,6 +155,16 @@ flats
}
}
// Colormap sources
colormaps
{
standard1
{
start = "C_START";
end = "C_END";
}
}
/*
GAME DETECT PATTERN

View file

@ -166,6 +166,16 @@ flats
}
}
// Colormap sources
colormaps
{
standard1
{
start = "C_START";
end = "C_END";
}
}
/*
GAME DETECT PATTERN

View file

@ -176,6 +176,16 @@ flats
}
}
// Colormap sources
colormaps
{
standard1
{
start = "C_START";
end = "C_END";
}
}
/*
GAME DETECT PATTERN

View file

@ -165,6 +165,16 @@ flats
}
}
// Colormap sources
colormaps
{
standard1
{
start = "C_START";
end = "C_END";
}
}
/*
GAME DETECT PATTERN

View file

@ -165,6 +165,16 @@ flats
}
}
// Colormap sources
colormaps
{
standard1
{
start = "C_START";
end = "C_END";
}
}
/*
GAME DETECT PATTERN

View file

@ -667,12 +667,14 @@
<DependentUpon>ThingBrowserControl.cs</DependentUpon>
</Compile>
<Compile Include="Data\ColorImage.cs" />
<Compile Include="Data\ColormapImage.cs" />
<Compile Include="Data\HighResImage.cs" />
<Compile Include="Data\PK3FileImage.cs" />
<Compile Include="Data\PK3StructuredReader.cs" />
<Compile Include="General\CRC.cs" />
<Compile Include="General\ErrorItem.cs" />
<Compile Include="General\ErrorLogger.cs" />
<Compile Include="IO\DoomColormapReader.cs" />
<Compile Include="Map\SelectionType.cs" />
<Compile Include="Windows\ErrorsForm.cs">
<SubType>Form</SubType>
@ -872,4 +874,4 @@
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
</Project>
</Project>

View file

@ -83,6 +83,7 @@ namespace CodeImp.DoomBuilder.Config
private IDictionary flatranges;
private IDictionary patchranges;
private IDictionary spriteranges;
private IDictionary colormapranges;
// Things
private List<string> defaultthingflags;
@ -163,6 +164,7 @@ namespace CodeImp.DoomBuilder.Config
public IDictionary FlatRanges { get { return flatranges; } }
public IDictionary PatchRanges { get { return patchranges; } }
public IDictionary SpriteRanges { get { return spriteranges; } }
public IDictionary ColormapRanges { get { return colormapranges; } }
// Things
public ICollection<string> DefaultThingFlags { get { return defaultthingflags; } }
@ -276,6 +278,7 @@ namespace CodeImp.DoomBuilder.Config
flatranges = cfg.ReadSetting("flats", new Hashtable());
patchranges = cfg.ReadSetting("patches", new Hashtable());
spriteranges = cfg.ReadSetting("sprites", new Hashtable());
colormapranges = cfg.ReadSetting("colormaps", new Hashtable());
// Map lumps
LoadMapLumps();

View file

@ -0,0 +1,121 @@
#region ================== Copyright (c) 2007 Pascal vd Heiden
/*
* Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
* This program is released under GNU General Public License
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#endregion
#region ================== Namespaces
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using CodeImp.DoomBuilder.IO;
#endregion
namespace CodeImp.DoomBuilder.Data
{
internal sealed class ColormapImage : ImageData
{
#region ================== Constructor / Disposer
// Constructor
public ColormapImage(string name)
{
// Initialize
SetName(name);
// We have no destructor
GC.SuppressFinalize(this);
}
#endregion
#region ================== Methods
// This loads the image
protected override void LocalLoadImage()
{
Stream lumpdata;
MemoryStream mem;
IImageReader reader;
byte[] membytes;
// Leave when already loaded
if(this.IsImageLoaded) return;
lock(this)
{
// Get the lump data stream
lumpdata = General.Map.Data.GetColormapData(Name);
if(lumpdata != null)
{
// Copy lump data to memory
lumpdata.Seek(0, SeekOrigin.Begin);
membytes = new byte[(int)lumpdata.Length];
lumpdata.Read(membytes, 0, (int)lumpdata.Length);
mem = new MemoryStream(membytes);
mem.Seek(0, SeekOrigin.Begin);
// Get a reader for the data
reader = ImageDataFormat.GetImageReader(mem, ImageDataFormat.DOOMCOLORMAP, General.Map.Data.Palette);
if(reader is UnknownImageReader)
{
// Data is in an unknown format!
General.ErrorLogger.Add(ErrorType.Error, "Colormap lump '" + Name + "' data format could not be read. Does this lump contain valid colormap data at all?");
bitmap = null;
}
else
{
// Read data as bitmap
mem.Seek(0, SeekOrigin.Begin);
if(bitmap != null) bitmap.Dispose();
bitmap = reader.ReadAsBitmap(mem);
}
// Done
mem.Dispose();
if(bitmap != null)
{
// Get width and height from image
width = bitmap.Size.Width;
height = bitmap.Size.Height;
scaledwidth = (float)width * General.Map.Config.DefaultFlatScale;
scaledheight = (float)height * General.Map.Config.DefaultFlatScale;
}
else
{
loadfailed = true;
}
}
else
{
// Missing a patch lump!
General.ErrorLogger.Add(ErrorType.Error, "Missing colormap lump '" + Name + "'. Did you forget to include required resources?");
loadfailed = true;
}
// Pass on to base
base.LocalLoadImage();
}
}
#endregion
}
}

View file

@ -207,8 +207,9 @@ namespace CodeImp.DoomBuilder.Data
// This loads all data resources
internal void Load(DataLocationList locations)
{
int texcount, flatcount, spritecount, thingcount;
int texcount, flatcount, spritecount, thingcount, colormapcount;
Dictionary<long, ImageData> texturesonly = new Dictionary<long, ImageData>();
Dictionary<long, ImageData> colormapsonly = new Dictionary<long, ImageData>();
Dictionary<long, ImageData> flatsonly = new Dictionary<long, ImageData>();
DataReader c;
@ -289,10 +290,18 @@ namespace CodeImp.DoomBuilder.Data
LoadPalette();
texcount = LoadTextures(texturesonly);
flatcount = LoadFlats(flatsonly);
colormapcount = LoadColormaps(colormapsonly);
thingcount = LoadDecorateThings();
spritecount = LoadSprites();
LoadInternalSprites();
// Process colormaps (we just put them in as textures)
foreach(KeyValuePair<long, ImageData> t in colormapsonly)
{
textures.Add(t.Key, t.Value);
texturenames.Add(t.Value.Name);
}
// Process textures
foreach(KeyValuePair<long, ImageData> t in texturesonly)
{
@ -369,7 +378,7 @@ namespace CodeImp.DoomBuilder.Data
StartBackgroundLoader();
// Output info
General.WriteLogLine("Loaded " + texcount + " textures, " + flatcount + " flats, " + spritecount + " sprites, " + thingcount + " decorate things");
General.WriteLogLine("Loaded " + texcount + " textures, " + flatcount + " flats, " + colormapcount + " colormaps, " + spritecount + " sprites, " + thingcount + " decorate things");
}
// This unloads all data
@ -677,8 +686,60 @@ namespace CodeImp.DoomBuilder.Data
#endregion
#region ================== Colormaps
// This loads the colormaps
private int LoadColormaps(Dictionary<long, ImageData> list)
{
ICollection<ImageData> images;
int counter = 0;
// Go for all opened containers
foreach(DataReader dr in containers)
{
// Load colormaps
images = dr.LoadColormaps();
if(images != null)
{
// Go for all colormaps
foreach(ImageData img in images)
{
// Add or replace in flats list
list.Remove(img.LongName);
list.Add(img.LongName, img);
counter++;
// Add to preview manager
previews.AddImage(img);
}
}
}
// Output info
return counter;
}
// This returns a specific colormap stream
internal Stream GetColormapData(string pname)
{
Stream colormap;
// Go for all opened containers
for(int i = containers.Count - 1; i >= 0; i--)
{
// This contain provides this flat?
colormap = containers[i].GetColormapData(pname);
if(colormap != null) return colormap;
}
// No such patch found
return null;
}
#endregion
#region ================== Textures
// This loads the textures
private int LoadTextures(Dictionary<long, ImageData> list)
{
@ -758,7 +819,7 @@ namespace CodeImp.DoomBuilder.Data
// No such patch found
return null;
}
// This returns an image by string
public ImageData GetTextureImage(string name)
{

View file

@ -102,6 +102,16 @@ namespace CodeImp.DoomBuilder.Data
#endregion
#region ================== Colormaps
// When implemented, this loads the colormaps
public virtual ICollection<ImageData> LoadColormaps() { return null; }
// When implemented, this returns the colormap lump
public virtual Stream GetColormapData(string pname) { return null; }
#endregion
#region ================== Textures
// When implemented, this should read the patch names

View file

@ -137,6 +137,39 @@ namespace CodeImp.DoomBuilder.Data
return null;
}
// This finds and returns a colormap stream
public override Stream GetColormapData(string pname)
{
// Error when suspended
if(issuspended) throw new Exception("Data reader is suspended");
// Find in any of the wad files
// Note the backward order, because the last wad's images have priority
for(int i = wads.Count - 1; i >= 0; i--)
{
Stream data = wads[i].GetColormapData(pname);
if(data != null) return data;
}
try
{
// Find in patches directory
string path = Path.Combine(COLORMAPS_DIR, Path.GetDirectoryName(pname));
string filename = FindFirstFile(path, Path.GetFileName(pname), true);
if((filename != null) && FileExists(filename))
{
return LoadFile(filename);
}
}
catch(Exception e)
{
General.ErrorLogger.Add(ErrorType.Error, e.GetType().Name + " while loading colormap '" + pname + "' from directory: " + e.Message);
}
// Nothing found
return null;
}
#endregion
#region ================== Sprites
@ -215,9 +248,23 @@ namespace CodeImp.DoomBuilder.Data
}
// This creates an image
protected override ImageData CreateImage(string name, string filename, bool flat)
protected override ImageData CreateImage(string name, string filename, int imagetype)
{
return new FileImage(name, Path.Combine(location.location, filename), flat);
switch(imagetype)
{
case ImageDataFormat.DOOMFLAT:
return new FileImage(name, Path.Combine(location.location, filename), true);
case ImageDataFormat.DOOMPICTURE:
return new FileImage(name, Path.Combine(location.location, filename), false);
case ImageDataFormat.DOOMCOLORMAP:
return new ColormapImage(name);
default:
throw new ArgumentException("Invalid image format specified!");
return null;
}
}
// This returns true if the specified file exists

View file

@ -35,6 +35,7 @@ namespace CodeImp.DoomBuilder.Data
public const int UNKNOWN = 0; // No clue.
public const int DOOMPICTURE = 1; // Could be Doom Picture format (column list rendered data)
public const int DOOMFLAT = 2; // Could be Doom Flat format (raw 8-bit pixel data)
public const int DOOMCOLORMAP = 3; // Could be Doom Colormap format (raw 8-bit pixel palette mapping)
// File format signatures
private static readonly int[] PNG_SIGNATURE = new int[] { 137, 80, 78, 71, 13, 10, 26, 10 };
@ -47,6 +48,7 @@ namespace CodeImp.DoomBuilder.Data
BinaryReader bindata = new BinaryReader(data);
DoomPictureReader picreader;
DoomFlatReader flatreader;
DoomColormapReader colormapreader;
// First check the formats that provide the means to 'ensure' that
// it actually is that format. Then guess the Doom image format.
@ -87,6 +89,14 @@ namespace CodeImp.DoomBuilder.Data
flatreader = new DoomFlatReader(palette);
if(flatreader.Validate(data)) return flatreader;
}
// Could it be a doom colormap?
else if(guessformat == DOOMCOLORMAP)
{
// Check if data is valid for a doom colormap
data.Seek(0, SeekOrigin.Begin);
colormapreader = new DoomColormapReader(palette);
if(colormapreader.Validate(data)) return colormapreader;
}
// Format not supported
return new UnknownImageReader();

View file

@ -153,6 +153,31 @@ namespace CodeImp.DoomBuilder.Data
return null;
}
// This finds and returns a colormap stream
public override Stream GetColormapData(string pname)
{
// Error when suspended
if(issuspended) throw new Exception("Data reader is suspended");
// Find in any of the wad files
// Note the backward order, because the last wad's images have priority
for(int i = wads.Count - 1; i >= 0; i--)
{
Stream data = wads[i].GetColormapData(pname);
if(data != null) return data;
}
// Find in patches directory
string filename = FindFirstFile(COLORMAPS_DIR, pname, true);
if((filename != null) && FileExists(filename))
{
return LoadFile(filename);
}
// Nothing found
return null;
}
#endregion
#region ================== Sprites
@ -219,9 +244,23 @@ namespace CodeImp.DoomBuilder.Data
}
// This creates an image
protected override ImageData CreateImage(string name, string filename, bool flat)
protected override ImageData CreateImage(string name, string filename, int imagetype)
{
return new PK3FileImage(this, name, filename, flat);
switch(imagetype)
{
case ImageDataFormat.DOOMFLAT:
return new PK3FileImage(this, name, filename, true);
case ImageDataFormat.DOOMPICTURE:
return new PK3FileImage(this, name, filename, false);
case ImageDataFormat.DOOMCOLORMAP:
return new ColormapImage(name);
default:
throw new ArgumentException("Invalid image format specified!");
return null;
}
}
// This returns true if the specified file exists

View file

@ -39,6 +39,7 @@ namespace CodeImp.DoomBuilder.Data
protected const string FLATS_DIR = "flats";
protected const string HIRES_DIR = "hires";
protected const string SPRITES_DIR = "sprites";
protected const string COLORMAPS_DIR = "colormaps";
#endregion
@ -175,12 +176,12 @@ namespace CodeImp.DoomBuilder.Data
// Should we load the images in this directory as textures?
if(roottextures)
{
collection = LoadDirectoryImages("", false, false);
collection = LoadDirectoryImages("", ImageDataFormat.DOOMPICTURE, false);
AddImagesToList(images, collection);
}
// Add images from texture directory
collection = LoadDirectoryImages(TEXTURES_DIR, false, true);
collection = LoadDirectoryImages(TEXTURES_DIR, ImageDataFormat.DOOMPICTURE, true);
AddImagesToList(images, collection);
// Load TEXTURE1 lump file
@ -279,12 +280,12 @@ namespace CodeImp.DoomBuilder.Data
// Should we load the images in this directory as flats?
if(rootflats)
{
collection = LoadDirectoryImages("", true, false);
collection = LoadDirectoryImages("", ImageDataFormat.DOOMFLAT, false);
AddImagesToList(images, collection);
}
// Add images from flats directory
collection = LoadDirectoryImages(FLATS_DIR, true, true);
collection = LoadDirectoryImages(FLATS_DIR, ImageDataFormat.DOOMFLAT, true);
AddImagesToList(images, collection);
// Add images to the container-specific texture set
@ -296,6 +297,38 @@ namespace CodeImp.DoomBuilder.Data
#endregion
#region ================== Colormaps
// This loads the textures
public override ICollection<ImageData> LoadColormaps()
{
Dictionary<long, ImageData> images = new Dictionary<long, ImageData>();
ICollection<ImageData> collection;
// Error when suspended
if(issuspended) throw new Exception("Data reader is suspended");
// Load from wad files
// Note the backward order, because the last wad's images have priority
for(int i = wads.Count - 1; i >= 0; i--)
{
collection = wads[i].LoadColormaps();
AddImagesToList(images, collection);
}
// Add images from flats directory
collection = LoadDirectoryImages(COLORMAPS_DIR, ImageDataFormat.DOOMCOLORMAP, true);
AddImagesToList(images, collection);
// Add images to the container-specific texture set
foreach(ImageData img in images.Values)
textureset.AddFlat(img);
return new List<ImageData>(images.Values);
}
#endregion
#region ================== Decorate
// This finds and returns a sprite stream
@ -329,7 +362,7 @@ namespace CodeImp.DoomBuilder.Data
#region ================== Methods
// This loads the images in this directory
private ICollection<ImageData> LoadDirectoryImages(string path, bool flats, bool includesubdirs)
private ICollection<ImageData> LoadDirectoryImages(string path, int imagetype, bool includesubdirs)
{
List<ImageData> images = new List<ImageData>();
string[] files;
@ -345,7 +378,7 @@ namespace CodeImp.DoomBuilder.Data
if(name.Length > 0)
{
// Add image to list
images.Add(CreateImage(name, f, flats));
images.Add(CreateImage(name, f, imagetype));
}
else
{
@ -371,7 +404,7 @@ namespace CodeImp.DoomBuilder.Data
}
// This must create an image
protected abstract ImageData CreateImage(string name, string filename, bool flat);
protected abstract ImageData CreateImage(string name, string filename, int imagetype);
// This must return true if the specified file exists
protected abstract bool FileExists(string filename);

View file

@ -60,6 +60,7 @@ namespace CodeImp.DoomBuilder.Data
private List<LumpRange> patchranges;
private List<LumpRange> spriteranges;
private List<LumpRange> textureranges;
private List<LumpRange> colormapranges;
#endregion
@ -84,12 +85,14 @@ namespace CodeImp.DoomBuilder.Data
spriteranges = new List<LumpRange>();
flatranges = new List<LumpRange>();
textureranges = new List<LumpRange>();
colormapranges = new List<LumpRange>();
// Find ranges
FindRanges(patchranges, General.Map.Config.PatchRanges, "patches");
FindRanges(spriteranges, General.Map.Config.SpriteRanges, "sprites");
FindRanges(flatranges, General.Map.Config.FlatRanges, "flats");
FindRanges(textureranges, General.Map.Config.TextureRanges, "textures");
FindRanges(colormapranges, General.Map.Config.ColormapRanges, "colormaps");
// We have no destructor
GC.SuppressFinalize(this);
@ -195,6 +198,96 @@ namespace CodeImp.DoomBuilder.Data
#endregion
#region ================== Colormaps
// This loads the textures
public override ICollection<ImageData> LoadColormaps()
{
List<ImageData> images = new List<ImageData>();
string rangestart, rangeend;
// Error when suspended
if(issuspended) throw new Exception("Data reader is suspended");
// Read ranges from configuration
foreach(DictionaryEntry r in General.Map.Config.ColormapRanges)
{
// Read start and end
rangestart = General.Map.Config.ReadSetting("colormaps." + r.Key + ".start", "");
rangeend = General.Map.Config.ReadSetting("colormaps." + r.Key + ".end", "");
if((rangestart.Length > 0) && (rangeend.Length > 0))
{
// Load texture range
LoadColormapsRange(rangestart, rangeend, ref images);
}
}
// Add images to the container-specific texture set
foreach(ImageData img in images)
textureset.AddFlat(img);
// Return result
return images;
}
// This loads a range of colormaps
private void LoadColormapsRange(string startlump, string endlump, ref List<ImageData> images)
{
int startindex, endindex;
float defaultscale;
ColormapImage image;
// Determine default scale
defaultscale = General.Map.Config.DefaultTextureScale;
// Continue until no more start can be found
startindex = file.FindLumpIndex(startlump);
while(startindex > -1)
{
// Find end index
endindex = file.FindLumpIndex(endlump, startindex + 1);
if(endindex > -1)
{
// Go for all lumps between start and end exclusive
for(int i = startindex + 1; i < endindex; i++)
{
// Lump not zero-length?
if(file.Lumps[i].Length > 0)
{
// Make the image object
image = new ColormapImage(file.Lumps[i].Name);
// Add image to collection
images.Add(image);
}
}
}
// Find the next start
startindex = file.FindLumpIndex(startlump, startindex + 1);
}
}
// This finds and returns a colormap stream
public override Stream GetColormapData(string pname)
{
Lump lump;
// Error when suspended
if(issuspended) throw new Exception("Data reader is suspended");
// Find the lump in ranges
foreach(LumpRange range in colormapranges)
{
lump = file.FindLump(pname, range.start, range.end);
if(lump != null) return lump.Stream;
}
return null;
}
#endregion
#region ================== Textures
// This loads the textures
@ -460,7 +553,7 @@ namespace CodeImp.DoomBuilder.Data
return null;
}
#endregion
#region ================== Flats

View file

@ -0,0 +1,242 @@
#region ================== Copyright (c) 2007 Pascal vd Heiden
/*
* Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
* This program is released under GNU General Public License
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#endregion
#region ================== Namespaces
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.IO;
using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.Geometry;
using System.Drawing;
using CodeImp.DoomBuilder.Data;
using CodeImp.DoomBuilder.Rendering;
using System.Drawing.Imaging;
#endregion
namespace CodeImp.DoomBuilder.IO
{
internal unsafe class DoomColormapReader : IImageReader
{
#region ================== Variables
// Palette to use
private Playpal palette;
#endregion
#region ================== Constructor / Disposer
// Constructor
public DoomColormapReader(Playpal palette)
{
// Initialize
this.palette = palette;
// We have no destructor
GC.SuppressFinalize(this);
}
#endregion
#region ================== Methods
// This validates the data as doom flat
public bool Validate(Stream stream)
{
int remainder;
// Check if the data can be divided by 256 (each palette is 256 bytes)
remainder = (int)stream.Length % 256;
if(remainder == 0)
{
// Success when not 0
return (stream.Length > 0);
}
// Format invalid
return false;
}
// This creates a Bitmap from the given data
// Returns null on failure
public Bitmap ReadAsBitmap(Stream stream, out int offsetx, out int offsety)
{
offsetx = int.MinValue;
offsety = int.MinValue;
return ReadAsBitmap(stream);
}
// This creates a Bitmap from the given data
// Returns null on failure
public Bitmap ReadAsBitmap(Stream stream)
{
BitmapData bitmapdata;
PixelColorBlock pixeldata;
PixelColor* targetdata;
int width, height;
Bitmap bmp;
// Read pixel data
pixeldata = ReadAsPixelData(stream, out width, out height);
if(pixeldata != null)
{
try
{
// Create bitmap and lock pixels
bmp = new Bitmap(width, height, PixelFormat.Format32bppArgb);
bitmapdata = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
targetdata = (PixelColor*)bitmapdata.Scan0.ToPointer();
// Copy the pixels
General.CopyMemory(targetdata, pixeldata.Pointer, (uint)(width * height * sizeof(PixelColor)));
// Done
bmp.UnlockBits(bitmapdata);
}
catch(Exception e)
{
// Unable to make bitmap
General.ErrorLogger.Add(ErrorType.Error, "Unable to make Doom flat data. " + e.GetType().Name + ": " + e.Message);
return null;
}
}
else
{
// Failed loading picture
bmp = null;
}
// Return result
return bmp;
}
// This draws the picture to the given pixel color data
// Throws exception on failure
public unsafe void DrawToPixelData(Stream stream, PixelColor* target, int targetwidth, int targetheight, int x, int y)
{
Bitmap bmp;
BitmapData bmpdata;
PixelColor* pixels;
int ox, oy, tx, ty;
int width, height;
// Get bitmap
bmp = ReadAsBitmap(stream);
width = bmp.Size.Width;
height = bmp.Size.Height;
// Lock bitmap pixels
bmpdata = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
pixels = (PixelColor*)bmpdata.Scan0.ToPointer();
// Go for all pixels in the original image
for(ox = 0; ox < width; ox++)
{
for(oy = 0; oy < height; oy++)
{
// Copy this pixel?
if(pixels[oy * width + ox].a > 0.5f)
{
// Calculate target pixel and copy when within bounds
tx = x + ox;
ty = y + oy;
if((tx >= 0) && (tx < targetwidth) && (ty >= 0) && (ty < targetheight))
target[ty * targetwidth + tx] = pixels[oy * width + ox];
}
}
}
// Done
bmp.UnlockBits(bmpdata);
bmp.Dispose();
}
// This creates pixel color data from the given data
// Returns null on failure
private PixelColorBlock ReadAsPixelData(Stream stream, out int width, out int height)
{
BinaryReader reader = new BinaryReader(stream);
PixelColorBlock pixeldata = null;
byte[] bytes;
// Image will be 128x128
width = 128;
height = 128;
#if !DEBUG
try
{
#endif
// Allocate memory
pixeldata = new PixelColorBlock(width, height);
pixeldata.Clear();
// Read flat bytes from stream
bytes = new byte[width * height];
stream.Read(bytes, 0, width * height);
// Draw blocks using the palette
// We want to draw 8x8 blocks for each color
// 16 wide and 16 high
uint i = 0;
for(int by = 0; by < 16; by++)
{
for(int bx = 0; bx < 16; bx++)
{
PixelColor bc = palette[bytes[i++]];
PixelColor bc1 = General.Colors.CreateBrightVariant(palette[bytes[i++]]);
PixelColor bc2 = General.Colors.CreateDarkVariant(palette[bytes[i++]]);
for(int py = 0; py < 8; py++)
{
for(int px = 0; px < 8; px++)
{
int p = ((by * 8) + py) * width + (bx * 8) + px;
// We make the borders slightly brighter and darker
if((py == 0) || (px == 0))
pixeldata.Pointer[p] = bc1;
else if((py == 7) || (px == 7))
pixeldata.Pointer[p] = bc2;
else
pixeldata.Pointer[p] = bc;
}
}
}
}
// Return pointer
return pixeldata;
#if !DEBUG
}
catch(Exception)
{
// Return nothing
return null;
}
#endif
}
#endregion
}
}

View file

@ -228,29 +228,41 @@ namespace CodeImp.DoomBuilder.Rendering
// This creates assist colors
internal void CreateAssistColors()
{
Color4 o;
Color4 c = new Color4(1f, 0f, 0f, 0f);
// Go for all colors
for(int i = 0; i < NUM_COLORS; i++)
{
// Get original color
o = colors[i].ToColorValue();
// Create brighter color
c.Red = Saturate(o.Red * BRIGHT_MULTIPLIER + BRIGHT_ADDITION);
c.Green = Saturate(o.Green * BRIGHT_MULTIPLIER + BRIGHT_ADDITION);
c.Blue = Saturate(o.Blue * BRIGHT_MULTIPLIER + BRIGHT_ADDITION);
brightcolors[i] = PixelColor.FromInt(c.ToArgb());
// Create darker color
c.Red = Saturate(o.Red * DARK_MULTIPLIER + DARK_ADDITION);
c.Green = Saturate(o.Green * DARK_MULTIPLIER + DARK_ADDITION);
c.Blue = Saturate(o.Blue * DARK_MULTIPLIER + DARK_ADDITION);
darkcolors[i] = PixelColor.FromInt(c.ToArgb());
// Create assist colors
brightcolors[i] = CreateBrightVariant(colors[i]);
darkcolors[i] = CreateDarkVariant(colors[i]);
}
}
// This creates a brighter color
public PixelColor CreateBrightVariant(PixelColor pc)
{
Color4 o = pc.ToColorValue();
Color4 c = new Color4(1f, 0f, 0f, 0f);
// Create brighter color
c.Red = Saturate(o.Red * BRIGHT_MULTIPLIER + BRIGHT_ADDITION);
c.Green = Saturate(o.Green * BRIGHT_MULTIPLIER + BRIGHT_ADDITION);
c.Blue = Saturate(o.Blue * BRIGHT_MULTIPLIER + BRIGHT_ADDITION);
return PixelColor.FromInt(c.ToArgb());
}
// This creates a darker color
public PixelColor CreateDarkVariant(PixelColor pc)
{
Color4 o = pc.ToColorValue();
Color4 c = new Color4(1f, 0f, 0f, 0f);
// Create darker color
c.Red = Saturate(o.Red * DARK_MULTIPLIER + DARK_ADDITION);
c.Green = Saturate(o.Green * DARK_MULTIPLIER + DARK_ADDITION);
c.Blue = Saturate(o.Blue * DARK_MULTIPLIER + DARK_ADDITION);
return PixelColor.FromInt(c.ToArgb());
}
// This saves colors to configuration
internal void SaveColors(Configuration cfg)
{