Home | History | Annotate | Download | only in jbig2
      1 // Copyright 2014 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include "core/src/fxcodec/jbig2/JBig2_HuffmanTable.h"
      8 
      9 #include <algorithm>
     10 #include <vector>
     11 
     12 #include "core/include/fxcrt/fx_memory.h"
     13 #include "core/src/fxcodec/jbig2/JBig2_BitStream.h"
     14 #include "core/src/fxcodec/jbig2/JBig2_Define.h"
     15 #include "core/src/fxcodec/jbig2/JBig2_HuffmanTable_Standard.h"
     16 
     17 CJBig2_HuffmanTable::CJBig2_HuffmanTable(const JBig2TableLine* pTable,
     18                                          FX_DWORD nLines,
     19                                          bool bHTOOB)
     20     : m_bOK(true), HTOOB(bHTOOB), NTEMP(nLines) {
     21   ParseFromStandardTable(pTable);
     22 }
     23 
     24 CJBig2_HuffmanTable::CJBig2_HuffmanTable(CJBig2_BitStream* pStream)
     25     : HTOOB(false), NTEMP(0) {
     26   m_bOK = ParseFromCodedBuffer(pStream);
     27 }
     28 
     29 CJBig2_HuffmanTable::~CJBig2_HuffmanTable() {
     30 }
     31 
     32 void CJBig2_HuffmanTable::ParseFromStandardTable(const JBig2TableLine* pTable) {
     33   PREFLEN.resize(NTEMP);
     34   RANGELEN.resize(NTEMP);
     35   RANGELOW.resize(NTEMP);
     36   for (FX_DWORD i = 0; i < NTEMP; ++i) {
     37     PREFLEN[i] = pTable[i].PREFLEN;
     38     RANGELEN[i] = pTable[i].RANDELEN;
     39     RANGELOW[i] = pTable[i].RANGELOW;
     40   }
     41   InitCodes();
     42 }
     43 
     44 bool CJBig2_HuffmanTable::ParseFromCodedBuffer(CJBig2_BitStream* pStream) {
     45   unsigned char cTemp;
     46   if (pStream->read1Byte(&cTemp) == -1)
     47     return false;
     48 
     49   HTOOB = !!(cTemp & 0x01);
     50   unsigned char HTPS = ((cTemp >> 1) & 0x07) + 1;
     51   unsigned char HTRS = ((cTemp >> 4) & 0x07) + 1;
     52   FX_DWORD HTLOW;
     53   FX_DWORD HTHIGH;
     54   if (pStream->readInteger(&HTLOW) == -1 ||
     55       pStream->readInteger(&HTHIGH) == -1) {
     56     return false;
     57   }
     58 
     59   const int low = static_cast<int>(HTLOW);
     60   const int high = static_cast<int>(HTHIGH);
     61   if (low > high)
     62     return false;
     63 
     64   ExtendBuffers(false);
     65   int cur_low = low;
     66   do {
     67     if ((pStream->readNBits(HTPS, &PREFLEN[NTEMP]) == -1) ||
     68         (pStream->readNBits(HTRS, &RANGELEN[NTEMP]) == -1)) {
     69       return false;
     70     }
     71     RANGELOW[NTEMP] = cur_low;
     72     cur_low += (1 << RANGELEN[NTEMP]);
     73     ExtendBuffers(true);
     74   } while (cur_low < high);
     75 
     76   if (pStream->readNBits(HTPS, &PREFLEN[NTEMP]) == -1)
     77     return false;
     78 
     79   RANGELEN[NTEMP] = 32;
     80   RANGELOW[NTEMP] = low - 1;
     81   ExtendBuffers(true);
     82 
     83   if (pStream->readNBits(HTPS, &PREFLEN[NTEMP]) == -1)
     84     return false;
     85 
     86   RANGELEN[NTEMP] = 32;
     87   RANGELOW[NTEMP] = high;
     88   ExtendBuffers(true);
     89 
     90   if (HTOOB) {
     91     if (pStream->readNBits(HTPS, &PREFLEN[NTEMP]) == -1)
     92       return false;
     93 
     94     ++NTEMP;
     95   }
     96 
     97   InitCodes();
     98   return true;
     99 }
    100 
    101 void CJBig2_HuffmanTable::InitCodes() {
    102   int lenmax = 0;
    103   for (FX_DWORD i = 0; i < NTEMP; ++i)
    104     lenmax = std::max(PREFLEN[i], lenmax);
    105 
    106   CODES.resize(NTEMP);
    107   std::vector<int> LENCOUNT(lenmax + 1);
    108   std::vector<int> FIRSTCODE(lenmax + 1);
    109   for (int len : PREFLEN)
    110     ++LENCOUNT[len];
    111 
    112   FIRSTCODE[0] = 0;
    113   LENCOUNT[0] = 0;
    114   for (int i = 1; i <= lenmax; ++i) {
    115     FIRSTCODE[i] = (FIRSTCODE[i - 1] + LENCOUNT[i - 1]) << 1;
    116     int CURCODE = FIRSTCODE[i];
    117     for (FX_DWORD j = 0; j < NTEMP; ++j) {
    118       if (PREFLEN[j] == i)
    119         CODES[j] = CURCODE++;
    120     }
    121   }
    122 }
    123 
    124 void CJBig2_HuffmanTable::ExtendBuffers(bool increment) {
    125   if (increment)
    126     ++NTEMP;
    127 
    128   size_t size = PREFLEN.size();
    129   if (NTEMP < size)
    130     return;
    131 
    132   size += 16;
    133   ASSERT(NTEMP < size);
    134   PREFLEN.resize(size);
    135   RANGELEN.resize(size);
    136   RANGELOW.resize(size);
    137 }
    138