mirror of
https://github.com/kwsch/pk3DS.git
synced 2026-10-02 05:46:47 -05:00
Add ETC1 reading from png2bclim/Tharsis
Settled for the external dll method. Thank you to Tharsis's creator, xdaniel.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
10
pk3DS/Properties/Resources.Designer.cs
generated
10
pk3DS/Properties/Resources.Designer.cs
generated
@@ -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>
|
||||
|
||||
@@ -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
BIN
pk3DS/Resources/ETC1Lib.dll
Normal file
Binary file not shown.
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user