preliminary WORKING implementation of KiSS CEL picture and KCF palette data formats
This commit is contained in:
parent
de41a5f081
commit
d290894b1f
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<UniversalEditor Version="4.0">
|
||||
<Associations>
|
||||
<Association>
|
||||
<Filters>
|
||||
<Filter Title="KiSS KCF palette" HintComparison="MagicThenFilter" ContentType="application/x-kiss-kcf">
|
||||
<FileNameFilters>
|
||||
<FileNameFilter>*.kcf</FileNameFilter>
|
||||
</FileNameFilters>
|
||||
<MagicByteSequences>
|
||||
<MagicByteSequence>
|
||||
<MagicByte Type="String">KiSS</MagicByte>
|
||||
<MagicByte Type="HexString">10</MagicByte>
|
||||
</MagicByteSequence>
|
||||
</MagicByteSequences>
|
||||
</Filter>
|
||||
</Filters>
|
||||
<ObjectModels>
|
||||
<ObjectModel TypeName="UniversalEditor.ObjectModels.Multimedia.Palette.PaletteObjectModel" />
|
||||
</ObjectModels>
|
||||
<DataFormats>
|
||||
<DataFormat TypeName="UniversalEditor.DataFormats.Multimedia.Palette.KISS.KCFDataFormat" />
|
||||
</DataFormats>
|
||||
</Association>
|
||||
</Associations>
|
||||
</UniversalEditor>
|
||||
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<UniversalEditor Version="4.0">
|
||||
<Associations>
|
||||
<Association>
|
||||
<Filters>
|
||||
<Filter Title="KiSS CEL image" HintComparison="FilterThenMagic" ContentType="image/x-kiss-cel">
|
||||
<FileNameFilters>
|
||||
<FileNameFilter>*.cel</FileNameFilter>
|
||||
</FileNameFilters>
|
||||
<MagicByteSequences>
|
||||
<MagicByteSequence>
|
||||
<MagicByte Type="String">KiSS</MagicByte>
|
||||
<MagicByte Type="HexString">20</MagicByte>
|
||||
</MagicByteSequence>
|
||||
</MagicByteSequences>
|
||||
</Filter>
|
||||
</Filters>
|
||||
<ObjectModels>
|
||||
<ObjectModel TypeName="UniversalEditor.ObjectModels.Multimedia.Picture.PictureObjectModel" />
|
||||
</ObjectModels>
|
||||
<DataFormats>
|
||||
<DataFormat TypeName="UniversalEditor.DataFormats.Multimedia.Picture.KISS.CELDataFormat" />
|
||||
</DataFormats>
|
||||
</Association>
|
||||
</Associations>
|
||||
</UniversalEditor>
|
||||
@ -0,0 +1,111 @@
|
||||
//
|
||||
// KCFDataFormat.cs
|
||||
//
|
||||
// Author:
|
||||
// Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// Copyright (c) 2021 Mike Becker's Software
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
using System;
|
||||
using MBS.Framework.Drawing;
|
||||
using UniversalEditor.ObjectModels.Multimedia.Palette;
|
||||
|
||||
namespace UniversalEditor.DataFormats.Multimedia.Palette.KISS
|
||||
{
|
||||
public class KCFDataFormat : DataFormat
|
||||
{
|
||||
private static DataFormatReference _dfr = null;
|
||||
protected override DataFormatReference MakeReferenceInternal()
|
||||
{
|
||||
if (_dfr == null)
|
||||
{
|
||||
_dfr = base.MakeReferenceInternal();
|
||||
_dfr.Capabilities.Add(typeof(PaletteObjectModel), DataFormatCapabilities.All);
|
||||
}
|
||||
return _dfr;
|
||||
}
|
||||
|
||||
protected override void LoadInternal(ref ObjectModel objectModel)
|
||||
{
|
||||
PaletteObjectModel palette = (objectModel as PaletteObjectModel);
|
||||
if (palette == null)
|
||||
throw new ObjectModelNotSupportedException();
|
||||
|
||||
string signature = Accessor.Reader.ReadFixedLengthString(4);
|
||||
if (signature != "KiSS")
|
||||
throw new InvalidDataFormatException("file does not begin with 'KiSS'");
|
||||
|
||||
byte formatCode = Accessor.Reader.ReadByte();
|
||||
byte pixelDepth = Accessor.Reader.ReadByte();
|
||||
if (formatCode != 0x10)
|
||||
{
|
||||
throw new InvalidDataFormatException("KCF palette file does not contain format code 0x10");
|
||||
}
|
||||
|
||||
ushort unknown = Accessor.Reader.ReadUInt16(); // 8224
|
||||
ushort ncolors = Accessor.Reader.ReadUInt16();
|
||||
ushort npalettes = Accessor.Reader.ReadUInt16();
|
||||
|
||||
Accessor.Reader.Seek(20, IO.SeekOrigin.Current); // unknown
|
||||
|
||||
for (ushort i = 0; i < npalettes; i++)
|
||||
{
|
||||
for (ushort j = 0; j < ncolors; j++)
|
||||
{
|
||||
if (pixelDepth == 24)
|
||||
{
|
||||
byte r = Accessor.Reader.ReadByte();
|
||||
byte g = Accessor.Reader.ReadByte();
|
||||
byte b = Accessor.Reader.ReadByte();
|
||||
palette.Entries.Add(new PaletteEntry(Color.FromRGBAByte(r, g, b)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
protected override void SaveInternal(ObjectModel objectModel)
|
||||
{
|
||||
PaletteObjectModel palette = (objectModel as PaletteObjectModel);
|
||||
if (palette == null)
|
||||
throw new ObjectModelNotSupportedException();
|
||||
|
||||
Accessor.Writer.WriteFixedLengthString("KiSS");
|
||||
|
||||
Accessor.Writer.WriteByte(0x10); // palette
|
||||
|
||||
byte pixelDepth = 24;
|
||||
Accessor.Writer.WriteByte(pixelDepth); // only 24bit color support for now
|
||||
|
||||
Accessor.Writer.WriteUInt16(0); // reserved
|
||||
Accessor.Writer.WriteUInt16((ushort)palette.Entries.Count);
|
||||
Accessor.Writer.WriteUInt16(1); // only 1 palette supported for now
|
||||
|
||||
Accessor.Writer.WriteBytes(new byte[20]); // reserved
|
||||
|
||||
for (ushort i = 0; i < 1; i++)
|
||||
{
|
||||
for (ushort j = 0; j < palette.Entries.Count; j++)
|
||||
{
|
||||
if (pixelDepth == 24)
|
||||
{
|
||||
Color color = palette.Entries[j].Color;
|
||||
Accessor.Writer.WriteByte(color.GetRedByte());
|
||||
Accessor.Writer.WriteByte(color.GetGreenByte());
|
||||
Accessor.Writer.WriteByte(color.GetBlueByte());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,245 @@
|
||||
//
|
||||
// CELDataFormat.cs
|
||||
//
|
||||
// Author:
|
||||
// Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// Copyright (c) 2021 Mike Becker's Software
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
using System;
|
||||
using MBS.Framework.Drawing;
|
||||
using MBS.Framework.Settings;
|
||||
using UniversalEditor.Accessors;
|
||||
using UniversalEditor.DataFormats.Multimedia.Palette.KISS;
|
||||
using UniversalEditor.ObjectModels.Multimedia.Palette;
|
||||
using UniversalEditor.ObjectModels.Multimedia.Picture;
|
||||
|
||||
namespace UniversalEditor.DataFormats.Multimedia.Picture.KISS
|
||||
{
|
||||
public class CELDataFormat : DataFormat
|
||||
{
|
||||
private static DataFormatReference _dfr = null;
|
||||
protected override DataFormatReference MakeReferenceInternal()
|
||||
{
|
||||
if (_dfr == null)
|
||||
{
|
||||
_dfr = base.MakeReferenceInternal();
|
||||
_dfr.Capabilities.Add(typeof(PictureObjectModel), DataFormatCapabilities.All);
|
||||
_dfr.ImportOptions.SettingsGroups[0].Settings.Add(new FileSetting("ExternalPaletteFileName", "External _palette file name", null, true, "*KiSS palette (.kcf)|*.kcf")
|
||||
{
|
||||
Required = true
|
||||
});
|
||||
|
||||
_dfr.ExportOptions.SettingsGroups[0].Settings.Add(new ChoiceSetting("ImageType", "_Image type", CELImageType.RGBA32bppVersion2, new ChoiceSetting.ChoiceSettingValue[]
|
||||
{
|
||||
new ChoiceSetting.ChoiceSettingValue("RGBA32bppVersion2", "Indexed, 4 bits per pixel (0x20 0x04)", CELImageType.Indexed4bpp),
|
||||
new ChoiceSetting.ChoiceSettingValue("RGBA32bppVersion2", "Indexed, 8 bits per pixel (0x20 0x08)", CELImageType.Indexed8bpp),
|
||||
new ChoiceSetting.ChoiceSettingValue("RGBA32bppVersion2", "RGBA, 32 bits per pixel, version 1 (0x21 0x20)", CELImageType.RGBA32bppVersion1),
|
||||
new ChoiceSetting.ChoiceSettingValue("RGBA32bppVersion2", "RGBA, 32 bits per pixel, version 2 (0x20 0x20)", CELImageType.RGBA32bppVersion2)
|
||||
}));
|
||||
}
|
||||
return _dfr;
|
||||
}
|
||||
|
||||
public CELImageType ImageType { get; set; } = CELImageType.RGBA32bppVersion2;
|
||||
public string ExternalPaletteFileName { get; set; } = null;
|
||||
public PaletteObjectModel ExternalPalette { get; set; } = null;
|
||||
|
||||
protected override void LoadInternal(ref ObjectModel objectModel)
|
||||
{
|
||||
PictureObjectModel pic = (objectModel as PictureObjectModel);
|
||||
if (pic == null)
|
||||
throw new ObjectModelNotSupportedException();
|
||||
|
||||
string signature = Accessor.Reader.ReadFixedLengthString(4);
|
||||
if (signature != "KiSS")
|
||||
throw new InvalidDataFormatException("file does not begin with 'KiSS'");
|
||||
|
||||
string externalPaletteFileName = null;
|
||||
if (!String.IsNullOrEmpty(ExternalPaletteFileName))
|
||||
{
|
||||
externalPaletteFileName = ExternalPaletteFileName;
|
||||
}
|
||||
else
|
||||
{
|
||||
externalPaletteFileName = System.IO.Path.ChangeExtension(Accessor.GetFileName(), "kcf");
|
||||
}
|
||||
if (!System.IO.File.Exists(externalPaletteFileName))
|
||||
externalPaletteFileName = null;
|
||||
|
||||
if (ExternalPalette == null && externalPaletteFileName != null)
|
||||
{
|
||||
PaletteObjectModel palette = new PaletteObjectModel();
|
||||
Document.Load(palette, new KCFDataFormat(), new FileAccessor(externalPaletteFileName));
|
||||
ExternalPalette = palette;
|
||||
}
|
||||
|
||||
byte formatCode = Accessor.Reader.ReadByte();
|
||||
byte pixelDepth = Accessor.Reader.ReadByte();
|
||||
if (formatCode == 0x20 && pixelDepth == 0x04)
|
||||
{
|
||||
ImageType = CELImageType.Indexed4bpp;
|
||||
if (ExternalPalette == null)
|
||||
{
|
||||
throw new ArgumentException("external palette file required but not found");
|
||||
}
|
||||
}
|
||||
else if (formatCode == 0x20 && pixelDepth == 0x08)
|
||||
{
|
||||
ImageType = CELImageType.Indexed8bpp;
|
||||
if (ExternalPalette == null)
|
||||
{
|
||||
throw new ArgumentException("external palette file required but not found");
|
||||
}
|
||||
}
|
||||
else if (formatCode == 0x21 && pixelDepth == 0x20)
|
||||
{
|
||||
ImageType = CELImageType.RGBA32bppVersion1;
|
||||
}
|
||||
else if (formatCode == 0x20 && pixelDepth == 0x20)
|
||||
{
|
||||
ImageType = CELImageType.RGBA32bppVersion2;
|
||||
}
|
||||
else if (formatCode == 0x10)
|
||||
{
|
||||
throw new InvalidDataFormatException("this is probably a KCF palette file");
|
||||
}
|
||||
|
||||
ushort unknown = Accessor.Reader.ReadUInt16(); // 8224
|
||||
|
||||
ushort width = Accessor.Reader.ReadUInt16();
|
||||
ushort height = Accessor.Reader.ReadUInt16();
|
||||
pic.Width = width;
|
||||
pic.Height = height;
|
||||
|
||||
Accessor.Reader.Seek(20, IO.SeekOrigin.Current); // unknown
|
||||
|
||||
byte bit = 0;
|
||||
byte lastindex = 0;
|
||||
for (ushort y = 0; y < height; y++)
|
||||
{
|
||||
for (ushort x = 0; x < width; x++)
|
||||
{
|
||||
switch (ImageType)
|
||||
{
|
||||
case CELImageType.Indexed4bpp:
|
||||
{
|
||||
byte index = 0;
|
||||
if (bit == 0)
|
||||
{
|
||||
lastindex = Accessor.Reader.ReadByte();
|
||||
index = (byte)lastindex.GetBits(0, 4);
|
||||
bit = 1;
|
||||
}
|
||||
else if (bit == 1)
|
||||
{
|
||||
index = (byte)lastindex.GetBits(4, 4);
|
||||
bit = 0;
|
||||
}
|
||||
|
||||
Color color = ExternalPalette.Entries[index].Color;
|
||||
if (index == 0)
|
||||
color = Colors.Transparent;
|
||||
|
||||
pic.SetPixel(color, x, y);
|
||||
break;
|
||||
}
|
||||
case CELImageType.Indexed8bpp:
|
||||
{
|
||||
byte index = Accessor.Reader.ReadByte();
|
||||
|
||||
Color color = ExternalPalette.Entries[index].Color;
|
||||
if (index == 0)
|
||||
color = Colors.Transparent;
|
||||
|
||||
pic.SetPixel(color, x, y);
|
||||
break;
|
||||
}
|
||||
case CELImageType.RGBA32bppVersion1:
|
||||
case CELImageType.RGBA32bppVersion2:
|
||||
{
|
||||
byte b = Accessor.Reader.ReadByte();
|
||||
byte g = Accessor.Reader.ReadByte();
|
||||
byte r = Accessor.Reader.ReadByte();
|
||||
byte a = Accessor.Reader.ReadByte();
|
||||
|
||||
Color color = Color.FromRGBAByte(r, g, b, a);
|
||||
pic.SetPixel(color, x, y);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void SaveInternal(ObjectModel objectModel)
|
||||
{
|
||||
PictureObjectModel pic = (objectModel as PictureObjectModel);
|
||||
if (pic == null)
|
||||
throw new ObjectModelNotSupportedException();
|
||||
|
||||
Accessor.Writer.WriteFixedLengthString("KiSS");
|
||||
|
||||
switch (ImageType)
|
||||
{
|
||||
case CELImageType.Indexed4bpp:
|
||||
{
|
||||
Accessor.Writer.WriteByte(0x20);
|
||||
Accessor.Writer.WriteByte(0x04);
|
||||
break;
|
||||
}
|
||||
case CELImageType.Indexed8bpp:
|
||||
{
|
||||
Accessor.Writer.WriteByte(0x20);
|
||||
Accessor.Writer.WriteByte(0x08);
|
||||
break;
|
||||
}
|
||||
case CELImageType.RGBA32bppVersion1:
|
||||
{
|
||||
Accessor.Writer.WriteByte(0x21);
|
||||
Accessor.Writer.WriteByte(0x20);
|
||||
break;
|
||||
}
|
||||
case CELImageType.RGBA32bppVersion2:
|
||||
{
|
||||
Accessor.Writer.WriteByte(0x20);
|
||||
Accessor.Writer.WriteByte(0x20);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Accessor.Writer.WriteUInt16(0); // unknown
|
||||
|
||||
ushort width = (ushort)pic.Width;
|
||||
ushort height = (ushort)pic.Height;
|
||||
Accessor.Writer.WriteUInt16(width);
|
||||
Accessor.Writer.WriteUInt16(height);
|
||||
|
||||
Accessor.Writer.WriteBytes(new byte[20]); // unknown
|
||||
|
||||
for (ushort y = 0; y < height; y++)
|
||||
{
|
||||
for (ushort x = 0; x < width; x++)
|
||||
{
|
||||
Color color = pic.GetPixel(x, y);
|
||||
Accessor.Writer.WriteByte(color.GetBlueByte());
|
||||
Accessor.Writer.WriteByte(color.GetGreenByte());
|
||||
Accessor.Writer.WriteByte(color.GetRedByte());
|
||||
Accessor.Writer.WriteByte(color.GetAlphaByte());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
//
|
||||
// CELImageType.cs
|
||||
//
|
||||
// Author:
|
||||
// Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// Copyright (c) 2021 Mike Becker's Software
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
using System;
|
||||
namespace UniversalEditor.DataFormats.Multimedia.Picture.KISS
|
||||
{
|
||||
public enum CELImageType
|
||||
{
|
||||
Indexed4bpp,
|
||||
Indexed8bpp,
|
||||
RGBA32bppVersion1,
|
||||
RGBA32bppVersion2
|
||||
}
|
||||
}
|
||||
@ -341,6 +341,9 @@
|
||||
<Compile Include="DataFormats\Multimedia\Palette\Adobe\ACT\ACTDataFormat.cs" />
|
||||
<Compile Include="DataFormats\Multimedia\Palette\Adobe\SwatchExchange\ASEDataFormat.cs" />
|
||||
<Compile Include="DataFormats\Multimedia\Picture\Targa\TargaFormatVersion.cs" />
|
||||
<Compile Include="DataFormats\Multimedia\Picture\KISS\CELDataFormat.cs" />
|
||||
<Compile Include="DataFormats\Multimedia\Picture\KISS\CELImageType.cs" />
|
||||
<Compile Include="DataFormats\Multimedia\Palette\KISS\KCFDataFormat.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Libraries\UniversalEditor.Compression\UniversalEditor.Compression.csproj">
|
||||
@ -401,6 +404,8 @@
|
||||
<Folder Include="DataFormats\Multimedia\Palette\Adobe\ACO\" />
|
||||
<Folder Include="DataFormats\Multimedia\Palette\Adobe\ACT\" />
|
||||
<Folder Include="DataFormats\Multimedia\Palette\Adobe\SwatchExchange\" />
|
||||
<Folder Include="DataFormats\Multimedia\Picture\KISS\" />
|
||||
<Folder Include="DataFormats\Multimedia\Palette\KISS\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Associations\Playlist\ASX.uexml" />
|
||||
@ -474,6 +479,8 @@
|
||||
<EmbeddedResource Include="Associations\SynthesizedAudio\SPC.uexml" />
|
||||
<EmbeddedResource Include="Associations\Palette\Adobe\ACTColorPalette.uexml" />
|
||||
<EmbeddedResource Include="Associations\Palette\RIFFPalette.uexml" />
|
||||
<EmbeddedResource Include="Associations\Picture\KISS.uexml" />
|
||||
<EmbeddedResource Include="Associations\Palette\KISS.uexml" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user