--- a/JPEGReader.st Mon Apr 14 17:11:16 1997 +0200
+++ b/JPEGReader.st Wed Apr 16 22:11:53 1997 +0200
@@ -10,8 +10,11 @@
hereby transferred.
"
+'From Smalltalk/X, Version:3.1.6 on 16-apr-1997 at 9:09:50 pm' !
+
ImageReader subclass:#JPEGReader
- instanceVariableNames:''
+ instanceVariableNames:'jpeg_decompress_struct jpeg_error_mgr_struct decompressBuffer
+ colorComponents forceGrayscale forceDitherMode'
classVariableNames:''
poolDictionaries:''
category:'Graphics-Images-Support'
@@ -25,8 +28,79 @@
* and typedefs come here.
*/
-#include <jpeglib.h>
-#include <jerror.h>
+#include <stdio.h>
+
+#ifndef NO_TESTING
+# include "../../support/libjpeg-6a/jpeglib.h"
+# include "../../support/libjpeg-6a/jerror.h"
+#else
+# include <jpeglib.h>
+# include <jerror.h>
+#endif
+
+%}
+! !
+
+!JPEGReader primitiveFunctions!
+%{
+
+/*
+ * any local C (helper) functions
+ * come here (please, define as static)
+ */
+
+/*
+ * Optional progress monitor: display a percent-done figure on stderr.
+ */
+
+#ifdef PROGRESS_REPORT
+
+void
+JPG_progress_monitor (j_common_ptr cinfo)
+{
+ cd_progress_ptr prog = (cd_progress_ptr) cinfo->progress;
+ int total_passes = prog->pub.total_passes + prog->total_extra_passes;
+ int percent_done = (int) (prog->pub.pass_counter*100L/prog->pub.pass_limit);
+
+ if (percent_done != prog->percent_done) {
+ prog->percent_done = percent_done;
+ if (total_passes > 1) {
+ fprintf(stderr, "\rPass %d/%d: %3d%% ",
+ prog->pub.completed_passes + prog->completed_extra_passes + 1,
+ total_passes, percent_done);
+ } else {
+ fprintf(stderr, "\r %3d%% ", percent_done);
+ }
+ fflush(stderr);
+ }
+}
+
+
+void
+JPG_start_progress_monitor (j_common_ptr cinfo, cd_progress_ptr progress)
+{
+ /* Enable progress display, unless trace output is on */
+ if (cinfo->err->trace_level == 0) {
+ progress->pub.progress_monitor = progress_monitor;
+ progress->completed_extra_passes = 0;
+ progress->total_extra_passes = 0;
+ progress->percent_done = -1;
+ cinfo->progress = &progress->pub;
+ }
+}
+
+
+void
+JPG_end_progress_monitor (j_common_ptr cinfo)
+{
+ /* Clear away progress display */
+ if (cinfo->err->trace_level == 0) {
+ fprintf(stderr, "\r \r");
+ fflush(stderr);
+ }
+}
+
+#endif
%}
! !
@@ -83,39 +157,6 @@
"Modified: 1.2.1997 / 15:01:55 / cg"
! !
-!JPEGReader class methodsFor:'reading from file'!
-
-fromFile:aFileName
- "read a jpg image from a file.
- Make it the easy way: let djpeg convert it to gif,
- then let GIFReader read the file."
-
- |tempFileName reader|
-
- tempFileName := '/tmp/img' , (OperatingSystem getProcessId printString).
-
- 'JPEGREADER [info]: converting to ppm ..' infoPrintCR.
- (OperatingSystem executeCommand:'djpeg -pnm ' , aFileName , ' > ' , tempFileName)
- ifFalse:[
- (OperatingSystem executeCommand:'../../support/libjpeg/djpeg -pnm ' , aFileName , ' > ' , tempFileName)
- ifFalse:[
- 'JPEGREADER [warning]: conversion failed ..' errorPrintCR.
- 'JPEGREADER [warning]: .. cannot execute converter: djpeg' errorPrintCR.
- ^ nil
- ].
- ].
-
- reader := PBMReader fromFile:tempFileName.
- OperatingSystem executeCommand:'rm ' , tempFileName.
- ^ reader
-
- "
- JPEGReader fromFile:'bitmaps/testimg.jpg'
- "
-
- "Modified: 11.4.1997 / 16:39:59 / cg"
-! !
-
!JPEGReader class methodsFor:'testing'!
isValidImageFile:aFileName
@@ -129,9 +170,294 @@
"Created: 11.4.1997 / 16:26:25 / cg"
! !
+!JPEGReader methodsFor:'accessing'!
+
+forceDitherMode:something
+ "set the dither mode, to one of #none or #ordered"
+
+ forceDitherMode := something.
+
+ "Modified: 16.4.1997 / 20:34:59 / cg"
+!
+
+forceGrayscale:something
+ "set the forceGrayscale mode; if true, grayScale images are
+ returned, even if the input contains a color image."
+
+ forceGrayscale := something.
+
+ "Created: 16.4.1997 / 20:33:44 / cg"
+ "Modified: 16.4.1997 / 20:34:29 / cg"
+! !
+
+!JPEGReader methodsFor:'private'!
+
+create_jpeg_decompress_struct
+ |structSize fp|
+
+ fp := inStream filePointer.
+ fp isNil ifTrue:[
+ self error:'can only read from an external stream'.
+ ^ self.
+ ].
+
+%{
+ structSize = __MKSMALLINT(sizeof(struct jpeg_error_mgr));
+%}.
+
+ jpeg_error_mgr_struct := ExternalBytes unprotectedNew:structSize.
+
+%{
+ structSize = __MKSMALLINT(sizeof(struct jpeg_decompress_struct));
+%}.
+
+ jpeg_decompress_struct := ExternalBytes unprotectedNew:structSize.
+
+%{
+ struct jpeg_decompress_struct *cinfoPtr;
+ struct jpeg_error_mgr *jerrPtr;
+ OBJ j_e_m = __INST(jpeg_error_mgr_struct);
+ OBJ j_d_s = __INST(jpeg_decompress_struct);
+ FILE *f = __FILEVal(fp);
+
+ if (__isExternalBytes(j_d_s)
+ && __isExternalBytes(j_e_m)) {
+ cinfoPtr = (struct jpeg_decompress_struct *)(__externalBytesAddress(j_d_s));
+ jerrPtr = (struct jpeg_error_mgr *)(__externalBytesAddress(j_e_m));
+
+ /*
+ * Initialize the JPEG decompression object with default error handling.
+ */
+ cinfoPtr->err = jpeg_std_error(jerrPtr);
+
+ jpeg_create_decompress(cinfoPtr);
+#if 0
+ /*
+ * Insert custom COM marker processor.
+ */
+ jpeg_set_marker_processor(cinfoPtr, JPEG_COM, COM_handler);
+#endif
+ cinfoPtr->err->trace_level = 0;
+
+#if 0
+ /* colors setting */
+ cinfoPtr->desired_number_of_colors = val;
+ cinfoPtr->quantize_colors = TRUE;
+#endif
+#if 0
+ /* dct setting */
+ cinfoPtr->dct_method = JDCT_ISLOW;
+ or: cinfoPtr->dct_method = JDCT_IFAST;
+ or: cinfoPtr->dct_method = JDCT_FLOAT;
+#endif
+
+ /* dither setting */
+ cinfoPtr->dither_mode = JDITHER_FS;
+ if (__INST(forceDitherMode) == @symbol(none)) {
+ cinfoPtr->dither_mode = JDITHER_NONE;
+ } else {
+ if (__INST(forceDitherMode) == @symbol(ordered)) {
+ cinfoPtr->dither_mode = JDITHER_ORDERED;
+ }
+ }
+
+#if 0
+ /* fast setting */
+ cinfoPtr->two_pass_quantize = FALSE;
+ cinfoPtr->dither_mode = JDITHER_ORDERED;
+ cinfoPtr->desired_number_of_colors = 216;
+ cinfoPtr->dct_method = JDCT_FASTEST;
+ cinfoPtr->do_fancy_upsampling = FALSE;
+#endif
+
+ if (__INST(forceGrayscale) == true) {
+ /* grayscale setting */
+ cinfoPtr->out_color_space = JCS_GRAYSCALE;
+ }
+
+#if 0
+ /* maxmemory setting */
+ cinfoPtr->mem->max_memory_to_use = lval * 1000L;
+#endif
+#if 0
+ /* nosmooth setting */
+ cinfoPtr->do_fancy_upsampling = FALSE;
+#endif
+#if 0
+ /* onepass setting */
+ cinfoPtr->two_pass_quantize = FALSE;
+#endif
+
+ /* Specify data source for decompression */
+ jpeg_stdio_src(cinfoPtr, f);
+
+ /* Read file header, set default decompression parameters */
+ (void) jpeg_read_header(cinfoPtr, TRUE);
+
+ /* Calculate output image dimensions so we can allocate space */
+ jpeg_calc_output_dimensions(cinfoPtr);
+
+ __INST(width) = __MKSMALLINT(cinfoPtr->output_width);
+ __INST(height) = __MKSMALLINT(cinfoPtr->output_height);
+ __INST(colorComponents) = __MKSMALLINT(cinfoPtr->output_components);
+
+ printf("colorComponents: %d\n", cinfoPtr->output_components);
+
+#if 0
+ /* could now set additional values in cinfo
+ * (colormap)
+ */
+#endif
+ }
+%}
+
+!
+
+decompressChunk
+%{
+ struct jpeg_decompress_struct *cinfoPtr;
+ char *rgbRow;
+ OBJ j_d_s = __INST(jpeg_decompress_struct);
+ int num_scanlines;
+ JSAMPROW rowPointers[4];
+
+ if (__isExternalBytes(j_d_s)
+ && __isByteArray(__INST(decompressBuffer))) {
+ cinfoPtr = (struct jpeg_decompress_struct *)(__externalBytesAddress(j_d_s));
+ rgbRow = __ByteArrayInstPtr(__INST(decompressBuffer))->ba_element;
+
+ rowPointers[0] = (JSAMPROW) rgbRow;
+ rowPointers[1] = NULL;
+ rowPointers[2] = NULL;
+ rowPointers[3] = NULL;
+
+ if (cinfoPtr->output_scanline < cinfoPtr->output_height) {
+ num_scanlines = jpeg_read_scanlines(cinfoPtr,
+ rowPointers,
+ 1);
+ RETURN (__MKSMALLINT(num_scanlines));
+ }
+ RETURN (__MKSMALLINT(0));
+ }
+%}.
+ self halt.
+!
+
+decompressChunkInto:aByteArray startingAt:index
+%{
+ struct jpeg_decompress_struct *cinfoPtr;
+ char *rowPtr;
+ OBJ j_d_s = __INST(jpeg_decompress_struct);
+ int num_scanlines;
+ char *rowPointers[4];
+
+ if (__isExternalBytes(j_d_s)
+ && __isByteArray(aByteArray)) {
+ cinfoPtr = (struct jpeg_decompress_struct *)(__externalBytesAddress(j_d_s));
+ rowPtr = (char *)(__ByteArrayInstPtr(aByteArray)->ba_element);
+ rowPtr += __intVal(index) - 1;
+
+ rowPointers[0] = rowPtr;
+ rowPointers[1] = NULL;
+ rowPointers[2] = NULL;
+ rowPointers[3] = NULL;
+
+ if (cinfoPtr->output_scanline < cinfoPtr->output_height) {
+ num_scanlines = jpeg_read_scanlines(cinfoPtr,
+ rowPointers,
+ 1);
+ RETURN (__MKSMALLINT(num_scanlines));
+ }
+ RETURN (__MKSMALLINT(0));
+ }
+%}.
+ self halt.
+!
+
+finish_decompress
+%{
+ struct jpeg_decompress *cinfoPtr;
+ OBJ j_d_s = __INST(jpeg_decompress_struct);
+
+ if (__isExternalBytes(j_d_s)) {
+ cinfoPtr = (struct jpeg_decompress *)(__externalBytesAddress(j_d_s));
+
+ /* Start decompressor */
+ (void) jpeg_finish_decompress(cinfoPtr);
+ (void) jpeg_destroy_decompress(cinfoPtr);
+ }
+%}
+
+
+!
+
+start_decompress
+ decompressBuffer := ByteArray new:(width * colorComponents).
+
+%{
+ struct jpeg_decompress *cinfoPtr;
+ OBJ j_d_s = __INST(jpeg_decompress_struct);
+
+ if (__isExternalBytes(j_d_s)) {
+ cinfoPtr = (struct jpeg_decompress *)(__externalBytesAddress(j_d_s));
+
+ /* Start decompressor */
+ (void) jpeg_start_decompress(cinfoPtr);
+ }
+%}
+! !
+
+!JPEGReader methodsFor:'reading from stream'!
+
+fromStream:aStream
+ "read a JPG image from a stream"
+
+ |dataIdx bytesPerRow|
+
+ inStream := aStream.
+
+ self create_jpeg_decompress_struct.
+ self start_decompress.
+
+ data := ByteArray uninitializedNew:(width * height * colorComponents).
+ dataIdx := 1.
+ bytesPerRow := colorComponents * width.
+
+ [(self decompressChunkInto:data startingAt:dataIdx) ~~ 0] whileTrue:[
+ "/ got a row in the buffer ...
+ dataIdx := dataIdx + bytesPerRow
+ ].
+
+ self finish_decompress.
+
+ colorComponents == 3 ifTrue:[
+ photometric := #rgb.
+ samplesPerPixel := 3.
+ bitsPerSample := #(8 8 8).
+ ] ifFalse:[
+ self halt:'unexpected value'
+ ].
+
+ "
+ JPEGReader fromFile:'../../support/libjpeg-6a/testimg.jpg'
+ "
+ "
+ |stream reader|
+
+ stream := '../../support/libjpeg-6a/testimg.jpg' asFilename readStream.
+ reader := JPEGReader new.
+ reader forceGrayscale:true.
+ reader forceDitherMode:#ordered.
+ reader fromStream:stream.
+ ^ reader image
+ "
+
+ "Modified: 16.4.1997 / 20:36:12 / cg"
+! !
+
!JPEGReader class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libview2/JPEGReader.st,v 1.19 1997-04-11 14:44:54 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libview2/JPEGReader.st,v 1.20 1997-04-16 20:11:53 cg Exp $'
! !
JPEGReader initialize!