#FEATURE
authorClaus Gittinger <cg@exept.de>
Thu, 18 Feb 2016 13:46:54 +0100
changeset 3564 8946f8362c63
parent 3562 822b6d67ea95
child 3565 76899d7114cd
#FEATURE class: JPEGReader added: #examples comment/format in: #documentation #save:onStream:
JPEGReader.st
--- a/JPEGReader.st	Wed Feb 17 17:31:16 2016 +0100
+++ b/JPEGReader.st	Thu Feb 18 13:46:54 2016 +0100
@@ -1,3 +1,5 @@
+"{ Encoding: utf8 }"
+
 "
  COPYRIGHT (c) 1993 by Claus Gittinger
 	      All Rights Reserved
@@ -11,9 +13,12 @@
 "
 "{ Package: 'stx:libview2' }"
 
+"{ NameSpace: Smalltalk }"
+
 ImageReader subclass:#JPEGReader
-	instanceVariableNames:'jpeg_decompress_struct jpeg_compress_struct jpeg_error_mgr_struct colorComponents
-		forceGrayscale forceDitherMode app1SegmentHandler compressQuality bytesPerRow'
+	instanceVariableNames:'jpeg_decompress_struct jpeg_compress_struct jpeg_error_mgr_struct
+		colorComponents forceGrayscale forceDitherMode app1SegmentHandler
+		compressQuality bytesPerRow'
 	classVariableNames:'ErrorPrinting'
 	poolDictionaries:''
 	category:'Graphics-Images-Readers'
@@ -174,13 +179,81 @@
 
     This uses the libpeg library to read the image
 
-    Only reading of files is supported.
+    Only writing of depth24 images is currently supported.
 
     [See also:]
-	Image Form Icon
-	BlitImageReader FaceReader GIFReader PBMReader PCXReader
-	ST80FormReader SunRasterReader TargaReader TIFFReader WindowsIconReader
-	XBMReader XPMReader XWDReader
+        Image Form Icon
+        BlitImageReader FaceReader GIFReader PBMReader PCXReader
+        ST80FormReader SunRasterReader TargaReader TIFFReader WindowsIconReader
+        XBMReader XPMReader XWDReader
+"
+!
+
+examples
+"
+    good quality:
+                                                                [exBegin]
+     |i i24 i2|
+
+     Transcript printf:'gif original %d\n' with:( '../../goodies/bitmaps/gifImages/garfield.gif' asFilename fileSize ).
+     i := Image fromFile:'../../goodies/bitmaps/gifImages/garfield.gif'.
+     i24 := Depth24Image fromImage:i.
+     JPEGReader save:i24 onFile:'test100.jpg'.
+     i2 := Image fromFile:'test100.jpg'.
+     Transcript printf:'jpg 100%% %d\n' with:( 'test100.jpg' asFilename fileSize ).
+     i2 inspect
+                                                                [exEnd]
+
+
+    normal quality:
+                                                                [exBegin]
+     |i i24 i2|
+
+     Transcript printf:'gif original %d\n' with:( '../../goodies/bitmaps/gifImages/garfield.gif' asFilename fileSize ).
+     i := Image fromFile:'../../goodies/bitmaps/gifImages/garfield.gif'.
+     i24 := Depth24Image fromImage:i.
+     JPEGReader save:i24 onFile:'test80.jpg'.
+     i2 := Image fromFile:'test80.jpg'.
+     Transcript printf:'jpg 80%% %d\n' with:( 'test80.jpg' asFilename fileSize ).
+     i2 inspect
+                                                                [exEnd]
+
+
+    low quality:
+                                                                [exBegin]
+     |i i24 i2|
+
+     i := Image fromFile:'../../goodies/bitmaps/gifImages/garfield.gif'.
+     i24 := Depth24Image fromImage:i.
+     JPEGReader new save:i24 onStream:('test50.jpg' asFilename writeStream) compressQuality:50.
+     i2 := Image fromFile:'test50.jpg'.
+     Transcript printf:'jpg 50%% %d\n' with:( 'test50.jpg' asFilename fileSize ).
+     i2 inspect
+                                                                [exEnd]
+
+    bad quality:
+                                                                [exBegin]
+     |i i24 i2|
+
+     i := Image fromFile:'../../goodies/bitmaps/gifImages/garfield.gif'.
+     i24 := Depth24Image fromImage:i.
+     JPEGReader new save:i24 onStream:('test20.jpg' asFilename writeStream) compressQuality:20.
+     i2 := Image fromFile:'test20.jpg'.
+     Transcript printf:'jpg 20%% %d\n' with:( 'test20.jpg' asFilename fileSize ).
+     i2 inspect
+                                                                [exEnd]
+
+    very bad quality:
+                                                                [exBegin]
+     |i i24 i2|
+
+     i := Image fromFile:'../../goodies/bitmaps/gifImages/garfield.gif'.
+     i24 := Depth24Image fromImage:i.
+     JPEGReader new save:i24 onStream:('test10.jpg' asFilename writeStream) compressQuality:10.
+     i2 := Image fromFile:'test10.jpg'.
+     Transcript printf:'jpg 10%% %d\n' with:( 'test10.jpg' asFilename fileSize ).
+     i2 inspect
+                                                                [exEnd]
 "
 ! !
 
@@ -196,6 +269,12 @@
     "Modified: 1.2.1997 / 15:01:55 / cg"
 ! !
 
+!JPEGReader class methodsFor:'defaults'!
+
+defaultCompressQuality
+    ^ 85
+! !
+
 !JPEGReader class methodsFor:'testing'!
 
 isValidImageFile:aFilenameOrString
@@ -255,6 +334,85 @@
     ^ cb code.  "can be passed to C."
 !
 
+create_jpeg_compress_struct
+    |errMgrStructSize compressStructSize fp errorOccurred|
+
+    self assert:(photometric == #rgb).
+    self assert:(samplesPerPixel == 3).
+    self assert:(bitsPerSample asArray = #(8 8 8)).
+
+    fp := outStream filePointer.
+    fp isNil ifTrue:[
+	self error:'can only write to an external stream'.
+	^ false.
+    ].
+
+%{
+    errMgrStructSize = __mkSmallInteger(sizeof(struct my_error_mgr));
+    compressStructSize = __mkSmallInteger(sizeof(struct jpeg_compress_struct));
+%}.
+
+    jpeg_error_mgr_struct := ExternalBytes unprotectedNew:errMgrStructSize.
+    jpeg_compress_struct := ExternalBytes unprotectedNew:compressStructSize.
+    errorOccurred := false.
+
+%{  /* STACK: 400000 */
+    struct jpeg_compress_struct *cinfoPtr;
+    struct my_error_mgr *jerrPtr;
+    OBJ j_e_m = __INST(jpeg_error_mgr_struct);
+    OBJ j_c_s = __INST(jpeg_compress_struct);
+    FILE *f = __FILEVal(fp);
+    char *outBuffer;
+
+    if (__isExternalBytesLike(j_c_s)
+     && __isExternalBytesLike(j_e_m)) {
+	cinfoPtr = (struct jpeg_compress_struct *)(__externalBytesAddress(j_c_s));
+	jerrPtr = (struct my_error_mgr *)(__externalBytesAddress(j_e_m));
+
+	/*
+	 * Initialize the JPEG decompression object with default error handling.
+	 */
+	cinfoPtr->err = jpeg_std_error(&jerrPtr->pub);
+
+	/*
+	 * prepare to handle errors smoothly ...
+	 */
+	jerrPtr->pub.error_exit = my_error_exit;
+	if (setjmp(jerrPtr->setjmp_buffer)) {
+	    /*
+	     * error occurred ...
+	     */
+	    jpeg_destroy_compress(cinfoPtr);
+	    RETURN (false);
+	}
+
+	/*
+	 * use my message print function
+	 */
+	jerrPtr->pub.output_message = my_output_message;
+
+	jpeg_create_compress(cinfoPtr);
+
+	/* Specify data destination for compression */
+	jpeg_stdio_dest(cinfoPtr, f);
+
+	cinfoPtr->image_width      = __intVal(__INST(width));
+	cinfoPtr->image_height     = __intVal(__INST(height));
+	cinfoPtr->input_components = __intVal(__INST(samplesPerPixel));
+	cinfoPtr->in_color_space   = JCS_RGB;
+
+	jpeg_set_defaults(cinfoPtr);
+	/*set the quality [0..100]  */
+	jpeg_set_quality (cinfoPtr, __intVal(__INST(compressQuality)), 1);
+	jpeg_start_compress(cinfoPtr, 1);
+
+
+	cinfoPtr->err->trace_level = 0;
+    }
+%}.
+    ^ true
+!
+
 create_jpeg_decompress_struct
     |errMgrStructSize decompressStructSize fp errorOccurred app1SegmentCallbackFunction|
 
@@ -409,85 +567,6 @@
     ^ true
 !
 
-create_jpeg_compress_struct
-    |errMgrStructSize compressStructSize fp errorOccurred|
-
-    self assert:(photometric == #rgb).
-    self assert:(samplesPerPixel == 3).
-    self assert:(bitsPerSample asArray = #(8 8 8)).
-
-    fp := outStream filePointer.
-    fp isNil ifTrue:[
-	self error:'can only write to an external stream'.
-	^ false.
-    ].
-
-%{
-    errMgrStructSize = __mkSmallInteger(sizeof(struct my_error_mgr));
-    compressStructSize = __mkSmallInteger(sizeof(struct jpeg_compress_struct));
-%}.
-
-    jpeg_error_mgr_struct := ExternalBytes unprotectedNew:errMgrStructSize.
-    jpeg_compress_struct := ExternalBytes unprotectedNew:compressStructSize.
-    errorOccurred := false.
-
-%{  /* STACK: 400000 */
-    struct jpeg_compress_struct *cinfoPtr;
-    struct my_error_mgr *jerrPtr;
-    OBJ j_e_m = __INST(jpeg_error_mgr_struct);
-    OBJ j_c_s = __INST(jpeg_compress_struct);
-    FILE *f = __FILEVal(fp);
-    char *outBuffer;
-
-    if (__isExternalBytesLike(j_c_s)
-     && __isExternalBytesLike(j_e_m)) {
-	cinfoPtr = (struct jpeg_compress_struct *)(__externalBytesAddress(j_c_s));
-	jerrPtr = (struct my_error_mgr *)(__externalBytesAddress(j_e_m));
-
-	/*
-	 * Initialize the JPEG decompression object with default error handling.
-	 */
-	cinfoPtr->err = jpeg_std_error(&jerrPtr->pub);
-
-	/*
-	 * prepare to handle errors smoothly ...
-	 */
-	jerrPtr->pub.error_exit = my_error_exit;
-	if (setjmp(jerrPtr->setjmp_buffer)) {
-	    /*
-	     * error occurred ...
-	     */
-	    jpeg_destroy_compress(cinfoPtr);
-	    RETURN (false);
-	}
-
-	/*
-	 * use my message print function
-	 */
-	jerrPtr->pub.output_message = my_output_message;
-
-	jpeg_create_compress(cinfoPtr);
-
-	/* Specify data destination for compression */
-	jpeg_stdio_dest(cinfoPtr, f);
-
-	cinfoPtr->image_width      = __intVal(__INST(width));
-	cinfoPtr->image_height     = __intVal(__INST(height));
-	cinfoPtr->input_components = __intVal(__INST(samplesPerPixel));
-	cinfoPtr->in_color_space   = JCS_RGB;
-
-	jpeg_set_defaults(cinfoPtr);
-	/*set the quality [0..100]  */
-	jpeg_set_quality (cinfoPtr, __intVal(__INST(compressQuality)), 1);
-	jpeg_start_compress(cinfoPtr, 1);
-
-
-	cinfoPtr->err->trace_level = 0;
-    }
-%}.
-    ^ true
-!
-
 decompressChunkInto:aByteArray startingAt:index
 %{  /* STACK: 400000 */
     struct jpeg_decompress_struct *cinfoPtr;
@@ -563,6 +642,31 @@
     app1SegmentHandler value:data.
 !
 
+finish_compress
+%{  /* STACK: 400000 */
+    struct jpeg_compress_struct *cinfoPtr;
+    struct my_error_mgr *jerrPtr;
+    OBJ j_c_s = __INST(jpeg_compress_struct);
+    OBJ j_e_m = __INST(jpeg_error_mgr_struct);
+
+    if (__isExternalBytesLike(j_c_s)
+     && __isExternalBytesLike(j_e_m)) {
+	cinfoPtr = (struct jpeg_compress_struct *)(__externalBytesAddress(j_c_s));
+	jerrPtr = (struct my_error_mgr *)(__externalBytesAddress(j_e_m));
+
+	if (setjmp(jerrPtr->setjmp_buffer)) {
+	    jpeg_destroy_compress(cinfoPtr);
+	    RETURN (false);
+	}
+
+	/* finish decompressor */
+	(void) jpeg_finish_compress(cinfoPtr);
+	(void) jpeg_destroy_compress(cinfoPtr);
+	RETURN (true);
+    }
+%}
+!
+
 finish_decompress
 %{  /* STACK: 400000 */
     struct jpeg_decompress_struct *cinfoPtr;
@@ -588,31 +692,6 @@
 %}
 !
 
-finish_compress
-%{  /* STACK: 400000 */
-    struct jpeg_compress_struct *cinfoPtr;
-    struct my_error_mgr *jerrPtr;
-    OBJ j_c_s = __INST(jpeg_compress_struct);
-    OBJ j_e_m = __INST(jpeg_error_mgr_struct);
-
-    if (__isExternalBytesLike(j_c_s)
-     && __isExternalBytesLike(j_e_m)) {
-	cinfoPtr = (struct jpeg_compress_struct *)(__externalBytesAddress(j_c_s));
-	jerrPtr = (struct my_error_mgr *)(__externalBytesAddress(j_e_m));
-
-	if (setjmp(jerrPtr->setjmp_buffer)) {
-	    jpeg_destroy_compress(cinfoPtr);
-	    RETURN (false);
-	}
-
-	/* finish decompressor */
-	(void) jpeg_finish_compress(cinfoPtr);
-	(void) jpeg_destroy_compress(cinfoPtr);
-	RETURN (true);
-    }
-%}
-!
-
 get_error_message
 %{
     j_common_ptr cinfoPtr;
@@ -781,17 +860,60 @@
     "Modified: / 12-12-2011 / 21:34:48 / cg"
 ! !
 
-!JPEGReader class methodsFor:'defaults'!
-defaultCompressQuality
-    ^ 85
-! !
+!JPEGReader methodsFor:'writing'!
+
+compressScanlines
+%{
+    unsigned char *rowPtr;
+    int bpr = __intVal(__INST(bytesPerRow));
+    int row;
+    int __height = __intVal(__INST(height));
+    struct jpeg_compress_struct *cinfoPtr;
+    struct my_error_mgr *jerrPtr;
+    OBJ j_c_s = __INST(jpeg_compress_struct);
+    OBJ j_e_m = __INST(jpeg_error_mgr_struct);
+    OBJ __data = __INST(data);
 
-!JPEGReader methodsFor:'writing'!
+    if (__isByteArray(__data)) {
+	rowPtr = (char *)(__ByteArrayInstPtr(__data)->ba_element);
+    } else if (__isExternalBytesLike(__data)) {
+	rowPtr = __externalBytesAddress(__data);
+    }
+
+    if (__isExternalBytesLike(j_c_s)
+     && __isExternalBytesLike(j_e_m)) {
+	cinfoPtr = (struct jpeg_compress_struct *)(__externalBytesAddress(j_c_s));
+	jerrPtr = (struct my_error_mgr *)(__externalBytesAddress(j_e_m));
+
+	if (setjmp(jerrPtr->setjmp_buffer)) {
+	    jpeg_destroy_compress(cinfoPtr);
+	    RETURN (false);
+	}
+
+	for (row=0; row<__height; row++) {
+	    jpeg_write_scanlines(cinfoPtr, &rowPtr, 1);
+	    rowPtr += bpr;
+	}
+    }
+%}
+!
 
 save:image onStream:aStream
     "save image in JPG-file-format onto aStream"
 
     self save:image onStream:aStream compressQuality:(self class defaultCompressQuality)
+
+    "
+     |i i24 i2|
+
+     i := Image fromFile:'../../goodies/bitmaps/gifImages/garfield.gif'.
+     i24 := Depth24Image fromImage:i.
+     JPEGReader save:i24 onFile:'test.jpg'.
+     i2 := Image fromFile:'test.jpg'.
+     i2 inspect
+    "
+
+    "Modified (comment): / 18-02-2016 / 02:36:44 / cg"
 !
 
 save:image onStream:aStream compressQuality:qualityInPercent
@@ -827,42 +949,6 @@
 
     self compressScanlines.
     self finish_compress.
-!
-
-compressScanlines
-%{
-    unsigned char *rowPtr;
-    int bpr = __intVal(__INST(bytesPerRow));
-    int row;
-    int __height = __intVal(__INST(height));
-    struct jpeg_compress_struct *cinfoPtr;
-    struct my_error_mgr *jerrPtr;
-    OBJ j_c_s = __INST(jpeg_compress_struct);
-    OBJ j_e_m = __INST(jpeg_error_mgr_struct);
-    OBJ __data = __INST(data);
-
-    if (__isByteArray(__data)) {
-	rowPtr = (char *)(__ByteArrayInstPtr(__data)->ba_element);
-    } else if (__isExternalBytesLike(__data)) {
-	rowPtr = __externalBytesAddress(__data);
-    }
-
-    if (__isExternalBytesLike(j_c_s)
-     && __isExternalBytesLike(j_e_m)) {
-	cinfoPtr = (struct jpeg_compress_struct *)(__externalBytesAddress(j_c_s));
-	jerrPtr = (struct my_error_mgr *)(__externalBytesAddress(j_e_m));
-
-	if (setjmp(jerrPtr->setjmp_buffer)) {
-	    jpeg_destroy_compress(cinfoPtr);
-	    RETURN (false);
-	}
-
-	for (row=0; row<__height; row++) {
-	    jpeg_write_scanlines(cinfoPtr, &rowPtr, 1);
-	    rowPtr += bpr;
-	}
-    }
-%}
 ! !
 
 !JPEGReader class methodsFor:'documentation'!