Files
PCK-Studio/PckStudio.Core/IO/TGA/TGAWriter.cs
2025-11-07 23:45:58 +01:00

141 lines
5.4 KiB
C#

/* Copyright (c) 2022-present miku-666
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1.The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
using System;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Text;
using OMI;
namespace PckStudio.Core.IO.TGA
{
internal class TGAWriter
{
private Bitmap _bitmap;
private int extensionDataOffset = 0;
public TGAWriter()
{
}
private void WriteHeader(EndiannessAwareBinaryWriter writer)
{
writer.Write(new byte[]
{
0, // header.Id.Length
0, // colormap type
(byte)TGADataTypeCode.RGB
});
writer.Write(0); // Colormap.Origin
writer.Write(0); // Colormap.Length
writer.Write(0); // Colormap.Depth
writer.Write(0); // Origin.X
writer.Write(0); // Origin.Y
writer.Write(_bitmap.Width);
writer.Write(_bitmap.Height);
writer.Write(32); // BitsPerPixel
writer.Write(8); // ImageDescriptor
}
private void WriteImage(EndiannessAwareBinaryWriter writer)
{
_bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
BitmapData bitmapData = _bitmap.LockBits(
new Rectangle(0, 0, _bitmap.Width, _bitmap.Height),
ImageLockMode.ReadOnly,
PixelFormat.Format32bppArgb);
byte[] buffer = new byte[_bitmap.Width * _bitmap.Height * 4];
Marshal.Copy(bitmapData.Scan0, buffer, 0, _bitmap.Width * _bitmap.Height * 4);
writer.Write(buffer);
}
private void WriteFooter(EndiannessAwareBinaryWriter writer)
{
writer.Write(extensionDataOffset); // extensionDataOffset
writer.Write(0); // developerAreaDataOffset
writer.WriteString(TGAFooter.Signature);
writer.Write((byte)0x2E);
writer.Write((byte)0x00);
}
private void WriteExtensionData(EndiannessAwareBinaryWriter writer)
{
extensionDataOffset = Convert.ToInt32(writer.BaseStream.Position);
TGAExtentionData extentionData = TGAExtentionData.Create();
writer.Write(TGAExtentionData.ExtensionSize);
// Author Name
writer.WriteString(extentionData.AuthorName, 41);
// Author Comment
writer.WriteString(extentionData.AuthorComment, 324);
// Timestamp
writer.Write((short)extentionData.TimeStamp.Month);
writer.Write((short)extentionData.TimeStamp.Day);
writer.Write((short)extentionData.TimeStamp.Year);
writer.Write((short)extentionData.TimeStamp.Hour);
writer.Write((short)extentionData.TimeStamp.Minute);
writer.Write((short)extentionData.TimeStamp.Second);
// Job id
writer.WriteString(extentionData.JobID, 41);
// Job time
writer.Write((short)extentionData.JobTime.Hours);
writer.Write((short)extentionData.JobTime.Minutes);
writer.Write((short)extentionData.JobTime.Seconds);
// Software Id
writer.WriteString(extentionData.SoftwareID, 41);
// Software version
writer.Write(extentionData.SoftwareVersion, 0, 3);
// Key color
writer.Write(extentionData.KeyColor);
// Pixel aspect ratio
writer.Write(extentionData.PixelAspectRatio);
// Gamma value
writer.Write(extentionData.GammaValue);
// Color correction offset
writer.Write(extentionData.ColorCorrectionOffset);
// Postage stamp offset
writer.Write(extentionData.PostageStampOffset);
// Scan line offset
writer.Write(extentionData.ScanLineOffset);
// Attributes type
writer.Write(extentionData.AttributesType);
}
public void WriteToStream(Stream stream, Image image)
{
_bitmap = new Bitmap(image);
using (var writer = new EndiannessAwareBinaryWriter(stream, Encoding.ASCII, leaveOpen: true, ByteOrder.LittleEndian))
{
WriteHeader(writer);
WriteImage(writer);
WriteExtensionData(writer);
WriteFooter(writer);
}
}
public void WriteToFile(string filename, Image image)
{
using (FileStream fs = File.OpenWrite(filename))
{
WriteToStream(fs, image);
}
}
}
}