In dem Blog von Antti Kupila (ganz nebenbei – er ist einer der Crew12) habe ich eine AS3-Klasse gefunden, die ich schon in vielen Projekt hätte gebrauchen können (wenn sie denn AS3 gewesen wären): eine Klasse (JPGSizeExtractor.as), die mir vor dem Laden eines Bildes schon die Abmessungen, sprich width und height, des zu ladenen Bildes wiedergibt. Mit der Info kann man dann wunderbar schon Rahmen, Hintergründe zeichen, bevor das Bild geladen ist…
Das ganze funktioniert dadurch, dass Antti bei Laden jedes einzelne Byte sofort analysiert. Wenn er dann den JFIF-Header in der jpg-Datei findet, kann er die Größe des Bildes auslesen und den Ladevorgang abbrechen.
Leider warnt er auch davor, dass diese Technik nicht bei allen JPGs funktionieren soll, da bei einigen die Headerinformation nicht gefunden werden kann. Also Fallback-Lösung einplanen in den Projekten…
Die Analyse der Bytes ist etwas komplizierter, aber in kurzen Worten gefaßt: In einem Hex-Editor wird einem ein JPG-Bild mit seinen Hex-Nummern angezeigt. Dort sucht man jetzt einfach nach der gewünschten Hex-Kombination (0xFF 0xC0 0x00 0x11 0x08), die für die Größe des Bildes steht. Diese Kombi sucht dann die Klasse und liest dementsprechend die Werte aus:

Hier der komplette Code dafür:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | protected function progressHandler( e : ProgressEvent ) : void { dataLoaded = bytesAvailable; var APPSections : Array = new Array( ); for ( var i : int = 1; i <16; i++ ) { APPSections[ i ] = [ 0xFF, 0xE0 + i ]; } var index : uint = 0; var byte : int = 0; var address : int = 0; while ( bytesAvailable>= SOF0.length + 4 ) { var match : Boolean = false; // Only look for new APP table if no jump is in queue if ( jumpLength == 0 ) { byte = readUnsignedByte( ); address++; // Check for APP table for each ( var APP : Array in APPSections ) { if ( byte == APP[ index ] ) { match = true; if ( index+1>= APP.length ) { if ( traceDebugInfo ) trace( "APP" + Number( byte - 0xE0 ).toString( 16 ).toUpperCase( ) + " found at 0x" + address.toString( 16 ).toUpperCase( ) ); // APP table found, skip it as it may contain thumbnails in JPG (we don't want their SOF's) jumpLength = readUnsignedShort( ) - 2; // -2 for the short we just read } } } } // Jump here, so that data has always loaded if ( jumpLength> 0 ) { if ( traceDebugInfo ) trace( "Trying to jump " + jumpLength + " bytes (available " + Math.round( Math.min( bytesAvailable / jumpLength, 1 ) * 100 ) + "%)" ); if ( bytesAvailable>= jumpLength ) { if ( traceDebugInfo ) trace( "Jumping " + jumpLength + " bytes to 0x" + Number( address + jumpLength ).toString( 16 ).toUpperCase( ) ); jumpBytes( jumpLength ); match = false; jumpLength = 0; } else break; // Load more data and continue } else { // Check for SOF if ( byte == SOF0[ index ] ) { match = true; if ( index+1>= SOF0.length ) { // Matched SOF0 if ( traceDebugInfo ) trace( "SOF0 found at 0x" + address.toString( 16 ).toUpperCase( ) ); jpgHeight = readUnsignedShort( ); jpgWidth = readUnsignedShort( ); if ( traceDebugInfo ) trace( "Dimensions: " + jpgWidth + " x " + jpgHeight ); removeEventListener( ProgressEvent.PROGRESS, progressHandler ); // No need to look for dimensions anymore if ( stopWhenParseComplete && connected ) close( ); dispatchEvent( new Event( PARSE_COMPLETE ) ); break; } } if ( match ) { index++; } else { index = 0; } } } } protected function jumpBytes( count : uint ) : void { for ( var i : uint = 0; i readByte( ); } } |
Kommentar schreiben