mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2024-11-25 21:31:14 +00:00
651 lines
27 KiB
C#
Executable file
651 lines
27 KiB
C#
Executable file
|
|
#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.Runtime.InteropServices;
|
|
using System.IO;
|
|
using System.Drawing;
|
|
using CodeImp.DoomBuilder.Rendering;
|
|
using System.Drawing.Imaging;
|
|
using CodeImp.DoomBuilder.Data;
|
|
|
|
#endregion
|
|
|
|
namespace CodeImp.DoomBuilder.IO
|
|
{
|
|
class PcxImageReader : IImageReader
|
|
{
|
|
public Bitmap ReadAsBitmap(Stream stream, out int offsetx, out int offsety)
|
|
{
|
|
offsetx = int.MinValue;
|
|
offsety = int.MinValue;
|
|
|
|
using (BinaryReader reader = new BinaryReader(stream, System.Text.Encoding.UTF8, true))
|
|
{
|
|
int manufacturer = reader.ReadByte(); // 10=ZSoft
|
|
int version = reader.ReadByte();
|
|
// 0=PC Paintbrush v2.5
|
|
// 2=PC Paintbrush v2.8 w palette information
|
|
// 3=PC Paintbrush v2.8 w/o palette information
|
|
// 4=PC Paintbrush/Windows
|
|
// 5=PC Paintbrush v3.0+
|
|
int encoding = reader.ReadByte(); // 1 = RLE, none other known
|
|
int bitsPerComponent = reader.ReadByte();
|
|
int leftMargin = reader.ReadUInt16();
|
|
int topMargin = reader.ReadUInt16();
|
|
int rightMargin = reader.ReadUInt16();
|
|
int bottomMargin = reader.ReadUInt16();
|
|
int dpiX = reader.ReadUInt16();
|
|
int dpiY = reader.ReadUInt16();
|
|
byte[] egaPalette = reader.ReadBytes(48); // 16 RGB triplets
|
|
reader.ReadByte(); // reserved
|
|
int numColorPlanes = reader.ReadByte();
|
|
int planePitch = reader.ReadUInt16(); // always even
|
|
int paletteInfo = reader.ReadUInt16(); // 1=color/bw palette, 2=grayscale image
|
|
int screenwidth = reader.ReadUInt16();
|
|
int screenheight = reader.ReadUInt16();
|
|
reader.ReadBytes(54); // reserved
|
|
|
|
int width = rightMargin - leftMargin + 1;
|
|
int height = bottomMargin - topMargin + 1;
|
|
|
|
if (width == 0 || height == 0)
|
|
throw new InvalidDataException("Invalid pcx image file");
|
|
|
|
int vgaPaletteID = 0;
|
|
byte[] vgaPalette = null;
|
|
|
|
int srcpitch = numColorPlanes * planePitch;
|
|
byte[] scanlines = new byte[srcpitch * height];
|
|
|
|
int pos = 0;
|
|
while (pos < scanlines.Length)
|
|
{
|
|
byte value = reader.ReadByte();
|
|
if ((value & 0xc0) == 0xc0) // two last bits
|
|
{
|
|
byte length = (byte)(value & 0x3f);
|
|
value = reader.ReadByte();
|
|
while (length > 0)
|
|
{
|
|
scanlines[pos++] = value;
|
|
length--;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
scanlines[pos++] = value;
|
|
}
|
|
}
|
|
|
|
byte[] imageData = new byte[width * height * 4];
|
|
int destpitch = width * 4;
|
|
|
|
if (bitsPerComponent == 4 && numColorPlanes == 1 && paletteInfo < 2) // 16 colors from a palette
|
|
{
|
|
for (int y = 0; y < height; y++)
|
|
{
|
|
for (int x = 0; x < width; x++)
|
|
{
|
|
int srcshift = ((x & 1) << 2);
|
|
int srcoffset = (x >> 1) + y * srcpitch;
|
|
int palentry = (scanlines[srcoffset] >> srcshift) & 15;
|
|
int offset = x * 4 + y * destpitch;
|
|
imageData[offset + 2] = egaPalette[palentry * 3];
|
|
imageData[offset + 1] = egaPalette[palentry * 3 + 1];
|
|
imageData[offset + 0] = egaPalette[palentry * 3 + 2];
|
|
imageData[offset + 3] = 255;
|
|
}
|
|
}
|
|
}
|
|
else if (bitsPerComponent == 4 && numColorPlanes == 4 && paletteInfo == 2) // 4096 colors with 16 levels of transparency
|
|
{
|
|
for (int y = 0; y < height; y++)
|
|
{
|
|
for (int x = 0; x < width; x++)
|
|
{
|
|
int srcshift = ((x & 1) << 2);
|
|
int srcoffset = (x >> 1) + y * srcpitch;
|
|
int red = (scanlines[srcoffset] >> srcshift) & 15;
|
|
int green = (scanlines[srcoffset + planePitch] >> srcshift) & 15;
|
|
int blue = (scanlines[srcoffset + planePitch * 2] >> srcshift) & 15;
|
|
int alpha = (scanlines[srcoffset + planePitch * 3] >> srcshift) & 15;
|
|
|
|
int offset = x * 4 + y * destpitch;
|
|
imageData[offset + 2] = (byte)((red * 255 + 7) / 15);
|
|
imageData[offset + 1] = (byte)((green * 255 + 7) / 15);
|
|
imageData[offset + 0] = (byte)((blue * 255 + 7) / 15);
|
|
imageData[offset + 3] = (byte)((alpha * 255 + 7) / 15);
|
|
}
|
|
}
|
|
}
|
|
else if (bitsPerComponent == 8 && numColorPlanes == 1 && paletteInfo < 2) // 256 colors from a palette
|
|
{
|
|
if (version == 5)
|
|
{
|
|
vgaPaletteID = reader.ReadByte(); // 0x0c
|
|
vgaPalette = reader.ReadBytes(768); // 256 RGB triplets
|
|
}
|
|
else
|
|
{
|
|
throw new InvalidDataException("No vga palette in pcx");
|
|
}
|
|
|
|
for (int y = 0; y < height; y++)
|
|
{
|
|
for (int x = 0; x < width; x++)
|
|
{
|
|
int palentry = scanlines[x + y * srcpitch];
|
|
int offset = x * 4 + y * destpitch;
|
|
imageData[offset + 2] = vgaPalette[palentry * 3];
|
|
imageData[offset + 1] = vgaPalette[palentry * 3 + 1];
|
|
imageData[offset + 0] = vgaPalette[palentry * 3 + 2];
|
|
imageData[offset + 3] = 255;
|
|
}
|
|
}
|
|
}
|
|
else if (bitsPerComponent == 8 && numColorPlanes == 1 && paletteInfo == 2) // 256 shades of gray
|
|
{
|
|
for (int y = 0; y < height; y++)
|
|
{
|
|
for (int x = 0; x < width; x++)
|
|
{
|
|
byte gray = scanlines[x + y * srcpitch];
|
|
int offset = x * 4 + y * destpitch;
|
|
imageData[offset + 2] = gray;
|
|
imageData[offset + 1] = gray;
|
|
imageData[offset + 0] = gray;
|
|
imageData[offset + 3] = 255;
|
|
}
|
|
}
|
|
}
|
|
else if (bitsPerComponent == 8 && numColorPlanes == 3) // 24 true color
|
|
{
|
|
for (int y = 0; y < height; y++)
|
|
{
|
|
for (int x = 0; x < width; x++)
|
|
{
|
|
int srcoffset = x + y * srcpitch;
|
|
int offset = x * 4 + y * destpitch;
|
|
imageData[offset + 2] = scanlines[srcoffset];
|
|
imageData[offset + 1] = scanlines[srcoffset + planePitch];
|
|
imageData[offset + 0] = scanlines[srcoffset + planePitch * 2];
|
|
imageData[offset + 3] = 255;
|
|
}
|
|
}
|
|
}
|
|
else if (bitsPerComponent == 8 && numColorPlanes == 4) // 24 true color with alpha channel
|
|
{
|
|
for (int y = 0; y < height; y++)
|
|
{
|
|
for (int x = 0; x < width; x++)
|
|
{
|
|
int srcoffset = x + y * srcpitch;
|
|
int offset = x * 4 + y * destpitch;
|
|
imageData[offset + 2] = scanlines[srcoffset];
|
|
imageData[offset + 1] = scanlines[srcoffset + planePitch];
|
|
imageData[offset + 0] = scanlines[srcoffset + planePitch * 2];
|
|
imageData[offset + 3] = scanlines[srcoffset + planePitch * 3];
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw new InvalidDataException(string.Format("Unsupported pcx subformat (bits={0}, planes={1})", bitsPerComponent, numColorPlanes));
|
|
}
|
|
|
|
return new Bitmap(width, height, destpitch, PixelFormat.Format32bppArgb, Marshal.UnsafeAddrOfPinnedArrayElement(imageData, 0));
|
|
}
|
|
}
|
|
}
|
|
|
|
class TgaImageReader : IImageReader
|
|
{
|
|
public Bitmap ReadAsBitmap(Stream stream, out int offsetx, out int offsety)
|
|
{
|
|
offsetx = int.MinValue;
|
|
offsety = int.MinValue;
|
|
|
|
using (BinaryReader reader = new BinaryReader(stream, System.Text.Encoding.UTF8, true))
|
|
{
|
|
read_header(reader);
|
|
read_image_id(reader);
|
|
read_color_map(reader);
|
|
read_image_data(reader);
|
|
decode_palette();
|
|
byte[] image = decode_image();
|
|
return new Bitmap(image_width, image_height, image_width * 4, PixelFormat.Format32bppArgb, Marshal.UnsafeAddrOfPinnedArrayElement(image, 0));
|
|
}
|
|
}
|
|
|
|
void read_header(BinaryReader reader)
|
|
{
|
|
id_length = reader.ReadByte();
|
|
colormap_type = reader.ReadByte();
|
|
image_type = reader.ReadByte();
|
|
|
|
colormap_orig = reader.ReadUInt16();
|
|
colormap_length = reader.ReadUInt16();
|
|
colormap_entry_size = reader.ReadByte();
|
|
|
|
image_x_orig = reader.ReadInt16();
|
|
image_y_orig = reader.ReadInt16();
|
|
image_width = reader.ReadUInt16();
|
|
image_height = reader.ReadUInt16();
|
|
image_pixel_size = reader.ReadByte();
|
|
image_descriptor = reader.ReadByte();
|
|
|
|
if (colormap_type > 1)
|
|
throw new InvalidDataException("Invalid or unsupported targa image file");
|
|
|
|
if (image_type != 1 && image_type != 2 && image_type != 3 && image_type != 9 && image_type != 10 && image_type != 11)
|
|
throw new InvalidDataException("Invalid or unsupported targa image type");
|
|
|
|
if (image_width == 0 || image_height == 0)
|
|
throw new InvalidDataException("Invalid targa image file");
|
|
|
|
if (colormap_type == 0)
|
|
colormap_length = 0;
|
|
|
|
bytes_per_colormap_entry = (colormap_entry_size + 7) / 8;
|
|
bytes_per_pixel_entry = (image_pixel_size + 7) / 8;
|
|
|
|
if (bytes_per_pixel_entry > 4)
|
|
throw new InvalidDataException("Unsupported targa image file");
|
|
|
|
num_alpha_bits = image_descriptor & 0x0f;
|
|
right_to_left = (image_descriptor & 0x10) != 0;
|
|
top_down = (image_descriptor & 0x20) != 0;
|
|
}
|
|
|
|
void read_image_id(BinaryReader reader)
|
|
{
|
|
image_id = reader.ReadBytes(id_length);
|
|
}
|
|
|
|
void read_color_map(BinaryReader reader)
|
|
{
|
|
colormap_data = reader.ReadBytes(bytes_per_colormap_entry * colormap_length);
|
|
}
|
|
|
|
void read_image_data(BinaryReader reader)
|
|
{
|
|
if (image_type == 9 || image_type == 10 || image_type == 11) // RLE compressed
|
|
{
|
|
image_data = new byte[bytes_per_pixel_entry * image_width * image_height];
|
|
|
|
byte[] rle_data = reader.ReadBytes((int)(reader.BaseStream.Length - reader.BaseStream.Position));
|
|
|
|
int input = 0;
|
|
int output = 0;
|
|
int pixels_left = image_width * image_height;
|
|
int input_available = rle_data.Length;
|
|
while (pixels_left > 0 && input_available > 0)
|
|
{
|
|
int code = rle_data[input];
|
|
int count = (code & 0x7f) + 1;
|
|
bool rle_packet = (code & 0x80) != 0;
|
|
|
|
input++;
|
|
input_available--;
|
|
|
|
if (rle_packet)
|
|
{
|
|
if (bytes_per_pixel_entry > input_available && pixels_left >= count) // Check for buffer overruns
|
|
break;
|
|
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
for (int j = 0; j < bytes_per_pixel_entry; j++)
|
|
image_data[output + i * bytes_per_pixel_entry + j] = rle_data[input + j];
|
|
}
|
|
|
|
input += bytes_per_pixel_entry;
|
|
}
|
|
else
|
|
{
|
|
if (count * bytes_per_pixel_entry >= input_available && pixels_left >= count) // Check for buffer overruns
|
|
break;
|
|
|
|
for (int j = 0; j < count * bytes_per_pixel_entry; j++)
|
|
image_data[output + j] = rle_data[input + j];
|
|
|
|
input += count * bytes_per_pixel_entry;
|
|
}
|
|
|
|
output += bytes_per_pixel_entry * count;
|
|
pixels_left -= count;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
image_data = reader.ReadBytes(bytes_per_pixel_entry * image_width * image_height);
|
|
}
|
|
}
|
|
|
|
void decode_palette()
|
|
{
|
|
palette = new byte[colormap_length * 4];
|
|
if (image_type == 1 || image_type == 9)
|
|
{
|
|
if (colormap_entry_size == 32)
|
|
{
|
|
for (int i = 0; i < colormap_length * 4; i++)
|
|
palette[i] = colormap_data[i];
|
|
|
|
if (num_alpha_bits == 0)
|
|
{
|
|
for (int i = 0; i < colormap_length; i++)
|
|
palette[i * 4 + 3] = 255;
|
|
}
|
|
}
|
|
else if (colormap_entry_size == 24)
|
|
{
|
|
for (int i = 0; i < colormap_length; i++)
|
|
{
|
|
palette[i * 4] = colormap_data[i * 3];
|
|
palette[i * 4 + 1] = colormap_data[i * 3 + 1];
|
|
palette[i * 4 + 2] = colormap_data[i * 3 + 2];
|
|
palette[i * 4 + 3] = 255;
|
|
}
|
|
}
|
|
else if (colormap_entry_size == 16) // 5,5,5,1
|
|
{
|
|
for (int i = 0; i < colormap_length; i++)
|
|
{
|
|
int color = colormap_data[i * 2] | (((int)colormap_data[i * 2 + 1]) << 8);
|
|
int alpha_bit = (num_alpha_bits != 0) ? ((color >> 15) & 0x1) : 1;
|
|
|
|
palette[i * 4] = (byte)(((color >> 10) & 0x1f) << 3);
|
|
palette[i * 4 + 1] = (byte)(((color >> 5) & 0x1f) << 3);
|
|
palette[i * 4 + 2] = (byte)((color & 0x1f) << 3);
|
|
palette[i * 4 + 3] = (byte)((alpha_bit == 1) ? 255 : 0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw new InvalidDataException("Unsupported targa image file");
|
|
}
|
|
}
|
|
}
|
|
|
|
byte[] decode_image()
|
|
{
|
|
// single color-map index for Pseudo-Color
|
|
// Attribute, Red, Green and Blue ordered data for True-Color
|
|
// independent color-map indices for Direct-Color
|
|
|
|
if (image_type == 0) // no image data
|
|
{
|
|
return new byte[image_width * image_height * 4];
|
|
}
|
|
else if (image_type == 1 || image_type == 9) // color-mapped
|
|
{
|
|
return decode_color_mapped();
|
|
}
|
|
else if (image_type == 2 || image_type == 10) // true-color
|
|
{
|
|
return decode_true_color();
|
|
}
|
|
else if (image_type == 3 || image_type == 11) // black-and-white
|
|
{
|
|
return decode_grayscale();
|
|
}
|
|
else
|
|
{
|
|
throw new InvalidDataException("Invalid or unsupported targa image file");
|
|
}
|
|
}
|
|
|
|
byte[] decode_color_mapped()
|
|
{
|
|
var image = new byte[image_width * image_height * 4];
|
|
|
|
for (int y = 0; y < image_height; y++)
|
|
{
|
|
int output_line = (top_down ? y : image_height - y - 1) * image_width * 4;
|
|
for (int x = 0; x < image_width; x++)
|
|
{
|
|
int inx = (x + y * image_width) * bytes_per_pixel_entry;
|
|
int outx = output_line + (right_to_left ? image_width - 1 - x : x) * 4;
|
|
|
|
int index = 0;
|
|
for (int i = 0; i < bytes_per_pixel_entry; i++)
|
|
index |= ((int)image_data[inx + i]) << (i * 8);
|
|
index = Math.Min(Math.Max(index - colormap_orig, 0), (int)colormap_length - 1);
|
|
index *= 4;
|
|
|
|
image[outx] = palette[index];
|
|
image[outx + 1] = palette[index + 1];
|
|
image[outx + 2] = palette[index + 2];
|
|
image[outx + 3] = palette[index + 3];
|
|
}
|
|
}
|
|
|
|
return image;
|
|
}
|
|
|
|
byte[] decode_true_color()
|
|
{
|
|
var image = new byte[image_width * image_height * 4];
|
|
|
|
if (image_pixel_size == 32)
|
|
{
|
|
for (int y = 0; y < image_height; y++)
|
|
{
|
|
int input_line = y * image_width * 4;
|
|
int output_line = (top_down ? y : image_height - y - 1) * image_width * 4;
|
|
for (int x = 0; x < image_width; x++)
|
|
{
|
|
int inx = input_line + x * 4;
|
|
int outx = output_line + (right_to_left ? image_width - 1 - x : x) * 4;
|
|
image[outx] = image_data[inx];
|
|
image[outx + 1] = image_data[inx + 1];
|
|
image[outx + 2] = image_data[inx + 2];
|
|
image[outx + 3] = (num_alpha_bits != 0) ? image_data[inx + 3] : (byte)255;
|
|
}
|
|
}
|
|
}
|
|
else if (image_pixel_size == 24)
|
|
{
|
|
for (int y = 0; y < image_height; y++)
|
|
{
|
|
int input_line = y * image_width * 3;
|
|
int output_line = (top_down ? y : image_height - y - 1) * image_width * 4;
|
|
for (int x = 0; x < image_width; x++)
|
|
{
|
|
int inx = input_line + x * 3;
|
|
int outx = output_line + (right_to_left ? image_width - 1 - x : x) * 4;
|
|
image[outx] = image_data[inx];
|
|
image[outx + 1] = image_data[inx + 1];
|
|
image[outx + 2] = image_data[inx + 2];
|
|
image[outx + 3] = 255;
|
|
}
|
|
}
|
|
}
|
|
else if (image_pixel_size == 16)
|
|
{
|
|
for (int y = 0; y < image_height; y++)
|
|
{
|
|
int input_line = y * image_width * 2;
|
|
int output_line = (top_down ? y : image_height - y - 1) * image_width * 4;
|
|
for (int x = 0; x < image_width; x++)
|
|
{
|
|
int inx = input_line + x * 2;
|
|
int outx = output_line + (right_to_left ? image_width - 1 - x : x) * 4;
|
|
|
|
int color = image_data[inx] | (((int)image_data[inx + 1]) << 8);
|
|
int alpha_bit = (num_alpha_bits != 0) ? ((color >> 15) & 0x1) : 1;
|
|
|
|
image[outx] = (byte)(((color >> 10) & 0x1f) << 3);
|
|
image[outx + 1] = (byte)(((color >> 5) & 0x1f) << 3);
|
|
image[outx + 2] = (byte)((color & 0x1f) << 3);
|
|
image[outx + 3] = (byte)((alpha_bit == 1) ? 255 : 0);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw new InvalidDataException("Unsupported targa image file");
|
|
}
|
|
|
|
return image;
|
|
}
|
|
|
|
byte[] decode_grayscale()
|
|
{
|
|
var image = new byte[image_width * image_height * 4];
|
|
|
|
if (image_pixel_size == 8)
|
|
{
|
|
for (int y = 0; y < image_height; y++)
|
|
{
|
|
int input_line = y * image_width;
|
|
int output_line = (top_down ? y : image_height - y - 1) * image_width * 4;
|
|
for (int x = 0; x < image_width; x++)
|
|
{
|
|
int inx = input_line + x;
|
|
int outx = output_line + (right_to_left ? image_width - 1 - x : x) * 4;
|
|
image[outx] = image_data[inx];
|
|
image[outx + 1] = image_data[inx];
|
|
image[outx + 2] = image_data[inx];
|
|
image[outx + 3] = 255;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw new InvalidDataException("Unsupported targa image file");
|
|
}
|
|
|
|
return image;
|
|
}
|
|
|
|
byte id_length;
|
|
byte colormap_type;
|
|
byte image_type;
|
|
|
|
ushort colormap_orig;
|
|
ushort colormap_length;
|
|
ushort colormap_entry_size;
|
|
|
|
short image_x_orig;
|
|
short image_y_orig;
|
|
ushort image_width;
|
|
ushort image_height;
|
|
byte image_pixel_size;
|
|
byte image_descriptor;
|
|
|
|
int bytes_per_colormap_entry;
|
|
int bytes_per_pixel_entry;
|
|
|
|
int num_alpha_bits;
|
|
bool right_to_left;
|
|
bool top_down;
|
|
|
|
byte[] image_id;
|
|
byte[] colormap_data;
|
|
byte[] palette;
|
|
byte[] image_data;
|
|
}
|
|
|
|
class FrameworkImageReader : IImageReader
|
|
{
|
|
bool isPng;
|
|
|
|
public FrameworkImageReader(bool isPng)
|
|
{
|
|
this.isPng = isPng;
|
|
}
|
|
|
|
public Bitmap ReadAsBitmap(Stream stream, out int offsetx, out int offsety)
|
|
{
|
|
using (var image = Image.FromStream(new NoCloseStream(stream)))
|
|
{
|
|
ReadPngOffsets(stream, out offsetx, out offsety);
|
|
return new Bitmap(image);
|
|
}
|
|
}
|
|
|
|
void ReadPngOffsets(Stream stream, out int offsetx, out int offsety)
|
|
{
|
|
offsetx = int.MinValue;
|
|
offsety = int.MinValue;
|
|
|
|
if (isPng)
|
|
{
|
|
stream.Position = 8;
|
|
using (BinaryReader reader = new BinaryReader(stream, System.Text.Encoding.UTF8, true))
|
|
{
|
|
// Read chunks untill we encounter either "grAb" or "IDAT"
|
|
while (reader.BaseStream.Position < reader.BaseStream.Length)
|
|
{
|
|
// Big Endian!
|
|
int chunklength = ToInt32BigEndian(reader.ReadBytes(4));
|
|
string chunkname = new string(reader.ReadChars(4));
|
|
|
|
if (chunkname == "grAb")
|
|
{
|
|
offsetx = ToInt32BigEndian(reader.ReadBytes(4));
|
|
offsety = ToInt32BigEndian(reader.ReadBytes(4));
|
|
break;
|
|
}
|
|
else if (chunkname == "IDAT")
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
// Skip the rest of the chunk
|
|
reader.BaseStream.Position += chunklength + 4;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static int ToInt32BigEndian(byte[] buffer)
|
|
{
|
|
return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3];
|
|
}
|
|
|
|
// This wraps a stream but makes Close/Dispose do nothing. That prevents.net's Image.FromStream from closing it as we want to fall back to other image loaders.
|
|
class NoCloseStream : Stream
|
|
{
|
|
Stream stream;
|
|
public NoCloseStream(Stream s) { stream = s; }
|
|
public override bool CanRead { get { return stream.CanRead; } }
|
|
public override bool CanSeek { get { return stream.CanSeek; } }
|
|
public override bool CanWrite { get { return stream.CanWrite; } }
|
|
public override bool CanTimeout { get { return stream.CanTimeout; } }
|
|
public override int ReadTimeout { get { return stream.ReadTimeout; } }
|
|
public override int WriteTimeout { get { return stream.WriteTimeout; } }
|
|
public override int EndRead(IAsyncResult asyncResult) { return stream.EndRead(asyncResult); }
|
|
public override void EndWrite(IAsyncResult asyncResult) { stream.EndWrite(asyncResult); }
|
|
public override int ReadByte() { return stream.ReadByte(); }
|
|
public override long Length { get { return stream.Length; } }
|
|
public override void WriteByte(byte value) { stream.WriteByte(value); }
|
|
public override long Position { get { return stream.Position; } set { stream.Position = value; } }
|
|
public override void Flush() { stream.Flush(); }
|
|
public override int Read(byte[] buffer, int offset, int count) { return stream.Read(buffer, offset, count); }
|
|
public override long Seek(long offset, SeekOrigin origin) { return stream.Seek(offset, origin); }
|
|
public override void SetLength(long value) { stream.SetLength(value); }
|
|
public override void Write(byte[] buffer, int offset, int count) { stream.Write(buffer, offset, count); }
|
|
}
|
|
}
|
|
}
|