compressdialog.cpp

来自「著名的7zip的压缩算法,压缩比最高,但是压缩时间也比较长!」· C++ 代码 · 共 1,256 行 · 第 1/3 页

CPP
1,256
字号
    lstrcat(s, TEXT(" K"));
  else if (maga)
    lstrcat(s, TEXT(" M"));
  else
    lstrcat(s, TEXT(" "));
  lstrcat(s, TEXT("B"));
  int index = m_Dictionary.AddString(s);
  m_Dictionary.SetItemData(index, size);
  return index;
}

int CCompressDialog::AddDictionarySize(UInt32 size)
{
  if (size > 0)
  {
    if ((size & 0xFFFFF) == 0)
      return AddDictionarySize(size, false, true);
    if ((size & 0x3FF) == 0)
      return AddDictionarySize(size, true, false);
  }
  return AddDictionarySize(size, false, false);
}

void CCompressDialog::SetDictionary()
{
  m_Dictionary.ResetContent();
  const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
  const CArchiverInfo &ai = m_ArchiverInfoList[m_Format.GetCurSel()];
  int index = FindRegistryFormat(ai.Name);
  UInt32 defaultDictionary = UInt32(-1);
  if (index >= 0)
  {
    const NCompression::CFormatOptions &fo = m_RegistryInfo.FormatOptionsVector[index];
    if (fo.Method.CompareNoCase(GetMethodSpec()) == 0)
      defaultDictionary = fo.Dictionary;
  }
  int methodID = GetMethodID();
  int level = GetLevel2();
  if (methodID < 0)
  {
    SetMemoryUsage();
    return;
  }
  const UInt64 maxRamSize = GetMaxRamSizeForProgram();
  switch (methodID)
  {
    case kLZMA:
    {
      static const kMinDicSize = (1 << 16);
      if (defaultDictionary == UInt32(-1))
      {
        if (level >= 9)
          defaultDictionary = (1 << 26);
        else if (level >= 7)
          defaultDictionary = (1 << 24);
        else if (level >= 5)
          defaultDictionary = (1 << 22);
        else if (level >= 3)
          defaultDictionary = (1 << 20);
        else
          defaultDictionary = (kMinDicSize);
      }
      int i;
      AddDictionarySize(kMinDicSize);
      m_Dictionary.SetCurSel(0);
      for (i = 20; i <= 30; i++)
        for (int j = 0; j < 2; j++)
        {
          if (i == 20 && j > 0)
            continue;
          UInt32 dictionary = (1 << i) + (j << (i - 1));
          if (dictionary >
          #ifdef _WIN64
            (1 << 30)
          #else
            (1 << 27)
          #endif
            )
            continue;
          AddDictionarySize(dictionary);
          UInt64 decomprSize;
          UInt64 requiredComprSize = GetMemoryUsage(dictionary, false, decomprSize);
          if (dictionary <= defaultDictionary && requiredComprSize <= maxRamSize)
             m_Dictionary.SetCurSel(m_Dictionary.GetCount() - 1);
        }

      // SetNearestSelectComboBox(m_Dictionary, defaultDictionary);
      break;
    }
    case kPPMd:
    {
      if (defaultDictionary == UInt32(-1))
      {
        if (level >= 9)
          defaultDictionary = (192 << 20);
        else if (level >= 7)
          defaultDictionary = (64 << 20);
        else if (level >= 5)
          defaultDictionary = (16 << 20);
        else
          defaultDictionary = (4 << 20);
      }
      int i;
      for (i = 20; i < 31; i++)
        for (int j = 0; j < 2; j++)
        {
          if (i == 20 && j > 0)
            continue;
          UInt32 dictionary = (1 << i) + (j << (i - 1));
          if (dictionary >= (1 << 31))
            continue;
          AddDictionarySize(dictionary);
          UInt64 decomprSize;
          UInt64 requiredComprSize = GetMemoryUsage(dictionary, false, decomprSize);
          if (dictionary <= defaultDictionary && requiredComprSize <= maxRamSize || m_Dictionary.GetCount() == 0)
             m_Dictionary.SetCurSel(m_Dictionary.GetCount() - 1);
        }
      SetNearestSelectComboBox(m_Dictionary, defaultDictionary);
      break;
    }
    case kDeflate:
    {
      AddDictionarySize(32 << 10);
      m_Dictionary.SetCurSel(0);
      break;
    }
    case kDeflate64:
    {
      AddDictionarySize(64 << 10);
      m_Dictionary.SetCurSel(0);
      break;
    }
    case kBZip2:
    {
      UInt32 defaultDictionary;
      if (level >= 5)
        defaultDictionary = (900 << 10);
      else if (level >= 3)
        defaultDictionary = (500 << 10);
      else
        defaultDictionary = (100 << 10);
      for (int i = 1; i <= 9; i++)
      {
        UInt32 dictionary = (i * 100) << 10;
        AddDictionarySize(dictionary);
        if (dictionary <= defaultDictionary || m_Dictionary.GetCount() == 0)
           m_Dictionary.SetCurSel(m_Dictionary.GetCount() - 1);
      }
      break;
    }
  }
  SetMemoryUsage();
}

UInt32 CCompressDialog::GetDictionary()
{
  if (m_Dictionary.GetCount() <= 0)
    return -1;
  return m_Dictionary.GetItemData(m_Dictionary.GetCurSel());
}

UInt32 CCompressDialog::GetDictionarySpec()
{
  if (m_Dictionary.GetCount() <= 1)
    return -1;
  return GetDictionary();
}

int CCompressDialog::AddOrder(UInt32 size)
{
  TCHAR s[40];
  ConvertUInt64ToString(size, s);
  int index = m_Order.AddString(s);
  m_Order.SetItemData(index, size);
  return index;
}

void CCompressDialog::SetOrder()
{
  m_Order.ResetContent();
  const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
  const CArchiverInfo &ai = m_ArchiverInfoList[m_Format.GetCurSel()];
  int index = FindRegistryFormat(ai.Name);
  UInt32 defaultOrder = UInt32(-1);
  if (index >= 0)
  {
    const NCompression::CFormatOptions &fo = m_RegistryInfo.FormatOptionsVector[index];
    if (fo.Method.CompareNoCase(GetMethodSpec()) == 0)
      defaultOrder = fo.Order;
  }
  int methodID = GetMethodID();
  int level = GetLevel2();
  if (methodID < 0)
  {
    SetMemoryUsage();
    return;
  }
  switch (methodID)
  {
    case kLZMA:
    {
      if (defaultOrder == UInt32(-1))
        defaultOrder = (level >= 7) ? 64 : 32;
      for (int i = 3; i <= 8; i++)
        for (int j = 0; j < 2; j++)
        {
          UInt32 order = (1 << i) + (j << (i - 1));
          if (order <= 256)
            AddOrder(order);
        }
      AddOrder(273);
      SetNearestSelectComboBox(m_Order, defaultOrder);
      break;
    }
    case kPPMd:
    {
      if (defaultOrder == UInt32(-1))
      {
        if (level >= 9)
          defaultOrder = 32;
        else if (level >= 7)
          defaultOrder = 16;
        else if (level >= 5)
          defaultOrder = 6;
        else
          defaultOrder = 4;
      }
      int i;
      AddOrder(2);
      AddOrder(3);
      for (i = 2; i < 8; i++)
        for (int j = 0; j < 4; j++)
        {
          UInt32 order = (1 << i) + (j << (i - 2));
          if (order < 32)
            AddOrder(order);
        }
      AddOrder(32);
      SetNearestSelectComboBox(m_Order, defaultOrder);
      break;
    }
    case kDeflate:
    case kDeflate64:
    {
      if (defaultOrder == UInt32(-1))
      {
        if (level >= 9)
          defaultOrder = 128;
        else if (level >= 7)
          defaultOrder = 64;
        else
          defaultOrder = 32;
      }
      int i;
      for (i = 3; i <= 8; i++)
        for (int j = 0; j < 2; j++)
        {
          UInt32 order = (1 << i) + (j << (i - 1));
          if (order <= 256)
            AddOrder(order);
        }
      AddOrder(methodID == kDeflate64 ? 257 : 258);
      SetNearestSelectComboBox(m_Order, defaultOrder);
      break;
    }
    case kBZip2:
    {
      break;
    }
  }
  SetMemoryUsage();
}

bool CCompressDialog::GetOrderMode()
{
  switch (GetMethodID())
  {
    case kPPMd:
      return true;
  }
  return false;
}

UInt32 CCompressDialog::GetOrder()
{
  if (m_Order.GetCount() <= 0)
    return -1;
  return m_Order.GetItemData(m_Order.GetCurSel());
}

UInt32 CCompressDialog::GetOrderSpec()
{
  if (m_Order.GetCount() <= 1)
    return -1;
  return GetOrder();
}

UInt64 CCompressDialog::GetMemoryUsage(UInt32 dictionary, bool isMultiThread, UInt64 &decompressMemory)
{
  decompressMemory = UInt64(Int64(-1));
  int level = GetLevel2();
  if (level == 0)
  {
    decompressMemory = (1 << 20);
    return decompressMemory;
  }
  UInt64 size = 0;

  const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
  if (fi.Filter && level >= 9)
    size += (12 << 20) * 2 + (5 << 20);
  switch (GetMethodID())
  {
    case kLZMA:
    {
      UInt32 hs = dictionary - 1;
      hs |= (hs >> 1);
      hs |= (hs >> 2);
      hs |= (hs >> 4);
      hs |= (hs >> 8);
      hs >>= 1;
      hs |= 0xFFFF;
      if (hs > (1 << 24))
        hs >>= 1;
      hs++;
      size += hs * 4;
      size += (UInt64)dictionary * 11 / 2;
      if (level >= 5)
        size += dictionary * 4;
      size += (2 << 20);
      if (isMultiThread && level >= 5)
        size += (2 << 20) + (4 << 20);

      decompressMemory = dictionary + (2 << 20);
      return size;
    }
    case kPPMd:
    {
      decompressMemory = dictionary + (2 << 20);
      return size + decompressMemory;
    }
    case kDeflate:
    case kDeflate64:
    {
      UInt32 order = GetOrder();
      if (order == UInt32(-1))
        order = 32;
      if (level >= 7)
        size += (1 << 20);
      size += 3 << 20;
      decompressMemory = (2 << 20);
      return size;
    }
    case kBZip2:
    {
      decompressMemory = (7 << 20);
      UInt64 memForOneThread = (10 << 20);
      if (isMultiThread)
        memForOneThread *= NSystem::GetNumberOfProcessors();
      return size + (10 << 20);
    }
  }
  return UInt64(Int64(-1));
}

UInt64 CCompressDialog::GetMemoryUsage(UInt64 &decompressMemory)
{
  return GetMemoryUsage(GetDictionary(), IsMultiThread(), decompressMemory);
}

void CCompressDialog::PrintMemUsage(UINT res, UInt64 value)
{
  if (value == (UInt64)Int64(-1))
  {
    SetItemText(res, TEXT("?"));
    return;
  }
  value = (value + (1 << 20) - 1) >> 20;
  TCHAR s[40];
  ConvertUInt64ToString(value, s);
  lstrcat(s, TEXT(" MB"));
  SetItemText(res, s);
}
    
void CCompressDialog::SetMemoryUsage()
{
  UInt64 decompressMem; 
  UInt64 memUsage = GetMemoryUsage(decompressMem);
  PrintMemUsage(IDC_STATIC_COMPRESS_MEMORY_VALUE, memUsage);
  PrintMemUsage(IDC_STATIC_COMPRESS_MEMORY_DE_VALUE, decompressMem);
}

void CCompressDialog::SetParams()
{
  const CArchiverInfo &ai = m_ArchiverInfoList[m_Format.GetCurSel()];
  m_Params.SetText(TEXT(""));
  int index = FindRegistryFormat(ai.Name);
  if (index >= 0)
  {
    const NCompression::CFormatOptions &fo = m_RegistryInfo.FormatOptionsVector[index];
    m_Params.SetText(fo.Options);
  }
}

void CCompressDialog::SaveOptionsInMem()
{
  const CArchiverInfo &ai = m_ArchiverInfoList[Info.ArchiverInfoIndex];
  int index = FindRegistryFormatAlways(ai.Name);
  m_Params.GetText(Info.Options);
  Info.Options.Trim();
  NCompression::CFormatOptions &fo = m_RegistryInfo.FormatOptionsVector[index];
  fo.Options = Info.Options;
  fo.Level = GetLevelSpec();
  fo.Dictionary = GetDictionarySpec();
  fo.Order = GetOrderSpec();
  fo.Method = GetMethodSpec();
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?