Пример #1
0
 /// <summary>
 /// コンストラクタ
 /// </summary>
 public ScanJpeg()
 {
     for (int i = 0; i < _dcHDT.Length; i++)
     {
         _dcHDT[i] = new HuffmanDecodeTable();
         _acHDT[i] = new HuffmanDecodeTable();
     }
 }
Пример #2
0
            /// <summary>
            /// ブロックデータを読み出す。
            /// </summary>
            /// <param name="qDct">量子化後のDCT係数列格納メモリ</param>
            /// <param name="qDctIndex">qDctのインデックス</param>
            /// <param name="pred">直流係数予測値</param>
            /// <param name="dcHDT">直流係数用ハフマン復号テーブル(DC HDT)</param>
            /// <param name="acHDT">交流係数用ハフマン復号テーブル(AC HDT)</param>
            /// <returns>処理結果</returns>
            private ReturnID ReadBlockData(ref short[] qDct, int qDctIndex, ref short pred, HuffmanDecodeTable dcHDT, HuffmanDecodeTable acHDT)
            {
                // 直流係数を復号する。
                {
                    // 直流係数と予測値の差分のカテゴリ(=後続のビット数)を復号する。
                    byte index = dcHDT.CodeToIndexLookUpTable[PeepBits(dcHDT.BitLengthMax)];
                    if (index > dcHDT.IndexMax)
                    {
                        return(ReturnID.JpegDataErrorUnexpectedData);  // 予期せぬJPEGデータ
                    }
                    SkipBits(dcHDT.BitLength[index]);

                    byte dcDiffBitLength = dcHDT.Symbol[index];
                    if (dcDiffBitLength > 11)
                    {
                        return(ReturnID.JpegDataErrorUnexpectedData);  // 予期せぬJPEGデータ
                    }
                    // 後続のビットがある場合
                    if (dcDiffBitLength != 0)
                    {
                        // 後続のビットを読み出し、直流係数と予測値の差分を求める。
                        short dcDiff = (short)ReadBits(dcDiffBitLength);
                        if (dcDiff < _positive[dcDiffBitLength])
                        {
                            dcDiff += _makeNegative[dcDiffBitLength];
                        }

                        // 直流係数を計算する。この値は次ブロックの直流係数の予測値となる。
                        pred += dcDiff;
                    }
                    // 後続のビットがない場合は、予測値がそのまま直流係数になるので計算不要。

                    if (qDct != null)
                    {
                        // 直流係数を量子化後のDCT係数列格納メモリに代入する。
                        qDct[qDctIndex] = pred;
                    }
                }

                // 交流係数を復号する。
                for (int k = 1; k < 64;)        // ジグザグスキャン順
                {
                    // 交流係数符号表(ゼロ係数の連長と非ゼロ係数の振幅の組み合わせ)を復号する。
                    byte index = acHDT.CodeToIndexLookUpTable[PeepBits(acHDT.BitLengthMax)];
                    if (index > acHDT.IndexMax)
                    {
                        return(ReturnID.JpegDataErrorUnexpectedData);  // 予期せぬJPEGデータ
                    }
                    SkipBits(acHDT.BitLength[index]);

                    byte zeroRun_AcBitLen = acHDT.Symbol[index];
                    byte zeroRun          = (byte)(zeroRun_AcBitLen >> 4);
                    byte acBitLength      = (byte)(zeroRun_AcBitLen & 0x0F);
                    if (acBitLength > 10)
                    {
                        return(ReturnID.JpegDataErrorUnexpectedData);  // 予期せぬJPEGデータ
                    }
                    // 後続のビットがある場合
                    if (acBitLength != 0)
                    {
                        k += zeroRun;

                        if (qDct != null)
                        {
                            // 後続のビットを読み出し、非ゼロ交流係数を求める。
                            short acVal = (short)ReadBits(acBitLength);
                            if (acVal < _positive[acBitLength])
                            {
                                acVal += _makeNegative[acBitLength];
                            }

                            // 非ゼロ交流係数を量子化後のDCT係数列格納メモリに代入する。
                            qDct[qDctIndex + k++] = acVal;
                        }
                        else
                        {
                            // 後続のビットをスキップする。
                            SkipBits(acBitLength);
                            k++;
                        }
                    }
                    // 後続のビットがない場合
                    else
                    {
                        if (15 == zeroRun)
                        {
                            k += 16;
                        }
                        else
                        {
                            k = 64;
                        }
                    }
                }

                return(ReturnID.Success);
            }
Пример #3
0
            /// <summary>
            /// ハフマン復号テーブルを作成する。
            /// </summary>
            /// <param name="dhts">ハフマンテーブル定義補助</param>
            /// <returns>処理結果</returns>
            private ReturnID MakeHuffDecTbl(DefineHuffmanTableSub dhts)
            {
                if (dhts == null || dhts.Tc > 1 || dhts.Th > 1 || dhts.Total == 0 || dhts.Total > 256)
                {
                    return(ReturnID.ErrorInvalidParam);      // 不正な引数
                }

                // 処理対象となるハフマン復号テーブルを取得する。
                HuffmanDecodeTable hdt = dhts.Tc == 0 ? _dcHDT[dhts.Th] : _acHDT[dhts.Th];

                // ハフマン復号テーブルをクリアする。
                hdt.BitLengthMax = 0;
                hdt.IndexMax     = 0;
                if (hdt.CodeToIndexLookUpTable != null)
                {
                    hdt.CodeToIndexLookUpTable = null;
                }
                Array.Clear(hdt.BitLength, 0, hdt.BitLength.Length);
                Array.Clear(hdt.Symbol, 0, hdt.Symbol.Length);

                // 符号語格納メモリ(符号語テーブル)を確保する。
                ushort[] codeTable = new ushort[dhts.Total];

                // 符号語長の配列と符号語テーブルに値を代入する。
                byte   bitLengthMax   = 0;
                ushort code           = 0;
                int    bitLengthIndex = 0;
                int    codeTableIndex = 0;

                for (byte bitLength = 1; bitLength <= 16; bitLength++)
                {
                    byte numOfCodes = dhts.Li[bitLength - 1];
                    if (numOfCodes != 0)
                    {
                        bitLengthMax = bitLength;

                        for (byte count = 0; count < numOfCodes; count++)
                        {
                            hdt.BitLength[bitLengthIndex++] = bitLength;
                            codeTable[codeTableIndex++]     = code++;
                        }
                    }
                    code <<= 1;
                }

                if (bitLengthMax == 0)
                {
                    return(ReturnID.JpegDataErrorUnexpectedData);  // 予期せぬJPEGデータ
                }

                // ハフマン復号用のLookUpTableのメモリを確保し、-1で初期化する。
                hdt.CodeToIndexLookUpTable = new byte[1 << bitLengthMax];
                for (int i = 0; i < hdt.CodeToIndexLookUpTable.Length; i++)
                {
                    hdt.CodeToIndexLookUpTable[i] = 0xFF;
                }
                // ハフマン復号テーブルに適切な値を代入する。
                hdt.BitLengthMax = bitLengthMax;
                hdt.IndexMax     = (byte)(dhts.Total - 1);
                Array.Copy(dhts.Vij, 0, hdt.Symbol, 0, dhts.Total);

                // ハフマン復号用のLookUpTableに値を代入する。
                bitLengthIndex = 0;
                codeTableIndex = 0;
                for (ushort wIdx = 0; wIdx < dhts.Total; wIdx++)
                {
                    // 最大符号語長と各符号語長との差(nLenDiff)を求める。
                    int nLenDiff = bitLengthMax - hdt.BitLength[bitLengthIndex++];
                    if (nLenDiff != 0)
                    {
                        // 符号語をMSB側に寄せた値をLUTの最初のインデックスとし、そこから必要な個数(注)
                        // だけ符号語長およびシンボル値の配列のインデックスを代入する。
                        // (注) 符号語をMSB側に寄せたためにLSB側に空いたビットを埋めるのに必要な個数。
                        ushort wLUTIdx = (ushort)(codeTable[codeTableIndex++] << nLenDiff);
                        for (int i = 0; i < 1 << nLenDiff; i++)
                        {
                            hdt.CodeToIndexLookUpTable[wLUTIdx + i] = (byte)wIdx;
                        }
                    }
                    else
                    {
                        hdt.CodeToIndexLookUpTable[codeTable[codeTableIndex++]] = (byte)wIdx;
                    }
                }

                return(ReturnID.Success);
            }