将 QPixmap 列表保存到 .ico 文件
Posted
技术标签:
【中文标题】将 QPixmap 列表保存到 .ico 文件【英文标题】:Save a list of QPixmaps to .ico file 【发布时间】:2019-01-21 10:54:11 【问题描述】:我有兴趣从QPixmap
图像列表(尺寸为 16x16、32x32、48x48...)中创建单个 .ico 文件(具有透明度)。我在Qt的文档中没有看到任何相关的方法:QPixmap
、QImage
、QIcon
(用于存储UI状态的图像,与文件格式无关)...
Qt 有这样的功能吗?我怎样才能保存这样的文件?可能与 Windows API 混合使用?
PS:一个低级的解决方案是直接写.ico file,但如果可能的话,我更感兴趣的是不要重新发明***。
【问题讨论】:
您可以将QPixmap
转换为 HICON
句柄 (doc.qt.io/qt-5/qtwin.html#toHICON) 并将其保存到 ICO 文件 (***.com/questions/2289894/…)。
谢谢@vahancho,但我怎样才能结合 HICON?此方法将为每个 QPixmap 提供一个 HICON(因此每个图像一个文件),而不是单个 .ico 文件(我正在更新要清除的问题)
据我所知,Qt 中没有对此类转换的内置支持。这里列出了支持的图像格式(用于写作):doc.qt.io/qt-5/qimagewriter.html#supportedImageFormats.
再次感谢@vahancho!基于此,我实现了一个作家并将其作为答案发布
【参考方案1】:
Qt 中似乎没有内置的支持来编写 ICO 文件,所以我在这里发布一个代码 sn-p 来从像素图列表中生成一个。希望它对其他人有用。
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 中也提供代码。
【讨论】:
以上是关于将 QPixmap 列表保存到 .ico 文件的主要内容,如果未能解决你的问题,请参考以下文章
delphi提取文件中的ICO图标的问题,保存到本地全部都是32* 32的,如何判断图标尺寸?
如何将 HTML5 <canvas> 保存为 ICO 图像(图标文件)或 .cur 文件(静态鼠标光标)而不是 JavaScript 中的 PNG?