Add ETC1 reading from png2bclim/Tharsis

Settled for the external dll method.

Thank you to Tharsis's creator, xdaniel.
This commit is contained in:
Kurt
2015-06-21 14:10:55 -07:00
parent bcfcb02e6d
commit 45a4808157
6 changed files with 117 additions and 17 deletions

View File

@@ -2,6 +2,8 @@
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
using pk3DS.Properties; // For other projects, replace this line with the namespace that contains your ETC1Lib.dll resource.
namespace CTR
{
@@ -97,7 +99,7 @@ internal static Image makeBMP(string path, bool autosave = false, bool crop = tr
else
img = getIMG(bclim);
if (img == null) return img;
if (img == null) return null;
Rectangle cropRect = new Rectangle(0, 0, bclim.Width, bclim.Height);
Bitmap CropBMP = new Bitmap(cropRect.Width, cropRect.Height);
using (Graphics g = Graphics.FromImage(CropBMP))
@@ -235,22 +237,99 @@ internal static Bitmap getIMG_XY7(CLIM bclim)
}
internal static Bitmap getIMG_ETC(CLIM bclim)
{
//int format = bclim.FileFormat;
//if (format != 10 && format != 11)
// return null;
Bitmap img = new Bitmap(Math.Max(nlpo2(bclim.Width), 16), Math.Max(nlpo2(bclim.Height), 16));
string dllpath = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location) + "\\ETC1Lib.dll";
if (!File.Exists(dllpath)) File.WriteAllBytes(dllpath, Resources.ETC1Lib);
//byte[] data = ETC1_Decompress(bclim.Data, bclim.Width, bclim.Height, format + 2);
//Bitmap img = new Bitmap(bclim.Width, bclim.Height);
try
{
/* http://jul.rustedlogic.net/thread.php?id=17312
* Much of this code is taken/modified from Tharsis. Thank you to Tharsis's creator, xdaniel.
* https://github.com/xdanieldzd/Tharsis
*/
//for (int i = 0; i < bclim.Width * bclim.Height; i++) // for every pixel
//{
// Color c = DecodeColor(BitConverter.ToUInt32(data, i * 4), 9);
// int x = i % bclim.Width;
// int y = i / bclim.Width;
// img.SetPixel(x, y, c);
//}
//return img;
return null;
/* Get compressed data & handle to it */
byte[] textureData = bclim.Data;
//textureData = switchEndianness(textureData, 0x10);
ushort[] input = new ushort[textureData.Length/sizeof (ushort)];
Buffer.BlockCopy(textureData, 0, input, 0, textureData.Length);
GCHandle pInput = GCHandle.Alloc(input, GCHandleType.Pinned);
/* Marshal data around, invoke ETC1.dll for conversion, etc */
UInt32 size1 = 0;
UInt16 w = (ushort)img.Width, h = (ushort)img.Height;
ETC1.ConvertETC1(IntPtr.Zero, ref size1, IntPtr.Zero, w, h, bclim.FileFormat == 0xB); // true = etc1a4, false = etc1
// System.Diagnostics.Debug.WriteLine(size1);
uint[] output = new uint[size1];
GCHandle pOutput = GCHandle.Alloc(output, GCHandleType.Pinned);
ETC1.ConvertETC1(pOutput.AddrOfPinnedObject(), ref size1, pInput.AddrOfPinnedObject(), w, h, bclim.FileFormat == 0xB);
pOutput.Free();
pInput.Free();
/* Unscramble if needed // could probably be done in ETC1Lib.dll, it's probably pretty ugly, but whatever... */
/* Non-square code blocks could need some cleanup, verification, etc. as well... */
uint[] finalized = new uint[output.Length];
// Act if it's square because BCLIM swizzling is stupid
Buffer.BlockCopy(output, 0, finalized, 0, finalized.Length);
byte[] tmp = new byte[finalized.Length];
Buffer.BlockCopy(finalized, 0, tmp, 0, tmp.Length);
byte[] imgData = tmp;
for (int i = 0; i < w; i++)
{
for (int j = 0; j < h; j++)
{
int k = (j + i*img.Height)*4;
img.SetPixel(i, j, Color.FromArgb(imgData[k + 3], imgData[k], imgData[k + 1], imgData[k + 2]));
}
}
// Image is 13 instead of 12
// 24 34
img.RotateFlip(RotateFlipType.Rotate90FlipX);
if (w > h)
{
// Image is now in appropriate order, but the shifting is messed up. Let's fix that.
Bitmap img2 = new Bitmap(Math.Max(nlpo2(bclim.Width), 16), Math.Max(nlpo2(bclim.Height), 16));
for (int y = 0; y < Math.Max(nlpo2(bclim.Width), 16); y += 8)
{
for (int x = 0; x < Math.Max(nlpo2(bclim.Height), 16); x++)
{
for (int j = 0; j < 8; j++)
// Treat every 8 vertical pixels as 1 pixel for purposes of calculation, add to offset later.
{
int x1 = (x + ((y/8)*h))%img2.Width; // Reshift x
int y1 = ((x + ((y/8)*h))/img2.Width)*8; // Reshift y
img2.SetPixel(x1, y1 + j, img.GetPixel(x, y + j)); // Reswizzle
}
}
}
img = img2;
}
else if (h > w)
{
Bitmap img2 = new Bitmap(Math.Max(nlpo2(bclim.Width), 16), Math.Max(nlpo2(bclim.Height), 16));
for (int y = 0; y < Math.Max(nlpo2(bclim.Width), 16); y += 8)
{
for (int x = 0; x < Math.Max(nlpo2(bclim.Height), 16); x++)
{
for (int j = 0; j < 8; j++)
// Treat every 8 vertical pixels as 1 pixel for purposes of calculation, add to offset later.
{
int x1 = x%img2.Width; // Reshift x
int y1 = ((x + ((y/8)*h))/img2.Width)*8; // Reshift y
img2.SetPixel(x1, y1 + j, img.GetPixel(x, y + j)); // Reswizzle
}
}
}
img = img2;
}
}
catch { }
return img;
}
// BCLIM Data Writing

View File

@@ -1,6 +1,11 @@
namespace CTR
using System;
using System.Runtime.InteropServices;
namespace CTR
{
class ETC1
{
[DllImport("ETC1Lib.dll", EntryPoint = "ConvertETC1", CallingConvention = CallingConvention.Cdecl)]
public static extern void ConvertETC1(IntPtr dataOut, ref UInt32 dataOutSize, IntPtr dataIn, UInt16 width, UInt16 height, bool alpha);
}
}
}

View File

@@ -10470,6 +10470,16 @@ internal class Resources {
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] ETC1Lib {
get {
object obj = ResourceManager.GetObject("ETC1Lib", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>

View File

@@ -4519,4 +4519,7 @@
<data name="_3dsgames" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\romdata\txt\3dsgames.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
</data>
<data name="ETC1Lib" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\ETC1Lib.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
</root>

BIN
pk3DS/Resources/ETC1Lib.dll Normal file

Binary file not shown.

View File

@@ -4677,6 +4677,9 @@
<ItemGroup>
<None Include="Resources\romdata\txt\3dsgames.txt" />
</ItemGroup>
<ItemGroup>
<None Include="Resources\ETC1Lib.dll" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.