UltimateZoneBuilder/Source/Core/IO/DoomFlatReader.cs

231 lines
5.5 KiB
C#
Raw Normal View History

#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.IO;
using System.Drawing;
using CodeImp.DoomBuilder.Data;
using CodeImp.DoomBuilder.Rendering;
using System.Drawing.Imaging;
#endregion
namespace CodeImp.DoomBuilder.IO
{
internal unsafe class DoomFlatReader : IImageReader
{
#region ================== Variables
// Palette to use
private readonly Playpal palette;
#endregion
#region ================== Constructor / Disposer
// Constructor
public DoomFlatReader(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)
{
// Check if the flat is square
float sqrlength = (float)Math.Sqrt(stream.Length);
if(sqrlength == (float)Math.Truncate(sqrlength))
{
// Success when not 0
return ((int)sqrlength > 0);
}
// Valid if the data is more than 4096
return stream.Length > 4096;
}
// 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 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)
{
Added, Texture Browser: added "Show textures in subdirectories" checkbox (enabled by default). When enabled, textures from current PK3/PK7/Directory resource directory and it's subdirectories will be shown. Otherwise, only textures from current directory will be shown. Removed, Texture Browser: removed "Show image sizes" checkbox. "Show texture and flat sizes in browsers" preferences setting is now used instead. Fixed, Things mode: event line between pre-last and the last PatrolPoint was not drawn. Fixed, Things mode: highlight range for sizeless things (things with "fixedsize" game configuration property) was calculated incorrectly. Fixed: fixed a crash when opening Script Editor after using "Open map in current wad" command to switch to UDMF map with SCRIPTS lump when current script configuration was not saved in the wad's .dbs file. Fixed: map closing events were not triggered when using "Open map in current wad" command, which could potentially result in plugin crashes/incorrect behavior. Fixed: Sector Drawing overrides panel could trigger an exception when closing the map during resource loading. Internal: added "Debug + Profiler" solution configuration, added 2 profiling methods to DebugConsole. Internal: rewrote MainForm.DisplayStatus() / StatusInfo to handle selection info in a more structured way. Fixed, internal: some destructors could potentially be executed more than once potentially leading to exceptions. Other destructors were not called at all. Updated ZDoom_DECORATE.cfg.
2015-09-16 12:10:43 +00:00
//new BinaryReader(stream);
PixelColorBlock pixeldata;
float sqrlength;
byte[] bytes;
// Check if the flat is square
sqrlength = (float)Math.Sqrt(stream.Length);
if(sqrlength == (float)Math.Truncate(sqrlength))
{
// Calculate image size
width = (int)sqrlength;
height = (int)sqrlength;
}
// Check if the data is more than 4096
else if(stream.Length > 4096)
{
// Image will be 64x64
width = 64;
height = 64;
}
else
{
// Invalid
width = 0;
height = 0;
return null;
}
#if !DEBUG
try
{
#endif
// Valid width and height?
if((width <= 0) || (height <= 0)) return null;
// 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);
// Convert bytes with palette
for(uint i = 0; i < width * height; i++) pixeldata.Pointer[i] = palette[bytes[i]];
// Return pointer
return pixeldata;
#if !DEBUG
}
catch(Exception)
{
// Return nothing
return null;
}
#endif
}
#endregion
}
}