1
0
mirror of synced 2024-12-04 20:08:00 +01:00
Switch-Toolbox/Switch_Toolbox_Library/Texture Decoding/3DS/ETC1_Encoder.cs
2020-02-08 14:06:01 -05:00

210 lines
7.1 KiB
C#

using System;
using System.Drawing;
using System.Runtime.InteropServices;
using Toolbox.Library.IO;
namespace SmashForge
{
//Ported from https://raw.githubusercontent.com/jam1garner/Smash-Forge/master/Smash%20Forge/Filetypes/Textures/RG_ETC1.cs
//This encoder is pretty good
class RG_ETC1
{
public static byte[] encodeETC(Bitmap b)
{
int width = b.Width;
int height = b.Height;
int[] pixels = new int[width * height];
init();
int i, j;
var mem = new System.IO.MemoryStream();
using (var writer = new FileWriter(mem)) {
writer.ByteOrder = Syroot.BinaryData.ByteOrder.LittleEndian;
for (i = 0; i < height; i += 8)
{
for (j = 0; j < width; j += 8)
{
int x, y;
Color[] temp = new Color[16];
int pi = 0;
for (x = i; x < i + 4; x++)
for (y = j; y < j + 4; y++)
temp[pi++] = b.GetPixel(y, x);
writer.Write(GenETC1(temp));
temp = new Color[16];
pi = 0;
for (x = i; x < i + 4; x++)
for (y = j + 4; y < j + 8; y++)
temp[pi++] = b.GetPixel(y, x);
writer.Write(GenETC1(temp));
temp = new Color[16];
pi = 0;
for (x = i + 4; x < i + 8; x++)
for (y = j; y < j + 4; y++)
temp[pi++] = b.GetPixel(y, x);
writer.Write(GenETC1(temp));
temp = new Color[16];
pi = 0;
for (x = i + 4; x < i + 8; x++)
for (y = j + 4; y < j + 8; y++)
temp[pi++] = b.GetPixel(y, x);
writer.Write(GenETC1(temp));
}
}
}
return mem.ToArray();
}
public static byte[] GenETC1(Color[] colors)
{
uint[] pixels = new uint[colors.Length];
for (int i = 0; i < colors.Length; i++)
{
pixels[i] = (uint)((colors[i].A << 24) | (colors[i].B << 16) | (colors[i].G << 8) | colors[i].R);
}
IntPtr ptr = encode_etc1(pixels, (int)ETC1_Quality.med, false);
byte[] result = new byte[8];
Marshal.Copy(ptr, result, 0, 8);
ReleaseMemory(ptr);
byte[] block = result;//pack_etc1_block(pixels);
byte[] ne = new byte[8];
ne[0] = block[7];
ne[1] = block[6];
ne[2] = block[5];
ne[3] = block[4];
ne[4] = block[3];
ne[5] = block[2];
ne[6] = block[1];
ne[7] = block[0];
return ne;
}
public static byte[] encodeETCa4(Bitmap b)
{
int width = b.Width;
int height = b.Height;
int[] pixels = new int[width * height];
init();
int i, j;
var mem = new System.IO.MemoryStream();
using (var writer = new FileWriter(mem))
{
writer.ByteOrder = Syroot.BinaryData.ByteOrder.LittleEndian;
for (i = 0; i < height; i += 8)
{
for (j = 0; j < width; j += 8)
{
int x, y;
Color[] temp = new Color[16];
int pi = 0;
for (x = i; x < i + 4; x++)
for (y = j; y < j + 4; y++)
temp[pi++] = b.GetPixel(y, x);
for (int ax = 0; ax < 4; ax++)
for (int ay = 0; ay < 4; ay++)
{
int a = (temp[ax + ay * 4].A >> 4);
ay++;
a |= (temp[ax + ay * 4].A >> 4) << 4;
writer.Write((byte)a);
}
writer.Write(GenETC1(temp));
temp = new Color[16];
pi = 0;
for (x = i; x < i + 4; x++)
for (y = j + 4; y < j + 8; y++)
temp[pi++] = b.GetPixel(y, x);
for (int ax = 0; ax < 4; ax++)
for (int ay = 0; ay < 4; ay++)
{
int a = (temp[ax + ay * 4].A >> 4);
ay++;
a |= (temp[ax + ay * 4].A >> 4) << 4;
writer.Write((byte)a);
}
writer.Write(GenETC1(temp));
temp = new Color[16];
pi = 0;
for (x = i + 4; x < i + 8; x++)
for (y = j; y < j + 4; y++)
temp[pi++] = b.GetPixel(y, x);
for (int ax = 0; ax < 4; ax++)
for (int ay = 0; ay < 4; ay++)
{
int a = (temp[ax + ay * 4].A >> 4);
ay++;
a |= (temp[ax + ay * 4].A >> 4) << 4;
writer.Write((byte)a);
}
writer.Write(GenETC1(temp));
temp = new Color[16];
pi = 0;
for (x = i + 4; x < i + 8; x++)
for (y = j + 4; y < j + 8; y++)
temp[pi++] = b.GetPixel(y, x);
for (int ax = 0; ax < 4; ax++)
for (int ay = 0; ay < 4; ay++)
{
int a = (temp[ax + ay * 4].A >> 4);
ay++;
a |= (temp[ax + ay * 4].A >> 4) << 4;
writer.Write((byte)a);
}
writer.Write(GenETC1(temp));
}
}
}
return mem.ToArray();
}
public enum ETC1_Quality
{
low = 0,
med = 1,
high = 2
}
[DllImport("Lib\\RG_ETC1.dll")]
public static extern void init();
[DllImport("Lib\\RG_ETC1.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr encode_etc1(uint[] pSrc_pixels_rgba, int quality, bool dither);
[DllImport("Lib\\RG_ETC1.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int ReleaseMemory(IntPtr ptr);
}
}