osg::Image 转 QImage
osg::ref_ptr<osg::Image> image = osgDB::readImageFile(......);
/*******************************************************************
* 根据图像类型,如是否有透明度等,选择合适的QImage::Format
* 如带有透明通道,一般选Format_RGBA8888,不带透明通道则选择Format_RGB888,
* 其他情形需要自行判断
*********************************************************************/
QImage img((const uchar*)image ->data(), image->s(), image->t(),
image->getRowSizeInBytes(),QImage::Format_RGB888);
// 2023.05.11 更新
/*******************************************************************
* 通过以上方法,构造的QImage,在有些场景下会出现垂直方向颠倒的情况
* 这种情况下,通过以下代码实现图像的垂直翻转,具体函数说明参见Qt Assistant
* 中关于QImage::mirrored的部分
* 第一个参数false,表示水平方向不翻转
* 第二个参数true,表示垂直方向翻转
********************************************************************/
img = img.mirrored(false,true);
QImage 转 osg::Image
// 以下格式转换函数代码从库QGLWidget.cpp获取
#include <QImage>
const int GL_BGRA = 0x80E1;
const int GL_RGBA = 0x1908;
static inline QRgb convertToGLPixelFormat(QRgb src_pixel, GLenum texture_format)
{
if (texture_format == GL_BGRA) {
if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
return ((src_pixel << 24) & 0xff000000)
| ((src_pixel >> 24) & 0x000000ff)
| ((src_pixel << 8) & 0x00ff0000)
| ((src_pixel >> 8) & 0x0000ff00);
}
else {
return src_pixel;
}
}
else { // GL_RGBA
if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
return (src_pixel << 8) | ((src_pixel >> 24) & 0xff);
}
else {
return ((src_pixel << 16) & 0xff0000)
| ((src_pixel >> 16) & 0xff)
| (src_pixel & 0xff00ff00);
}
}
}
static void convertQImageToGLFormat(QImage &dst, const QImage &img, GLenum texture_format)
{
if (dst.size() != img.size()) {
int target_width = dst.width();
int target_height = dst.height();
qreal sx = target_width / qreal(img.width());
qreal sy = target_height / qreal(img.height());
quint32 *dest = (quint32 *)dst.scanLine(0); // NB! avoid detach here
const uchar *srcPixels = img.constScanLine(img.height() - 1);
int sbpl = img.bytesPerLine();
int dbpl = dst.bytesPerLine();
int ix = int(0x00010000 / sx);
int iy = int(0x00010000 / sy);
quint32 basex = int(0.5 * ix);
quint32 srcy = int(0.5 * iy);
// scale, swizzle and mirror in one loop
while (target_height--) {
const uint *src = (const quint32 *)(srcPixels - (srcy >> 16) * sbpl);
int srcx = basex;
for (int x = 0; x < target_width; ++x) {
dest[x] = convertToGLPixelFormat(src[srcx >> 16], texture_format);
srcx += ix;
}
dest = (quint32 *)(((uchar *)dest) + dbpl);
srcy += iy;
}
}
else {
const int width = img.width();
const int height = img.height();
const uint *p = (const uint*)img.scanLine(img.height() - 1);
uint *q = (uint*)dst.scanLine(0);
if (texture_format == GL_BGRA) {
if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
// mirror + swizzle
for (int i = 0; i < height; ++i) {
const uint *end = p + width;
while (p < end) {
*q = ((*p << 24) & 0xff000000)
| ((*p >> 24) & 0x000000ff)
| ((*p << 8) & 0x00ff0000)
| ((*p >> 8) & 0x0000ff00);
p++;
q++;
}
p -= 2 * width;
}
}
else {
const uint bytesPerLine = img.bytesPerLine();
for (int i = 0; i < height; ++i) {
memcpy(q, p, bytesPerLine);
q += width;
p -= width;
}
}
}
else {
if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
for (int i = 0; i < height; ++i) {
const uint *end = p + width;
while (p < end) {
*q = (*p << 8) | ((*p >> 24) & 0xff);
p++;
q++;
}
p -= 2 * width;
}
}
else {
for (int i = 0; i < height; ++i) {
const uint *end = p + width;
while (p < end) {
*q = ((*p << 16) & 0xff0000) | ((*p >> 16) & 0xff) | (*p & 0xff00ff00);
p++;
q++;
}
p -= 2 * width;
}
}
}
}
}
static QImage convertToGLFormat(const QImage& img)
{
QImage res(img.size(), QImage::Format_ARGB32);
convertQImageToGLFormat(res, img.convertToFormat(QImage::Format_ARGB32), GL_RGBA);
return res;
}
// 下面是调用转换函数实现格式转换的示例代码
// 将QImage转为osg::Image
QImage image(.....);
auto osgimage = new osg::Image;
osgimage->setImage(
image.width(), image.height(), 1, 4, GL_RGBA, GL_UNSIGNED_BYTE, image.bits()
, osg::Image::NO_DELETE, 1);