#FEATURE
class: JPEGReader
added: #examples
comment/format in:
#documentation
#save:onStream:
--- 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'!