PDA

View Full Version : Sequence of RGBA channels in DDS



maxoutlaw
11th September 2012, 16:27
Hello.
There is a method to change a sequence of RGBA channels directly in DDS files of textures?
The problem is that (if I am not mistaken) means of Qt allow to read only DDS files, but not to change them.
I couldn't find the solution of this problem. ((
p.s. Unfortunately with DDS I have no experience.
Thanks in advance.

wysota
12th September 2012, 09:28
You can use pure OpenGL calls to load the texture.

maxoutlaw
12th September 2012, 18:43
You can use pure OpenGL calls to load the texture.
You can show me a simple example of opening and saving of textures please?
I have no experience in this area, and I don't know, with what I need to begin.

wysota
12th September 2012, 22:56
I think it will be easier if you ask at some OpenGL forum :)

maxoutlaw
14th September 2012, 20:38
I found a method:
1) texture loading by means of QtOpenGL;
2) receiving QImage from QGLPixelBuffer;
3) change of an order of channels;
4) image writing in the file means of API for Nvidia Texture Tools 2.

But I had a problem on 1 step - I am not sure that correctly I load a texture because the received image contains only black color aka Malevich's Black Square.

ddstexture.h

#ifndef DDSTEXTURE_H
#define DDSTEXTURE_H

#include <QtOpenGL>
#include <QGLWidget>
#include <QImage>
#include <QDebug>
#include <nvtt/include/nvtt.h>

class DDSTexture : public QGLWidget
{
Q_OBJECT

private:
struct DDS_PIXELFORMAT{
unsigned long Size;
unsigned long Flags;
unsigned long FourCC;
unsigned long RGBBitCount;
unsigned long RBitMask;
unsigned long GBitMask;
unsigned long BBitMask;
unsigned long ABitMask;
};

typedef struct{
unsigned long Size;
unsigned long Flags;
unsigned long Height;
unsigned long Width;
unsigned long PitchOrLinearSize;
unsigned long Depth;
unsigned long MipMapCount;
unsigned long Reserved1[11];
DDS_PIXELFORMAT ddspf;
unsigned long Caps;
unsigned long Caps2;
unsigned long Caps3;
unsigned long Caps4;
unsigned long Reserved2;
}DDS_HEADER;

QSize p_getDDSSize(const QString &path);
QImage p_getImageFromDDS(const QString &path);

QImage image;
QGLPixelBuffer *pbuffer;

public:
explicit DDSTexture(QWidget *parent = 0);
~DDSTexture();

signals:

public slots:

};

#endif // DDSTEXTURE_H

ddstexture.cpp

#include "ddstexture.h"

QSize DDSTexture::p_getDDSSize(const QString &path)
{
DDS_HEADER DDSHeader = {0};
DDSHeader.Size = sizeof(DDS_HEADER);
QFile ddsFile(path);
if(ddsFile.open(QIODevice::ReadOnly)){
ddsFile.seek(4);
ddsFile.read((char*)&DDSHeader, sizeof(DDS_HEADER));
}
ddsFile.close();
qDebug() << "height = " << DDSHeader.Height;
qDebug() << "width = " << DDSHeader.Width;
qDebug() << "size = " << DDSHeader.Size;

return QSize(DDSHeader.Width, DDSHeader.Height);
}

QImage DDSTexture::p_getImageFromDDS(const QString &path)
{
pbuffer = new QGLPixelBuffer(p_getDDSSize(path), format(), this);
makeCurrent();
pbuffer->bindTexture(path);
QImage image = pbuffer->toImage();
image.save("D:\\Programming\\MyProjects\\ConverterChannelsDDS\ \test.png", "PNG");
return pbuffer->toImage();
}



DDSTexture::DDSTexture(QWidget *parent):QGLWidget(QGLFormat(QGL::SampleBuffers), parent)
{
this->p_getImageFromDDS(QString("D:\\Programming\\MyProjects\\ConverterChannelsDDS\ \wind_01_n.dds"));
}

DDSTexture::~DDSTexture()
{
delete pbuffer;
}

What do I do not correctly?
p.s. I need to process channels only, without an output of the loaded texture somewhere.

wysota
14th September 2012, 20:58
You don't need QGLWidget then. QGLContext should be enough.

maxoutlaw
16th September 2012, 19:36
QGLContext should be enough.
I tried to use QGLContext, but it isn't created - doesn't pass check on a validity:

DDSChannels::DDSChannels(QObject *parent):QObject(parent)
{
pixmap = new QPixmap;
glContext = new QGLContext(QGLFormat::defaultFormat(), pixmap);
glContext->makeCurrent();
qDebug() << "GLContext is valid: " << glContext->isValid();
qDebug() << "texture ID is: " << glContext->bindTexture(QString("D:\\Programming\\MyProjects\\ConverterChannelsDDS\ \wind_01_n.dds"));
}

GLContext is valid: false

wysota
16th September 2012, 20:49
You didn't call QGLContext::create().

maxoutlaw
16th September 2012, 22:38
You didn't call QGLContext::create().
I corrected a mistake,

DDSChannels::DDSChannels(QObject *parent):QObject(parent)
{
pixmap = new QPixmap(512, 512);
glContext = new QGLContext(QGLFormat::defaultFormat(), pixmap);
glContext->create();
glContext->makeCurrent();
if(glContext->isValid()){
id = glContext->bindTexture(QString("D:\\Programming\\MyProjects\\ConverterChannelsDDS\ \wind_01_n.dds"));
qDebug() << "texture id: " << id;
qDebug() << "pixmap width: " << pixmap->width();
qDebug() << "pixmap height: " << pixmap->height();
qDebug() << "pixmap has alpha channel: " << pixmap->hasAlphaChannel();
pixmap->save("D:\\Programming\\MyProjects\\ConverterChannelsDDS\ \test.png", "PNG");
}
}

but when loading a texture the message is deduced:

QGLContext::bindTexture(): The GL implementation does not support texture compression extensions.
texture id: 0
pixmap width: 512
pixmap height: 512
pixmap has alpha channel: false
The ID of the loaded texture is zero, and the container QPixmap is empty. The file "test.png" contains only black color.