Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Bild mit JEDI ZLib komprimieren (https://www.delphipraxis.net/171650-bild-mit-jedi-zlib-komprimieren.html)

ByTheTime 16. Nov 2012 21:48

Bild mit JEDI ZLib komprimieren
 
Hallo,
ich würde gerne ein Bild komprimieren, da ich esüber INDY TIdTCPClient als MemoryStream verschicke. Mir fallen 2 Möglichkeiten ein:

1. Mit den CompressionIntercepts der Indy's, leider kenne ich mich damit nicht aus.
2. Oder der ZLib Komponente, der JEDI's.

Als alternative wäre noch die Versionen, mit ZLib, etc. die hier im Forum zu finden sind. Aer was würdet ihr mir empfehlen. Das mit den Indy-Intercepts hört sich vielversprechend an, aber mir geht es im weitetsen Sinn um die Geschwindigkeit und die beste verkleinerung. Dehalb frag ich euch, was am geeignetsten wäre. :)

Danke,
Lukas

Bummi 16. Nov 2012 21:54

AW: Bild mit JEDI ZLib komprimieren
 
ZLib sollte bei XE2 dabei sein, verwendung von TZCompressionStream gibt einen 3 Zeiler.
Die Frage ist was für Bilder Du verschicken möchtest, wenn es beispielsweise JPG's sind bringt das Zippen eh nichts mehr.

ByTheTime 17. Nov 2012 09:39

AW: Bild mit JEDI ZLib komprimieren
 
Es sind BMP's und die sind natürlich etwas füllig :D

himitsu 17. Nov 2012 12:11

AW: Bild mit JEDI ZLib komprimieren
 
PNG ist bei XE2 auch mit dabei.
- verlustlos
und
- Komprimierung ist gleich eingebaut

ByTheTime 17. Nov 2012 16:38

AW: Bild mit JEDI ZLib komprimieren
 
Ja, aber ich bastel an einem Chat via. WebCam. Ich kriege, kommt drauf an wie es gerade "rutscht", ca. 1 Bild pro Sekunde. Kleinere Intervalle habe ich nocht nicht ausprobiert. Ich kreige das Bild als BMP von der Kamera. Es ist ca. 1MB groß, bei einer Auflösung von 640x480. Soll ich es jetzt eurer Meinung nach in PNG komprimieren oder mit ZLib oder doch JPEG? Mir geht es in erster Linie um die Qualität der Kompression und die Geschwindigkeit dieser. Ich möchte erstmal die Bildrate optimieren, bevor ich auf die Qualität des Bildes eingehe.

jfheins 17. Nov 2012 16:42

AW: Bild mit JEDI ZLib komprimieren
 
Das klingt als bräuchtest du einen Video-Codec, keinen Bild-codec.
Der Unterschied ist gewaltig, weil erstere viel besser darauf optimiert sind, aufeinanderfolgende Frames stark zu komprimieren.
Das Problem ist, dass gerade die guten Codecs nicht "einfach so" zu haben sind. Du könntest mal gucken ob es VP8 für Delphi gibt.

ByTheTime 17. Nov 2012 16:50

AW: Bild mit JEDI ZLib komprimieren
 
Also ich habe mich hier bedient und hier hatte ich mal einen Thread dazu. Dreht sich alles um den DirectX Port hier aus dem Forum. Ich schicke Befehle mit den Sockets, diese starten dann die Cam, bzw. stoppen sie. Also ich denke, dann mangelt es doch eher an der Übertragungsgeschwindigkeit, als am Codec, oder reden wir gearde anneinader vorbei.

ByTheTime 17. Nov 2012 16:54

AW: Bild mit JEDI ZLib komprimieren
 
Habe hier was gefunden. Keine Ahnung warum das von Google ist, aber ich kann mal reinschauen. Hast recht, die guten Codecs sind teuer! Hier einer für Delphi. Free To Try, aber kostet voll 700$ :D

sx2008 17. Nov 2012 19:50

AW: Bild mit JEDI ZLib komprimieren
 
Zitat:

Zitat von ByTheTime (Beitrag 1191710)
Ich kreige das Bild als BMP von der Kamera

Nun dann ist ja schon mal geklärt, welche Art vom Komprimierung angewendet werden sollte.
Es verlustlose und verlustbehaftete Komprimierung.
Bei Bildern von einer Webcam greift man ganz klar zur verlustbehafteten Komprimierung weil man damit wesentlich höhere Komprimierungsgrade erreichen kann.
Das heisst in der Praxis JPEG.

Die JEDI ZLib ist nicht das richtige Werkzeug zum Komprimieren von Bildern einer Webcam.
Der nächste Schritt wäre also das Bitmap in ein TJpegImage zu konvertieren (property CompressionQuality auf 30 einstllen) und zu schauen wie gross das JPeg wird.

himitsu 17. Nov 2012 21:09

AW: Bild mit JEDI ZLib komprimieren
 
Man kann auch, wenn man verlustfreie Kompessionsverfahren nutzt, nur Differenzbilder verschicken.

Vollbild machen
komprimieren (PNG, auch Bitmap+ZLib oder so)
verschicken

Bild machen
Differenzbild zum Vorherrigen berechnen
komprimieren
verschicken

Bild machen
Differenzbild zum Vorherrigen berechnen
komprimieren
verschicken

...

alle paar Bilder ein Vollbild schicken, um Übertragungs-/Rechenfehler auszugleichen



So ähnlich machet es auch MPEG, nur daß die es noch mit einer Art JPeg-Komprimierung verbinden (alle paar Frames dann ein Vollbild, weil ja bei JPeg rechenfehler durch die Komprimierung entstehen)

Wenn man da noch die Farbtiefe verringert, kleines Rauschen aus dem Quellbild entfernt und eventuell auch noch andere kleiner Differenzen einfach weglässt, dann kann man die Daten im Differenzbild verringern und somit die Komprimierung verbessern



Im Grundprinzip machen die Videokodecs auch nichts Anderes.

Das "Weglassen" kann man auch noch, wie bei MP3 geziehlt behandeln.
- nicht zufällig alles verkleinern, sondern geziehld sowas weglassen, was das menschliche Auge vermutlich eh nicht sieht/mitbekommt

Und abhängig von der möglichen Datenrate kann man dann auch noch die Bildqualität verringern.
- kommen zu wenige Bilder die Sekunde rüber, wird die Qualli schlechter, bis eine Mindestbildrate erreicht wird und bei "zu vielen" Bildern wird sie wieder besser.

ByTheTime 17. Nov 2012 22:09

AW: Bild mit JEDI ZLib komprimieren
 
@himitsu: Ja, davon habe ich schonmal gehört. Die Frage ist, wie lange es dauert das auszuführen. Ich bastel gerade mit Jpg's. Also wenn ich Quality 30 setzte, das hämmer ich ein 1,1MB BMP runter auf ein 14KB JPG! Finde ich ziemlich gut, den ich sehe keinen großen Unterschied. Und bei meiner langsamen Leitung (6000 Down, 600 UP!; Durch Ausbau im Dorf bald 50.000 :D), wäre das dann optimal :)

Aber es hängt an einer Stelle. Habe es bis zum Empfangen umgesetzt, bekomme aber den JPEG Fehler #42:
Delphi-Quellcode:
procedure TfrmCam.CamServerExecute(AContext: TIdContext);
var
  FStream: TMemoryStream;
  ReceivePic: TJPEGImage;
begin
  FStream := TMemoryStream.Create;
  ReceivePic := TJPEGImage.Create;

  try
    AContext.Connection.Socket.ReadStream(FStream);
  finally
    try
      FStream.Position := 0;
      ReceivePic.LoadFromStream(FStream);
      RVideo.Picture.Assign(ReceivePic);
    finally
      FStream.Free;
      ReceivePic.Free;
    end;
  end;
end;
Okay, meinen ersten Fehler habe ich gelöst, gab ein Problem bei der größe des VideoFensters auf der ClientSeite (oben ist der Server). Doch nun gibt es beim stoppen einen fehler, ich schau nochmal und poste dann mal meinen Arbeitstand.

Bummi 17. Nov 2012 23:49

AW: Bild mit JEDI ZLib komprimieren
 
Zacherl hatte zu einem verwandten Thema eine Thread
http://www.delphipraxis.net/171035-s...-netzwerk.html

sx2008 18. Nov 2012 00:11

AW: Bild mit JEDI ZLib komprimieren
 
Zitat:

Zitat von ByTheTime (Beitrag 1191755)
Habe es bis zum Empfangen umgesetzt, bekomme aber den JPEG Fehler #42:

Du darfst nicht einfach "blind" aus dem TCP/IP-Stream lesen, sondern für jedes Bild muss die Grösse beim Empfänger bekannt sein.
Wenn z.B. ein bestimmtes Jpeg-Bild 16548 Bytes hat, dann müssen auch genau die Anzahl von Bytes in den temporären Memorystream geschrieben werden, bevor man ein JPegImage rekonstruiert.
Der Sender muss dazu zuerst die Anzahl der Bytes (L) gefolgt von den Nutzdaten (n) abschicken.
Auf der "Leitung" sieht das so aus.
Code:
LLLLnnnnnnnnnnnnnnnnnnnnnnnn...nLLLLnnnnnnnnnnnnnnnnnnnn...n
Der Empfänger muss also immer 4 Bytes Längenangabe lesen und dann so lange Bytes lesen und sammeln bis die Länge erreicht wird.

Die Senderseite ist sehr leicht zu programmieren; die Empfangsseite ist schon deutlich kniffliger.

himitsu 18. Nov 2012 02:38

AW: Bild mit JEDI ZLib komprimieren
 
Ob es sich beim JPeg lohnt noch einen Binärdiff anzufertigen :gruebel:
Ich glaub bei Assarbad(Olly) hatte ich mal auf der Webseite ein Diff-Programm/Code gesehn, welcher von Binärdateien ein Differenzabbild erzeugt.
- Das war eine Datei, wo "nur" drinsteht, was man alles in einer Ursprungsdatei ändern muß, damit eine Zieldatei entsteht.
Ich glaub das ging auch recht flott, aber ob das hier, beim JPeg, was "Positives" (Datenreduzierung) bewirkt, weiß ich nicht.

Ein Differenzbild von einem BitMap ist sehr flott erstellt, aber nach der JPeg-Komprimierung und Dekomprimierung dürften sich solche "Fehler" enschleichen, bei der starken Komprimierung, daß man das nun verfälschte Differenzbitmap vermutlich nicht mehr so gut verrechnen kann.


Delphi-Quellcode:
Und bei meiner langsamen Leitung (6000 Down, 600 UP!; Durch Ausbau im Dorf bald 50.000 ), wäre das dann optimal
Merkel hat versprochen, daß in 2 Jahren (also bis Ende 2011) alle Bürger mindestens 10 MBit daheim haben werden ... egal wo sie wohnen.
An deiner Stelle würde ich die Alte mal darauf ansprechen.

Aber sei froh, daß du kein LTE von der Telekom hast ... 100 MBit/s für nur 10€ im Monat und nach 48sec hat man das Traffic-Limit erreicht :lol:

ByTheTime 18. Nov 2012 08:46

AW: Bild mit JEDI ZLib komprimieren
 
@Bummi: Ja ganz am Ende, steht eine fertige Codec Unit, schau ich mir auf jeden Fall an :)
@sx2008: Ich befasse mich erstmal mit der Unit, in Zacherl's Thread. Aber danke für den Hinweiß :)
@himitsu: Also ich schau mir erstmla die Unit von oben an. Aber ich bin mit meines ersten Ergebniss erstmal zufrieden, den 14Kb sind ja fast nichts :) Ich denke, vllt. würde die berechnung des Differenzbildes sogar etwas mehr Zeit in anspruch nehmen, als das senden:?: Und über die Rechenleistung habe ich mir auch keine Gedanken gemacht. Aber es wäre schön, < 20000K zu bleiben. Zum Internet: Ja, schön wärs :D Wir haben zwar ne LTE Antenne direkt neben dem Haus, aber ich warte jetzt lieber noch 4-5 Wochen, bis ich die 50.000er nutzen kann. Zum Glück steht mein Kaff besser dar als die Nachbardörfer :) Die freuen sich über 6000 bei ihrer 1000er Leitung da :D

ByTheTime 18. Nov 2012 09:00

AW: Bild mit JEDI ZLib komprimieren
 
Eine Frage hab ich aber nochmal, ich habe mir mal die Unit in dem Thread von Zacherl angeschaut:

Delphi-Quellcode:
procedure WriteDiffPkg(last, next: TBitmap; zipPkg: TMemoryStream; var startLine: Byte; lineStep: Byte);
procedure ReadDiffPkg(last: TBitmap; zipPkg: TStream);
Ich verstehe leider die beiden prozeduren nicht ganz.
1. Prozedure:
  • last = ?
  • next = ?
  • // Kommt da eine Bitmap rein, oder wird sie dann da ausgegeben?!
  • zipPkg = Der verpackte Stream
  • startLine = Die Zeile, in der er anfangen soll sie umzuwandeln?
  • lineStep = Schickt jede "n"-te Zeile

2. Prozedure:
  • last = Das ankommende, entpackte Bild
  • zipPkg = Der ankommende Stream // Muss das nicht auhc TMemoryStream sein, ich dachte TStream, gibt es garnicht mehr

So habe ich das jetzt verstanden. Schade, dass das angehängte Beispielprogramm nicht Quellenoffen ist, dann würde sich mir vllt. mehr erschließen :/

ByTheTime 18. Nov 2012 17:50

AW: Bild mit JEDI ZLib komprimieren
 
@sx2008: Eine Sache ist mir aber noch ausgefallen: Der JPEG-Fehler #42 kommt nicht bei dem lesen aus dem Stream, sondern wenn ich dem TImage wo das Bild reinkommt das Bild eines anderen TImage zuweiße (damit dan wieder ein WebCam-Logo zu sehen ist :) ). Allerdings ist das ein PNG. :?: Mal schauen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:13 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz