added:
authorClaus Gittinger <cg@exept.de>
Mon, 12 Dec 2011 21:22:59 +0100
changeset 2972 c9b3ef795181
parent 2971 07bd4e98036e
child 2973 b708ff319811
added: #extractApp1DataFrom: #extractExifDataFrom: comment/format in: #fromStream:
JPEGReader.st
--- a/JPEGReader.st	Mon Dec 12 21:19:08 2011 +0100
+++ b/JPEGReader.st	Mon Dec 12 21:22:59 2011 +0100
@@ -258,38 +258,6 @@
     ^ cb code.  'can be passed to C'.
 !
 
-fetchApp1SegmentData
-    |byte1 byte2 count|
-
-    byte1 := self jpeg_getc.
-    byte2 := self jpeg_getc.
-    count := (byte1 bitShift:8) + byte2. "/ msb first
-    count := count - 2. "/ count itself is included
-    data := ByteArray new:count.
-    1 to: count do:[:i |
-	data at:i put:(self jpeg_getc).
-    ].
-    self halt.
-    app1SegmentHandler value:data.
-!
-
-jpeg_getc
-%{
-    OBJ j_d_s = __INST(jpeg_decompress_struct);
-
-    if (__isExternalBytesLike(j_d_s)) {
-	struct jpeg_decompress_struct *cinfoPtr;
-	int byte;
-
-	cinfoPtr = (struct jpeg_decompress_struct *)(__externalBytesAddress(j_d_s));
-
-	byte = JPG_jpeg_getc (cinfoPtr);
-	RETURN( __MKSMALLINT(byte) );
-    }
-%}.
-    self primitiveFailed
-!
-
 create_jpeg_decompress_struct
     |errMgrStructSize decompressStructSize fp errorOccurred app1SegmentCallbackFunction|
 
@@ -490,6 +458,35 @@
     self halt:'bad arguments'.
 !
 
+extractApp1DataFrom:data
+    (data startsWith:#[16r45 16r78 16r69 16r66 16r0] " = 'Exif' + 0-byte" ) ifTrue:[
+        self extractExifDataFrom:data.
+    ].
+
+    "Created: / 12-12-2011 / 21:22:23 / cg"
+!
+
+extractExifDataFrom:data
+    self halt
+
+    "Created: / 12-12-2011 / 21:22:32 / cg"
+!
+
+fetchApp1SegmentData
+    |byte1 byte2 count|
+
+    byte1 := self jpeg_getc.
+    byte2 := self jpeg_getc.
+    count := (byte1 bitShift:8) + byte2. "/ msb first
+    count := count - 2. "/ count itself is included
+    data := ByteArray new:count.
+    1 to: count do:[:i |
+	data at:i put:(self jpeg_getc).
+    ].
+    self halt.
+    app1SegmentHandler value:data.
+!
+
 finish_decompress
 %{  /* STACK: 400000 */
     struct jpeg_decompress_struct *cinfoPtr;
@@ -532,6 +529,23 @@
     ^ nil
 !
 
+jpeg_getc
+%{
+    OBJ j_d_s = __INST(jpeg_decompress_struct);
+
+    if (__isExternalBytesLike(j_d_s)) {
+	struct jpeg_decompress_struct *cinfoPtr;
+	int byte;
+
+	cinfoPtr = (struct jpeg_decompress_struct *)(__externalBytesAddress(j_d_s));
+
+	byte = JPG_jpeg_getc (cinfoPtr);
+	RETURN( __MKSMALLINT(byte) );
+    }
+%}.
+    self primitiveFailed
+!
+
 start_decompress
 %{  /* STACK: 400000 */
     struct jpeg_decompress_struct *cinfoPtr;
@@ -564,51 +578,54 @@
     |dataIdx bytesPerRow returnCode pos1 ok tmpFile s|
 
     aStream isExternalStream ifFalse:[
-	"/ libJpeg can only handle real OS-streams
+        "/ libJpeg can only handle real OS-streams
 
-	tmpFile := Filename newTemporary.
-	[
-	    s := tmpFile writeStream binary.
-	    s nextPutAll:aStream contents.
-	    s close.
-	    s := tmpFile readStream binary.
-	    ^ self fromStream:s.
-	] ensure:[
-	    s notNil ifTrue:[s close].
-	    tmpFile delete.
-	].
+        tmpFile := Filename newTemporary.
+        [
+            s := tmpFile writeStream binary.
+            s nextPutAll:aStream contents.
+            s close.
+            s := tmpFile readStream binary.
+            ^ self fromStream:s.
+        ] ensure:[
+            s notNil ifTrue:[s close].
+            tmpFile delete.
+        ].
 
-	"/ 'JPEGReader [info]: can only read from real streams' infoPrintCR.
-	"/ ^ nil
+        "/ 'JPEGReader [info]: can only read from real streams' infoPrintCR.
+        "/ ^ nil
     ].
 
     inStream := aStream.
     pos1 := inStream position.
 
+    "/ to extract app1 data (for example, exif geolocation tags),
+    "/ uncomment the following and implement the exif tag reader...
+    "/ app1SegmentHandler := [:data | self extractApp1DataFrom:data].
 
     (self create_jpeg_decompress_struct not
     or:[self start_decompress not]) ifTrue:[
-	ok := false.
+        ok := false.
 
-	"/ if there was no SOI marker,
-	"/ try again, skipping first 128 bytes
-	"/ (seems to be generated by some jpg writers)
+        "/ if there was no SOI marker,
+        "/ try again, skipping first 128 bytes
+        "/ (seems to be generated by some jpg writers)
 
-	inStream position:pos1.
-	((inStream nextByte ~~ 16rFF)
-	or:[inStream nextByte ~~ 16rD8]) ifTrue:[
-	    inStream position:pos1 + 128.
-	    ((inStream nextByte == 16rFF)
-	    and:[inStream nextByte == 16rD8]) ifTrue:[
-		inStream position:pos1 + 128.
-		ok := self create_jpeg_decompress_struct
-		      and:[self start_decompress]
-	    ].
-	].
-	ok ifFalse:[
-	    'JPEGReader [info]: ' infoPrint. self get_error_message infoPrintCR.
-	    ^ nil
-	]
+        inStream position:pos1.
+        ((inStream nextByte ~~ 16rFF)
+        or:[inStream nextByte ~~ 16rD8]) ifTrue:[
+            inStream position:pos1 + 128.
+            ((inStream nextByte == 16rFF)
+            and:[inStream nextByte == 16rD8]) ifTrue:[
+                inStream position:pos1 + 128.
+                ok := self create_jpeg_decompress_struct
+                      and:[self start_decompress]
+            ].
+        ].
+        ok ifFalse:[
+            'JPEGReader [info]: ' infoPrint. self get_error_message infoPrintCR.
+            ^ nil
+        ]
     ].
 
     data := ByteArray uninitializedNew:(width * height * colorComponents).
@@ -616,27 +633,27 @@
     bytesPerRow := colorComponents * width.
 
     [(returnCode := self decompressChunkInto:data startingAt:dataIdx) > 0] whileTrue:[
-	"/ got a row in the buffer ...
-	dataIdx := dataIdx + bytesPerRow
+        "/ got a row in the buffer ...
+        dataIdx := dataIdx + bytesPerRow
     ].
     returnCode < 0 ifTrue:[
-	'JPEGReader [info]: ' infoPrint. self get_error_message infoPrintCR.
-	^ nil
+        'JPEGReader [info]: ' infoPrint. self get_error_message infoPrintCR.
+        ^ nil
     ].
 
     (self finish_decompress) ifFalse:[
-	'JPEGReader [info]: ' infoPrint. self get_error_message infoPrintCR.
-	^ nil
+        'JPEGReader [info]: ' infoPrint. self get_error_message infoPrintCR.
+        ^ nil
     ].
 
     colorComponents == 3 ifTrue:[
-	photometric := #rgb.
-	samplesPerPixel := 3.
-	bitsPerSample := #(8 8 8).
+        photometric := #rgb.
+        samplesPerPixel := 3.
+        bitsPerSample := #(8 8 8).
     ] ifFalse:[
-	photometric := #blackIs0.
-	samplesPerPixel := 1.
-	bitsPerSample := #(8).
+        photometric := #blackIs0.
+        samplesPerPixel := 1.
+        bitsPerSample := #(8).
     ].
 
     "
@@ -653,17 +670,17 @@
      ^ reader image
     "
 
-    "Modified: / 4.4.1998 / 18:48:46 / cg"
+    "Modified: / 12-12-2011 / 21:20:56 / cg"
 ! !
 
 !JPEGReader class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libview2/JPEGReader.st,v 1.51 2011-12-12 20:19:08 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libview2/JPEGReader.st,v 1.52 2011-12-12 20:22:59 cg Exp $'
 !
 
 version_CVS
-    ^ '$Header: /cvs/stx/stx/libview2/JPEGReader.st,v 1.51 2011-12-12 20:19:08 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libview2/JPEGReader.st,v 1.52 2011-12-12 20:22:59 cg Exp $'
 ! !
 
 JPEGReader initialize!