PDA

View Full Version : External Lib read from QBuffer on Calback problem



patrik08
1st June 2008, 10:55
I read compressed image from libpng .. my EncoderWriteCallback write is ok and running
but the read (EncoderReadCallback) is not ok why?

is the same 1:1 QByteArray wo libpng has writteln ... why now it can not read?
the QByteArray is not from qpixmap or qimage.

on debug qbuffer is readable and having size ..


I start the callback so...


png_ptr_read = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if(png_ptr_read == NULL) {
qWarning("unable to create read struct");
return;
}
info_ptr_read = png_create_info_struct(png_ptr_read);
if(info_ptr_read == NULL) {
qWarning("unable to create info struct");
return;
}
png_set_sig_bytes(png_ptr_read, 8);
APNGImageStream myqtchunk(0,frame.stream()); /* stream() = QByteArray */
png_set_read_fn(png_ptr_read,&myqtchunk,EncoderReadCallback);



and this is reader and writer


#define PNG_USER_MEM_SUPPORTED
#define PNG_WRITE_bKGD_SUPPORTED


////base ref http://www.littlesvr.ca/apng/tutorial/x148.html
/* png lib from firefox 3 is patch to APNG format! */
#include "../moz_png/png.h"

/* device to write or read image frames */
class APNGImageStream {
public:
APNGImageStream( const int mode , QByteArray in = QByteArray() )
:dev(new QBuffer()),bytes(in)
{
dev->setBuffer(&bytes);
if (mode == 1) {
dev->open(QIODevice::WriteOnly);
} else {
dev->open(QIODevice::ReadOnly);
}
}
~APNGImageStream()
{
dev->close();
}
QBuffer *device() { return dev; }
bool isValid() { return img.loadFromData(dev->data()); }
QByteArray stream() { return dev->data(); }
QImage img;
QBuffer *dev;
QByteArray bytes;
};

// Called by libpng to flush its internal buffer to ours.
static void EncoderWriteCallback(png_structp png, png_bytep data,
png_size_t size) {
APNGImageStream *state = static_cast<APNGImageStream*>(png_get_io_ptr(png));
Q_ASSERT(state->device());
state->device()->write((char*)data,size);
}

// Called by libpng to read original QByteArray that has self created .
static void EncoderReadCallback(png_structp png, png_bytep data,
png_size_t sizer) {
APNGImageStream *state = static_cast<APNGImageStream*>(png_get_io_ptr(png));
Q_ASSERT(state->device());
qDebug() << "### size to read 1/0 " << state->stream().size() << "," << state->device()->isReadable();
state->device()->read((char*)data,sizer);
qDebug() << "### read callback length " << sizer;
}

patrik08
2nd June 2008, 11:18
i try to write on device and i leave dev->setBuffer(&bytes);
is the same, libpng can only write on device .. why not read ..

qt access the image isValid on read & write ....

i can not set file over 100 png frame movie....




public:
APNGImageStream( const int mode , QByteArray in = QByteArray() )
:dev(new QBuffer()),bytes(in)
{
if (mode == 1) {
/* pnglib write in */
dev->setBuffer(&bytes);
dev->open(QIODevice::WriteOnly);
} else {
/* qt write in && png read out */
dev->open(QIODevice::ReadWrite);
dev->write(bytes);
dev->seek(0);
}
}

patrik08
2nd June 2008, 19:43
I have resolved the big QBuffer problem
only writeBlock && readBlock and all external lib ... in this case libpng can write or read like a virtual file... && class PngEventBuffer : public QEvent the post event can paint a progress dialog by read or write.... :)

QEvent inside a CallBack function .. this is new tecnology...




class APNGwrittelStream {
public:
APNGwrittelStream(QObject *o) :d(new QBuffer()),creator(o)
{
d->open(QIODevice::ReadWrite);
start();
}
~APNGwrittelStream()
{
d->close();
}
void start() { d->seek(0); }
QBuffer *device() { return d; }
bool isValid() { return img.loadFromData(stream()); }
QByteArray stream() { return d->data(); }
QImage img;
QBuffer *d;
QObject *creator;
};


/* read and write progress */
class PngEventBuffer : public QEvent
{
//QEvent::User==1000

public:
PngEventBuffer(int status, int total )
: QEvent( QEvent::User ),s(status),t(total)
{ }
int pos() const { return s; }
int sum() const { return t; }

private:
int s;
int t;
};


// Called by libpng to flush its internal buffer to ours.
static void EncoderWriteCallback(png_structp png, png_bytep data,
png_size_t size) {
APNGwrittelStream *state = static_cast<APNGwrittelStream*>(png_get_io_ptr(png));
Q_ASSERT(state->device());
state->device()->writeBlock((char*)data,size);
///////qDebug() << "### pos ->" << state->device()->pos();
qApp->postEvent(state->creator,new PngEventBuffer(state->device()->pos(),
0));

}

// Called by libpng to read QImage on buffer .
static void EncoderReaderCallback(png_structp png, png_bytep data,
png_size_t size)
{
APNGwrittelStream *state = static_cast<APNGwrittelStream*>(png_get_io_ptr(png));
Q_ASSERT(state->device());
state->device()->readBlock((char*)data,size);
/////////qDebug() << "### pos ->" << state->device()->pos();
qApp->postEvent(state->creator,new PngEventBuffer(state->device()->pos(),
state->device()->bytesAvailable()));
}