AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language GetJPGSize Funktion (wollen wir sie verbessern?)

GetJPGSize Funktion (wollen wir sie verbessern?)

Ein Thema von MicMic · begonnen am 7. Feb 2020 · letzter Beitrag vom 19. Feb 2020
Antwort Antwort
Seite 3 von 3     123
Benutzerbild von Luckie
Luckie
(Moderator)

Registriert seit: 29. Mai 2002
37.586 Beiträge
 
Delphi 2006 Professional
 
#21

AW: GetJPGSize Funktion (wollen wir sie verbessern?)

  Alt 14. Feb 2020, 14:03
Verkürzt vielleicht, aber nicht vereinfacht. Du hast eine 5 Ebenen tiefe Verschachtelung.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
dummzeuch

Registriert seit: 11. Aug 2012
Ort: Essen
582 Beiträge
 
Delphi 2007 Professional
 
#22

AW: GetJPGSize Funktion (wollen wir sie verbessern?)

  Alt 14. Feb 2020, 14:03
Hmm..

Das Problem ist leider, das der Header zwischen nur wenigen Bytes bis hin zu KB (mit XML-EXIF Daten) aufgeblasen werden kann.
Meist stehen diese dann noch am Anfang und die $Cx kommen zum Schluss des Headers....

Ich weiß auch nicht zu 100% wie der FileStream dies intern händelt..
Puffert dieser, oder liest gleich Blockweise ?
Nein, er puffert überhaupt nicht, er liest die Blöcke so, wie die Read-Aufrufe es vorgeben. Nur der Windows-Cache sitzt dann noch dazwischen, und der bringt beim ersten Lesen nicht viel.

Ich habe mir eine Stream-Cache Klasse geschrieben, die das für mich übernimmt. Allerdings würde ich die in solch einer Funktion nicht verwenden, denn das würde wieder eine Abhängigkeit schaffen, die man da nicht unbedingt haben will.

(Andererseits: Wenn ich eine Funktion in meiner dzlib habe, die davon profitieren würde, habe ich kein Problem damit den Stream-Cache zu verwenden, schließlich ist er ja selbst Teil der Bibliothek.)

Falls sich jemand den Code ansehen will: Die verlinkte Seite verweist noch auf Sourceforge, dzlib ist aber inzwischen auf OSDN.
Thomas Mueller

Geändert von dummzeuch (14. Feb 2020 um 14:06 Uhr)
  Mit Zitat antworten Zitat
HolgerX

Registriert seit: 10. Apr 2006
Ort: Leverkusen
834 Beiträge
 
Delphi 6 Professional
 
#23

AW: GetJPGSize Funktion (wollen wir sie verbessern?)

  Alt 14. Feb 2020, 14:09
Hmm..

Ist Dir eigentlich bewusst, wie sich ein Header einer JPG aufbaut?

Am Anfang (2 Bytes) das SOI (FFD8)
Dann gefolgt von mehreren Segmenten (beliebige Anzahl, einige Typen jedoch nur jeweils einmal).
Zum Abschlus (2 Bytes) das SOS (FFDA) und somit das Ende des Headers...

Danach kommen die eigentlichen Bilddaten...


Jedes Segment besteht aus einem Identifer (2 Bytes), das erste Byte ist FF das 2. Byte gibt den Typ des Segmentes an.
Nach dem Identifer kommt immer die Länge der Daten des Segmentes (2 Bytes).
Im Anschluss die Daten des Segmentes mit der angegebenen Länge (da die 2 Bytes der Länge auch in der Länge eingerechtet sind müssen dieses abgezogen werden).

Es gibt die Segmente welche die Kodierung definieren, Kommentare und weitere, wie auch das EXIF-Segment.

Ohne die Längenangabe des aktuellen Segments kannst Du den Anfang des nächsten Segments nicht finden..

Und eben in den Segmenten (SOFx) für die Definition der Kodierung ($C0, $C1.. ) steht in den Daten die Größe drinnen.

Somit ist dein else Zweig (If Not (BD In [$01,$D0,$D1,..) schonmal Blödsin, da es egal ist, welches andere Segment kommt, da Du nur nach dem SOFx suchst.
(Ja ich Verwende Delphi 6 Pro und will NICHT wechseln!)
  Mit Zitat antworten Zitat
MicMic

Registriert seit: 26. Mai 2018
229 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#24

AW: GetJPGSize Funktion (wollen wir sie verbessern?)

  Alt 15. Feb 2020, 01:59
Hi Holger.
Es ist schwer alle Infos zu bekommen und natürlich bin ich nicht gleich überall gleich schlau. Hier und da dauert das bei mir Bei diesem Thema wird's auch noch dauern *lach
Aber ich verstehe schon ein wenig mehr. Zum Beispiel das mit der Längenangabe.

Aber mal ein Beispiel... da findet man ein Source-Code mit $C0 und $C1 (für's ermitteln der Bildgröße) und dann stolpert man irgendwo auf $C2.
Jetzt nutzt du in deiner Funktion $C3,$C9,$CA und $CB.

Inzwischen habe ich Wikipedia (in DE und EN) gelesen.
DE: https://de.wikipedia.org/wiki/JPEG_F...rchange_Format
EN: https://en.wikipedia.org/wiki/JPEG

Auf der englischen kann man in einer Tabelle lesen, dass u.a. die Bildbreite/Höhe in Verbindung mit $C0 (bzw. 0xC0) und $C2 steht. Von anderen Tags (also das 2. Byte - der Typ) ist hier nicht die Rede (in Verbindung der Bildgröße). Mein am Anfang gefundenes Beispiel nutzte nur $C0 und $C1. $C2 habe ich dann noch selbst hinzugefügt.

Jetzt schreibst du:
Code:
Und eben in den Segmenten (SOFx) für die Definition der Kodierung ($C0, $C1.. ) steht in den Daten die Größe drinnen.
Müsste man dann nicht nur "$C0,$C1,$C2,$C3,$C9,$CA,$CB" (wie in deinem Beispiel), sondern auch noch andere nutzen. Zumindest laut DE-Wikipedia dann auch $C5,$C6,$C7,$C9,$CD,$CE und $CF (diese mit SOFx gekennzeichnet sind).

Und zu diesem Zweig "(If Not (BD In [$01,$D0,$D1,..)". Das habe ich aus einem Beispiel übernommen. In der DE-Wikipedia steht dazu beispielsweise "Ausnahme: Folgt dem FF einer der Restart-Marker (D0 - D7) so setzen sich die Daten direkt dahinter weiter fort:". Fragt sich natürlich noch was $01 bedeutet. Da ich aber nicht alles ganz verstehe, dachte ich natürlich... "oh... Ausnahmen; na der Beispiel-Coder hat sich wohl dabei was gedacht". Aber du sagt jetzt ja, dass im SOF Bereich (Start of Frame Marker) die Daten (Bildgröße) stehen. Jedoch suche ich vergeblich eine Info zu "End of Frame Marker" . Ist es hier SOF15?*

Gruß Mike

*Eben gesehen... laut deinem Code ist $DA dann sozusagen das Ende. Also bei SOS (Start of Scan)

Geändert von MicMic (15. Feb 2020 um 02:17 Uhr)
  Mit Zitat antworten Zitat
HolgerX

Registriert seit: 10. Apr 2006
Ort: Leverkusen
834 Beiträge
 
Delphi 6 Professional
 
#25

AW: GetJPGSize Funktion (wollen wir sie verbessern?)

  Alt 15. Feb 2020, 07:52
Hmm..

Lt. Wiki hast Du bei den $Cx recht, dass dort noch weitere als DCT definiert sind, somit könnten alle $Cx von 0 bis F für die Größenangaben genutzt werden, außer $C4, $C8, $CC. Jedes JPEG sollte nur einen dieser SOF enthalten.

Meine Angaben hatte ich aus einer ISO Norm, wohl auch schon was älter entnommen.

Hoer noch ein anderer Link:
http://www.aboutvb.de/bas/formate/pdf/jpg.pdf
(Ja ich Verwende Delphi 6 Pro und will NICHT wechseln!)
  Mit Zitat antworten Zitat
MicMic

Registriert seit: 26. Mai 2018
229 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#26

AW: GetJPGSize Funktion (wollen wir sie verbessern?)

  Alt 15. Feb 2020, 22:20
Das PDF von aboutvb hatte ich auch mal kurz überflogen aber alles nicht so einfach zu verstehen um es in Delphi umzusetzen.
Also ich kannte es schon. Trotzdem Danke für den Link. Versuche mich gerade daran nochmal.
Deine Funktion versuche ich erst mal zu ignorieren und will meine Funktion abändern. Einfach um alles besser zu verstehen.
Inzwischen habe ich meine Funktion ein wenig geändert. Funktioniert soweit abgesehen von einer Sache (die bei dir wohl auch noch nicht funktioniert), nämlich Hoch/Querformat. Bei Hochformat werden die Angaben vertauscht (in Breite steht die Höhe, in Höhe die Breite).

Hier mal mein neuer Code und schnell mal bissl Kommentare dazu:
Delphi-Quellcode:
Procedure GetJPGSize(sFile: String; Out WW, WH: DWord);
Var
  FS: TFileStream;
  BD: Byte;
  WD : Word;
  RL: LongInt;
  HW : Array[0..3] Of Byte;
  LE : Array[0..1] Of Byte;
Begin
  sFile := '\\?\'+SFile;
  WW := 0;
  WH := 0;
  FS := TFileStream.Create(sFile, fmShareDenyNone);
  Try

    // Erste 2 Bytes lesen
    RL := FS.Read(WD, 2);
    // Wenn FFD8 nicht vorhanden, dann RL auf 0 setzen
    If (Lo(WD) <> $FF) And (Hi(WD) <> $D8) Then RL := 0;

    If RL > 0 Then
    Begin

      // Nächstes Byte lesen. Ist (oder sollte) immer FF sein
      RL := FS.Read(BD, 1);

      While (BD = $FF) And (RL > 0) Do
      Begin
        // Nächstes Byte lesen
        RL := FS.Read(BD, 1);

        // Wenn alles außer FF, dann...
        If BD <> $FF Then
        Begin
          // Prüfen auf diese C0,C1 usw.
          If BD In [$C0,$C1,$C2] Then // <- kommt noch mehr dazu
          Begin
            // 3 Bytes weiter. Längenangabe (2 Bytes) sowie die Bit-Tiefe (1 Byte)
            // wird nicht benötigt
            FS.Seek(3,soFromCurrent);
            FS.Read(HW,4); // 4 Bytes (2 für Breite und 2 für Höhe)
            WH := HW[0] Shl 8 + HW[1];
            WW := HW[2] Shl 8 + HW[3];

            // ...
            // Hier muss noch was rein, wegen Hoch/Querformat
            // ...

            // Breite/Höhe gespeichert. Vielleicht ja noch mal prüfen? Jedenfalls hier Abbrechen
            Break;
          End Else
          Begin
            If BD<>$DA Then
            Begin
              FS.Read(Le,2); // 2 Bytes lesen (Längenangabe)
              WD := LE[0] Shl 8 + Le[1]; // Länge in Little Endian zurück (soll ja im JPG immer in BIG-Endian abgespeichert sein)
              FS.Seek(WD - 2, soFromCurrent); // Position zum nächsten Segment (-2 wegen 2 Byte-Längenangabe)
              FS.Read(BD, 1); // Erstes $FF lesen
            End Else Break; // <- DA gefunden, also fertig.
          End;
        End;
      End;
    End;
  Finally
    FS.Free;
  End;
End;
Bei aboutvb ist nun auf Seite 764 erst mal eine Tabelle (Tabelle 27.13) mit diesen C1,C2,C3 usw. Hier wurden die 3 (C4,C8,CC) auch weggelassen... also so, wie ich es bei Wikipedia las. Soweit so gut. In Tabelle 27.14 geht es dann weiter. Dort wird aber wieder (erste Zeile in der Tabelle) von FFDxH gesprochen. Auch weiter unten im Text...

"Wegen der geforderten Baseline DCT Komprimierung sollte die Signatur FFD0H auftreten."

Meinte der Autor hier nicht "FFC0H"?

In meinem Code jedenfalls überspringe ich 3 Bytes mit Seek.
Kommentar in meinem Code dort "3 Bytes weiter. Längenangabe (2 Bytes) sowie die Bit-Tiefe (1 Byte) wird nicht benötigt"

Es funktioniert jedenfalls so. Wenn ich mir die Tabelle 27.14 (aboutvb) betrachte, scheint dies ja so richtig zu sein. Abgesehen von der Angabe dort "FFD0H". Was wohl "FFC0H" sein sollte. Oder bringe ich was durcheinander?

Jedenfalls müsste ich dann wohl noch folgendes einfügen... bei meinem Kommentar (Hier muss noch was rein, wegen Hoch/Querformat) im Code:

1. 2 Byte überspringen
2. 1 Byte lesen und Werte prüfen.
3. ggf. Variablen für Breite/Höhe vertauschen

Laut Tabelle: Wert 0-3 vertikal und 4-7 horizontal müsste ich ermittelt bekommen.

Ich erreiche aber Werte von 17 (Querformat), mal 34 und auch mal 33 für Hochformat. Also so ganz klappt's noch nicht aber wohl fast.

Am Ende müsste man sich noch fragen, ob man die richtigen Werte vom Bild bekommt. In JPG soll man ja auch kleinere Vorschaubilder speichern können. 1 Vorschaubild? Mehrere? Wohl mehrere. Ich denke damit sind diese "ID x. Komponenten" gemeint. Im PDF (aboutvb) ist ja schon von "ID 3. Komponente" die Rede. Wobei dort in der Tabelle (27.14) nicht mehr von Bildgrößen zu lesen ist, sondern nur noch (pro Komponente) von Hoch/Querformat (Abtastfaktor) und einer Nummer von einer Quantisierungstabelle. Was auch immer das nun wieder ist Aber wenn es kleinere Vorschaubilder geben kann, gibt es sicherlich auch für diese ganze 4 Bytes für das Abfragen der Breite/Höhe. Hoffentlich ist das 1. immer das Originalbild. Alles was danach kommt (ob nun mit Vorschaubilder oder nicht) könnte ja einem dann egal sein. Zumindest für dieses Thema (Ermitteln der JPG Bildgröße).
  Mit Zitat antworten Zitat
MicMic

Registriert seit: 26. Mai 2018
229 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#27

AW: GetJPGSize Funktion (wollen wir sie verbessern?)

  Alt 15. Feb 2020, 22:32
Nachtrag:

"Ich erreiche aber Werte von 17 (Querformat), mal 34 und auch mal 33 für Hochformat. Also so ganz klappt's noch nicht aber wohl fast."

Ach... da steht ja BIT 0-3 und 4-7 (für das Format)
Wird gleich funktionieren (aber muss trotzdem schauen wie ich da die erste 4 und letzten 4 Bits teile)
  Mit Zitat antworten Zitat
MicMic

Registriert seit: 26. Mai 2018
229 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#28

AW: GetJPGSize Funktion (wollen wir sie verbessern?)

  Alt 16. Feb 2020, 00:00
Ich bekomme noch die Kriese.
Dieser Wert "Abtastfaktor" hat gar nichts mit dem Format zu tun.
Ich las "vertikal/horizontal" und dachte...

Ich habe jedenfalls ein Bild im Hochformat aufgenommen, dass hier leider Breite/Höhe vertauscht. ExifTool gibt an (beim Orientation-Flag): Rotate 270 CW. Jetzt muss man wohl noch EXIF-Daten auslesen. Wobei es nicht immer EXIF-Daten gibt aber hier (ohne EXIF Daten bei Hochformat) vertauscht Windows selbst die Werte.
  Mit Zitat antworten Zitat
HolgerX

Registriert seit: 10. Apr 2006
Ort: Leverkusen
834 Beiträge
 
Delphi 6 Professional
 
#29

AW: GetJPGSize Funktion (wollen wir sie verbessern?)

  Alt 16. Feb 2020, 06:36
Hm..

Das ist halt die Krux, wenn Kamera Hersteller meinen es 'besser' machen zu wollen...
Die Höhle und Breite werden dann getauscht, wenn mit der Kamera um 90/270 Grad gedrehtes Bild gemacht wird.
Diese Drehung steht dann nur in den EXIF informationen, diese könnten jedoch mal entfernt werden, womit diese Angaben weg sind.

Nur mit Programmen, welche auch die EXIF (Segment $FFE1 = APP1) auslesen und interpretieren, können das erkennen.
Diese EXIF Daten können Binär oder XML sein.. Viel Spaß wenn Du diese selber auslesen willst ohne entsprechende Komponenten.

Ein Thumbnail kann entweder im $FFE0 = APP0 sein, wenn dies den Identifier "JFIF" hat.
Alternativ auch in den zusätzlichen JFIF extension APP0 mit einem anderen APP0 Identifier "JFXX".
Oder ich glaube auch in den EXIF Daten..
Ach ja, jeweils in anderem Bild-Format..


Wenn Du all diese Information haben möchtest (Größe/Drehung/Thumb..) dann kannst Du deine Funktion vergessen und musst, wie in meinem Beispiel, Segmentbasierend arbeiten. Bei meinem Source brauche ich nur im Case die weiteren Kinds hinzufügen und dann mit Casten die Daten per vorher definierten Records sauber auslesen. Nur so behältst Du die Übersicht in deinem Source.
(Ja ich Verwende Delphi 6 Pro und will NICHT wechseln!)
  Mit Zitat antworten Zitat
MicMic

Registriert seit: 26. Mai 2018
229 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#30

AW: GetJPGSize Funktion (wollen wir sie verbessern?)

  Alt 19. Feb 2020, 18:57
Ne, auf EXIF habe ich erst mal keine Lust
Der Fokus lag jetzt auf die Bildgröße und das verstehen des JPG-Headers. Zwar ein wenig blöd, wenn evtl. bei manchen Dateien die Breite/Höhe vertauscht ist aber das schieb ich mal nach hinten und kümmere mich um andere Codezeilen.
Also mal Danke an alle. Ich habe ein wenig dazugelernt.

Mike
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:06 Uhr.
Powered by vBulletin® Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2019 by Daniel R. Wolf