Сохраните список QPixmaps в файл .ico - PullRequest
0 голосов
/ 21 января 2019

Я заинтересован в создании одного .ico-файла (с прозрачностью) из списка QPixmap изображений (с размерами 16x16, 32x32, 48x48 ...). Я не видел ни одного связанного метода в документации Qt: QPixmap, QImage, QIcon (который предназначен для хранения изображений для состояний пользовательского интерфейса, не связанных с форматом файла) ...

Есть ли в Qt такая функциональность? Как я могу сохранить такой файл? Может быть, микширование с Windows API?

PS: Низкоуровневым решением было бы написать файл .ico напрямую, но меня больше интересует не изобретать велосипед, если это возможно.

1 Ответ

0 голосов
/ 21 января 2019

Кажется, что в Qt нет встроенной поддержки для записи файлов ICO, поэтому здесь я публикую фрагмент кода, чтобы сгенерировать его из списка растровых изображений. Надеюсь, что это может быть полезно для кого-то еще.

template<typename T>
void write(QFile& f, const T t)
{
  f.write((const char*)&t, sizeof(t));
}

bool savePixmapsToICO(const QList<QPixmap>& pixmaps, const QString& path)
{
  static_assert(sizeof(short) == 2, "short int is not 2 bytes");
  static_assert(sizeof(int) == 4, "int is not 4 bytes");

  QFile f(path);
  if (!f.open(QFile::OpenModeFlag::WriteOnly)) return false;

  // Header
  write<short>(f, 0);
  write<short>(f, 1);
  write<short>(f, pixmaps.count());

  // Compute size of individual images
  QList<int> images_size;
  for (int ii = 0; ii < pixmaps.count(); ++ii) {
    QTemporaryFile temp;
    temp.setAutoRemove(true);
    if (!temp.open()) return false;

    const auto& pixmap = pixmaps[ii];
    pixmap.save(&temp, "PNG");

    temp.close();

    images_size.push_back(QFileInfo(temp).size());
  }

  // Images directory
  constexpr unsigned int entry_size = sizeof(char) + sizeof(char) + sizeof(char) + sizeof(char) + sizeof(short) + sizeof(short) + sizeof(unsigned int) + sizeof(unsigned int);
  static_assert(entry_size == 16, "wrong entry size");

  unsigned int offset = 3 * sizeof(short) + pixmaps.count() * entry_size;
  for (int ii = 0; ii < pixmaps.count(); ++ii) {
    const auto& pixmap = pixmaps[ii];
    if (pixmap.width() > 256 || pixmap.height() > 256) continue;

    write<char>(f, pixmap.width() == 256 ? 0 : pixmap.width());
    write<char>(f, pixmap.height() == 256 ? 0 : pixmap.height());
    write<char>(f, 0); // palette size
    write<char>(f, 0); // reserved
    write<short>(f, 1); // color planes
    write<short>(f, pixmap.depth()); // bits-per-pixel
    write<unsigned int>(f, images_size[ii]); // size of image in bytes
    write<unsigned int>(f, offset); // offset
    offset += images_size[ii];
  }

  for (int ii = 0; ii < pixmaps.count(); ++ii) {
    const auto& pixmap = pixmaps[ii];
    if (pixmap.width() > 256 || pixmap.height() > 256) continue;
    pixmap.save(&f, "PNG");
  }

  return true;
}

Код также доступен в GitHub .

...