geloest::Externe LibPNG callback mit QBuffer problem nur

Alles rund um die Programmierung mit Qt
Antworten
patrik08
Beiträge: 746
Registriert: 27. Februar 2006 10:48
Wohnort: DE Freiburg

geloest::Externe LibPNG callback mit QBuffer problem nur

Beitrag 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; 
}
Zuletzt geändert von patrik08 am 2. Juni 2008 20:53, insgesamt 1-mal geändert.
.........................
speack português italiano deutsch english castellà qt
patrik08
Beiträge: 746
Registriert: 27. Februar 2006 10:48
Wohnort: DE Freiburg

Beitrag 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?
.........................
speack português italiano deutsch english castellà qt
close1
Beiträge: 39
Registriert: 9. April 2008 14:28
Kontaktdaten:

Beitrag 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)
MfG

close1
patrik08
Beiträge: 746
Registriert: 27. Februar 2006 10:48
Wohnort: DE Freiburg

Beitrag 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
.........................
speack português italiano deutsch english castellà qt
close1
Beiträge: 39
Registriert: 9. April 2008 14:28
Kontaktdaten:

Beitrag 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?
MfG

close1
patrik08
Beiträge: 746
Registriert: 27. Februar 2006 10:48
Wohnort: DE Freiburg

Beitrag 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?
.........................
speack português italiano deutsch english castellà qt
patrik08
Beiträge: 746
Registriert: 27. Februar 2006 10:48
Wohnort: DE Freiburg

Beitrag 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()));
}

.........................
speack português italiano deutsch english castellà qt
Antworten