diff --git a/ArcFormats/ArcFormats.csproj b/ArcFormats/ArcFormats.csproj
index 2d4f87b0..69f63024 100644
--- a/ArcFormats/ArcFormats.csproj
+++ b/ArcFormats/ArcFormats.csproj
@@ -66,6 +66,7 @@
+
diff --git a/ArcFormats/Entis/ArcERI.cs b/ArcFormats/Entis/ArcERI.cs
index ddb26212..ca94edc4 100644
--- a/ArcFormats/Entis/ArcERI.cs
+++ b/ArcFormats/Entis/ArcERI.cs
@@ -115,7 +115,7 @@ namespace GameRes.Formats.Entis
var earc = (EriMultiImage)arc;
var eent = (EriEntry)entry;
var pixels = earc.GetFrame (eent.FrameIndex);
- if (32 == earc.Info.BPP && 0 == (earc.Info.FormatType & (int)EriImage.WithAlpha))
+ if (32 == earc.Info.BPP && 0 == (earc.Info.FormatType & EriType.WithAlpha))
{
for (int p = 3; p < pixels.Length; p += 4)
pixels[p] = 0xFF;
diff --git a/ArcFormats/Entis/EriReader.cs b/ArcFormats/Entis/EriReader.cs
index 14752f49..29a8e075 100644
--- a/ArcFormats/Entis/EriReader.cs
+++ b/ArcFormats/Entis/EriReader.cs
@@ -22,20 +22,20 @@ namespace GameRes.Formats.Entis
ERISADecodeContext m_context;
int m_dst;
- uint m_nBlockSize;
- uint m_nBlockArea;
- uint m_nBlockSamples;
- uint m_nChannelCount;
- uint m_nWidthBlocks;
- uint m_nHeightBlocks;
+ int m_nBlockSize;
+ int m_nBlockArea;
+ int m_nBlockSamples;
+ int m_nChannelCount;
+ int m_nWidthBlocks;
+ int m_nHeightBlocks;
int m_dwBytesPerLine;
int m_ptrDstBlock;
int m_nDstLineBytes;
int m_nDstPixelBytes;
- uint m_nDstWidth;
- uint m_nDstHeight;
+ int m_nDstWidth;
+ int m_nDstHeight;
// buffers for lossless encoding
byte[] m_ptrOperations;
@@ -45,6 +45,28 @@ namespace GameRes.Formats.Entis
sbyte[] m_ptrArrangeBuf;
int[] m_pArrangeTable = new int[4];
+ // lossy encoding
+ int m_nBlocksetCount;
+ int m_nYUVLineBytes;
+ int m_nYUVPixelBytes;
+ sbyte[] m_ptrLossyOps;
+ float[] m_ptrVertBufLOT;
+ float[] m_ptrHorzBufLOT;
+ float[][] m_ptrBlocksetBuf;
+ float[] m_ptrMatrixBuf;
+ float[] m_ptrIQParamBuf;
+ byte[] m_ptrIQParamTable;
+
+ sbyte[] m_ptrBlockLineBuf;
+ sbyte[] m_ptrNextBlockBuf;
+ sbyte[] m_ptrImageBuf;
+ sbyte[] m_ptrYUVImage;
+
+ sbyte[] m_ptrMovingVector;
+ sbyte[] m_ptrMoveVecFlags;
+ int[] m_ptrMovePrevBlocks;
+ int[] m_ptrNextPrevBlocks;
+
HuffmanTree m_pHuffmanTree;
ErisaProbModel m_pProbERISA;
@@ -60,6 +82,40 @@ namespace GameRes.Formats.Entis
{
m_info = info;
m_src_frame = key_frame;
+ switch (m_info.Architecture)
+ {
+ case EriCode.Nemesis:
+ case EriCode.RunlengthHuffman:
+ case EriCode.RunlengthGamma:
+ if (CvType.Lossless_ERI == m_info.Transformation && 0 == m_info.BlockingDegree)
+ throw new InvalidFormatException();
+ break;
+ case EriCode.ArithmeticCode:
+ if (CvType.Lossless_ERI != m_info.Transformation)
+ throw new InvalidFormatException();
+ break;
+ default:
+ throw new InvalidFormatException();
+ }
+ switch (m_info.FormatType & EriType.Mask)
+ {
+ case EriType.RGB:
+ if (m_info.BPP <= 8)
+ m_nChannelCount = 1;
+ else if (0 == (m_info.FormatType & EriType.WithAlpha))
+ m_nChannelCount = 3;
+ else
+ m_nChannelCount = 4;
+ break;
+
+ case EriType.Gray:
+ m_nChannelCount = 1;
+ break;
+
+ default:
+ throw new InvalidFormatException();
+ }
+
if (CvType.Lossless_ERI == m_info.Transformation)
InitializeLossless();
else if (CvType.LOT_ERI == m_info.Transformation
@@ -67,6 +123,7 @@ namespace GameRes.Formats.Entis
InitializeLossy();
else
throw new NotSupportedException ("Not supported ERI compression");
+
if (null != palette)
Palette = new BitmapPalette (palette);
CreateImageBuffer();
@@ -95,46 +152,13 @@ namespace GameRes.Formats.Entis
private void InitializeLossless ()
{
- switch (m_info.Architecture)
- {
- case EriCode.Nemesis:
- case EriCode.RunlengthHuffman:
- case EriCode.RunlengthGamma:
- if (0 == m_info.BlockingDegree)
- throw new InvalidFormatException();
- break;
- case EriCode.ArithmeticCode:
- break;
- default:
- throw new InvalidFormatException();
- }
-
- switch (m_info.FormatType & (int)EriImage.TypeMask)
- {
- case (int)EriImage.RGB:
- if (m_info.BPP <= 8)
- m_nChannelCount = 1;
- else if (0 == (m_info.FormatType & (int)EriImage.WithAlpha))
- m_nChannelCount = 3;
- else
- m_nChannelCount = 4;
- break;
-
- case (int)EriImage.Gray:
- m_nChannelCount = 1;
- break;
-
- default:
- throw new InvalidFormatException();
- }
-
if (0 != m_info.BlockingDegree)
{
- m_nBlockSize = (uint) (1 << m_info.BlockingDegree);
- m_nBlockArea = (uint) (1 << (m_info.BlockingDegree * 2));
+ m_nBlockSize = 1 << m_info.BlockingDegree;
+ m_nBlockArea = 1 << (m_info.BlockingDegree * 2);
m_nBlockSamples = m_nBlockArea * m_nChannelCount;
- m_nWidthBlocks = (uint)((m_info.Width + m_nBlockSize - 1) >> m_info.BlockingDegree);
- m_nHeightBlocks = (uint)((m_info.Height + m_nBlockSize - 1) >> m_info.BlockingDegree);
+ m_nWidthBlocks = ((int)m_info.Width + m_nBlockSize - 1) >> m_info.BlockingDegree;
+ m_nHeightBlocks = ((int)m_info.Height + m_nBlockSize - 1) >> m_info.BlockingDegree;
m_ptrOperations = new byte[m_nWidthBlocks * m_nHeightBlocks];
m_ptrColumnBuf = new sbyte[m_nBlockSize * m_nChannelCount];
@@ -165,25 +189,99 @@ namespace GameRes.Formats.Entis
private void InitializeLossy ()
{
- throw new NotImplementedException ("Lossy ERI compression not implemented");
+ if (3 != m_info.BlockingDegree)
+ throw new InvalidFormatException();
+
+ m_nBlockSize = 1 << m_info.BlockingDegree;
+ m_nBlockArea = 1 << (m_info.BlockingDegree * 2);
+ m_nBlockSamples = m_nBlockArea * m_nChannelCount;
+ m_nWidthBlocks = ((int)m_info.Width + m_nBlockSize * 2 - 1) >> (m_info.BlockingDegree + 1);
+ m_nHeightBlocks = ((int)m_info.Height + m_nBlockSize * 2 - 1) >> (m_info.BlockingDegree + 1);
+
+ if (CvType.LOT_ERI == m_info.Transformation)
+ {
+ ++m_nWidthBlocks;
+ ++m_nHeightBlocks;
+ }
+
+ if (EriSampling.YUV_4_4_4 == m_info.SamplingFlags)
+ {
+ m_nBlocksetCount = m_nChannelCount * 4;
+ }
+ else if (EriSampling.YUV_4_1_1 == m_info.SamplingFlags)
+ {
+ switch (m_nChannelCount)
+ {
+ case 1:
+ m_nBlocksetCount = 4;
+ break;
+ case 3:
+ m_nBlocksetCount = 6;
+ break;
+ case 4:
+ m_nBlocksetCount = 10;
+ break;
+ default:
+ throw new InvalidFormatException();
+ }
+ }
+ else
+ throw new InvalidFormatException();
+
+ m_ptrDecodeBuf = new sbyte[m_nBlockArea * 16];
+ m_ptrVertBufLOT = new float[m_nBlockSamples * 2 * m_nWidthBlocks];
+ m_ptrHorzBufLOT = new float[m_nBlockSamples * 2];
+ m_ptrBlocksetBuf = new float[16][];
+ m_ptrMatrixBuf = new float[m_nBlockArea * 16];
+ m_ptrIQParamBuf = new float[m_nBlockArea * 2];
+ m_ptrIQParamTable = new byte[m_nBlockArea * 2];
+
+ int dwTotalBlocks = m_nWidthBlocks * m_nHeightBlocks;
+ m_ptrLossyOps = new sbyte[dwTotalBlocks * 2];
+ m_ptrImageBuf = new sbyte[dwTotalBlocks * m_nBlockArea * m_nBlocksetCount];
+ m_ptrMovingVector = new sbyte[dwTotalBlocks * 4];
+ m_ptrMoveVecFlags = new sbyte[dwTotalBlocks];
+ m_ptrMovePrevBlocks = new int[dwTotalBlocks * 4];
+
+ for (int i = 0; i < 16; i ++)
+ {
+ m_ptrBlocksetBuf[i] = new float[m_nBlockArea];
+ }
+
+ m_nYUVPixelBytes = m_nChannelCount;
+ if (3 == m_nYUVPixelBytes)
+ {
+ m_nYUVPixelBytes = 4;
+ }
+ m_nYUVLineBytes = ((m_nYUVPixelBytes * m_nWidthBlocks * m_nBlockSize * 2) + 0xF) & (~0xF);
+ int nYUVImageSize = m_nYUVLineBytes * m_nHeightBlocks * m_nBlockSize * 2;
+ m_ptrBlockLineBuf = new sbyte[m_nYUVLineBytes * 16];
+ m_ptrYUVImage = new sbyte[nYUVImageSize];
+
+ InitializeZigZagTable();
+
+ m_pHuffmanTree = new HuffmanTree();
+ m_pProbERISA = new ErisaProbModel();
+
+ m_context = new HuffmanDecodeContext (0x10000);
}
int[] m_ptrTable;
void InitializeArrangeTable ()
{
- uint i, j, k, l, m;
+ int i, j, k, l, m;
m_ptrTable = new int[m_nBlockSamples * 4];
m_pArrangeTable[0] = 0;
- m_pArrangeTable[1] = (int)m_nBlockSamples;
- m_pArrangeTable[2] = (int)m_nBlockSamples * 2;
- m_pArrangeTable[3] = (int)m_nBlockSamples * 3;
+ m_pArrangeTable[1] = m_nBlockSamples;
+ m_pArrangeTable[2] = m_nBlockSamples * 2;
+ m_pArrangeTable[3] = m_nBlockSamples * 3;
int ptrNext = m_pArrangeTable[0];
for (i = 0; i < m_nBlockSamples; ++i)
{
- m_ptrTable[ptrNext+i] = (int)i;
+ m_ptrTable[ptrNext+i] = i;
}
ptrNext = m_pArrangeTable[1];
@@ -195,7 +293,7 @@ namespace GameRes.Formats.Entis
m = l + j;
for (k = 0; k < m_nBlockSize; k++)
{
- m_ptrTable[ptrNext++] = (int)m;
+ m_ptrTable[ptrNext++] = m;
m += m_nBlockSize;
}
}
@@ -207,7 +305,7 @@ namespace GameRes.Formats.Entis
k = i;
for (j = 0; j < m_nChannelCount; j++)
{
- m_ptrTable[ptrNext++] = (int)k;
+ m_ptrTable[ptrNext++] = k;
k += m_nBlockArea;
}
}
@@ -221,13 +319,63 @@ namespace GameRes.Formats.Entis
l += m_nBlockSize;
for (k = 0; k < m_nChannelCount; k++)
{
- m_ptrTable[ptrNext++] = (int)m;
+ m_ptrTable[ptrNext++] = m;
m += m_nBlockArea;
}
}
}
}
+ void InitializeZigZagTable ()
+ {
+ m_ptrTable = new int[m_nBlockArea];
+ m_pArrangeTable[0] = 0;
+
+ uint i = 0;
+ int x = 0, y = 0;
+ for (;;)
+ {
+ for (;;)
+ {
+ m_ptrTable[i++] = x + y * m_nBlockSize;
+ if (i >= m_nBlockArea)
+ return;
+ ++x;
+ --y;
+ if (x >= m_nBlockSize)
+ {
+ --x;
+ y += 2;
+ break;
+ }
+ else if (y < 0)
+ {
+ y = 0;
+ break;
+ }
+ }
+ for (;;)
+ {
+ m_ptrTable[i++] = x + y * m_nBlockSize;
+ if (i >= m_nBlockArea)
+ return;
+ ++y;
+ --x;
+ if (y >= m_nBlockSize)
+ {
+ --y;
+ x += 2;
+ break;
+ }
+ else if (x < 0)
+ {
+ x = 0;
+ break;
+ }
+ }
+ }
+ }
+
private void CreateImageBuffer ()
{
m_dwBytesPerLine = (((int)m_info.Width * m_info.BPP / 8) + 3) & ~3;
@@ -301,11 +449,11 @@ namespace GameRes.Formats.Entis
}
int i;
int ptrNextOperation = 0; // index within m_ptrOperations
- if ((0 != (fEncodeType & 0x01)) && (m_nChannelCount >= 3))
+ if ((0 != (fEncodeType & 1)) && (m_nChannelCount >= 3))
{
if (m_info.Architecture == EriCode.Nemesis)
throw new InvalidFormatException();
- int nAllBlockCount = (int)(m_nWidthBlocks * m_nHeightBlocks);
+ int nAllBlockCount = m_nWidthBlocks * m_nHeightBlocks;
for (i = 0; i < nAllBlockCount; i++)
{
if (EriCode.RunlengthGamma == m_info.Architecture)
@@ -324,7 +472,7 @@ namespace GameRes.Formats.Entis
if (EriCode.RunlengthGamma == m_info.Architecture)
{
- if (0 != (fEncodeType & 0x01))
+ if (0 != (fEncodeType & 1))
{
context.InitGammaContext();
}
@@ -338,31 +486,27 @@ namespace GameRes.Formats.Entis
Debug.Assert (EriCode.Nemesis == m_info.Architecture);
(context as ProbDecodeContext).PrepareToDecodeERISACode();
}
- int nWidthSamples = (int)(m_nChannelCount * m_nWidthBlocks * m_nBlockSize);
+ int nWidthSamples = m_nChannelCount * m_nWidthBlocks * m_nBlockSize;
for (i = 0; i < nWidthSamples; ++i)
m_ptrLineBuf[i] = 0;
- int nAllBlockLines = (int)(m_nBlockSize * m_nChannelCount);
+ int nAllBlockLines = m_nBlockSize * m_nChannelCount;
int nLeftHeight = (int)m_info.Height;
- for (int nPosY = 0; nPosY < (int) m_nHeightBlocks; ++nPosY)
+ for (int nPosY = 0; nPosY < m_nHeightBlocks; ++nPosY)
{
- int nColumnBufSamples = (int)(m_nBlockSize * m_nChannelCount);
+ int nColumnBufSamples = m_nBlockSize * m_nChannelCount;
for (i = 0; i < nColumnBufSamples; ++i)
m_ptrColumnBuf[i] = 0;
- m_ptrDstBlock = m_dst + nPosY * m_dwBytesPerLine * (int)m_nBlockSize;
- m_nDstHeight = m_nBlockSize;
- if ((int)m_nDstHeight > nLeftHeight)
- {
- m_nDstHeight = (uint)nLeftHeight;
- }
+ m_ptrDstBlock = m_dst + nPosY * m_dwBytesPerLine * m_nBlockSize;
+ m_nDstHeight = Math.Min (m_nBlockSize, nLeftHeight);
int nLeftWidth = (int)m_info.Width;
int ptrNextLineBuf = 0; // m_ptrLineBuf;
- for (int nPosX = 0; nPosX < (int)m_nWidthBlocks; ++nPosX)
+ for (int nPosX = 0; nPosX < m_nWidthBlocks; ++nPosX)
{
- m_nDstWidth = Math.Min (m_nBlockSize, (uint)nLeftWidth);
+ m_nDstWidth = Math.Min (m_nBlockSize, nLeftWidth);
uint dwOperationCode;
if (m_nChannelCount >= 3)
@@ -388,20 +532,20 @@ namespace GameRes.Formats.Entis
}
else
{
- if ((int)EriImage.Gray == m_info.FormatType)
+ if (EriType.Gray == m_info.FormatType)
{
dwOperationCode = 0xC0;
}
else
{
- dwOperationCode = 0x00;
+ dwOperationCode = 0;
}
- if (0 == (fEncodeType & 0x01) && m_info.Architecture == EriCode.RunlengthGamma)
+ if (0 == (fEncodeType & 1) && m_info.Architecture == EriCode.RunlengthGamma)
{
context.InitGammaContext();
}
}
- if (context.DecodeBytes (m_ptrArrangeBuf, m_nBlockSamples) < m_nBlockSamples)
+ if (context.DecodeBytes (m_ptrArrangeBuf, (uint)m_nBlockSamples) < m_nBlockSamples)
{
throw new InvalidFormatException();
}
@@ -410,18 +554,22 @@ namespace GameRes.Formats.Entis
pfnRestoreFunc();
- m_ptrDstBlock += (int)(m_nDstPixelBytes * m_nBlockSize);
- nLeftWidth -= (int) m_nBlockSize;
+ m_ptrDstBlock += m_nDstPixelBytes * m_nBlockSize;
+ nLeftWidth -= m_nBlockSize;
}
- nLeftHeight -= (int)m_nBlockSize;
+ nLeftHeight -= m_nBlockSize;
}
}
+ #pragma warning disable 162 // unreachable code
+
private void DecodeType2Image (RLEDecodeContext context)
{
if (m_info.BPP != 8)
throw new InvalidFormatException();
+ throw new NotImplementedException ("Arithmetic compression not implemented");
+
if (EriCode.ArithmeticCode == m_info.Architecture)
{
// (context as ArithmeticContext).InitArithmeticContext (8);
@@ -444,6 +592,149 @@ namespace GameRes.Formats.Entis
private void DecodeLossyImage (HuffmanDecodeContext context)
{
throw new NotImplementedException ("Lossy ERI compression not implemented");
+ context.FlushBuffer();
+
+ uint nERIVersion = context.GetNBits (8);
+ uint fOpTable = context.GetNBits (8);
+ uint fEncodeType = context.GetNBits (8);
+ uint nBitCount = context.GetNBits (8);
+
+ var orig_trans = m_info.Transformation;
+ CalcImageSizeInBlocks ((fEncodeType == 1) ? CvType.DCT_ERI : orig_trans);
+
+ m_ptrDstBlock = m_dst;
+ m_nDstPixelBytes = m_info.BPP >> 3;
+ m_nDstLineBytes = m_dwBytesPerLine;
+ m_nDstWidth = (int)m_info.Width;
+ m_nDstHeight = (int)m_info.Height;
+
+ var pfnRestoreFunc = GetLSRestoreFunc (m_info.FormatType, m_info.BPP);
+ if (null == pfnRestoreFunc)
+ throw new InvalidFormatException();
+
+ if (context.GetABit() != 0)
+ throw new InvalidFormatException();
+
+ if (0x28 == nERIVersion)
+ {
+ if (EriCode.RunlengthGamma != m_info.Architecture)
+ throw new InvalidFormatException();
+ Debug.Assert (m_pHuffmanTree != null);
+ context.PrepareToDecodeERINACode (HuffmanDecodeContext.efERINAOrder0);
+ }
+ else
+ throw new InvalidFormatException();
+
+ for (int i = 0; i < m_nBlockArea * 2; ++i)
+ {
+ m_ptrIQParamTable[i] = (byte)context.GetHuffmanCode (m_pHuffmanTree);
+ }
+ int nTotalBlocks = m_nWidthBlocks * m_nHeightBlocks;
+ int nTotalSamples = nTotalBlocks * m_nBlockArea * m_nBlocksetCount;
+ context.InitGammaContext();
+ if (context.DecodeGammaCodeBytes (m_ptrLossyOps, (uint)nTotalBlocks * 2) < nTotalBlocks * 2)
+ throw new InvalidFormatException();
+
+ Debug.Assert (8 == m_nBlockSize);
+ const int nBlockSize = 16;
+ uint nWidthDivBlocks = (m_info.Width + (nBlockSize - 1)) / nBlockSize;
+ uint nHeightDivBlocks = (m_info.Height + (nBlockSize - 1)) / nBlockSize;
+ uint nTotalDivBlocks = nWidthDivBlocks * nHeightDivBlocks;
+
+ if (0 != (fOpTable & 1))
+ {
+ context.InitGammaContext();
+ if (context.DecodeGammaCodeBytes (m_ptrMoveVecFlags, nTotalDivBlocks) < nTotalDivBlocks)
+ throw new InvalidFormatException();
+ context.InitGammaContext();
+ if (context.DecodeGammaCodeBytes (m_ptrMovingVector, nTotalDivBlocks * 4) < nTotalDivBlocks * 4 )
+ throw new InvalidFormatException();
+ }
+ else if (null != m_src_frame)
+ {
+ for (uint i = 0; i < nTotalDivBlocks; ++i)
+ m_ptrMoveVecFlags[i] = 1;
+ for (uint i = 0; i < nTotalDivBlocks*4; ++i)
+ m_ptrMovingVector[i] = 0;
+ }
+ if (null != m_src_frame)
+ {
+ SetupMovingVector();
+ }
+ if (CvType.LOT_ERI == m_info.Transformation)
+ {
+ for (int i = 0; i < m_ptrVertBufLOT.Length; ++i)
+ m_ptrVertBufLOT[i] = 0;
+ }
+
+ Action pfnBlockMatrix;
+ if (CvType.LOT_ERI == m_info.Transformation)
+ pfnBlockMatrix = MatrixILOT8x8;
+ else
+ pfnBlockMatrix = MatrixIDCT8x8;
+
+ Action pfnBlockScaling;
+ if (EriSampling.YUV_4_1_1 == m_info.SamplingFlags)
+ pfnBlockScaling = BlockScaling411;
+ else
+ pfnBlockScaling = BlockScaling444;
+
+ int ptrQParam = 0; // m_ptrLossyOps
+ int nLineBlockSamples = m_nWidthBlocks * m_nBlockArea * m_nBlocksetCount;
+
+ m_ptrNextPrevBlocks = m_ptrMovePrevBlocks;
+ for (int nPosY = 0; nPosY < m_nHeightBlocks; ++nPosY)
+ {
+ if (CvType.LOT_ERI == m_info.Transformation)
+ {
+ for (int i = 0; i < m_ptrHorzBufLOT.Length; ++i)
+ m_ptrHorzBufLOT[i] = 0;
+ }
+ int ptrVertBufLOT = 0; // m_ptrVertBufLOT;
+ m_ptrNextBlockBuf = m_ptrBlockLineBuf;
+
+ if (context.DecodeBytes (m_ptrImageBuf, (uint)nLineBlockSamples) < nLineBlockSamples)
+ throw new InvalidFormatException();
+
+ int ptrSrcData = 0; // m_ptrImageBuf;
+
+ for (int nPosX = 0; nPosX < m_nWidthBlocks; ++nPosX)
+ {
+ ArrangeAndIQuantumize (ptrSrcData, ptrQParam);
+ ptrSrcData += m_nBlockArea * m_nBlocksetCount;
+ ptrQParam += 2;
+
+ pfnBlockMatrix (m_ptrVertBufLOT, ptrVertBufLOT);
+ ptrVertBufLOT += m_nBlockArea * 2 * m_nChannelCount;
+ pfnBlockScaling (nPosX, nPosY);
+ }
+ }
+ pfnRestoreFunc();
+
+ if (0 != (fOpTable & 0xC))
+ {
+ throw new NotImplementedException ("Filtering operations not implemented");
+ }
+ m_info.Transformation = orig_trans;
+ }
+
+ void CalcImageSizeInBlocks (CvType fdwTransformation)
+ {
+ m_info.Transformation = fdwTransformation;
+
+ m_nWidthBlocks = (((int)m_info.Width + m_nBlockSize * 2 - 1) >> (m_info.BlockingDegree + 1));
+ m_nHeightBlocks = ((int)m_info.Height + m_nBlockSize * 2 - 1) >> (m_info.BlockingDegree + 1);
+
+ if (CvType.LOT_ERI == fdwTransformation)
+ {
+ ++m_nWidthBlocks;
+ ++m_nHeightBlocks;
+ }
+ }
+
+ void SetupMovingVector ()
+ {
+ throw new NotImplementedException ("Lossy delta compression not implemented");
}
void PerformOperation (uint dwOpCode, int nAllBlockLines, sbyte[] pNextLineBuf, int iNextLineIdx )
@@ -456,7 +747,7 @@ namespace GameRes.Formats.Entis
if (0 == nArrangeCode)
{
- Buffer.BlockCopy (m_ptrArrangeBuf, 0, m_ptrDecodeBuf, 0, (int)m_nBlockSamples);
+ Buffer.BlockCopy (m_ptrArrangeBuf, 0, m_ptrDecodeBuf, 0, m_nBlockSamples);
if (0 == dwOpCode)
{
return;
@@ -465,7 +756,7 @@ namespace GameRes.Formats.Entis
else
{
int pArrange = m_pArrangeTable[nArrangeCode];
- for (i = 0; i < (int)m_nBlockSamples; i++)
+ for (i = 0; i < m_nBlockSamples; i++)
{
m_ptrDecodeBuf[m_ptrTable[pArrange + i]] = m_ptrArrangeBuf[i];
}
@@ -474,12 +765,12 @@ namespace GameRes.Formats.Entis
int ptrNextBuf = 0; // m_ptrDecodeBuf
int ptrNextColBuf = 0; // m_ptrColumnBuf
- if (0 != (nDiffOperation & 0x01))
+ if (0 != (nDiffOperation & 1))
{
for (i = 0; i < nAllBlockLines; i++)
{
sbyte nLastVal = m_ptrColumnBuf[ptrNextColBuf];
- for (j = 0; j < (int)m_nBlockSize; j++)
+ for (j = 0; j < m_nBlockSize; j++)
{
nLastVal += m_ptrDecodeBuf[ptrNextBuf];
m_ptrDecodeBuf[ptrNextBuf++] = nLastVal;
@@ -492,35 +783,35 @@ namespace GameRes.Formats.Entis
for (i = 0; i < nAllBlockLines; i ++)
{
m_ptrColumnBuf[ptrNextColBuf++] = m_ptrDecodeBuf[ptrNextBuf + m_nBlockSize - 1];
- ptrNextBuf += (int)m_nBlockSize;
+ ptrNextBuf += m_nBlockSize;
}
}
int iNextDst = 0;
- for (k = 0; k < (int)m_nChannelCount; k++)
+ for (k = 0; k < m_nChannelCount; k++)
{
sbyte[] ptrLastLine = pNextLineBuf;
int idxLastLine = iNextLineIdx;
- for (i = 0; i < (int)m_nBlockSize; i++)
+ for (i = 0; i < m_nBlockSize; i++)
{
- for (j = 0; j < (int)m_nBlockSize; j++)
+ for (j = 0; j < m_nBlockSize; j++)
{
m_ptrDecodeBuf[iNextDst+j] += ptrLastLine[idxLastLine+j];
}
ptrLastLine = m_ptrDecodeBuf;
idxLastLine = iNextDst;
- iNextDst += (int)m_nBlockSize;
+ iNextDst += m_nBlockSize;
}
- Buffer.BlockCopy (ptrLastLine, idxLastLine, pNextLineBuf, iNextLineIdx, (int)m_nBlockSize);
- iNextLineIdx += (int)m_nBlockSize;
+ Buffer.BlockCopy (ptrLastLine, idxLastLine, pNextLineBuf, iNextLineIdx, m_nBlockSize);
+ iNextLineIdx += m_nBlockSize;
}
}
- PtrProcedure GetLLRestoreFunc (int fdwFormatType, int dwBitsPerPixel)
+ PtrProcedure GetLLRestoreFunc (EriType fdwFormatType, int dwBitsPerPixel)
{
switch (dwBitsPerPixel)
{
case 32:
- if ((int)EriImage.RGBA == fdwFormatType)
+ if (EriType.RGBA == fdwFormatType)
{
Format = PixelFormats.Bgra32;
if (null == m_src_frame)
@@ -552,11 +843,45 @@ namespace GameRes.Formats.Entis
return null;
}
+ PtrProcedure GetLSRestoreFunc (EriType fdwFormatType, int dwBitsPerPixel)
+ {
+ switch (dwBitsPerPixel)
+ {
+ case 32:
+ if (EriType.RGBA == fdwFormatType)
+ {
+ Format = PixelFormats.Bgra32;
+ if (null == m_src_frame)
+ return LossyRestoreRGBA32;
+ else
+ return LossyRestoreDeltaRGBA32;
+ }
+ Format = PixelFormats.Bgr32;
+ if (null == m_src_frame)
+ return LossyRestoreRGB24;
+ else
+ return LossyRestoreDeltaRGB24;
+ case 24:
+ Format = PixelFormats.Bgr24;
+ if (null == m_src_frame)
+ return LossyRestoreRGB24;
+ else
+ return LossyRestoreDeltaRGB24;
+ case 8:
+ Format = PixelFormats.Gray8;
+ if (null == m_src_frame)
+ return LossyRestoreGray8;
+ else
+ return LossyRestoreDeltaGray8;
+ }
+ return null;
+ }
+
void RestoreRGBA32 ()
{
int ptrDstLine = m_ptrDstBlock;
int ptrSrcLine = 0; //m_ptrDecodeBuf;
- int nBlockSamples = (int)m_nBlockArea;
+ int nBlockSamples = m_nBlockArea;
int nBlockSamplesX3 = nBlockSamples * 3;
for (uint y = 0; y < m_nDstHeight; y++)
@@ -572,7 +897,7 @@ namespace GameRes.Formats.Entis
m_output[ptrDstNext++] = (byte)m_ptrDecodeBuf[ptrSrcNext + nBlockSamplesX3];
ptrSrcNext ++;
}
- ptrSrcLine += (int)m_nBlockSize;
+ ptrSrcLine += m_nBlockSize;
ptrDstLine += m_nDstLineBytes;
}
}
@@ -582,7 +907,7 @@ namespace GameRes.Formats.Entis
int ptrDstLine = m_ptrDstBlock;
int ptrSrcLine = 0; //m_ptrDecodeBuf;
int nBytesPerPixel = m_nDstPixelBytes;
- int nBlockSamples = (int)m_nBlockArea;
+ int nBlockSamples = m_nBlockArea;
for (uint y = 0; y < m_nDstHeight; y++)
{
@@ -597,7 +922,7 @@ namespace GameRes.Formats.Entis
ptrSrcNext ++;
ptrDstNext += nBytesPerPixel;
}
- ptrSrcLine += (int)m_nBlockSize;
+ ptrSrcLine += m_nBlockSize;
ptrDstLine += m_nDstLineBytes;
}
}
@@ -606,7 +931,7 @@ namespace GameRes.Formats.Entis
{
int ptrDstLine = m_ptrDstBlock;
int ptrSrcLine = 0; //m_ptrDecodeBuf;
- int nBlockSamples = (int)m_nBlockArea;
+ int nBlockSamples = m_nBlockArea;
int nBlockSamplesX3 = nBlockSamples * 3;
for (uint y = 0; y < m_nDstHeight; y++)
@@ -623,7 +948,7 @@ namespace GameRes.Formats.Entis
ptrSrcNext ++;
ptrDstNext += 4;
}
- ptrSrcLine += (int)m_nBlockSize;
+ ptrSrcLine += m_nBlockSize;
ptrDstLine += m_nDstLineBytes;
}
}
@@ -633,7 +958,7 @@ namespace GameRes.Formats.Entis
int ptrDstLine = m_ptrDstBlock;
int ptrSrcLine = 0; //m_ptrDecodeBuf;
int nBytesPerPixel = m_nDstPixelBytes;
- int nBlockSamples = (int)m_nBlockArea;
+ int nBlockSamples = m_nBlockArea;
for (uint y = 0; y < m_nDstHeight; y++)
{
@@ -648,7 +973,7 @@ namespace GameRes.Formats.Entis
ptrSrcNext ++;
ptrDstNext += nBytesPerPixel;
}
- ptrSrcLine += (int)m_nBlockSize;
+ ptrSrcLine += m_nBlockSize;
ptrDstLine += m_nDstLineBytes;
}
}
@@ -657,7 +982,7 @@ namespace GameRes.Formats.Entis
{
int ptrDstLine = m_ptrDstBlock;
int ptrSrcLine = 0; //m_ptrDecodeBuf;
- int nBlockSamples = (int)m_nBlockArea;
+ int nBlockSamples = m_nBlockArea;
for (uint y = 0; y < m_nDstHeight; y++)
{
@@ -673,7 +998,7 @@ namespace GameRes.Formats.Entis
m_output[ptrDstNext++] = (byte)(word >> 8);
ptrSrcNext ++;
}
- ptrSrcLine += (int)m_nBlockSize;
+ ptrSrcLine += m_nBlockSize;
ptrDstLine += m_nDstLineBytes;
}
}
@@ -685,12 +1010,200 @@ namespace GameRes.Formats.Entis
for (uint y = 0; y < m_nDstHeight; y++)
{
- Buffer.BlockCopy (m_ptrDecodeBuf, ptrSrcLine, m_output, ptrDstLine, (int)m_nDstWidth);
- ptrSrcLine += (int)m_nBlockSize;
+ Buffer.BlockCopy (m_ptrDecodeBuf, ptrSrcLine, m_output, ptrDstLine, m_nDstWidth);
+ ptrSrcLine += m_nBlockSize;
ptrDstLine += m_nDstLineBytes;
}
}
+ void LossyRestoreRGB24 ()
+ {
+ ConvertImageYUVtoRGB();
+
+ int nSrcLineBytes = m_nYUVLineBytes;
+ int nSrcPixelBytes = m_nYUVPixelBytes;
+ int ptrSrcImage = 0; // m_ptrYUVImage;
+ int nDstLineBytes = m_nDstLineBytes;
+ int nDstPixelBytes = m_nDstPixelBytes;
+ int ptrDstImage = m_ptrDstBlock;
+ int nWidth = m_nDstWidth;
+
+ for (uint y = 0; y < m_nDstHeight; ++y)
+ {
+ int ptrSrcLine = ptrSrcImage;
+ int ptrDstLine = ptrDstImage;
+ for (uint x = 0; x < nWidth; ++x)
+ {
+ m_output[ptrDstLine] = (byte)m_ptrYUVImage[ptrSrcLine];
+ m_output[ptrDstLine+1] = (byte)m_ptrYUVImage[ptrSrcLine+1];
+ m_output[ptrDstLine+2] = (byte)m_ptrYUVImage[ptrSrcLine+2];
+ ptrSrcLine += nSrcPixelBytes;
+ ptrDstLine += nDstPixelBytes;
+ }
+ ptrSrcImage += nSrcLineBytes;
+ ptrDstImage += nDstLineBytes;
+ }
+ }
+
+ void LossyRestoreRGBA32 ()
+ {
+ ConvertImageYUVtoRGB();
+
+ int nSrcLineBytes = m_nYUVLineBytes;
+ int ptrSrcImage = 0; //m_ptrYUVImage;
+ int nDstLineBytes = m_nDstLineBytes;
+ int ptrDstImage = m_ptrDstBlock;
+ int nLineBytes = m_nDstWidth*4;
+
+ for (uint y = 0; y < m_nDstHeight; ++y)
+ {
+ Buffer.BlockCopy (m_ptrYUVImage, ptrSrcImage, m_output, ptrDstImage, nLineBytes);
+ ptrSrcImage += nSrcLineBytes;
+ ptrDstImage += nDstLineBytes;
+ }
+ }
+
+ void LossyRestoreDeltaRGB24 ()
+ {
+ MoveImageWithVector();
+ ConvertImageYUVtoRGB (m_src_frame != null);
+
+ int nSrcLineBytes = m_nYUVLineBytes;
+ int nSrcPixelBytes = m_nYUVPixelBytes;
+ int ptrSrcImage = 0; //m_ptrYUVImage;
+ int nDstLineBytes = m_nDstLineBytes;
+ int nDstPixelBytes = m_nDstPixelBytes;
+ int ptrDstImage = m_ptrDstBlock;
+ int nWidth = m_nDstWidth;
+
+ for (uint y = 0; y < m_nDstHeight; ++y)
+ {
+ int ptrSrcLine = ptrSrcImage;
+ int ptrDstLine = ptrDstImage;
+ for (uint x = 0; x < nWidth; ++x)
+ {
+ int b = m_src_frame[ptrDstLine] + (m_ptrYUVImage[ptrSrcLine] << 1);
+ int g = m_src_frame[ptrDstLine+1] + (m_ptrYUVImage[ptrSrcLine+1] << 1);
+ int r = m_src_frame[ptrDstLine+2] + (m_ptrYUVImage[ptrSrcLine+2] << 1);
+
+ if ((uint)b > 0xFF)
+ {
+ b = (~b >> 31) & 0xFF;
+ }
+ if ((uint)g > 0xFF)
+ {
+ g = (~g >> 31) & 0xFF;
+ }
+ if ((uint)r > 0xFF)
+ {
+ r = (~r >> 31) & 0xFF;
+ }
+ m_output[ptrDstLine] = (byte)b;
+ m_output[ptrDstLine+1] = (byte)g;
+ m_output[ptrDstLine+2] = (byte)r;
+ ptrSrcLine += nSrcPixelBytes;
+ ptrDstLine += nDstPixelBytes;
+ }
+ ptrSrcImage += nSrcLineBytes;
+ ptrDstImage += nDstLineBytes;
+ }
+ }
+
+ void LossyRestoreDeltaRGBA32 ()
+ {
+ MoveImageWithVector();
+ ConvertImageYUVtoRGB (m_src_frame != null);
+
+ int nSrcLineBytes = m_nYUVLineBytes;
+ int ptrSrcImage = 0; // m_ptrYUVImage;
+ int nDstLineBytes = m_nDstLineBytes;
+ int ptrDstImage = m_ptrDstBlock;
+ int nWidth = m_nDstWidth;
+
+ for (uint y = 0; y < m_nDstHeight; ++y)
+ {
+ int ptrSrcLine = ptrSrcImage;
+ int ptrDstLine = ptrDstImage;
+ for (uint x = 0; x < nWidth; ++x)
+ {
+ int b = m_src_frame[ptrDstLine] + (m_ptrYUVImage[ptrSrcLine] << 1);
+ int g = m_src_frame[ptrDstLine+1] + (m_ptrYUVImage[ptrSrcLine+1] << 1);
+ int r = m_src_frame[ptrDstLine+2] + (m_ptrYUVImage[ptrSrcLine+2] << 1);
+ int a = m_src_frame[ptrDstLine+3] + (m_ptrYUVImage[ptrSrcLine+3] << 1);
+
+ if ((uint)b > 0xFF)
+ {
+ b = (~b >> 31) & 0xFF;
+ }
+ if ((uint)g > 0xFF)
+ {
+ g = (~g >> 31) & 0xFF;
+ }
+ if ((uint)r > 0xFF)
+ {
+ r = (~r >> 31) & 0xFF;
+ }
+ if ((uint) a > 0xFF)
+ {
+ a = (~a >> 31) & 0xFF;
+ }
+ m_output[ptrDstLine] = (byte)b;
+ m_output[ptrDstLine+1] = (byte)g;
+ m_output[ptrDstLine+2] = (byte)r;
+ m_output[ptrDstLine+3] = (byte)a;
+ ptrSrcLine += 4;
+ ptrDstLine += 4;
+ }
+ ptrSrcImage += nSrcLineBytes;
+ ptrDstImage += nDstLineBytes;
+ }
+ }
+
+ void LossyRestoreGray8 ()
+ {
+ int nSrcLineBytes = m_nYUVLineBytes;
+ int ptrSrcImage = 0; // m_ptrYUVImage
+ int nDstLineBytes = m_nDstLineBytes;
+ int ptrDstImage = m_ptrDstBlock;
+ for (uint y = 0; y < m_nDstHeight; ++y)
+ {
+ Buffer.BlockCopy (m_ptrYUVImage, ptrSrcImage, m_output, ptrDstImage, m_nDstWidth);
+ ptrSrcImage += nSrcLineBytes;
+ ptrDstImage += nDstLineBytes;
+ }
+ }
+
+ void LossyRestoreDeltaGray8 ()
+ {
+ int nSrcLineBytes = m_nYUVLineBytes;
+ int ptrSrcImage = 0; // m_ptrYUVImage
+ int nDstLineBytes = m_nDstLineBytes;
+ int ptrDstImage = m_ptrDstBlock;
+ int nWidth = m_nDstWidth;
+
+ for (uint y = 0; y < m_nDstHeight; ++y)
+ {
+ int ptrSrcLine = ptrSrcImage;
+ int ptrDstLine = ptrDstImage;
+ for (int x = 0; x < nWidth; ++x)
+ {
+ int g = m_output[ptrDstLine+x] + (m_ptrYUVImage[ptrSrcLine+x] << 1);
+ if ((uint)g > 0xFF)
+ {
+ g = (~g >> 31) & 0xFF;
+ }
+ m_output[ptrDstLine+x] = (byte)g;
+ }
+ ptrSrcImage += nSrcLineBytes;
+ ptrDstImage += nDstLineBytes;
+ }
+ }
+
+ void MoveImageWithVector ()
+ {
+ throw new NotImplementedException ("Lossy delta compression not implemented");
+ }
+
void ColorOperation0000 ()
{
}
@@ -698,8 +1211,8 @@ namespace GameRes.Formats.Entis
void ColorOperation0101 ()
{
int ptrNext = 0; // m_ptrDecodeBuf;
- uint nChSamples = m_nBlockArea;
- uint nRepCount = m_nBlockArea;
+ int nChSamples = m_nBlockArea;
+ int nRepCount = m_nBlockArea;
do
{
sbyte nBase = m_ptrDecodeBuf[ptrNext];
@@ -711,8 +1224,8 @@ namespace GameRes.Formats.Entis
void ColorOperation0110 ()
{
int ptrNext = 0; // m_ptrDecodeBuf;
- uint nChSamples = m_nBlockArea * 2;
- uint nRepCount = m_nBlockArea;
+ int nChSamples = m_nBlockArea * 2;
+ int nRepCount = m_nBlockArea;
do
{
sbyte nBase = m_ptrDecodeBuf[ptrNext];
@@ -724,8 +1237,8 @@ namespace GameRes.Formats.Entis
void ColorOperation0111 ()
{
int ptrNext = 0; // m_ptrDecodeBuf;
- uint nChSamples = m_nBlockArea;
- uint nRepCount = m_nBlockArea;
+ int nChSamples = m_nBlockArea;
+ int nRepCount = m_nBlockArea;
do
{
sbyte nBase = m_ptrDecodeBuf[ptrNext];
@@ -739,8 +1252,8 @@ namespace GameRes.Formats.Entis
void ColorOperation1001 ()
{
int ptrNext = 0; //m_ptrDecodeBuf;
- uint nChSamples = m_nBlockArea;
- uint nRepCount = m_nBlockArea;
+ int nChSamples = m_nBlockArea;
+ int nRepCount = m_nBlockArea;
do
{
sbyte nBase = m_ptrDecodeBuf[ptrNext + nChSamples];
@@ -752,8 +1265,8 @@ namespace GameRes.Formats.Entis
void ColorOperation1010 ()
{
int ptrNext = 0; // m_ptrDecodeBuf;
- uint nChSamples = m_nBlockArea;
- uint nRepCount = m_nBlockArea;
+ int nChSamples = m_nBlockArea;
+ int nRepCount = m_nBlockArea;
do
{
sbyte nBase = m_ptrDecodeBuf[ptrNext + nChSamples];
@@ -765,8 +1278,8 @@ namespace GameRes.Formats.Entis
void ColorOperation1011 ()
{
int ptrNext = 0; //m_ptrDecodeBuf;
- uint nChSamples = m_nBlockArea;
- uint nRepCount = m_nBlockArea;
+ int nChSamples = m_nBlockArea;
+ int nRepCount = m_nBlockArea;
do
{
sbyte nBase = m_ptrDecodeBuf[ptrNext + nChSamples];
@@ -780,8 +1293,8 @@ namespace GameRes.Formats.Entis
void ColorOperation1101 ()
{
int ptrNext = 0; //m_ptrDecodeBuf;
- uint nChSamples = m_nBlockArea * 2;
- uint nRepCount = m_nBlockArea;
+ int nChSamples = m_nBlockArea * 2;
+ int nRepCount = m_nBlockArea;
do
{
sbyte nBase = m_ptrDecodeBuf[ptrNext + nChSamples];
@@ -793,8 +1306,8 @@ namespace GameRes.Formats.Entis
void ColorOperation1110 ()
{
int ptrNext = 0; // m_ptrDecodeBuf;
- uint nChSamples = m_nBlockArea;
- uint nRepCount = m_nBlockArea;
+ int nChSamples = m_nBlockArea;
+ int nRepCount = m_nBlockArea;
do
{
sbyte nBase = m_ptrDecodeBuf[ptrNext + nChSamples * 2];
@@ -806,8 +1319,8 @@ namespace GameRes.Formats.Entis
void ColorOperation1111 ()
{
int ptrNext = 0; // m_ptrDecodeBuf;
- uint nChSamples = m_nBlockArea;
- uint nRepCount = m_nBlockArea;
+ int nChSamples = m_nBlockArea;
+ int nRepCount = m_nBlockArea;
do
{
sbyte nBase = m_ptrDecodeBuf[ptrNext + nChSamples * 2];
@@ -817,6 +1330,378 @@ namespace GameRes.Formats.Entis
}
while (0 != --nRepCount);
}
+
+ void ArrangeAndIQuantumize (int ptrSrcData, int ptrCoefficient)
+ {
+ int i, j, k;
+ float rMatrixScale = (float)(512.0 / m_nBlockSize);
+ var pIQParamPtr = new int[2];
+ for (i = 0; i < 2; ++i)
+ {
+ float rScale = 1.0f;
+ if (0 != (m_ptrLossyOps[ptrCoefficient+i] & 1))
+ {
+ rScale = 1.5f;
+ }
+ rScale *= (float)Math.Pow (2.0, (m_ptrLossyOps[ptrCoefficient+i] / 2));
+ rScale *= rMatrixScale;
+
+ int pIQParamTable = i * m_nBlockArea; // m_ptrIQParamTable
+ pIQParamPtr[i] = pIQParamTable; // m_ptrIQParamBuf
+ for (j = 0; j < m_nBlockArea; ++j)
+ {
+ m_ptrIQParamBuf[pIQParamPtr[i]+j] = (float)(rScale * (m_ptrIQParamTable[pIQParamTable+j] + 1));
+ }
+ }
+ if (CvType.DCT_ERI == m_info.Transformation)
+ {
+ m_ptrImageBuf[ptrSrcData+m_nBlockArea] += m_ptrImageBuf[ptrSrcData];
+ m_ptrImageBuf[ptrSrcData+m_nBlockArea*2] += m_ptrImageBuf[ptrSrcData];
+ m_ptrImageBuf[ptrSrcData+m_nBlockArea*3] += m_ptrImageBuf[ptrSrcData];
+
+ if (EriSampling.YUV_4_4_4 == m_info.SamplingFlags)
+ {
+ k = m_nBlockArea * 4;
+ j = 1;
+ }
+ else
+ {
+ k = m_nBlockArea * 6;
+ j = 3;
+ }
+ for (i = j; i < m_nChannelCount; ++i)
+ {
+ m_ptrImageBuf[ptrSrcData + k + m_nBlockArea] += m_ptrImageBuf[ptrSrcData+k];
+ m_ptrImageBuf[ptrSrcData + k + m_nBlockArea*2] += m_ptrImageBuf[ptrSrcData+k];
+ m_ptrImageBuf[ptrSrcData + k + m_nBlockArea*3] += m_ptrImageBuf[ptrSrcData+k];
+ k += m_nBlockArea * 4;
+ }
+ }
+ var pIQParam = new int[16]; // within m_ptrIQParamBuf
+ pIQParam[0] = pIQParam[1] = pIQParam[2] = pIQParam[3] = pIQParamPtr[0];
+ if (EriSampling.YUV_4_4_4 == m_info.SamplingFlags)
+ {
+ for (i = 4; i < 12; ++i)
+ {
+ pIQParam[i] = pIQParamPtr[1];
+ }
+ for (i = 12; i < m_nBlocksetCount; ++i)
+ {
+ pIQParam[i] = pIQParamPtr[0];
+ }
+ }
+ else
+ {
+ pIQParam[4] = pIQParam[5] = pIQParamPtr[1];
+ for (i = 6; i < m_nBlocksetCount; ++i)
+ {
+ pIQParam[i] = pIQParamPtr[0];
+ }
+ }
+ int pArrange = m_pArrangeTable[0];
+ for (i = 0; i < m_nBlocksetCount; ++i)
+ {
+ float[] ptrDst = m_ptrBlocksetBuf[i];
+ Erisa.ConvertArraySByteToFloat (m_ptrMatrixBuf, m_ptrImageBuf, ptrSrcData, m_nBlockArea);
+ ptrSrcData += m_nBlockArea;
+ Erisa.VectorMultiply (m_ptrMatrixBuf, m_ptrIQParamBuf, pIQParam[i], m_nBlockArea);
+ for (j = 0; j < m_nBlockArea; ++j)
+ {
+ ptrDst[m_ptrTable[pArrange + j]] = m_ptrMatrixBuf[j];
+ }
+ }
+ }
+
+ void MatrixIDCT8x8 (float[] matrix, int index)
+ {
+ for (int i = 0; i < m_nBlocksetCount; i ++ )
+ {
+ Erisa.FastIDCT8x8 (m_ptrBlocksetBuf[i]);
+ }
+ }
+
+ void MatrixILOT8x8 (float[] matrix, int ptrVertBufLOT)
+ {
+ int i, j, k, l = 0;
+ int ptrHorzBufLOT = 0; // m_ptrHorzBufLOT;
+ for (i = 0; i < 2; ++i)
+ {
+ for (j = 0; j < 2; ++j)
+ {
+ Erisa.FastILOT8x8 (m_ptrBlocksetBuf[l], m_ptrHorzBufLOT, ptrHorzBufLOT, matrix, ptrVertBufLOT + j * m_nBlockArea);
+ ++l;
+ }
+ ptrHorzBufLOT += m_nBlockArea;
+ }
+ ptrVertBufLOT += m_nBlockArea * 2;
+ if (m_nChannelCount < 3)
+ return;
+
+ if (EriSampling.YUV_4_4_4 == m_info.SamplingFlags)
+ {
+ for (k = 0; k < 2; k++)
+ {
+ for (i = 0; i < 2; i++)
+ {
+ for (j = 0; j < 2; j++)
+ {
+ Erisa.FastILOT8x8 (m_ptrBlocksetBuf[l], m_ptrHorzBufLOT, ptrHorzBufLOT, matrix, ptrVertBufLOT + j * m_nBlockArea );
+ l++;
+ }
+ ptrHorzBufLOT += m_nBlockArea;
+ }
+ ptrVertBufLOT += m_nBlockArea * 2;
+ }
+ }
+ else if (EriSampling.YUV_4_1_1 == m_info.SamplingFlags)
+ {
+ for (k = 0; k < 2; k++)
+ {
+ Erisa.FastILOT8x8 (m_ptrBlocksetBuf[l], m_ptrHorzBufLOT, ptrHorzBufLOT, matrix, ptrVertBufLOT);
+ l++;
+ ptrHorzBufLOT += m_nBlockArea;
+ ptrVertBufLOT += m_nBlockArea;
+ }
+ }
+ else
+ return;
+ if (m_nChannelCount < 4)
+ return;
+
+ for (i = 0; i < 2; i++)
+ {
+ for (j = 0; j < 2; j++)
+ {
+ Erisa.FastILOT8x8 (m_ptrBlocksetBuf[l], m_ptrHorzBufLOT, ptrHorzBufLOT, matrix, ptrVertBufLOT + j * m_nBlockArea);
+ l++;
+ }
+ ptrHorzBufLOT += m_nBlockArea;
+ }
+ ptrVertBufLOT += m_nBlockArea * 2;
+ }
+
+ void BlockScaling444 (int x, int y)
+ {
+ int nBlockOffset = m_info.Transformation == CvType.LOT_ERI ? 1 : 0;
+ for (int i = 0; i < 2; i++)
+ {
+ int yPos = y * 2 + i - nBlockOffset;
+ if (yPos < 0)
+ {
+ continue;
+ }
+ for (int j = 0; j < 2; j++)
+ {
+ int xPos = x * 2 + j - nBlockOffset;
+ if (xPos < 0)
+ continue;
+ int k = i * 2 + j;
+ if (null != m_src_frame)
+ {
+ Erisa.ConvertArrayFloatToSByte (m_ptrDecodeBuf, m_ptrBlocksetBuf[k], m_nBlockArea);
+ }
+ else
+ {
+ Erisa.ConvertArrayFloatToByte (m_ptrDecodeBuf, m_ptrBlocksetBuf[k], m_nBlockArea);
+ }
+ StoreYUVImageChannel (xPos, yPos, 0);
+
+ if (m_nChannelCount < 3)
+ {
+ continue;
+ }
+ Erisa.ConvertArrayFloatToSByte (m_ptrDecodeBuf, m_ptrBlocksetBuf[k + 4], m_nBlockArea );
+ StoreYUVImageChannel (xPos, yPos, 1);
+
+ Erisa.ConvertArrayFloatToSByte (m_ptrDecodeBuf, m_ptrBlocksetBuf[k + 8], m_nBlockArea);
+ StoreYUVImageChannel (xPos, yPos, 2);
+
+ if (m_nChannelCount < 4)
+ continue;
+ if (null != m_src_frame)
+ {
+ Erisa.ConvertArrayFloatToSByte (m_ptrDecodeBuf, m_ptrBlocksetBuf[k + 12], m_nBlockArea);
+ }
+ else
+ {
+ Erisa.ConvertArrayFloatToByte (m_ptrDecodeBuf, m_ptrBlocksetBuf[k + 12], m_nBlockArea);
+ }
+ StoreYUVImageChannel (xPos, yPos, 3);
+ }
+ }
+ }
+
+ void BlockScaling411 (int x, int y)
+ {
+ int nBlockOffset = m_info.Transformation == CvType.LOT_ERI ? 1 : 0;
+ for (int i = 0; i < 2; i++)
+ {
+ int yPos = y * 2 + i - nBlockOffset * 2;
+ if (yPos < 0)
+ continue;
+ for (int j = 0; j < 2; j++)
+ {
+ int xPos = x * 2 + j - nBlockOffset * 2;
+ if (xPos < 0)
+ continue;
+ int k = i * 2 + j;
+ if (null != m_src_frame)
+ {
+ Erisa.ConvertArrayFloatToSByte (m_ptrDecodeBuf, m_ptrBlocksetBuf[k], m_nBlockArea );
+ }
+ else
+ {
+ Erisa.ConvertArrayFloatToByte (m_ptrDecodeBuf, m_ptrBlocksetBuf[k], m_nBlockArea );
+ }
+ StoreYUVImageChannel (xPos, yPos, 0);
+
+ if (m_nChannelCount < 4)
+ continue;
+ if (null != m_src_frame)
+ {
+ Erisa.ConvertArrayFloatToSByte (m_ptrDecodeBuf, m_ptrBlocksetBuf[k + 6], m_nBlockArea);
+ }
+ else
+ {
+ Erisa.ConvertArrayFloatToByte (m_ptrDecodeBuf, m_ptrBlocksetBuf[k + 6], m_nBlockArea);
+ }
+ StoreYUVImageChannel (xPos, yPos, 3);
+ }
+ }
+ if (m_nChannelCount < 3)
+ return;
+
+ y -= nBlockOffset;
+ x -= nBlockOffset;
+ if (y < 0 || x < 0)
+ return;
+
+ Erisa.ConvertArrayFloatToSByte (m_ptrDecodeBuf, m_ptrBlocksetBuf[4], m_nBlockArea);
+ StoreYUVImageChannelX2 (x, y, 1);
+
+ Erisa.ConvertArrayFloatToSByte (m_ptrDecodeBuf, m_ptrBlocksetBuf[5], m_nBlockArea);
+ StoreYUVImageChannelX2 (x, y, 2);
+ }
+
+ void ConvertImageYUVtoRGB (bool differential = false)
+ {
+ if (m_nChannelCount < 3)
+ return;
+
+ int nPixelBytes = m_nYUVPixelBytes;
+ int nWidth = m_nDstWidth;
+ int nHeight = m_nDstHeight;
+ int ptrYUVLine = 0; // m_ptrYUVImage
+
+ for (uint y = 0; y < nHeight; ++y)
+ {
+ int ptrYUVPixel = ptrYUVLine;
+ if (differential)
+ {
+ for (uint x = 0; x < nWidth; ++x)
+ {
+ int Cy = m_ptrYUVImage[ptrYUVPixel];
+ int u = m_ptrYUVImage[ptrYUVPixel+1];
+ int v = m_ptrYUVImage[ptrYUVPixel+2];
+ int b = Cy + ((u * 7) >> 2) + 0x80;
+ int g = Cy - ((u * 3 + v * 6) >> 3) + 0x80;
+ int r = Cy + ((v * 3) >> 1) + 0x80;
+ if ((uint)b > 0xFF)
+ {
+ b = (~b >> 31) & 0xFF;
+ }
+ m_ptrYUVImage[ptrYUVPixel] = (sbyte)(b - 0x80);
+ if ((uint)g > 0xFF)
+ {
+ g = (~g >> 31) & 0xFF;
+ }
+ m_ptrYUVImage[ptrYUVPixel+1] = (sbyte)(g - 0x80);
+ if ((uint)r > 0xFF)
+ {
+ r = (~r >> 31) & 0xFF;
+ }
+ m_ptrYUVImage[ptrYUVPixel+2] = (sbyte)(r - 0x80);
+ ptrYUVPixel += nPixelBytes;
+ }
+ }
+ else
+ {
+ for (uint x = 0; x < nWidth; ++x)
+ {
+ int Cy = (byte)m_ptrYUVImage[ptrYUVPixel];
+ int u = m_ptrYUVImage[ptrYUVPixel+1];
+ int v = m_ptrYUVImage[ptrYUVPixel+2];
+ int b = Cy + ((u * 7) >> 2);
+ int g = Cy - ((u * 3 + v * 6) >> 3);
+ int r = Cy + ((v * 3) >> 1);
+ if ((uint)b > 0xFF)
+ {
+ b = (~b >> 31) & 0xFF;
+ }
+ m_ptrYUVImage[ptrYUVPixel] = (sbyte)b;
+ if ((uint)g > 0xFF)
+ {
+ g = (~g >> 31) & 0xFF;
+ }
+ m_ptrYUVImage[ptrYUVPixel+1] = (sbyte)g;
+ if ((uint)r > 0xFF)
+ {
+ r = (~r >> 31) & 0xFF;
+ }
+ m_ptrYUVImage[ptrYUVPixel+2] = (sbyte)r;
+ ptrYUVPixel += nPixelBytes;
+ }
+ }
+ ptrYUVLine += m_nYUVLineBytes;
+ }
+ }
+
+ void StoreYUVImageChannel (int xBlock, int yBlock, int iChannel)
+ {
+ int nPixelBytes = m_nYUVPixelBytes;
+ int nBlockSize = m_nBlockSize;
+ int nBlockArea = m_nBlockArea;
+ int ptrDstYUV = (yBlock * nBlockSize * m_nYUVLineBytes)
+ + (xBlock * nBlockSize * nPixelBytes) + iChannel;
+ int ptrSrcYUV = 0; // m_ptrDecodeBuf;
+
+ for (int y = 0; y < nBlockSize; y++)
+ {
+ int ptrDstLine = ptrDstYUV;
+ for (int x = 0; x < nBlockSize; x++)
+ {
+ m_ptrYUVImage[ptrDstLine] = m_ptrDecodeBuf[ptrSrcYUV++];
+ ptrDstLine += nPixelBytes;
+ }
+ ptrDstYUV += m_nYUVLineBytes;
+ }
+ }
+
+ void StoreYUVImageChannelX2 (int xBlock, int yBlock, int iChannel)
+ {
+ int nPixelBytes = m_nYUVPixelBytes;
+ int nLineBytes = m_nYUVLineBytes;
+ int nBlockSize = m_nBlockSize;
+ int nBlockArea = m_nBlockArea;
+ int ptrDstYUV = (yBlock * nBlockSize * 2 * nLineBytes)
+ + (xBlock * nBlockSize * 2 * nPixelBytes) + iChannel;
+ int ptrSrcYUV = 0; // m_ptrDecodeBuf;
+
+ for (int y = 0; y < nBlockSize; y++)
+ {
+ int ptrDstLine = ptrDstYUV;
+ for (int x = 0; x < nBlockSize; x++)
+ {
+ sbyte d = m_ptrDecodeBuf[ptrSrcYUV++];
+ m_ptrYUVImage[ptrDstLine + nLineBytes + nPixelBytes] = d;
+ m_ptrYUVImage[ptrDstLine + nLineBytes] = d;
+ m_ptrYUVImage[ptrDstLine + nPixelBytes] = d;
+ m_ptrYUVImage[ptrDstLine] = d;
+ ptrDstLine += nPixelBytes * 2;
+ }
+ ptrDstYUV += nLineBytes * 2;
+ }
+ }
}
internal static class Erina
@@ -826,7 +1711,7 @@ namespace GameRes.Formats.Entis
public const int HuffmanNull = 0x8000;
public const int HuffmanMax = 0x4000;
public const int HuffmanRoot = 0x200;
- };
+ }
internal class HuffmanNode
{
@@ -862,10 +1747,10 @@ namespace GameRes.Formats.Entis
}
for (int i = 0; i < 0x100; i++)
{
- m_iSymLookup[i] = (int)Erina.HuffmanNull;
+ m_iSymLookup[i] = Erina.HuffmanNull;
}
- m_iEscape = (int)Erina.HuffmanNull;
- m_iTreePointer = (int)Erina.HuffmanRoot;
+ m_iEscape = Erina.HuffmanNull;
+ m_iTreePointer = Erina.HuffmanRoot;
m_hnTree[Erina.HuffmanRoot].Weight = 0;
m_hnTree[Erina.HuffmanRoot].Parent = Erina.HuffmanNull;
m_hnTree[Erina.HuffmanRoot].ChildCode = Erina.HuffmanNull;
@@ -957,7 +1842,7 @@ namespace GameRes.Formats.Entis
var phnNew = m_hnTree[i];
phnNew.Weight = 1;
phnNew.ChildCode = Erina.CodeFlag | nNewCode;
- m_iSymLookup[nNewCode & 0xFF] = i ;
+ m_iSymLookup[nNewCode & 0xFF] = i;
var phnRoot = m_hnTree[Erina.HuffmanRoot];
if (phnRoot.ChildCode != Erina.HuffmanNull)
@@ -1410,7 +2295,7 @@ namespace GameRes.Formats.Entis
nCode = iChild & ~Erina.CodeFlag;
if (nCode != Erina.HuffmanEscape)
{
- return nCode ;
+ return nCode;
}
}
nCode = GetGammaCode();
@@ -1631,7 +2516,7 @@ namespace GameRes.Formats.Entis
SymTable[i].Occured = 1;
SymTable[i].Symbol = i;
}
- SymTable[0x100].Occured = 1 ;
+ SymTable[0x100].Occured = 1;
SymTable[0x100].Symbol = EscCode;
for (short i = 0; i < SubSortMax; ++i)
@@ -1664,7 +2549,7 @@ namespace GameRes.Formats.Entis
}
for (int i = 0; i < SubSortMax; ++i)
{
- SubModel[i].Occured >>= 1 ;
+ SubModel[i].Occured >>= 1;
}
}
diff --git a/ArcFormats/Entis/ErisaMatrix.cs b/ArcFormats/Entis/ErisaMatrix.cs
new file mode 100644
index 00000000..35aa570e
--- /dev/null
+++ b/ArcFormats/Entis/ErisaMatrix.cs
@@ -0,0 +1,488 @@
+//! \file ErisaMatrix.cs
+//! \date Fri Feb 26 01:12:26 2016
+//! \brief Erisa Library math methods.
+//
+// *****************************************************************************
+// E R I S A - L i b r a r y
+// ----------------------------------------------------------------------------
+// Copyright (C) 2000-2004 Leshade Entis. All rights reserved.
+// *****************************************************************************/
+//
+// C# port by morkt
+//
+
+using System;
+using System.Diagnostics;
+using GameRes.Utility;
+
+namespace GameRes.Formats.Entis
+{
+ internal static class Erisa
+ {
+ public const int MIN_DCT_DEGREE = 2;
+ public const int MAX_DCT_DEGREE = 12;
+
+ static readonly float ERI_rCosPI4 = (float)Math.Cos (Math.PI / 4);
+ static readonly float ERI_r2CosPI4 = 2 * ERI_rCosPI4;
+ static readonly float[] ERI_DCTofK2 = new float[2];
+
+ static readonly float[][] ERI_pMatrixDCTofK = new float[MAX_DCT_DEGREE][]
+ {
+ null,
+ ERI_DCTofK2, // = cos( (2*i+1) / 8 )
+ new float[4], // = cos( (2*i+1) / 16 )
+ new float[8], // = cos( (2*i+1) / 32 )
+ new float[16], // = cos( (2*i+1) / 64 )
+ new float[32], // = cos( (2*i+1) / 128 )
+ new float[64], // = cos( (2*i+1) / 256 )
+ new float[128], // = cos( (2*i+1) / 512 )
+ new float[256], // = cos( (2*i+1) / 1024 )
+ new float[512], // = cos( (2*i+1) / 2048 )
+ new float[1024], // = cos( (2*i+1) / 4096 )
+ new float[2048], // = cos( (2*i+1) / 8192 )
+ };
+
+ static Erisa ()
+ {
+ InitializeMatrix();
+ }
+
+ public static void InitializeMatrix ()
+ {
+ for (int i = 1; i < MAX_DCT_DEGREE; i++)
+ {
+ int n = (1 << i);
+ float[] pDCTofK = ERI_pMatrixDCTofK[i];
+ double nr = Math.PI / (4.0 * n);
+ double dr = nr + nr;
+ double ir = nr;
+ for (int j = 0; j < n; j++)
+ {
+ pDCTofK[j] = (float)Math.Cos (ir);
+ ir += dr;
+ }
+ }
+ }
+
+ public static void RoundR32ToWordArray (byte[] ptrDst, int dst, int nStep, float[] ptrSrc, int nCount)
+ {
+ nStep *= 2;
+ for (int i = 0; i < nCount; i++)
+ {
+ int nValue = RoundR32ToInt (ptrSrc[i]);
+ if (nValue <= -0x8000)
+ {
+ LittleEndian.Pack ((short)-0x8000, ptrDst, dst);
+ }
+ else if (nValue >= 0x7FFF)
+ {
+ LittleEndian.Pack ((short)0x7FFF, ptrDst, dst);
+ }
+ else
+ {
+ LittleEndian.Pack ((short)nValue, ptrDst, dst);
+ }
+ dst += nStep;
+ }
+ }
+
+ public static int RoundR32ToInt (float r)
+ {
+ if (r >= 0.0)
+ return (int)Math.Floor (r + 0.5);
+ else
+ return (int)Math.Ceiling (r - 0.5);
+ }
+
+ public static EriSinCos[] CreateRevolveParameter (int nDegreeDCT)
+ {
+ int nDegreeNum = 1 << nDegreeDCT;
+ int lc = 1;
+ for (int n = nDegreeNum / 2; n >= 8; n /= 8)
+ {
+ ++lc;
+ }
+ EriSinCos[] ptrRevolve = new EriSinCos[lc*8];
+
+ double k = Math.PI / (nDegreeNum * 2);
+ int ptrNextRev = 0;
+ int nStep = 2;
+ do
+ {
+ for (int i = 0; i < 7; i++)
+ {
+ double ws = 1.0;
+ double a = 0.0;
+ for (int j = 0; j < i; j++)
+ {
+ a += nStep;
+ ws = ws * ptrRevolve[ptrNextRev+j].rSin + ptrRevolve[ptrNextRev+j].rCos * Math.Cos (a * k);
+ }
+ double r = Math.Atan2 (ws, Math.Cos ((a + nStep) * k));
+ ptrRevolve[ptrNextRev+i].rSin = (float)Math.Sin (r);
+ ptrRevolve[ptrNextRev+i].rCos = (float)Math.Cos (r);
+ }
+ ptrNextRev += 7;
+ nStep *= 8;
+ }
+ while (nStep < nDegreeNum);
+ return ptrRevolve;
+ }
+
+ public static void OddGivensInverseMatrix (float[] ptrSrc, int src, EriSinCos[] ptrRevolve, int nDegreeDCT)
+ {
+ int nDegreeNum = 1 << nDegreeDCT;
+ int index = 1;
+ int nStep = 2;
+ int lc = (nDegreeNum / 2) / 8;
+ int resolve_idx = 0;
+ for (;;)
+ {
+ resolve_idx += 7;
+ index += nStep * 7;
+ nStep *= 8;
+ if (lc <= 8)
+ break;
+ lc /= 8;
+ }
+ int k = index + nStep * (lc - 2);
+ int j;
+ float r1, r2;
+ for (j = lc - 2; j >= 0; j--)
+ {
+ r1 = ptrSrc[src + k];
+ r2 = ptrSrc[src + k + nStep];
+ ptrSrc[src + k] = r1 * ptrRevolve[resolve_idx+j].rCos + r2 * ptrRevolve[resolve_idx+j].rSin;
+ ptrSrc[src + k + nStep] = r2 * ptrRevolve[resolve_idx+j].rCos - r1 * ptrRevolve[resolve_idx+j].rSin;
+ k -= nStep;
+ }
+ for (; lc <= (nDegreeNum / 2) / 8; lc *= 8)
+ {
+ resolve_idx -= 7;
+ nStep /= 8;
+ index -= nStep * 7;
+ for (int i = 0; i < lc; i++)
+ {
+ k = i * (nStep * 8) + index + nStep * 6;
+ for ( j = 6; j >= 0; j -- )
+ {
+ r1 = ptrSrc[src + k];
+ r2 = ptrSrc[src + k + nStep];
+ ptrSrc[src + k] =
+ r1 * ptrRevolve[resolve_idx+j].rCos + r2 * ptrRevolve[resolve_idx+j].rSin;
+ ptrSrc[src + k + nStep] =
+ r2 * ptrRevolve[resolve_idx+j].rCos - r1 * ptrRevolve[resolve_idx+j].rSin;
+ k -= nStep;
+ }
+ }
+ }
+ }
+
+ public static void FastIPLOT (float[] ptrSrc, int src, int nDegreeDCT)
+ {
+ int nDegreeNum = 1 << nDegreeDCT;
+ for (int i = 0; i < nDegreeNum; i += 2)
+ {
+ float r1 = ptrSrc[src + i];
+ float r2 = ptrSrc[src + i + 1];
+ ptrSrc[src + i] = 0.5f * (r1 + r2);
+ ptrSrc[src + i + 1] = 0.5f * (r1 - r2);
+ }
+ }
+
+ public static void FastILOT (float[] ptrDst, float[] ptrSrc1, int src1, float[] ptrSrc2, int src2, int nDegreeDCT)
+ {
+ int nDegreeNum = 1 << nDegreeDCT;
+ for (int i = 0; i < nDegreeNum; i += 2)
+ {
+ float r1 = ptrSrc1[src1 + i];
+ float r2 = ptrSrc2[src2 + i + 1];
+ ptrDst[i] = r1 + r2;
+ ptrDst[i + 1] = r1 - r2;
+ }
+ }
+
+ public static void FastDCT (float[] ptrDst, int dst, int nDstInterval, float[] ptrSrc, int src, float[] ptrWorkBuf, int work, int nDegreeDCT)
+ {
+ Debug.Assert ((nDegreeDCT >= MIN_DCT_DEGREE) && (nDegreeDCT <= MAX_DCT_DEGREE));
+
+ if (nDegreeDCT == MIN_DCT_DEGREE)
+ {
+ float[] r32Buf = new float[4];
+ r32Buf[0] = ptrSrc[src] + ptrSrc[src+3];
+ r32Buf[2] = ptrSrc[src] - ptrSrc[src+3];
+ r32Buf[1] = ptrSrc[src+1] + ptrSrc[src+2];
+ r32Buf[3] = ptrSrc[src+1] - ptrSrc[src+2];
+
+ ptrDst[dst] = 0.5f * (r32Buf[0] + r32Buf[1]);
+ ptrDst[dst+nDstInterval * 2] = ERI_rCosPI4 * (r32Buf[0] - r32Buf[1]);
+
+ r32Buf[2] = ERI_DCTofK2[0] * r32Buf[2];
+ r32Buf[3] = ERI_DCTofK2[1] * r32Buf[3];
+
+ r32Buf[0] = r32Buf[2] + r32Buf[3];
+ r32Buf[1] = ERI_r2CosPI4 * (r32Buf[2] - r32Buf[3]);
+
+ r32Buf[1] -= r32Buf[0];
+
+ ptrDst[dst+nDstInterval] = r32Buf[0];
+ ptrDst[dst+nDstInterval * 3] = r32Buf[1];
+ }
+ else
+ {
+ uint i;
+ uint nDegreeNum = 1u << nDegreeDCT;
+ uint nHalfDegree = nDegreeNum >> 1;
+ for (i = 0; i < nHalfDegree; i++)
+ {
+ ptrWorkBuf[work+i] = ptrSrc[src+i] + ptrSrc[src + nDegreeNum - i - 1];
+ ptrWorkBuf[work+i + nHalfDegree] = ptrSrc[src+i] - ptrSrc[src + nDegreeNum - i - 1];
+ }
+ int nDstStep = nDstInterval << 1;
+ FastDCT (ptrDst, dst, nDstStep, ptrWorkBuf, work, ptrSrc, src, nDegreeDCT - 1);
+
+ float[] pDCTofK = ERI_pMatrixDCTofK[nDegreeDCT - 1];
+ src = (int)(work+nHalfDegree); // ptrSrc = ptrWorkBuf + nHalfDegree;
+ dst += nDstInterval; // ptrDst += nDstInterval;
+
+ for (i = 0; i < nHalfDegree; i++)
+ {
+ ptrWorkBuf[src + i] *= pDCTofK[i];
+ }
+
+ FastDCT (ptrDst, dst, nDstStep, ptrWorkBuf, src, ptrWorkBuf, work, nDegreeDCT - 1);
+
+ int ptrNext = dst; // within ptrDst;
+ for (i = 0; i < nHalfDegree; i++)
+ {
+ ptrDst[ptrNext] += ptrDst[ptrNext]; // *ptrNext += *ptrNext;
+ ptrNext += nDstStep;
+ }
+ ptrNext = dst;
+ for (i = 1; i < nHalfDegree; i ++)
+ {
+ ptrDst[ptrNext + nDstStep] -= ptrDst[ptrNext];
+ ptrNext += nDstStep;
+ }
+ }
+ }
+
+ public static void FastIDCT (float[] ptrDst, float[] srcBuf, int ptrSrc, int nSrcInterval, float[] ptrWorkBuf, int nDegreeDCT)
+ {
+ FastIDCT (ptrDst, 0, srcBuf, ptrSrc, nSrcInterval, ptrWorkBuf, nDegreeDCT);
+ }
+
+ public static void FastIDCT (float[] dstBuf, int ptrDst, float[] srcBuf, int ptrSrc, int nSrcInterval, float[] ptrWorkBuf, int nDegreeDCT)
+ {
+ Debug.Assert ((nDegreeDCT >= MIN_DCT_DEGREE) && (nDegreeDCT <= MAX_DCT_DEGREE));
+
+ if (nDegreeDCT == MIN_DCT_DEGREE)
+ {
+ float[] r32Buf1 = new float[2];
+ float[] r32Buf2 = new float[4];
+
+ r32Buf1[0] = srcBuf[ptrSrc];
+ r32Buf1[1] = ERI_rCosPI4 * srcBuf[ptrSrc + nSrcInterval * 2];
+
+ r32Buf2[0] = r32Buf1[0] + r32Buf1[1];
+ r32Buf2[1] = r32Buf1[0] - r32Buf1[1];
+
+ r32Buf1[0] = ERI_DCTofK2[0] * srcBuf[ptrSrc + nSrcInterval];
+ r32Buf1[1] = ERI_DCTofK2[1] * srcBuf[ptrSrc + nSrcInterval * 3];
+
+ r32Buf2[2] = r32Buf1[0] + r32Buf1[1];
+ r32Buf2[3] = ERI_r2CosPI4 * (r32Buf1[0] - r32Buf1[1]);
+
+ r32Buf2[3] -= r32Buf2[2];
+
+ dstBuf[ptrDst] = r32Buf2[0] + r32Buf2[2];
+ dstBuf[ptrDst+3] = r32Buf2[0] - r32Buf2[2];
+ dstBuf[ptrDst+1] = r32Buf2[1] + r32Buf2[3];
+ dstBuf[ptrDst+2] = r32Buf2[1] - r32Buf2[3];
+ }
+ else
+ {
+ uint nDegreeNum = 1u << nDegreeDCT;
+ uint nHalfDegree = nDegreeNum >> 1;
+ int nSrcStep = nSrcInterval << 1;
+ FastIDCT (dstBuf, ptrDst, srcBuf, ptrSrc, nSrcStep, ptrWorkBuf, nDegreeDCT - 1);
+
+ float[] pDCTofK = ERI_pMatrixDCTofK[nDegreeDCT - 1];
+ int pOddDst = ptrDst + (int)nHalfDegree; // within dstBuf
+ int ptrNext = ptrSrc + nSrcInterval; // within srcBuf
+
+ uint i;
+ for (i = 0; i < nHalfDegree; i++)
+ {
+ ptrWorkBuf[i] = srcBuf[ptrNext] * pDCTofK[i];
+ ptrNext += nSrcStep;
+ }
+
+ FastDCT (dstBuf, pOddDst, 1, ptrWorkBuf, 0, ptrWorkBuf, (int)nHalfDegree, nDegreeDCT - 1);
+
+ for (i = 0; i < nHalfDegree; i ++)
+ {
+ dstBuf[pOddDst + i] += dstBuf[pOddDst + i];
+ }
+
+ for (i = 1; i < nHalfDegree; i++)
+ {
+ dstBuf[pOddDst + i] -= dstBuf[pOddDst + i - 1];
+ }
+ float[] r32Buf = new float[4];
+ uint nQuadDegree = nHalfDegree >> 1;
+ for (i = 0; i < nQuadDegree; i++)
+ {
+ r32Buf[0] = dstBuf[ptrDst+i] + dstBuf[nHalfDegree + i];
+ r32Buf[3] = dstBuf[ptrDst+i] - dstBuf[nHalfDegree + i];
+ r32Buf[1] = dstBuf[nHalfDegree - 1 - i] + dstBuf[ptrDst + nDegreeNum - 1 - i];
+ r32Buf[2] = dstBuf[nHalfDegree - 1 - i] - dstBuf[ptrDst + nDegreeNum - 1 - i];
+
+ dstBuf[ptrDst+i] = r32Buf[0];
+ dstBuf[nHalfDegree - 1 - i] = r32Buf[1];
+ dstBuf[nHalfDegree + i] = r32Buf[2];
+ dstBuf[ptrDst+nDegreeNum - 1 - i] = r32Buf[3];
+ }
+ }
+ }
+
+ public static void Revolve2x2 (float[] buf1, int ptrBuf1, float[] buf2, int ptrBuf2, float rSin, float rCos, int nStep, int nCount)
+ {
+ for (int i = 0; i < nCount; i++)
+ {
+ float r1 = buf1[ptrBuf1];
+ float r2 = buf2[ptrBuf2];
+
+ buf1[ptrBuf1] = r1 * rCos - r2 * rSin;
+ buf2[ptrBuf2] = r1 * rSin + r2 * rCos;
+
+ ptrBuf1 += nStep;
+ ptrBuf2 += nStep;
+ }
+ }
+
+ public static void ConvertArraySByteToFloat (float[] ptrDst, sbyte[] ptrSrc, int src, int nCount)
+ {
+ for (int i = 0; i < nCount; ++i)
+ {
+ ptrDst[i] = ptrSrc[src+i];
+ }
+ }
+
+ public static void VectorMultiply (float[] ptrDst, float[] ptrSrc, int src, int nCount)
+ {
+ for (int i = 0; i < nCount; ++i)
+ {
+ ptrDst[i] *= ptrSrc[src+i];
+ }
+ }
+
+ public static void FastIDCT8x8 (float[] ptrDst)
+ {
+ var rWork = new float[8];
+ var rTemp = new float[64];
+ for (int i = 0; i < 8; ++i)
+ FastIDCT (rTemp, i * 8, ptrDst, i, 8, rWork, 3);
+
+ for (int i = 0; i < 8; ++i)
+ FastIDCT (ptrDst, i * 8, rTemp, i, 8, rWork, 3);
+ }
+
+ static readonly EriSinCos[] escRev = new EriSinCos[3]
+ {
+ new EriSinCos { rSin = 0.734510f, rCos = 0.678598f },
+ new EriSinCos { rSin = 0.887443f, rCos = 0.460917f },
+ new EriSinCos { rSin = 0.970269f, rCos = 0.242030f }
+ };
+
+ public static void FastILOT8x8 (float[] ptrDst, float[] horz, int ptrHorzCur, float[] vert, int ptrVertCur)
+ {
+ var rWork = new float[8];
+ var rTemp = new float[64];
+ float s1, s2, r1, r2, r3;
+ int i, j, k;
+
+ for (i = 0; i < 8; i++)
+ {
+ for (j = 2, k = i + 40; j >= 0; j--, k -= 16)
+ {
+ r1 = ptrDst[k];
+ r2 = ptrDst[k + 16];
+ ptrDst[k] = r1 * escRev[j].rCos + r2 * escRev[j].rSin;
+ ptrDst[k + 16] = r2 * escRev[j].rCos - r1 * escRev[j].rSin;
+ }
+ }
+ for (i = 0; i < 64; i += 16)
+ {
+ for (j = 0; j < 8; j++)
+ {
+ k = i + j;
+ s1 = ptrDst[k];
+ s2 = ptrDst[k + 8];
+ r1 = 0.5f * (s1 + s2);
+ r2 = 0.5f * (s1 - s2);
+
+ r3 = vert[ptrVertCur+k];
+ vert[ptrVertCur+k] = r1;
+ vert[ptrVertCur+k + 8] = r2;
+ ptrDst[k] = r3 + r2;
+ ptrDst[k + 8] = r3 - r2;
+ }
+ }
+ for (i = 0; i < 64; i += 8)
+ {
+ for (j = 2, k = i + 5; j >= 0; j--, k -= 2)
+ {
+ r1 = ptrDst[k];
+ r2 = ptrDst[k + 2];
+ ptrDst[k] = r1 * escRev[j].rCos + r2 * escRev[j].rSin;
+ ptrDst[k + 2] = r2 * escRev[j].rCos - r1 * escRev[j].rSin;
+ }
+ for ( j = 0; j < 8; j += 2 )
+ {
+ k = i + j;
+ s1 = ptrDst[k];
+ s2 = ptrDst[k + 1];
+ r1 = 0.5f * (s1 + s2);
+ r2 = 0.5f * (s1 - s2);
+ r3 = horz[ptrHorzCur+k];
+ horz[ptrHorzCur+k] = r1;
+ horz[ptrHorzCur+k + 1] = r2;
+ ptrDst[k] = r3 + r2;
+ ptrDst[k + 1] = r3 - r2;
+ }
+ }
+ for (i = 0; i < 8; i++)
+ FastIDCT (rTemp, i * 8, ptrDst, i, 8, rWork, 3);
+
+ for (i = 0; i < 8; i++)
+ FastIDCT (ptrDst, i * 8, rTemp, i, 8, rWork, 3);
+ }
+
+ public static void ConvertArrayFloatToByte (sbyte[] ptrDst, float[] ptrSrc, int nCount)
+ {
+ for (int i = 0; i < nCount; i++)
+ {
+ int n = RoundR32ToInt (ptrSrc[i]);
+ if ((uint)n > 0xFF)
+ {
+ n = (~n >> 31) & 0xFF;
+ }
+ ptrDst[i] = (sbyte)n;
+ }
+ }
+
+ public static void ConvertArrayFloatToSByte (sbyte[] ptrDst, float[] ptrSrc, int nCount)
+ {
+ for (int i = 0; i < nCount; i++)
+ {
+ int n = RoundR32ToInt (ptrSrc[i]);
+ if (n < -0x80)
+ n = -0x80;
+ else if (n > 0x7F)
+ n = 0x7F;
+ ptrDst[i] = (sbyte)n;
+ }
+ }
+ }
+}
diff --git a/ArcFormats/Entis/ImageERI.cs b/ArcFormats/Entis/ImageERI.cs
index 99fdba8c..6c5570ea 100644
--- a/ArcFormats/Entis/ImageERI.cs
+++ b/ArcFormats/Entis/ImageERI.cs
@@ -40,10 +40,10 @@ namespace GameRes.Formats.Entis
public int Version;
public CvType Transformation;
public EriCode Architecture;
- public int FormatType;
+ public EriType FormatType;
public bool VerticalFlip;
public int ClippedPixel;
- public int SamplingFlags;
+ public EriSampling SamplingFlags;
public ulong QuantumizedBits;
public ulong AllottedBits;
public int BlockingDegree;
@@ -79,7 +79,8 @@ namespace GameRes.Formats.Entis
Nemesis = -16,
}
- public enum EriImage
+ [Flags]
+ public enum EriType
{
RGB = 0x00000001,
Gray = 0x00000002,
@@ -88,13 +89,20 @@ namespace GameRes.Formats.Entis
HSB = 0x00000006,
RGBA = 0x04000001,
BGRA = 0x04000003,
- TypeMask = 0x0000FFFF,
+ Mask = 0x0000FFFF,
WithPalette = 0x01000000,
UseClipping = 0x02000000,
WithAlpha = 0x04000000,
SideBySide = 0x10000000,
}
+ public enum EriSampling
+ {
+ YUV_4_4_4 = 0x00040404,
+ YUV_4_2_2 = 0x00040202,
+ YUV_4_1_1 = 0x00040101,
+ }
+
internal class EriFile : BinaryReader
{
internal struct Section
@@ -185,7 +193,7 @@ namespace GameRes.Formats.Entis
info = new EriMetaData { StreamPos = stream_pos, Version = version };
info.Transformation = (CvType)reader.ReadInt32();
info.Architecture = (EriCode)reader.ReadInt32();
- info.FormatType = reader.ReadInt32();
+ info.FormatType = (EriType)reader.ReadInt32();
int w = reader.ReadInt32();
int h = reader.ReadInt32();
info.Width = (uint)Math.Abs (w);
@@ -193,7 +201,7 @@ namespace GameRes.Formats.Entis
info.VerticalFlip = h < 0;
info.BPP = reader.ReadInt32();
info.ClippedPixel = reader.ReadInt32();
- info.SamplingFlags = reader.ReadInt32();
+ info.SamplingFlags = (EriSampling)reader.ReadInt32();
info.QuantumizedBits = reader.ReadUInt64();
info.AllottedBits = reader.ReadUInt64();
info.BlockingDegree = reader.ReadInt32();
diff --git a/ArcFormats/Entis/MioDecoder.cs b/ArcFormats/Entis/MioDecoder.cs
index 7526f93b..6ef32282 100644
--- a/ArcFormats/Entis/MioDecoder.cs
+++ b/ArcFormats/Entis/MioDecoder.cs
@@ -71,14 +71,6 @@ namespace GameRes.Formats.Entis
EriSinCos[] m_pRevolveParam;
readonly int[] m_nFrequencyPoint = new int[7];
- const int MIN_DCT_DEGREE = 2;
- const int MAX_DCT_DEGREE = 12;
-
- static MioDecoder ()
- {
- eriInitializeMatrix();
- }
-
public MioDecoder (MioInfoHeader info)
{
m_nBufLength = 0;
@@ -119,7 +111,7 @@ namespace GameRes.Formats.Entis
{
return false;
}
- if ((m_mioih.SubbandDegree < 8) || (m_mioih.SubbandDegree > MAX_DCT_DEGREE))
+ if ((m_mioih.SubbandDegree < 8) || (m_mioih.SubbandDegree > Erisa.MAX_DCT_DEGREE))
{
return false;
}
@@ -284,7 +276,7 @@ namespace GameRes.Formats.Entis
void InitializeWithDegree (int nSubbandDegree)
{
- m_pRevolveParam = eriCreateRevolveParameter (nSubbandDegree);
+ m_pRevolveParam = Erisa.CreateRevolveParameter (nSubbandDegree);
for (int i = 0, j = 0; i < 7; i ++)
{
int nFrequencyWidth = 1 << (nSubbandDegree + FreqWidth[i]);
@@ -525,17 +517,17 @@ namespace GameRes.Formats.Entis
IQuantumize (m_ptrMatrixBuf, 0, m_ptrBuffer2, m_ptrNextSource, m_nDegreeNum, nWeightCode, nCoefficient);
m_ptrNextSource += (int)m_nDegreeNum;
- eriOddGivensInverseMatrix (m_ptrMatrixBuf, 0, m_pRevolveParam, m_nSubbandDegree);
- eriFastIPLOT (m_ptrMatrixBuf, 0, m_nSubbandDegree);
- eriFastILOT (m_ptrWorkBuf, m_ptrLastDCT, m_ptrLastDCTBuf, m_ptrMatrixBuf, 0, m_nSubbandDegree);
+ Erisa.OddGivensInverseMatrix (m_ptrMatrixBuf, 0, m_pRevolveParam, m_nSubbandDegree);
+ Erisa.FastIPLOT (m_ptrMatrixBuf, 0, m_nSubbandDegree);
+ Erisa.FastILOT (m_ptrWorkBuf, m_ptrLastDCT, m_ptrLastDCTBuf, m_ptrMatrixBuf, 0, m_nSubbandDegree);
Array.Copy (m_ptrMatrixBuf, 0, m_ptrLastDCT, m_ptrLastDCTBuf, m_nDegreeNum);
Array.Copy (m_ptrWorkBuf, 0, m_ptrMatrixBuf, 0, m_nDegreeNum);
- eriFastIDCT (m_ptrInternalBuf, m_ptrMatrixBuf, 0, 1, m_ptrWorkBuf, m_nSubbandDegree);
+ Erisa.FastIDCT (m_ptrInternalBuf, m_ptrMatrixBuf, 0, 1, m_ptrWorkBuf, m_nSubbandDegree);
if (nSamples != 0)
{
- eriRoundR32ToWordArray (ptrDst, iDst, m_mioih.ChannelCount, m_ptrInternalBuf, (int)nSamples);
+ Erisa.RoundR32ToWordArray (ptrDst, iDst, m_mioih.ChannelCount, m_ptrInternalBuf, (int)nSamples);
}
}
@@ -551,12 +543,12 @@ namespace GameRes.Formats.Entis
m_ptrBuffer1[i * 2 + 1] = m_ptrBuffer2[m_ptrNextSource++];
}
IQuantumize (m_ptrLastDCT, m_ptrLastDCTBuf, m_ptrBuffer1, 0, m_nDegreeNum, nWeightCode, nCoefficient);
- eriOddGivensInverseMatrix (m_ptrLastDCT, m_ptrLastDCTBuf, m_pRevolveParam, m_nSubbandDegree);
+ Erisa.OddGivensInverseMatrix (m_ptrLastDCT, m_ptrLastDCTBuf, m_pRevolveParam, m_nSubbandDegree);
for (i = 0; i < m_nDegreeNum; i += 2)
{
m_ptrLastDCT[m_ptrLastDCTBuf + i] = m_ptrLastDCT[m_ptrLastDCTBuf + i + 1];
}
- eriFastIPLOT (m_ptrLastDCT, m_ptrLastDCTBuf, m_nSubbandDegree);
+ Erisa.FastIPLOT (m_ptrLastDCT, m_ptrLastDCTBuf, m_nSubbandDegree);
}
void DecodePostBlock (byte[] ptrDst, int iDst, uint nSamples)
@@ -571,22 +563,22 @@ namespace GameRes.Formats.Entis
m_ptrBuffer1[i * 2 + 1] = m_ptrBuffer2[m_ptrNextSource++];
}
IQuantumize (m_ptrMatrixBuf, 0, m_ptrBuffer1, 0, m_nDegreeNum, nWeightCode, nCoefficient);
- eriOddGivensInverseMatrix (m_ptrMatrixBuf, 0, m_pRevolveParam, m_nSubbandDegree);
+ Erisa.OddGivensInverseMatrix (m_ptrMatrixBuf, 0, m_pRevolveParam, m_nSubbandDegree);
for (i = 0; i < m_nDegreeNum; i += 2)
{
m_ptrMatrixBuf[i] = - m_ptrMatrixBuf[i + 1];
}
- eriFastIPLOT (m_ptrMatrixBuf, 0, m_nSubbandDegree);
- eriFastILOT (m_ptrWorkBuf, m_ptrLastDCT, m_ptrLastDCTBuf, m_ptrMatrixBuf, 0, m_nSubbandDegree);
+ Erisa.FastIPLOT (m_ptrMatrixBuf, 0, m_nSubbandDegree);
+ Erisa.FastILOT (m_ptrWorkBuf, m_ptrLastDCT, m_ptrLastDCTBuf, m_ptrMatrixBuf, 0, m_nSubbandDegree);
Array.Copy (m_ptrWorkBuf, 0, m_ptrMatrixBuf, 0, m_nDegreeNum);
- eriFastIDCT (m_ptrInternalBuf, m_ptrMatrixBuf, 0, 1, m_ptrWorkBuf, m_nSubbandDegree);
+ Erisa.FastIDCT (m_ptrInternalBuf, m_ptrMatrixBuf, 0, 1, m_ptrWorkBuf, m_nSubbandDegree);
if (nSamples != 0)
{
- eriRoundR32ToWordArray (ptrDst, iDst, m_mioih.ChannelCount, m_ptrInternalBuf, (int)nSamples);
+ Erisa.RoundR32ToWordArray (ptrDst, iDst, m_mioih.ChannelCount, m_ptrInternalBuf, (int)nSamples);
}
}
@@ -807,18 +799,18 @@ namespace GameRes.Formats.Entis
float rSin = (float)Math.Sin (nRevCode * Math.PI / 8);
float rCos = (float)Math.Cos (nRevCode * Math.PI / 8);
- eriRevolve2x2 (m_ptrLastDCT, ptrLapBuf1, m_ptrLastDCT, ptrLapBuf2, rSin, rCos, 1, m_nDegreeNum);
+ Erisa.Revolve2x2 (m_ptrLastDCT, ptrLapBuf1, m_ptrLastDCT, ptrLapBuf2, rSin, rCos, 1, m_nDegreeNum);
ptrLapBuf = 0; //m_ptrLastDCT;
for (i = 0; i < 2; i++)
{
- eriOddGivensInverseMatrix (m_ptrLastDCT, ptrLapBuf, m_pRevolveParam, m_nSubbandDegree);
+ Erisa.OddGivensInverseMatrix (m_ptrLastDCT, ptrLapBuf, m_pRevolveParam, m_nSubbandDegree);
for (j = 0; j < m_nDegreeNum; j += 2)
{
m_ptrLastDCT[ptrLapBuf + j] = m_ptrLastDCT[ptrLapBuf + j + 1];
}
- eriFastIPLOT (m_ptrLastDCT, ptrLapBuf, m_nSubbandDegree);
+ Erisa.FastIPLOT (m_ptrLastDCT, ptrLapBuf, m_nSubbandDegree);
ptrLapBuf += (int)m_nDegreeNum;
}
}
@@ -846,27 +838,27 @@ namespace GameRes.Formats.Entis
float rSin = (float) Math.Sin (nRevCode1 * Math.PI / 8);
float rCos = (float) Math.Cos (nRevCode1 * Math.PI / 8);
- eriRevolve2x2 (m_ptrMatrixBuf, ptrSrcBuf1, m_ptrMatrixBuf, ptrSrcBuf2, rSin, rCos, 2, m_nDegreeNum / 2);
+ Erisa.Revolve2x2 (m_ptrMatrixBuf, ptrSrcBuf1, m_ptrMatrixBuf, ptrSrcBuf2, rSin, rCos, 2, m_nDegreeNum / 2);
rSin = (float) Math.Sin (nRevCode2 * Math.PI / 8);
rCos = (float) Math.Cos (nRevCode2 * Math.PI / 8);
- eriRevolve2x2 (m_ptrMatrixBuf, ptrSrcBuf1 + 1, m_ptrMatrixBuf, ptrSrcBuf2 + 1, rSin, rCos, 2, m_nDegreeNum / 2);
+ Erisa.Revolve2x2 (m_ptrMatrixBuf, ptrSrcBuf1 + 1, m_ptrMatrixBuf, ptrSrcBuf2 + 1, rSin, rCos, 2, m_nDegreeNum / 2);
ptrSrcBuf = 0; // m_ptrMatrixBuf;
for (int i = 0; i < 2; i++)
{
- eriOddGivensInverseMatrix (m_ptrMatrixBuf, ptrSrcBuf, m_pRevolveParam, m_nSubbandDegree);
- eriFastIPLOT (m_ptrMatrixBuf, ptrSrcBuf, m_nSubbandDegree);
- eriFastILOT (m_ptrWorkBuf, m_ptrLastDCT, ptrLapBuf, m_ptrMatrixBuf, ptrSrcBuf, m_nSubbandDegree);
+ Erisa.OddGivensInverseMatrix (m_ptrMatrixBuf, ptrSrcBuf, m_pRevolveParam, m_nSubbandDegree);
+ Erisa.FastIPLOT (m_ptrMatrixBuf, ptrSrcBuf, m_nSubbandDegree);
+ Erisa.FastILOT (m_ptrWorkBuf, m_ptrLastDCT, ptrLapBuf, m_ptrMatrixBuf, ptrSrcBuf, m_nSubbandDegree);
Array.Copy (m_ptrMatrixBuf, ptrSrcBuf, m_ptrLastDCT, ptrLapBuf, m_nDegreeNum);
Array.Copy (m_ptrWorkBuf, 0, m_ptrMatrixBuf, ptrSrcBuf, m_nDegreeNum);
- eriFastIDCT (m_ptrInternalBuf, m_ptrMatrixBuf, ptrSrcBuf, 1, m_ptrWorkBuf, m_nSubbandDegree);
+ Erisa.FastIDCT (m_ptrInternalBuf, m_ptrMatrixBuf, ptrSrcBuf, 1, m_ptrWorkBuf, m_nSubbandDegree);
if (nSamples != 0)
{
- eriRoundR32ToWordArray (ptrDst, iDst + (int)i*2, 2, m_ptrInternalBuf, (int)nSamples);
+ Erisa.RoundR32ToWordArray (ptrDst, iDst + (int)i*2, 2, m_ptrInternalBuf, (int)nSamples);
}
ptrSrcBuf += m_nDegreeNum;
ptrLapBuf += m_nDegreeNum;
@@ -901,27 +893,27 @@ namespace GameRes.Formats.Entis
rSin = (float) Math.Sin (nRevCode * Math.PI / 8);
rCos = (float) Math.Cos (nRevCode * Math.PI / 8);
- eriRevolve2x2 (m_ptrMatrixBuf, ptrSrcBuf1, m_ptrMatrixBuf, ptrSrcBuf2, rSin, rCos, 1, m_nDegreeNum);
+ Erisa.Revolve2x2 (m_ptrMatrixBuf, ptrSrcBuf1, m_ptrMatrixBuf, ptrSrcBuf2, rSin, rCos, 1, m_nDegreeNum);
ptrSrcBuf = 0; // m_ptrMatrixBuf;
for (i = 0; i < 2; i ++)
{
- eriOddGivensInverseMatrix (m_ptrMatrixBuf, ptrSrcBuf, m_pRevolveParam, m_nSubbandDegree);
+ Erisa.OddGivensInverseMatrix (m_ptrMatrixBuf, ptrSrcBuf, m_pRevolveParam, m_nSubbandDegree);
for (j = 0; j < m_nDegreeNum; j += 2)
{
m_ptrMatrixBuf[ptrSrcBuf + j] = -m_ptrMatrixBuf[ptrSrcBuf + j + 1];
}
- eriFastIPLOT (m_ptrMatrixBuf, ptrSrcBuf, m_nSubbandDegree);
- eriFastILOT (m_ptrWorkBuf, m_ptrLastDCT, ptrLapBuf, m_ptrMatrixBuf, ptrSrcBuf, m_nSubbandDegree);
+ Erisa.FastIPLOT (m_ptrMatrixBuf, ptrSrcBuf, m_nSubbandDegree);
+ Erisa.FastILOT (m_ptrWorkBuf, m_ptrLastDCT, ptrLapBuf, m_ptrMatrixBuf, ptrSrcBuf, m_nSubbandDegree);
Array.Copy (m_ptrWorkBuf, 0, m_ptrMatrixBuf, ptrSrcBuf, m_nDegreeNum);
- eriFastIDCT (m_ptrInternalBuf, m_ptrMatrixBuf, ptrSrcBuf, 1, m_ptrWorkBuf, m_nSubbandDegree);
+ Erisa.FastIDCT (m_ptrInternalBuf, m_ptrMatrixBuf, ptrSrcBuf, 1, m_ptrWorkBuf, m_nSubbandDegree);
if (nSamples != 0)
{
- eriRoundR32ToWordArray (ptrDst, iDst + (int)i*2, 2, m_ptrInternalBuf, (int)nSamples);
+ Erisa.RoundR32ToWordArray (ptrDst, iDst + (int)i*2, 2, m_ptrInternalBuf, (int)nSamples);
}
ptrLapBuf += m_nDegreeNum;
ptrSrcBuf += m_nDegreeNum;
@@ -972,346 +964,5 @@ namespace GameRes.Formats.Entis
ptrDestination[dst + i] = (float) (rCoefficient * m_ptrWeightTable[i] * ptrQuantumized[qsrc+i]);
}
}
-
- static readonly float ERI_rCosPI4 = (float)Math.Cos (Math.PI / 4);
- static readonly float ERI_r2CosPI4 = 2 * ERI_rCosPI4;
- static readonly float[] ERI_DCTofK2 = new float[2]; // = cos( (2*i+1) / 8 )
- static readonly float[] ERI_DCTofK4 = new float[4]; // = cos( (2*i+1) / 16 )
- static readonly float[] ERI_DCTofK8 = new float[8]; // = cos( (2*i+1) / 32 )
- static readonly float[] ERI_DCTofK16 = new float[16]; // = cos( (2*i+1) / 64 )
- static readonly float[] ERI_DCTofK32 = new float[32]; // = cos( (2*i+1) / 128 )
- static readonly float[] ERI_DCTofK64 = new float[64]; // = cos( (2*i+1) / 256 )
- static readonly float[] ERI_DCTofK128 = new float[128]; // = cos( (2*i+1) / 512 )
- static readonly float[] ERI_DCTofK256 = new float[256]; // = cos( (2*i+1) / 1024 )
- static readonly float[] ERI_DCTofK512 = new float[512]; // = cos( (2*i+1) / 2048 )
- static readonly float[] ERI_DCTofK1024 = new float[1024]; // = cos( (2*i+1) / 4096 )
- static readonly float[] ERI_DCTofK2048 = new float[2048]; // = cos( (2*i+1) / 8192 )
-
- static readonly float[][] ERI_pMatrixDCTofK = new float[MAX_DCT_DEGREE][]
- {
- null,
- ERI_DCTofK2,
- ERI_DCTofK4,
- ERI_DCTofK8,
- ERI_DCTofK16,
- ERI_DCTofK32,
- ERI_DCTofK64,
- ERI_DCTofK128,
- ERI_DCTofK256,
- ERI_DCTofK512,
- ERI_DCTofK1024,
- ERI_DCTofK2048
- };
-
- static void eriInitializeMatrix ()
- {
- for (int i = 1; i < MAX_DCT_DEGREE; i++)
- {
- int n = (1 << i);
- float[] pDCTofK = ERI_pMatrixDCTofK[i];
- double nr = Math.PI / (4.0 * n);
- double dr = nr + nr;
- double ir = nr;
- for (int j = 0; j < n; j++)
- {
- pDCTofK[j] = (float)Math.Cos (ir);
- ir += dr;
- }
- }
- }
-
- static void eriRoundR32ToWordArray (byte[] ptrDst, int dst, int nStep, float[] ptrSrc, int nCount)
- {
- nStep *= 2;
- for (int i = 0; i < nCount; i++)
- {
- int nValue = eriRoundR32ToInt (ptrSrc[i]);
- if (nValue <= -0x8000)
- {
- LittleEndian.Pack ((short)-0x8000, ptrDst, dst);
- }
- else if (nValue >= 0x7FFF)
- {
- LittleEndian.Pack ((short)0x7FFF, ptrDst, dst);
- }
- else
- {
- LittleEndian.Pack ((short)nValue, ptrDst, dst);
- }
- dst += nStep;
- }
- }
-
- static int eriRoundR32ToInt (float r)
- {
- if (r >= 0.0)
- return (int)Math.Floor (r + 0.5);
- else
- return (int)Math.Ceiling (r - 0.5);
- }
-
- static EriSinCos[] eriCreateRevolveParameter (int nDegreeDCT)
- {
- int nDegreeNum = 1 << nDegreeDCT;
- int lc = 1;
- for (int n = nDegreeNum / 2; n >= 8; n /= 8)
- {
- ++lc;
- }
- EriSinCos[] ptrRevolve = new EriSinCos[lc*8];
-
- double k = Math.PI / (nDegreeNum * 2);
- int ptrNextRev = 0;
- int nStep = 2;
- do
- {
- for (int i = 0; i < 7; i++)
- {
- double ws = 1.0;
- double a = 0.0;
- for (int j = 0; j < i; j++)
- {
- a += nStep;
- ws = ws * ptrRevolve[ptrNextRev+j].rSin + ptrRevolve[ptrNextRev+j].rCos * Math.Cos (a * k);
- }
- double r = Math.Atan2 (ws, Math.Cos ((a + nStep) * k));
- ptrRevolve[ptrNextRev+i].rSin = (float)Math.Sin (r);
- ptrRevolve[ptrNextRev+i].rCos = (float)Math.Cos (r);
- }
- ptrNextRev += 7;
- nStep *= 8;
- }
- while (nStep < nDegreeNum);
- return ptrRevolve;
- }
-
- static void eriOddGivensInverseMatrix (float[] ptrSrc, int src, EriSinCos[] ptrRevolve, int nDegreeDCT)
- {
- int nDegreeNum = 1 << nDegreeDCT;
- int index = 1;
- int nStep = 2;
- int lc = (nDegreeNum / 2) / 8;
- int resolve_idx = 0;
- for (;;)
- {
- resolve_idx += 7;
- index += nStep * 7;
- nStep *= 8;
- if (lc <= 8)
- break;
- lc /= 8;
- }
- int k = index + nStep * (lc - 2);
- int j;
- float r1, r2;
- for (j = lc - 2; j >= 0; j--)
- {
- r1 = ptrSrc[src + k];
- r2 = ptrSrc[src + k + nStep];
- ptrSrc[src + k] = r1 * ptrRevolve[resolve_idx+j].rCos + r2 * ptrRevolve[resolve_idx+j].rSin;
- ptrSrc[src + k + nStep] = r2 * ptrRevolve[resolve_idx+j].rCos - r1 * ptrRevolve[resolve_idx+j].rSin;
- k -= nStep;
- }
- for (; lc <= (nDegreeNum / 2) / 8; lc *= 8)
- {
- resolve_idx -= 7;
- nStep /= 8;
- index -= nStep * 7;
- for (int i = 0; i < lc; i++)
- {
- k = i * (nStep * 8) + index + nStep * 6;
- for ( j = 6; j >= 0; j -- )
- {
- r1 = ptrSrc[src + k];
- r2 = ptrSrc[src + k + nStep];
- ptrSrc[src + k] =
- r1 * ptrRevolve[resolve_idx+j].rCos + r2 * ptrRevolve[resolve_idx+j].rSin;
- ptrSrc[src + k + nStep] =
- r2 * ptrRevolve[resolve_idx+j].rCos - r1 * ptrRevolve[resolve_idx+j].rSin;
- k -= nStep;
- }
- }
- }
- }
-
- static void eriFastIPLOT (float[] ptrSrc, int src, int nDegreeDCT)
- {
- int nDegreeNum = 1 << nDegreeDCT;
- for (int i = 0; i < nDegreeNum; i += 2)
- {
- float r1 = ptrSrc[src + i];
- float r2 = ptrSrc[src + i + 1];
- ptrSrc[src + i] = 0.5f * (r1 + r2);
- ptrSrc[src + i + 1] = 0.5f * (r1 - r2);
- }
- }
-
- static void eriFastILOT (float[] ptrDst, float[] ptrSrc1, int src1, float[] ptrSrc2, int src2, int nDegreeDCT)
- {
- int nDegreeNum = 1 << nDegreeDCT;
- for (int i = 0; i < nDegreeNum; i += 2)
- {
- float r1 = ptrSrc1[src1 + i];
- float r2 = ptrSrc2[src2 + i + 1];
- ptrDst[i] = r1 + r2;
- ptrDst[i + 1] = r1 - r2;
- }
- }
-
- static void eriFastDCT (float[] ptrDst, int dst, int nDstInterval, float[] ptrSrc, int src, float[] ptrWorkBuf, int work, int nDegreeDCT)
- {
- Debug.Assert ((nDegreeDCT >= MIN_DCT_DEGREE) && (nDegreeDCT <= MAX_DCT_DEGREE));
-
- if (nDegreeDCT == MIN_DCT_DEGREE)
- {
- float[] r32Buf = new float[4];
- r32Buf[0] = ptrSrc[src] + ptrSrc[src+3];
- r32Buf[2] = ptrSrc[src] - ptrSrc[src+3];
- r32Buf[1] = ptrSrc[src+1] + ptrSrc[src+2];
- r32Buf[3] = ptrSrc[src+1] - ptrSrc[src+2];
-
- ptrDst[dst] = 0.5f * (r32Buf[0] + r32Buf[1]);
- ptrDst[dst+nDstInterval * 2] = ERI_rCosPI4 * (r32Buf[0] - r32Buf[1]);
-
- r32Buf[2] = ERI_DCTofK2[0] * r32Buf[2];
- r32Buf[3] = ERI_DCTofK2[1] * r32Buf[3];
-
- r32Buf[0] = r32Buf[2] + r32Buf[3];
- r32Buf[1] = ERI_r2CosPI4 * (r32Buf[2] - r32Buf[3]);
-
- r32Buf[1] -= r32Buf[0];
-
- ptrDst[dst+nDstInterval] = r32Buf[0];
- ptrDst[dst+nDstInterval * 3] = r32Buf[1];
- }
- else
- {
- uint i;
- uint nDegreeNum = 1u << nDegreeDCT;
- uint nHalfDegree = nDegreeNum >> 1;
- for (i = 0; i < nHalfDegree; i++)
- {
- ptrWorkBuf[work+i] = ptrSrc[src+i] + ptrSrc[src + nDegreeNum - i - 1];
- ptrWorkBuf[work+i + nHalfDegree] = ptrSrc[src+i] - ptrSrc[src + nDegreeNum - i - 1];
- }
- int nDstStep = nDstInterval << 1;
- eriFastDCT (ptrDst, dst, nDstStep, ptrWorkBuf, work, ptrSrc, src, nDegreeDCT - 1);
-
- float[] pDCTofK = ERI_pMatrixDCTofK[nDegreeDCT - 1];
- src = (int)(work+nHalfDegree); // ptrSrc = ptrWorkBuf + nHalfDegree;
- dst += nDstInterval; // ptrDst += nDstInterval;
-
- for (i = 0; i < nHalfDegree; i++)
- {
- ptrWorkBuf[src + i] *= pDCTofK[i];
- }
-
- eriFastDCT (ptrDst, dst, nDstStep, ptrWorkBuf, src, ptrWorkBuf, work, nDegreeDCT - 1);
- // eriFastDCT (ptrDst, nDstStep, ptrSrc, ptrWorkBuf, nDegreeDCT - 1);
-
- int ptrNext = dst; // within ptrDst;
- for (i = 0; i < nHalfDegree; i++)
- {
- ptrDst[ptrNext] += ptrDst[ptrNext]; // *ptrNext += *ptrNext;
- ptrNext += nDstStep;
- }
- ptrNext = dst;
- for (i = 1; i < nHalfDegree; i ++)
- {
- ptrDst[ptrNext + nDstStep] -= ptrDst[ptrNext];
- ptrNext += nDstStep;
- }
- }
- }
-
- static void eriFastIDCT (float[] ptrDst, float[] srcBuf, int ptrSrc, int nSrcInterval, float[] ptrWorkBuf, int nDegreeDCT)
- {
- Debug.Assert ((nDegreeDCT >= MIN_DCT_DEGREE) && (nDegreeDCT <= MAX_DCT_DEGREE));
-
- if (nDegreeDCT == MIN_DCT_DEGREE)
- {
- float[] r32Buf1 = new float[2];
- float[] r32Buf2 = new float[4];
-
- r32Buf1[0] = srcBuf[ptrSrc];
- r32Buf1[1] = ERI_rCosPI4 * srcBuf[ptrSrc + nSrcInterval * 2];
-
- r32Buf2[0] = r32Buf1[0] + r32Buf1[1];
- r32Buf2[1] = r32Buf1[0] - r32Buf1[1];
-
- r32Buf1[0] = ERI_DCTofK2[0] * srcBuf[ptrSrc + nSrcInterval];
- r32Buf1[1] = ERI_DCTofK2[1] * srcBuf[ptrSrc + nSrcInterval * 3];
-
- r32Buf2[2] = r32Buf1[0] + r32Buf1[1];
- r32Buf2[3] = ERI_r2CosPI4 * (r32Buf1[0] - r32Buf1[1]);
-
- r32Buf2[3] -= r32Buf2[2];
-
- ptrDst[0] = r32Buf2[0] + r32Buf2[2];
- ptrDst[3] = r32Buf2[0] - r32Buf2[2];
- ptrDst[1] = r32Buf2[1] + r32Buf2[3];
- ptrDst[2] = r32Buf2[1] - r32Buf2[3];
- }
- else
- {
- uint nDegreeNum = 1u << nDegreeDCT;
- uint nHalfDegree = nDegreeNum >> 1;
- int nSrcStep = nSrcInterval << 1;
- eriFastIDCT (ptrDst, srcBuf, ptrSrc, nSrcStep, ptrWorkBuf, nDegreeDCT - 1);
-
- float[] pDCTofK = ERI_pMatrixDCTofK[nDegreeDCT - 1];
- int pOddDst = (int)nHalfDegree; // within ptrDst
- int ptrNext = ptrSrc + nSrcInterval; // within srcBuf
-
- uint i;
- for (i = 0; i < nHalfDegree; i++)
- {
- ptrWorkBuf[i] = srcBuf[ptrNext] * pDCTofK[i];
- ptrNext += nSrcStep;
- }
-
- eriFastDCT (ptrDst, pOddDst, 1, ptrWorkBuf, 0, ptrWorkBuf, (int)nHalfDegree, nDegreeDCT - 1);
- // eriFastDCT(pOddDst, 1, ptrWorkBuf, (ptrWorkBuf + nHalfDegree), nDegreeDCT - 1);
-
- for (i = 0; i < nHalfDegree; i ++)
- {
- ptrDst[pOddDst + i] += ptrDst[pOddDst + i];
- }
-
- for (i = 1; i < nHalfDegree; i++)
- {
- ptrDst[pOddDst + i] -= ptrDst[pOddDst + i - 1];
- }
- float[] r32Buf = new float[4];
- uint nQuadDegree = nHalfDegree >> 1;
- for (i = 0; i < nQuadDegree; i++)
- {
- r32Buf[0] = ptrDst[i] + ptrDst[nHalfDegree + i];
- r32Buf[3] = ptrDst[i] - ptrDst[nHalfDegree + i];
- r32Buf[1] = ptrDst[nHalfDegree - 1 - i] + ptrDst[nDegreeNum - 1 - i];
- r32Buf[2] = ptrDst[nHalfDegree - 1 - i] - ptrDst[nDegreeNum - 1 - i];
-
- ptrDst[i] = r32Buf[0];
- ptrDst[nHalfDegree - 1 - i] = r32Buf[1];
- ptrDst[nHalfDegree + i] = r32Buf[2];
- ptrDst[nDegreeNum - 1 - i] = r32Buf[3];
- }
- }
- }
-
- void eriRevolve2x2 (float[] buf1, int ptrBuf1, float[] buf2, int ptrBuf2, float rSin, float rCos, int nStep, int nCount)
- {
- for (int i = 0; i < nCount; i++)
- {
- float r1 = buf1[ptrBuf1];
- float r2 = buf2[ptrBuf2];
-
- buf1[ptrBuf1] = r1 * rCos - r2 * rSin;
- buf2[ptrBuf2] = r1 * rSin + r2 * rCos;
-
- ptrBuf1 += nStep;
- ptrBuf2 += nStep;
- }
- }
}
}