osg::Image和QImage互相转换

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);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值