210 lines
7.1 KiB
C#
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);
|
|
}
|
|
} |