他人の空似自作物置場

touhouSE_th145BGMOnly.zip/touhouSE_src/th135_utility.cpp


#include "stdafx.h"

namespace TouhouSE {

namespace TH135 {

std::vector<Color> readColor(
  std::vector<unsigned char>::const_iterator it,
  const unsigned int bitCount,
  const unsigned int colorCount,
  const std::vector<Color> * const palette)
{
  std::vector<Color> result(colorCount);
  if (bitCount == 32) {
    for (Color &c : result) {
      c.b = it[0];
      c.g = it[1];
      c.r = it[2];
      c.alpha = it[3];
      it += 4;
    }
  }
  else if (bitCount == 24) {
    for (Color &c : result) {
      c.b = it[0];
      c.g = it[1];
      c.r = it[2];
      c.alpha = 0xFF;
      it += 3;
    }
  }
  else if (bitCount == 16) {
    for (Color &c : result) {
      c.b = (it[0] & 0x1F) * 255 / 0x1F;
      c.g = (((it[1] & 0x03) << 3) | ((it[0] & 0xE0) >> 5)) * 255 / 0x1F;
      c.r = ((it[1] & 0x7C) >> 2) * 255 / 0x1F;
      c.alpha = ((it[1] & 0x80) == 0 ? 0x00 : 0xFF);
      it += 2;
    }
  }
  else if (bitCount == 8) {
    for (Color &c : result) {
      const Color &pal = palette->at(*it);
      c = pal;
      it++;
    }
  }
  return result;
}

std::vector<Color> readPalette(
  std::istream &in,
  const unsigned long long int fileSize)
{
  const unsigned int headerSize = 4 + 1 + 4;
#pragma pack(push, 1)
  struct {
    char signature[4];
    unsigned char version;
    unsigned int compSize;
  } header;
#pragma pack(pop)
  if (fileSize < headerSize) {
    return{};
  }
  in.read(reinterpret_cast<char *>(&header), sizeof(header));
  if (!in.good() || !std::equal(&header.signature[0], &header.signature[_countof(header.signature)], "TFPA") || header.version != 0) {
    return{};
  }
  const unsigned int colorCount = 256;
  const unsigned int colorByteCount = sizeof(Color);
  const unsigned int origSize = (colorByteCount * colorCount) /* 32bit color */ + (2 * colorCount) /* 16bit color */;
  if (header.compSize == 0 || header.compSize >= origSize || fileSize - headerSize != header.compSize) {
    return{};
  }
  std::vector<unsigned char> temp(header.compSize);
  in.read(reinterpret_cast<char *>(&temp.front()), temp.size());
  if (!in.good()) {
    return{};
  }
  std::vector<unsigned char> data(origSize);
  uLongf origSizeResult = data.size();
  if (Z_OK != ::uncompress(reinterpret_cast<unsigned char *>(&data.front()), &origSizeResult, &temp.front(), header.compSize)) {
    return{};
  }
  /* 16bit palette */
  //return readColor(data.begin(), 16, colorCount, NULL);
  return readColor(data.begin() + 2 * colorCount, 32, colorCount, NULL);
}

std::wstring normalize(const std::wstring &in) {
  std::wstring temp;
  temp.resize(in.size());
  std::locale loc;
  std::transform(in.begin(), in.end(), temp.begin(), [&loc](const wchar_t c) {
    if (c == L'/') {
      return L'\\';
    }
    // ascii範囲外文字ならそのまま返す
    if (c > 0xFF) {
      return c;
    }
    return std::tolower(c, loc);
  });
  return temp;
}

unsigned int calcFNV1aHash(const std::wstring &in, const unsigned int init) {
  const std::string temp = Utility::wStrToStr(normalize(in));
  return std::accumulate(temp.begin(), temp.end(), init, [](const unsigned int cur, const unsigned char c) {
    return (cur ^ c) * 0x1000193;
  });
}

unsigned int calcFNV1aHash2(const std::wstring &in, const unsigned int init) {
  const std::string temp = Utility::wStrToStr(normalize(in));
  return std::accumulate(temp.begin(), temp.end(), init, [](const unsigned int cur, const char c) {
    return (cur ^ c) * 0x1000193;
  });
}

} // TH135

} // TouhouSE