mirror of
https://github.com/Gericom/EveryFileExplorer.git
synced 2025-06-19 01:15:36 -04:00
581 lines
18 KiB
C#
581 lines
18 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Drawing;
|
|
using System.Drawing.Imaging;
|
|
using System.Runtime.InteropServices;
|
|
using LibEveryFileExplorer.IO;
|
|
using LibEveryFileExplorer.GFX;
|
|
|
|
namespace _3DS.GPU
|
|
{
|
|
public class Textures
|
|
{
|
|
public enum ImageFormat : uint
|
|
{
|
|
RGBA8 = 0,
|
|
RGB8 = 1,
|
|
RGBA5551 = 2,
|
|
RGB565 = 3,
|
|
RGBA4 = 4,
|
|
LA8 = 5,
|
|
HILO8 = 6,
|
|
L8 = 7,
|
|
A8 = 8,
|
|
LA4 = 9,
|
|
L4 = 10,
|
|
A4 = 11,
|
|
ETC1 = 12,
|
|
ETC1A4 = 13
|
|
}
|
|
|
|
private static readonly int[] Bpp = { 32, 24, 16, 16, 16, 16, 16, 8, 8, 8, 4, 4, 4, 8 };
|
|
|
|
private static readonly int[] TileOrder =
|
|
{
|
|
0, 1, 4, 5,
|
|
2, 3, 6, 7,
|
|
|
|
8, 9, 12, 13,
|
|
10, 11, 14, 15
|
|
};
|
|
|
|
private static readonly int[,] ETC1Modifiers =
|
|
{
|
|
{ 2, 8 },
|
|
{ 5, 17 },
|
|
{ 9, 29 },
|
|
{ 13, 42 },
|
|
{ 18, 60 },
|
|
{ 24, 80 },
|
|
{ 33, 106 },
|
|
{ 47, 183 }
|
|
};
|
|
|
|
public static int GetBpp(ImageFormat Format) { return Bpp[(uint)Format]; }
|
|
|
|
public static Bitmap ToBitmap(byte[] Data, int Width, int Height, ImageFormat Format, bool ExactSize = false)
|
|
{
|
|
return ToBitmap(Data, 0, Width, Height, Format, ExactSize);
|
|
}
|
|
|
|
public static unsafe Bitmap ToBitmap(byte[] Data, int Offset, int Width, int Height, ImageFormat Format, bool ExactSize = false)
|
|
{
|
|
if (Data == null || Data.Length < 1 || Offset < 0 || Offset >= Data.Length || Width < 1 || Height < 1) return null;
|
|
if (ExactSize && ((Width % 8) != 0 || (Height % 8) != 0)) return null;
|
|
int physicalwidth = Width;
|
|
int physicalheight = Height;
|
|
if (!ExactSize)
|
|
{
|
|
Width = 1 << (int)Math.Ceiling(Math.Log(Width, 2));
|
|
Height = 1 << (int)Math.Ceiling(Math.Log(Height, 2));
|
|
}
|
|
Bitmap bitm = new Bitmap(physicalwidth, physicalheight);
|
|
BitmapData d = bitm.LockBits(new Rectangle(0, 0, bitm.Width, bitm.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
|
|
uint* res = (uint*)d.Scan0;
|
|
int offs = Offset;//0;
|
|
int stride = d.Stride / 4;
|
|
switch (Format)
|
|
{
|
|
case ImageFormat.RGBA8:
|
|
for (int y = 0; y < Height; y += 8)
|
|
{
|
|
for (int x = 0; x < Width; x += 8)
|
|
{
|
|
for (int i = 0; i < 64; i++)
|
|
{
|
|
int x2 = i % 8;
|
|
if (x + x2 >= physicalwidth) continue;
|
|
int y2 = i / 8;
|
|
if (y + y2 >= physicalheight) continue;
|
|
int pos = TileOrder[x2 % 4 + y2 % 4 * 4] + 16 * (x2 / 4) + 32 * (y2 / 4);
|
|
res[(y + y2) * stride + x + x2] =
|
|
GFXUtil.ConvertColorFormat(
|
|
IOUtil.ReadU32LE(Data, offs + pos * 4),
|
|
ColorFormat.RGBA8888,
|
|
ColorFormat.ARGB8888);
|
|
/*GFXUtil.ToArgb(
|
|
Data[offs + pos * 4],
|
|
Data[offs + pos * 4 + 3],
|
|
Data[offs + pos * 4 + 2],
|
|
Data[offs + pos * 4 + 1]
|
|
);*/
|
|
}
|
|
offs += 64 * 4;
|
|
}
|
|
}
|
|
break;
|
|
case ImageFormat.RGB8:
|
|
for (int y = 0; y < Height; y += 8)
|
|
{
|
|
for (int x = 0; x < Width; x += 8)
|
|
{
|
|
for (int i = 0; i < 64; i++)
|
|
{
|
|
int x2 = i % 8;
|
|
if (x + x2 >= physicalwidth) continue;
|
|
int y2 = i / 8;
|
|
if (y + y2 >= physicalheight) continue;
|
|
int pos = TileOrder[x2 % 4 + y2 % 4 * 4] + 16 * (x2 / 4) + 32 * (y2 / 4);
|
|
res[(y + y2) * stride + x + x2] =
|
|
GFXUtil.ConvertColorFormat(
|
|
IOUtil.ReadU24LE(Data, offs + pos * 3),
|
|
ColorFormat.RGB888,
|
|
ColorFormat.ARGB8888);
|
|
/*GFXUtil.ToArgb(
|
|
Data[offs + pos * 3 + 2],
|
|
Data[offs + pos * 3 + 1],
|
|
Data[offs + pos * 3 + 0]
|
|
);*/
|
|
}
|
|
offs += 64 * 3;
|
|
}
|
|
}
|
|
break;
|
|
case ImageFormat.RGBA5551:
|
|
for (int y = 0; y < Height; y += 8)
|
|
{
|
|
for (int x = 0; x < Width; x += 8)
|
|
{
|
|
for (int i = 0; i < 64; i++)
|
|
{
|
|
int x2 = i % 8;
|
|
if (x + x2 >= physicalwidth) continue;
|
|
int y2 = i / 8;
|
|
if (y + y2 >= physicalheight) continue;
|
|
int pos = TileOrder[x2 % 4 + y2 % 4 * 4] + 16 * (x2 / 4) + 32 * (y2 / 4);
|
|
res[(y + y2) * stride + x + x2] =
|
|
GFXUtil.ConvertColorFormat(
|
|
IOUtil.ReadU16LE(Data, offs + pos * 2),
|
|
ColorFormat.ARGB1555,
|
|
ColorFormat.ARGB8888);
|
|
//GFXUtil.ARGB1555ToArgb(IOUtil.ReadU16LE(Data, offs + pos * 2));
|
|
}
|
|
offs += 64 * 2;
|
|
}
|
|
}
|
|
break;
|
|
case ImageFormat.RGB565:
|
|
for (int y = 0; y < Height; y += 8)
|
|
{
|
|
for (int x = 0; x < Width; x += 8)
|
|
{
|
|
for (int i = 0; i < 64; i++)
|
|
{
|
|
int x2 = i % 8;
|
|
if (x + x2 >= physicalwidth) continue;
|
|
int y2 = i / 8;
|
|
if (y + y2 >= physicalheight) continue;
|
|
int pos = TileOrder[x2 % 4 + y2 % 4 * 4] + 16 * (x2 / 4) + 32 * (y2 / 4);
|
|
res[(y + y2) * stride + x + x2] =
|
|
GFXUtil.ConvertColorFormat(
|
|
IOUtil.ReadU16LE(Data, offs + pos * 2),
|
|
ColorFormat.RGB565,
|
|
ColorFormat.ARGB8888);
|
|
//GFXUtil.RGB565ToArgb(IOUtil.ReadU16LE(Data, offs + pos * 2));
|
|
}
|
|
offs += 64 * 2;
|
|
}
|
|
}
|
|
break;
|
|
case ImageFormat.RGBA4:
|
|
for (int y = 0; y < Height; y += 8)
|
|
{
|
|
for (int x = 0; x < Width; x += 8)
|
|
{
|
|
for (int i = 0; i < 64; i++)
|
|
{
|
|
int x2 = i % 8;
|
|
if (x + x2 >= physicalwidth) continue;
|
|
int y2 = i / 8;
|
|
if (y + y2 >= physicalheight) continue;
|
|
int pos = TileOrder[x2 % 4 + y2 % 4 * 4] + 16 * (x2 / 4) + 32 * (y2 / 4);
|
|
res[(y + y2) * stride + x + x2] =
|
|
GFXUtil.ConvertColorFormat(
|
|
IOUtil.ReadU16LE(Data, offs + pos * 2),
|
|
ColorFormat.RGBA4444,
|
|
ColorFormat.ARGB8888);
|
|
/*GFXUtil.ToArgb(
|
|
(byte)((Data[offs + pos * 2] & 0xF) * 0x11),
|
|
(byte)((Data[offs + pos * 2 + 1] >> 4) * 0x11),
|
|
(byte)((Data[offs + pos * 2 + 1] & 0xF) * 0x11),
|
|
(byte)((Data[offs + pos * 2] >> 4) * 0x11)
|
|
);*/
|
|
}
|
|
offs += 64 * 2;
|
|
}
|
|
}
|
|
break;
|
|
case ImageFormat.LA8:
|
|
for (int y = 0; y < Height; y += 8)
|
|
{
|
|
for (int x = 0; x < Width; x += 8)
|
|
{
|
|
for (int i = 0; i < 64; i++)
|
|
{
|
|
int x2 = i % 8;
|
|
if (x + x2 >= physicalwidth) continue;
|
|
int y2 = i / 8;
|
|
if (y + y2 >= physicalheight) continue;
|
|
int pos = TileOrder[x2 % 4 + y2 % 4 * 4] + 16 * (x2 / 4) + 32 * (y2 / 4);
|
|
res[(y + y2) * stride + x + x2] = GFXUtil.ToColorFormat(
|
|
Data[offs + pos * 2],
|
|
Data[offs + pos * 2 + 1],
|
|
Data[offs + pos * 2 + 1],
|
|
Data[offs + pos * 2 + 1],
|
|
ColorFormat.ARGB8888
|
|
);
|
|
}
|
|
offs += 64 * 2;
|
|
}
|
|
}
|
|
break;
|
|
case ImageFormat.HILO8:
|
|
for (int y = 0; y < Height; y += 8)
|
|
{
|
|
for (int x = 0; x < Width; x += 8)
|
|
{
|
|
for (int i = 0; i < 64; i++)
|
|
{
|
|
int x2 = i % 8;
|
|
if (x + x2 >= physicalwidth) continue;
|
|
int y2 = i / 8;
|
|
if (y + y2 >= physicalheight) continue;
|
|
int pos = TileOrder[x2 % 4 + y2 % 4 * 4] + 16 * (x2 / 4) + 32 * (y2 / 4);
|
|
res[(y + y2) * stride + x + x2] = GFXUtil.ToColorFormat(
|
|
Data[offs + pos * 2],
|
|
Data[offs + pos * 2 + 1],
|
|
Data[offs + pos * 2 + 1],
|
|
Data[offs + pos * 2 + 1],
|
|
ColorFormat.ARGB8888
|
|
);
|
|
}
|
|
offs += 64 * 2;
|
|
}
|
|
}
|
|
break;
|
|
case ImageFormat.L8:
|
|
for (int y = 0; y < Height; y += 8)
|
|
{
|
|
for (int x = 0; x < Width; x += 8)
|
|
{
|
|
for (int i = 0; i < 64; i++)
|
|
{
|
|
int x2 = i % 8;
|
|
if (x + x2 >= physicalwidth) continue;
|
|
int y2 = i / 8;
|
|
if (y + y2 >= physicalheight) continue;
|
|
int pos = TileOrder[x2 % 4 + y2 % 4 * 4] + 16 * (x2 / 4) + 32 * (y2 / 4);
|
|
res[(y + y2) * stride + x + x2] = GFXUtil.ToColorFormat(
|
|
Data[offs + pos],
|
|
Data[offs + pos],
|
|
Data[offs + pos],
|
|
ColorFormat.ARGB8888
|
|
);
|
|
}
|
|
offs += 64;
|
|
}
|
|
}
|
|
break;
|
|
case ImageFormat.A8:
|
|
for (int y = 0; y < Height; y += 8)
|
|
{
|
|
for (int x = 0; x < Width; x += 8)
|
|
{
|
|
for (int i = 0; i < 64; i++)
|
|
{
|
|
int x2 = i % 8;
|
|
if (x + x2 >= physicalwidth) continue;
|
|
int y2 = i / 8;
|
|
if (y + y2 >= physicalheight) continue;
|
|
int pos = TileOrder[x2 % 4 + y2 % 4 * 4] + 16 * (x2 / 4) + 32 * (y2 / 4);
|
|
res[(y + y2) * stride + x + x2] = GFXUtil.ToColorFormat(
|
|
Data[offs + pos],
|
|
255,
|
|
255,
|
|
255,
|
|
ColorFormat.ARGB8888
|
|
);
|
|
}
|
|
offs += 64;
|
|
}
|
|
}
|
|
break;
|
|
case ImageFormat.LA4:
|
|
for (int y = 0; y < Height; y += 8)
|
|
{
|
|
for (int x = 0; x < Width; x += 8)
|
|
{
|
|
for (int i = 0; i < 64; i++)
|
|
{
|
|
int x2 = i % 8;
|
|
if (x + x2 >= physicalwidth) continue;
|
|
int y2 = i / 8;
|
|
if (y + y2 >= physicalheight) continue;
|
|
int pos = TileOrder[x2 % 4 + y2 % 4 * 4] + 16 * (x2 / 4) + 32 * (y2 / 4);
|
|
res[(y + y2) * stride + x + x2] = GFXUtil.ToColorFormat(
|
|
(byte)((Data[offs + pos] & 0xF) * 0x11),
|
|
(byte)((Data[offs + pos] >> 4) * 0x11),
|
|
(byte)((Data[offs + pos] >> 4) * 0x11),
|
|
(byte)((Data[offs + pos] >> 4) * 0x11),
|
|
ColorFormat.ARGB8888
|
|
);
|
|
}
|
|
offs += 64;
|
|
}
|
|
}
|
|
break;
|
|
case ImageFormat.L4:
|
|
for (int y = 0; y < Height; y += 8)
|
|
{
|
|
for (int x = 0; x < Width; x += 8)
|
|
{
|
|
for (int i = 0; i < 64; i++)
|
|
{
|
|
int x2 = i % 8;
|
|
if (x + x2 >= physicalwidth) continue;
|
|
int y2 = i / 8;
|
|
if (y + y2 >= physicalheight) continue;
|
|
int pos = TileOrder[x2 % 4 + y2 % 4 * 4] + 16 * (x2 / 4) + 32 * (y2 / 4);
|
|
int shift = (pos & 1) * 4;
|
|
res[(y + y2) * stride + x + x2] = GFXUtil.ToColorFormat(
|
|
(byte)(((Data[offs + pos / 2] >> shift) & 0xF) * 0x11),
|
|
(byte)(((Data[offs + pos / 2] >> shift) & 0xF) * 0x11),
|
|
(byte)(((Data[offs + pos / 2] >> shift) & 0xF) * 0x11),
|
|
ColorFormat.ARGB8888
|
|
);
|
|
}
|
|
offs += 64 / 2;
|
|
}
|
|
}
|
|
break;
|
|
case ImageFormat.A4:
|
|
for (int y = 0; y < Height; y += 8)
|
|
{
|
|
for (int x = 0; x < Width; x += 8)
|
|
{
|
|
for (int i = 0; i < 64; i++)
|
|
{
|
|
int x2 = i % 8;
|
|
if (x + x2 >= physicalwidth) continue;
|
|
int y2 = i / 8;
|
|
if (y + y2 >= physicalheight) continue;
|
|
int pos = TileOrder[x2 % 4 + y2 % 4 * 4] + 16 * (x2 / 4) + 32 * (y2 / 4);
|
|
int shift = (pos & 1) * 4;
|
|
res[(y + y2) * stride + x + x2] = GFXUtil.ToColorFormat(
|
|
(byte)(((Data[offs + pos / 2] >> shift) & 0xF) * 0x11),
|
|
255,
|
|
255,
|
|
255,
|
|
ColorFormat.ARGB8888
|
|
);
|
|
}
|
|
offs += 64 / 2;
|
|
}
|
|
}
|
|
break;
|
|
case ImageFormat.ETC1://Some reference: http://www.khronos.org/registry/gles/extensions/OES/OES_compressed_ETC1_RGB8_texture.txt
|
|
case ImageFormat.ETC1A4:
|
|
{
|
|
for (int y = 0; y < Height; y += 8)
|
|
{
|
|
for (int x = 0; x < Width; x += 8)
|
|
{
|
|
for (int i = 0; i < 8; i += 4)
|
|
{
|
|
for (int j = 0; j < 8; j += 4)
|
|
{
|
|
ulong alpha = 0xFFFFFFFFFFFFFFFF;
|
|
if (Format == ImageFormat.ETC1A4)
|
|
{
|
|
alpha = IOUtil.ReadU64LE(Data, offs);
|
|
offs += 8;
|
|
}
|
|
ulong data = IOUtil.ReadU64LE(Data, offs);
|
|
bool diffbit = ((data >> 33) & 1) == 1;
|
|
bool flipbit = ((data >> 32) & 1) == 1; //0: |||, 1: |-|
|
|
int r1, r2, g1, g2, b1, b2;
|
|
if (diffbit) //'differential' mode
|
|
{
|
|
int r = (int)((data >> 59) & 0x1F);
|
|
int g = (int)((data >> 51) & 0x1F);
|
|
int b = (int)((data >> 43) & 0x1F);
|
|
r1 = (r << 3) | ((r & 0x1C) >> 2);
|
|
g1 = (g << 3) | ((g & 0x1C) >> 2);
|
|
b1 = (b << 3) | ((b & 0x1C) >> 2);
|
|
r += (int)((data >> 56) & 0x7) << 29 >> 29;
|
|
g += (int)((data >> 48) & 0x7) << 29 >> 29;
|
|
b += (int)((data >> 40) & 0x7) << 29 >> 29;
|
|
r2 = (r << 3) | ((r & 0x1C) >> 2);
|
|
g2 = (g << 3) | ((g & 0x1C) >> 2);
|
|
b2 = (b << 3) | ((b & 0x1C) >> 2);
|
|
}
|
|
else //'individual' mode
|
|
{
|
|
r1 = (int)((data >> 60) & 0xF) * 0x11;
|
|
g1 = (int)((data >> 52) & 0xF) * 0x11;
|
|
b1 = (int)((data >> 44) & 0xF) * 0x11;
|
|
r2 = (int)((data >> 56) & 0xF) * 0x11;
|
|
g2 = (int)((data >> 48) & 0xF) * 0x11;
|
|
b2 = (int)((data >> 40) & 0xF) * 0x11;
|
|
}
|
|
int Table1 = (int)((data >> 37) & 0x7);
|
|
int Table2 = (int)((data >> 34) & 0x7);
|
|
for (int y3 = 0; y3 < 4; y3++)
|
|
{
|
|
for (int x3 = 0; x3 < 4; x3++)
|
|
{
|
|
if (x + j + x3 >= physicalwidth) continue;
|
|
if (y + i + y3 >= physicalheight) continue;
|
|
|
|
int val = (int)((data >> (x3 * 4 + y3)) & 0x1);
|
|
bool neg = ((data >> (x3 * 4 + y3 + 16)) & 0x1) == 1;
|
|
uint c;
|
|
if ((flipbit && y3 < 2) || (!flipbit && x3 < 2))
|
|
{
|
|
int add = ETC1Modifiers[Table1, val] * (neg ? -1 : 1);
|
|
c = GFXUtil.ToColorFormat((byte)(((alpha >> ((x3 * 4 + y3) * 4)) & 0xF) * 0x11), (byte)ColorClamp(r1 + add), (byte)ColorClamp(g1 + add), (byte)ColorClamp(b1 + add), ColorFormat.ARGB8888);
|
|
}
|
|
else
|
|
{
|
|
int add = ETC1Modifiers[Table2, val] * (neg ? -1 : 1);
|
|
c = GFXUtil.ToColorFormat((byte)(((alpha >> ((x3 * 4 + y3) * 4)) & 0xF) * 0x11), (byte)ColorClamp(r2 + add), (byte)ColorClamp(g2 + add), (byte)ColorClamp(b2 + add), ColorFormat.ARGB8888);
|
|
}
|
|
res[(i + y3) * stride + x + j + x3] = c;
|
|
}
|
|
}
|
|
offs += 8;
|
|
}
|
|
}
|
|
}
|
|
res += stride * 8;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
bitm.UnlockBits(d);
|
|
return bitm;
|
|
}
|
|
|
|
public static unsafe byte[] FromBitmap(Bitmap Picture, ImageFormat Format, bool ExactSize = false)
|
|
{
|
|
if (ExactSize && ((Picture.Width % 8) != 0 || (Picture.Height % 8) != 0)) return null;
|
|
int physicalwidth = Picture.Width;
|
|
int physicalheight = Picture.Height;
|
|
int ConvWidth = Picture.Width;
|
|
int ConvHeight = Picture.Height;
|
|
if (!ExactSize)
|
|
{
|
|
ConvWidth = 1 << (int)Math.Ceiling(Math.Log(Picture.Width, 2));
|
|
ConvHeight = 1 << (int)Math.Ceiling(Math.Log(Picture.Height, 2));
|
|
}
|
|
BitmapData d = Picture.LockBits(new Rectangle(0, 0, Picture.Width, Picture.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
|
|
uint* res = (uint*)d.Scan0;
|
|
byte[] result = new byte[ConvWidth * ConvHeight * GetBpp(Format) / 8];
|
|
int offs = 0;
|
|
switch (Format)
|
|
{
|
|
case ImageFormat.RGB8:
|
|
for (int y = 0; y < ConvHeight; y += 8)
|
|
{
|
|
for (int x = 0; x < ConvWidth; x += 8)
|
|
{
|
|
for (int i = 0; i < 64; i++)
|
|
{
|
|
int x2 = i % 8;
|
|
if (x + x2 >= physicalwidth) continue;
|
|
int y2 = i / 8;
|
|
if (y + y2 >= physicalheight) continue;
|
|
int pos = TileOrder[x2 % 4 + y2 % 4 * 4] + 16 * (x2 / 4) + 32 * (y2 / 4);
|
|
Color c = Color.FromArgb((int)res[(y + y2) * d.Stride / 4 + x + x2]);
|
|
result[offs + pos * 3 + 0] = c.B;
|
|
result[offs + pos * 3 + 1] = c.G;
|
|
result[offs + pos * 3 + 2] = c.R;
|
|
}
|
|
offs += 64 * 3;
|
|
}
|
|
}
|
|
break;
|
|
case ImageFormat.RGB565:
|
|
for (int y = 0; y < ConvHeight; y += 8)
|
|
{
|
|
for (int x = 0; x < ConvWidth; x += 8)
|
|
{
|
|
for (int i = 0; i < 64; i++)
|
|
{
|
|
int x2 = i % 8;
|
|
if (x + x2 >= physicalwidth) continue;
|
|
int y2 = i / 8;
|
|
if (y + y2 >= physicalheight) continue;
|
|
int pos = TileOrder[x2 % 4 + y2 % 4 * 4] + 16 * (x2 / 4) + 32 * (y2 / 4);
|
|
IOUtil.WriteU16LE(result, offs + pos * 2, (ushort)GFXUtil.ConvertColorFormat(res[(y + y2) * d.Stride / 4 + x + x2], ColorFormat.ARGB8888, ColorFormat.RGB565)); //GFXUtil.ArgbToRGB565(res[(y + y2) * d.Stride / 4 + x + x2]));
|
|
}
|
|
offs += 64 * 2;
|
|
}
|
|
}
|
|
break;
|
|
case ImageFormat.ETC1:
|
|
case ImageFormat.ETC1A4:
|
|
for (int y = 0; y < ConvHeight; y += 8)
|
|
{
|
|
for (int x = 0; x < ConvWidth; x += 8)
|
|
{
|
|
for (int i = 0; i < 8; i += 4)
|
|
{
|
|
for (int j = 0; j < 8; j += 4)
|
|
{
|
|
if (Format == ImageFormat.ETC1A4)
|
|
{
|
|
ulong alpha = 0;
|
|
int iiii = 0;
|
|
for (int xx = 0; xx < 4; xx++)
|
|
{
|
|
for (int yy = 0; yy < 4; yy++)
|
|
{
|
|
uint color;
|
|
if (x + j + xx >= physicalwidth) color = 0x00FFFFFF;
|
|
else if (y + i + yy >= physicalheight) color = 0x00FFFFFF;
|
|
else color = res[((y + i + yy) * (d.Stride / 4)) + x + j + xx];
|
|
uint a = color >> 24;
|
|
a >>= 4;
|
|
alpha |= (ulong)a << (iiii * 4);
|
|
iiii++;
|
|
}
|
|
}
|
|
IOUtil.WriteU64LE(result, offs, alpha);
|
|
offs += 8;
|
|
}
|
|
Color[] pixels = new Color[4 * 4];
|
|
for (int yy = 0; yy < 4; yy++)
|
|
{
|
|
for (int xx = 0; xx < 4; xx++)
|
|
{
|
|
if (x + j + xx >= physicalwidth) pixels[yy * 4 + xx] = Color.Transparent;
|
|
else if (y + i + yy >= physicalheight) pixels[yy * 4 + xx] = Color.Transparent;
|
|
else pixels[yy * 4 + xx] = Color.FromArgb((int)res[((y + i + yy) * (d.Stride / 4)) + x + j + xx]);
|
|
}
|
|
}
|
|
IOUtil.WriteU64LE(result, offs, ETC1.GenETC1(pixels));
|
|
offs += 8;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
throw new NotImplementedException("This format is not implemented yet.");
|
|
}
|
|
return result;
|
|
}
|
|
|
|
private static int ColorClamp(int Color)
|
|
{
|
|
if (Color > 255) Color = 255;
|
|
if (Color < 0) Color = 0;
|
|
return Color;
|
|
}
|
|
|
|
}
|
|
}
|