Exemplo n.º 1
0
            /// <summary>
            /// DHTマーカセグメントを読み出し、ハフマン復号テーブルを作成する。
            /// </summary>
            /// <returns>処理結果</returns>
            private ReturnID ReadDHTMarkerSeg()
            {
                // DHTマーカセグメント長
                int length = (_jpegData[_jpegDataIndex] << 8) + _jpegData[_jpegDataIndex + 1];

                if (length > _remainSize)
                {
                    return(ReturnID.JpegDataErrorShortOfData);        // JPEGデータ不足
                }
                else if (length <= 19)
                {
                    return(ReturnID.JpegDataErrorBadMmarkerSegment);   // 不正なJPEGマーカセグメント
                }
                _jpegDataIndex += 2;
                _remainSize    -= 2;
                length         -= 2;

                // ハフマンテーブル定義の個数分ループする。
                while (length > 0)
                {
                    // ハフマンテーブル定義補助構造体に値を代入する。
                    DefineHuffmanTableSub dhts = new DefineHuffmanTableSub()
                    {
                        Tc = (byte)((_jpegData[_jpegDataIndex] >> 4) & 0x0F),
                        Th = (byte)(_jpegData[_jpegDataIndex++] & 0x0F),
                    };

                    Array.Copy(_jpegData, _jpegDataIndex, dhts.Li, 0, 16);
                    _jpegDataIndex += 16;

                    for (int i = 0; i < 16; i++)
                    {
                        dhts.Total += dhts.Li[i];
                    }

                    if (dhts.Total > 256)
                    {
                        return(ReturnID.JpegDataErrorUnexpectedData);  // 予期せぬJPEGデータ
                    }
                    Array.Copy(_jpegData, _jpegDataIndex, dhts.Vij, 0, dhts.Total);
                    _jpegDataIndex += dhts.Total;
                    _remainSize    -= 17 + dhts.Total;
                    length         -= 17 + dhts.Total;

                    if (_remainSize < 0)
                    {
                        return(ReturnID.JpegDataErrorShortOfData);    // JPEGデータ不足
                    }
                    // ハフマン復号テーブルを作成する。
                    ReturnID returnID = MakeHuffDecTbl(dhts);
                    if (ReturnID.Success != returnID)
                    {
                        return(returnID);
                    }
                }

                return(ReturnID.Success);
            }
Exemplo n.º 2
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);
            }