/// <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); }
/// <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); }