JPEGReader.st
changeset 528 e7bc0efceac9
parent 522 93a9f3a8caae
child 532 66aa3109df17
equal deleted inserted replaced
527:8c9d7178db4b 528:e7bc0efceac9
     8  be provided or otherwise made available to, or used by, any
     8  be provided or otherwise made available to, or used by, any
     9  other person.  No title to or ownership of the software is
     9  other person.  No title to or ownership of the software is
    10  hereby transferred.
    10  hereby transferred.
    11 "
    11 "
    12 
    12 
       
    13 'From Smalltalk/X, Version:3.1.6 on 16-apr-1997 at 9:09:50 pm'                  !
       
    14 
    13 ImageReader subclass:#JPEGReader
    15 ImageReader subclass:#JPEGReader
    14 	instanceVariableNames:''
    16 	instanceVariableNames:'jpeg_decompress_struct jpeg_error_mgr_struct decompressBuffer
       
    17 		colorComponents forceGrayscale forceDitherMode'
    15 	classVariableNames:''
    18 	classVariableNames:''
    16 	poolDictionaries:''
    19 	poolDictionaries:''
    17 	category:'Graphics-Images-Support'
    20 	category:'Graphics-Images-Support'
    18 !
    21 !
    19 
    22 
    23 /*
    26 /*
    24  * includes, defines, structure definitions
    27  * includes, defines, structure definitions
    25  * and typedefs come here.
    28  * and typedefs come here.
    26  */
    29  */
    27 
    30 
    28 #include <jpeglib.h>
    31 #include <stdio.h>
    29 #include <jerror.h>
    32 
       
    33 #ifndef NO_TESTING
       
    34 # include "../../support/libjpeg-6a/jpeglib.h"
       
    35 # include "../../support/libjpeg-6a/jerror.h"
       
    36 #else
       
    37 # include <jpeglib.h>
       
    38 # include <jerror.h>
       
    39 #endif
       
    40 
       
    41 %}
       
    42 ! !
       
    43 
       
    44 !JPEGReader primitiveFunctions!
       
    45 %{
       
    46 
       
    47 /* 
       
    48  * any local C (helper) functions
       
    49  * come here (please, define as static)
       
    50  */
       
    51 
       
    52 /*
       
    53  * Optional progress monitor: display a percent-done figure on stderr.
       
    54  */
       
    55 
       
    56 #ifdef PROGRESS_REPORT
       
    57 
       
    58 void
       
    59 JPG_progress_monitor (j_common_ptr cinfo)
       
    60 {
       
    61   cd_progress_ptr prog = (cd_progress_ptr) cinfo->progress;
       
    62   int total_passes = prog->pub.total_passes + prog->total_extra_passes;
       
    63   int percent_done = (int) (prog->pub.pass_counter*100L/prog->pub.pass_limit);
       
    64 
       
    65   if (percent_done != prog->percent_done) {
       
    66     prog->percent_done = percent_done;
       
    67     if (total_passes > 1) {
       
    68       fprintf(stderr, "\rPass %d/%d: %3d%% ",
       
    69               prog->pub.completed_passes + prog->completed_extra_passes + 1,
       
    70               total_passes, percent_done);
       
    71     } else {
       
    72       fprintf(stderr, "\r %3d%% ", percent_done);
       
    73     }
       
    74     fflush(stderr);
       
    75   }
       
    76 }
       
    77 
       
    78 
       
    79 void
       
    80 JPG_start_progress_monitor (j_common_ptr cinfo, cd_progress_ptr progress)
       
    81 {
       
    82   /* Enable progress display, unless trace output is on */
       
    83   if (cinfo->err->trace_level == 0) {
       
    84     progress->pub.progress_monitor = progress_monitor;
       
    85     progress->completed_extra_passes = 0;
       
    86     progress->total_extra_passes = 0;
       
    87     progress->percent_done = -1;
       
    88     cinfo->progress = &progress->pub;
       
    89   }
       
    90 }
       
    91 
       
    92 
       
    93 void
       
    94 JPG_end_progress_monitor (j_common_ptr cinfo)
       
    95 {
       
    96   /* Clear away progress display */
       
    97   if (cinfo->err->trace_level == 0) {
       
    98     fprintf(stderr, "\r                \r");
       
    99     fflush(stderr);
       
   100   }
       
   101 }
       
   102 
       
   103 #endif
    30 
   104 
    31 %}
   105 %}
    32 ! !
   106 ! !
    33 
   107 
    34 !JPEGReader class methodsFor:'documentation'!
   108 !JPEGReader class methodsFor:'documentation'!
    81     Image addReader:self suffix:'jpeg'.
   155     Image addReader:self suffix:'jpeg'.
    82 
   156 
    83     "Modified: 1.2.1997 / 15:01:55 / cg"
   157     "Modified: 1.2.1997 / 15:01:55 / cg"
    84 ! !
   158 ! !
    85 
   159 
    86 !JPEGReader class methodsFor:'reading from file'!
       
    87 
       
    88 fromFile:aFileName
       
    89     "read a jpg image from a file.
       
    90      Make it the easy way: let djpeg convert it to gif,
       
    91      then let GIFReader read the file."
       
    92 
       
    93     |tempFileName reader|
       
    94 
       
    95     tempFileName := '/tmp/img' , (OperatingSystem getProcessId printString).
       
    96 
       
    97     'JPEGREADER [info]: converting to ppm ..' infoPrintCR.
       
    98     (OperatingSystem executeCommand:'djpeg -pnm ' , aFileName , ' > ' , tempFileName)
       
    99     ifFalse:[
       
   100         (OperatingSystem executeCommand:'../../support/libjpeg/djpeg -pnm ' , aFileName , ' > ' , tempFileName)    
       
   101         ifFalse:[
       
   102             'JPEGREADER [warning]: conversion failed ..' errorPrintCR.
       
   103             'JPEGREADER [warning]: .. cannot execute converter: djpeg' errorPrintCR.
       
   104             ^ nil
       
   105         ].
       
   106     ].
       
   107 
       
   108     reader := PBMReader fromFile:tempFileName.
       
   109     OperatingSystem executeCommand:'rm ' , tempFileName.
       
   110     ^ reader
       
   111 
       
   112     "
       
   113      JPEGReader fromFile:'bitmaps/testimg.jpg'
       
   114     "
       
   115 
       
   116     "Modified: 11.4.1997 / 16:39:59 / cg"
       
   117 ! !
       
   118 
       
   119 !JPEGReader class methodsFor:'testing'!
   160 !JPEGReader class methodsFor:'testing'!
   120 
   161 
   121 isValidImageFile:aFileName
   162 isValidImageFile:aFileName
   122     "return true, if aFileName contains a JPG image.
   163     "return true, if aFileName contains a JPG image.
   123      Only look at the files name here ..."
   164      Only look at the files name here ..."
   127     ^ false
   168     ^ false
   128 
   169 
   129     "Created: 11.4.1997 / 16:26:25 / cg"
   170     "Created: 11.4.1997 / 16:26:25 / cg"
   130 ! !
   171 ! !
   131 
   172 
       
   173 !JPEGReader methodsFor:'accessing'!
       
   174 
       
   175 forceDitherMode:something
       
   176     "set the dither mode, to one of #none or #ordered"
       
   177 
       
   178     forceDitherMode := something.
       
   179 
       
   180     "Modified: 16.4.1997 / 20:34:59 / cg"
       
   181 !
       
   182 
       
   183 forceGrayscale:something
       
   184     "set the forceGrayscale mode; if true, grayScale images are
       
   185      returned, even if the input contains a color image."
       
   186 
       
   187     forceGrayscale := something.
       
   188 
       
   189     "Created: 16.4.1997 / 20:33:44 / cg"
       
   190     "Modified: 16.4.1997 / 20:34:29 / cg"
       
   191 ! !
       
   192 
       
   193 !JPEGReader methodsFor:'private'!
       
   194 
       
   195 create_jpeg_decompress_struct
       
   196     |structSize fp|
       
   197 
       
   198     fp := inStream filePointer.
       
   199     fp isNil ifTrue:[
       
   200         self error:'can only read from an external stream'.
       
   201         ^ self.
       
   202     ].
       
   203 
       
   204 %{
       
   205     structSize = __MKSMALLINT(sizeof(struct jpeg_error_mgr));
       
   206 %}.
       
   207 
       
   208     jpeg_error_mgr_struct := ExternalBytes unprotectedNew:structSize.
       
   209 
       
   210 %{
       
   211     structSize = __MKSMALLINT(sizeof(struct jpeg_decompress_struct));
       
   212 %}.
       
   213 
       
   214     jpeg_decompress_struct := ExternalBytes unprotectedNew:structSize.
       
   215 
       
   216 %{
       
   217     struct jpeg_decompress_struct *cinfoPtr;
       
   218     struct jpeg_error_mgr *jerrPtr;
       
   219     OBJ j_e_m = __INST(jpeg_error_mgr_struct);
       
   220     OBJ j_d_s = __INST(jpeg_decompress_struct);
       
   221     FILE *f = __FILEVal(fp);
       
   222 
       
   223     if (__isExternalBytes(j_d_s)
       
   224      && __isExternalBytes(j_e_m)) {
       
   225         cinfoPtr = (struct jpeg_decompress_struct *)(__externalBytesAddress(j_d_s));
       
   226         jerrPtr = (struct jpeg_error_mgr *)(__externalBytesAddress(j_e_m));
       
   227 
       
   228         /* 
       
   229          * Initialize the JPEG decompression object with default error handling.
       
   230          */
       
   231         cinfoPtr->err = jpeg_std_error(jerrPtr);
       
   232 
       
   233         jpeg_create_decompress(cinfoPtr);
       
   234 #if 0
       
   235         /* 
       
   236          * Insert custom COM marker processor.
       
   237          */
       
   238         jpeg_set_marker_processor(cinfoPtr, JPEG_COM, COM_handler);
       
   239 #endif
       
   240         cinfoPtr->err->trace_level = 0;
       
   241 
       
   242 #if 0
       
   243         /* colors setting */
       
   244         cinfoPtr->desired_number_of_colors = val;
       
   245         cinfoPtr->quantize_colors = TRUE;
       
   246 #endif
       
   247 #if 0
       
   248         /* dct setting */
       
   249         cinfoPtr->dct_method = JDCT_ISLOW;
       
   250         or: cinfoPtr->dct_method = JDCT_IFAST;
       
   251         or: cinfoPtr->dct_method = JDCT_FLOAT;
       
   252 #endif
       
   253 
       
   254         /* dither setting */
       
   255         cinfoPtr->dither_mode = JDITHER_FS;
       
   256         if (__INST(forceDitherMode) == @symbol(none)) {
       
   257             cinfoPtr->dither_mode = JDITHER_NONE;
       
   258         } else {
       
   259             if (__INST(forceDitherMode) == @symbol(ordered)) {
       
   260                 cinfoPtr->dither_mode = JDITHER_ORDERED;
       
   261             }
       
   262         }
       
   263 
       
   264 #if 0
       
   265         /* fast setting */
       
   266         cinfoPtr->two_pass_quantize = FALSE;
       
   267         cinfoPtr->dither_mode = JDITHER_ORDERED;
       
   268         cinfoPtr->desired_number_of_colors = 216;
       
   269         cinfoPtr->dct_method = JDCT_FASTEST;
       
   270         cinfoPtr->do_fancy_upsampling = FALSE;
       
   271 #endif
       
   272 
       
   273         if (__INST(forceGrayscale) == true) {
       
   274             /* grayscale setting */
       
   275             cinfoPtr->out_color_space = JCS_GRAYSCALE;
       
   276         }
       
   277 
       
   278 #if 0
       
   279         /* maxmemory setting */
       
   280         cinfoPtr->mem->max_memory_to_use = lval * 1000L;
       
   281 #endif
       
   282 #if 0
       
   283         /* nosmooth setting */
       
   284         cinfoPtr->do_fancy_upsampling = FALSE;
       
   285 #endif
       
   286 #if 0
       
   287         /* onepass setting */
       
   288         cinfoPtr->two_pass_quantize = FALSE;
       
   289 #endif
       
   290 
       
   291         /* Specify data source for decompression */
       
   292         jpeg_stdio_src(cinfoPtr, f);
       
   293 
       
   294         /* Read file header, set default decompression parameters */
       
   295         (void) jpeg_read_header(cinfoPtr, TRUE);
       
   296 
       
   297         /* Calculate output image dimensions so we can allocate space */
       
   298         jpeg_calc_output_dimensions(cinfoPtr);
       
   299 
       
   300         __INST(width) = __MKSMALLINT(cinfoPtr->output_width);
       
   301         __INST(height) = __MKSMALLINT(cinfoPtr->output_height);
       
   302         __INST(colorComponents) = __MKSMALLINT(cinfoPtr->output_components);
       
   303 
       
   304         printf("colorComponents: %d\n", cinfoPtr->output_components);
       
   305 
       
   306 #if 0
       
   307         /* could now set additional values in cinfo
       
   308          * (colormap)
       
   309          */
       
   310 #endif
       
   311     }
       
   312 %} 
       
   313 
       
   314 !
       
   315 
       
   316 decompressChunk
       
   317 %{
       
   318     struct jpeg_decompress_struct *cinfoPtr;
       
   319     char *rgbRow;
       
   320     OBJ j_d_s = __INST(jpeg_decompress_struct);
       
   321     int num_scanlines;
       
   322     JSAMPROW rowPointers[4];
       
   323 
       
   324     if (__isExternalBytes(j_d_s)
       
   325      && __isByteArray(__INST(decompressBuffer))) {
       
   326         cinfoPtr = (struct jpeg_decompress_struct *)(__externalBytesAddress(j_d_s));
       
   327         rgbRow = __ByteArrayInstPtr(__INST(decompressBuffer))->ba_element;
       
   328 
       
   329         rowPointers[0] = (JSAMPROW) rgbRow;
       
   330         rowPointers[1] = NULL;
       
   331         rowPointers[2] = NULL;
       
   332         rowPointers[3] = NULL;
       
   333 
       
   334         if (cinfoPtr->output_scanline < cinfoPtr->output_height) {
       
   335             num_scanlines = jpeg_read_scanlines(cinfoPtr, 
       
   336                                                 rowPointers,
       
   337                                                 1);
       
   338             RETURN (__MKSMALLINT(num_scanlines));
       
   339         }
       
   340         RETURN (__MKSMALLINT(0));
       
   341     }
       
   342 %}.
       
   343     self halt.
       
   344 !
       
   345 
       
   346 decompressChunkInto:aByteArray startingAt:index
       
   347 %{
       
   348     struct jpeg_decompress_struct *cinfoPtr;
       
   349     char *rowPtr;
       
   350     OBJ j_d_s = __INST(jpeg_decompress_struct);
       
   351     int num_scanlines;
       
   352     char *rowPointers[4];
       
   353 
       
   354     if (__isExternalBytes(j_d_s)
       
   355      && __isByteArray(aByteArray)) {
       
   356         cinfoPtr = (struct jpeg_decompress_struct *)(__externalBytesAddress(j_d_s));
       
   357         rowPtr = (char *)(__ByteArrayInstPtr(aByteArray)->ba_element);
       
   358         rowPtr += __intVal(index) - 1;
       
   359 
       
   360         rowPointers[0] = rowPtr;
       
   361         rowPointers[1] = NULL;
       
   362         rowPointers[2] = NULL;
       
   363         rowPointers[3] = NULL;
       
   364 
       
   365         if (cinfoPtr->output_scanline < cinfoPtr->output_height) {
       
   366             num_scanlines = jpeg_read_scanlines(cinfoPtr, 
       
   367                                                 rowPointers,
       
   368                                                 1);
       
   369             RETURN (__MKSMALLINT(num_scanlines));
       
   370         }
       
   371         RETURN (__MKSMALLINT(0));
       
   372     }
       
   373 %}.
       
   374     self halt.
       
   375 !
       
   376 
       
   377 finish_decompress
       
   378 %{
       
   379     struct jpeg_decompress *cinfoPtr;
       
   380     OBJ j_d_s = __INST(jpeg_decompress_struct);
       
   381 
       
   382     if (__isExternalBytes(j_d_s)) {
       
   383         cinfoPtr = (struct jpeg_decompress *)(__externalBytesAddress(j_d_s));
       
   384 
       
   385         /* Start decompressor */
       
   386         (void) jpeg_finish_decompress(cinfoPtr);
       
   387         (void) jpeg_destroy_decompress(cinfoPtr);
       
   388     }
       
   389 %}
       
   390 
       
   391 
       
   392 !
       
   393 
       
   394 start_decompress
       
   395     decompressBuffer := ByteArray new:(width * colorComponents).
       
   396 
       
   397 %{
       
   398     struct jpeg_decompress *cinfoPtr;
       
   399     OBJ j_d_s = __INST(jpeg_decompress_struct);
       
   400 
       
   401     if (__isExternalBytes(j_d_s)) {
       
   402         cinfoPtr = (struct jpeg_decompress *)(__externalBytesAddress(j_d_s));
       
   403 
       
   404         /* Start decompressor */
       
   405         (void) jpeg_start_decompress(cinfoPtr);
       
   406     }
       
   407 %}
       
   408 ! !
       
   409 
       
   410 !JPEGReader methodsFor:'reading from stream'!
       
   411 
       
   412 fromStream:aStream
       
   413     "read a JPG image from a stream"
       
   414 
       
   415     |dataIdx bytesPerRow|
       
   416 
       
   417     inStream := aStream.
       
   418 
       
   419     self create_jpeg_decompress_struct.
       
   420     self start_decompress.
       
   421 
       
   422     data := ByteArray uninitializedNew:(width * height * colorComponents).
       
   423     dataIdx := 1.
       
   424     bytesPerRow := colorComponents * width.
       
   425 
       
   426     [(self decompressChunkInto:data startingAt:dataIdx) ~~ 0] whileTrue:[
       
   427         "/ got a row in the buffer ...
       
   428         dataIdx := dataIdx + bytesPerRow
       
   429     ].    
       
   430 
       
   431     self finish_decompress.
       
   432 
       
   433     colorComponents == 3 ifTrue:[
       
   434         photometric := #rgb.
       
   435         samplesPerPixel := 3.
       
   436         bitsPerSample := #(8 8 8).
       
   437     ] ifFalse:[
       
   438         self halt:'unexpected value'
       
   439     ].
       
   440 
       
   441     "
       
   442      JPEGReader fromFile:'../../support/libjpeg-6a/testimg.jpg'
       
   443     "
       
   444     "
       
   445      |stream reader|
       
   446 
       
   447      stream := '../../support/libjpeg-6a/testimg.jpg' asFilename readStream.
       
   448      reader := JPEGReader new.
       
   449      reader forceGrayscale:true.
       
   450      reader forceDitherMode:#ordered.
       
   451      reader fromStream:stream.
       
   452      ^ reader image
       
   453     "
       
   454 
       
   455     "Modified: 16.4.1997 / 20:36:12 / cg"
       
   456 ! !
       
   457 
   132 !JPEGReader class methodsFor:'documentation'!
   458 !JPEGReader class methodsFor:'documentation'!
   133 
   459 
   134 version
   460 version
   135     ^ '$Header: /cvs/stx/stx/libview2/JPEGReader.st,v 1.19 1997-04-11 14:44:54 cg Exp $'
   461     ^ '$Header: /cvs/stx/stx/libview2/JPEGReader.st,v 1.20 1997-04-16 20:11:53 cg Exp $'
   136 ! !
   462 ! !
   137 JPEGReader initialize!
   463 JPEGReader initialize!