Seite 1 von 1
geloest::Externe LibPNG callback mit QBuffer problem nur
Verfasst: 1. Juni 2008 13:08
von patrik08
Ich lese komprimierte png bilder mit der libpng.
beim schreiben EncoderWriteCallback > QBuffer geht es prima
aber das lesen read geht nicht warum was mache ich falsch?
- schreiben das geht starte ich so:
Code: Alles auswählen
APNGImageStream myqtchunk(1);
png_set_write_fn(png_ptr_write,&myqtchunk,EncoderWriteCallback, NULL);
- das lesen aus qbuffer das noch nicht geht so:
Code: Alles auswählen
APNGImageStream myqtchunk(0,frame.stream());
png_set_read_fn(png_ptr_read,&myqtchunk,EncoderReadCallback);
Und iher die structur / class vom QBuffer und die 2 lese/schreiben Callback
Code: Alles auswählen
////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;
}
Verfasst: 2. Juni 2008 12:13
von patrik08
Auch wenn ich die QByteArray hineinschreibe und das callback nur noch lesen muss geht es nicht, jedoch fuer qt ist die image immer isValid() true...
Ich begreifen nicht dass libpng hinschreiben kann aber nicht lesen ...
ich kann doch nicht in file schreiben wenn ein movie 100 frame hat...
ist doch einfach langsam....
Code: Alles auswählen
/* device to write or read image PNG movie frame/s */
class APNGImageStream {
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);
}
}
~APNGImageStream()
{
dev->close();
}
QBuffer *device() { return dev; }
bool isValid() { return img.loadFromData(dev->data()); }
QByteArray stream() { return dev->data(); }
QByteArray readstream() {
QByteArray allby = dev->readAll();
dev->seek(0); /* cursor to init .. */
return allby;
}
QImage img;
QBuffer *dev;
QByteArray bytes;
};
// 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());
state->device()->read((char*)data,sizer);
}
oder muss ich das dev->seek(0); immer auf die bit setzen die bereits gelesen worden sind?
Verfasst: 2. Juni 2008 12:23
von close1
mhh ich würde sagen wenn du in ein und die gleiche datei schreibst(und liest) musst du die Position wieder zurücksetzen(oder zum lesen nen extra filestream öffnen der readonly ist).
edit: hab deinen code nochmal durchgesehen, bist du sicher das der code beim lesen immer readonly ist? ich das trennen also das ich ja nicht in den writeonly schreibe der evtl. noch geöffnet ist..
Da (normalerweise) nach jedem filestream read(x) oder write(x) sich die Position um x ändert(hab bisher nicht mit den QFile klassen gearbeitet, könnte also falsch sein)
Verfasst: 2. Juni 2008 13:52
von patrik08
close1 hat geschrieben:
edit: hab deinen code nochmal durchgesehen, bist du sicher das der code beim lesen immer readonly ist? ich das trennen also das ich ja nicht in den writeonly schreibe der evtl. noch geöffnet ist..
..
Da (normalerweise) nach jedem filestream read(x) oder write(x) sich die Position um x ändert(hab bisher nicht mit den QFile klassen gearbeitet, könnte also falsch sein)
ch sein)
Nein kein file ... file ist separat...
ich oeffne ein/1 APNG file (alte methode FILE* file) mit 100 frame/bilder
diese 100 bilder muss ich im buffer (APNGImageStream) loop schreiben und nur das QByteArray rausnehmen das in eine structur kommt von alle einzelne frame
beim APNG file oeffnen gehe ich im buffer write only
doch nach dem editieren muss ich in read / write gehen wenn
was am bild oder in der millisekunden aendert... oder ein gif oder mng import das zu APNG geht
zuerst qt schreibt im buffer und die pnglib liest es um die loop frame wieder zusammensetzen...
Code: Alles auswählen
typedef struct {
QRect Maxframe; die erste frame oder die groeste rect
int zliblevel;
QByteArray dimg; original png stream
QPoint Position; x,y im Maxframe
uint play; millisekunde play
QColor BackgroundColor;
QStringList option; gamma version
int pos; frame nr
bool foundcolor; je nach version png lib
} AFRAMES;
IMO zur zeit gibt es nur 2 APNG editor
1 -
https://addons.mozilla.org/en-US/firefox/addon/5519
/* da kann man keinen hindergrund farbe setzen und andere optionen geht nicht */
2-
http://www.gamani.com/apng.htm 30 dollar
Verfasst: 2. Juni 2008 14:49
von close1
patrik08 hat geschrieben:...
doch nach dem editieren muss ich in read / write gehen wenn
was am bild oder in der millisekunden aendert... oder ein gif oder mng import das zu APNG geht
...
wenn der buffer ein stream ist(wovon ich ausgehe) und du read(x) machst verändert sich die position um x, das gleiche bei write.
darauf wollt ich hinaus :S das ist bei streams der normalfall(egal ob file oder buffer)
ein bsp:
Code: Alles auswählen
char a;
int x = 10;
//a = "", buffer->position = null
a = buffer->read(x);
//a = buffer[0 bis 9], buffer->position = 10
oder rede ich gerade an deiner Vorstellung vorbei?
Verfasst: 2. Juni 2008 15:41
von patrik08
close1 hat geschrieben:
wenn der buffer ein stream ist(wovon ich ausgehe) und du read(x)
ja beides read & write ist ein stream mit QBuffer
http://doc.trolltech.com/4.3/qbuffer.html
machst verändert sich die position um x, das gleiche bei write.
darauf wollt ich hinaus :S das ist bei streams der normalfall(egal ob file oder buffer)
ein bsp:
Code: Alles auswählen
char a;
int x = 10;
//a = "", buffer->position = null
a = buffer->read(x);
//a = buffer[0 bis 9], buffer->position = 10
oder rede ich gerade an deiner Vorstellung vorbei?
nein ist shon richtig QBuffer ist von mir aus einfacher ...
write geht ja prima in meinem Callback nur das write geht noch nicht
write das geht is einfach so.... und der zeiger kann QBuffer selber verwalten ....
write geht mit qt und pnglib aber das lesen muss ich der pnglib noch beibringen im QBuffer da mir die pnglib die werte geben muss von y,x position und die sekunden um das bild zu zeigen .. da jede frame andere sekunden einstellung hat ... is eben nicht wie im gif oder mng ... das macht apng interessant ... sowie die hindergrund- farbe fuer keinere bilder als das erste frame ...
darum is APNG 50% leichter als GIF und hat dazu noch mehr farbe ....
vergleich:
http://www.miwa-immobilien-allgaeu.de/p ... if2swf.htm
das eben die primitive callback methode die mir 100% funktioniert..
Code: Alles auswählen
// 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);
}
und dass read?
Verfasst: 2. Juni 2008 20:53
von patrik08
Ich habe es selber geloest...
im qbuffer ist in diesem fall besser writeBlock als nur write
und das ganze sended noch ein event aus dem callback um das progress zu zeigen wo gerade das lesen oder schreiben ist...
Ein postevent von einem callback aus das ist neue musik....
Code: Alles auswählen
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()));
}