Image.st
changeset 4717 c25149336a26
parent 4620 a9d593b2a056
child 4725 c8896df7bd3f
equal deleted inserted replaced
4716:d4fb48e2c72d 4717:c25149336a26
    45 
    45 
    46 documentation
    46 documentation
    47 "
    47 "
    48     this class provides (some time in the future) representation
    48     this class provides (some time in the future) representation
    49     for all kinds of images (monochrome, greyscale and color)
    49     for all kinds of images (monochrome, greyscale and color)
    50     and will finally replace Form. 
    50     and will finally replace Form.
    51     For now (only ;-) depths of 1, 2, 4, 8, 16 and 24 are supported.
    51     For now (only ;-) depths of 1, 2, 4, 8, 16 and 24 are supported.
    52 
    52 
    53     An Image keeps all of its information in a device independent way, 
    53     An Image keeps all of its information in a device independent way,
    54     but may be associated to a device. 
    54     but may be associated to a device.
    55     The data held keeps all information which was originally present, 
    55     The data held keeps all information which was originally present,
    56     even if the display-device has lower resolution.
    56     even if the display-device has lower resolution.
    57     Therefore, it is possible to process and manipulate images without loosing 
    57     Therefore, it is possible to process and manipulate images without loosing
    58     color information.
    58     color information.
    59 
    59 
    60     Images may be created manually (by providing a pixel array),
    60     Images may be created manually (by providing a pixel array),
    61     by screen capture or by reading a file (using an ImageReader).
    61     by screen capture or by reading a file (using an ImageReader).
    62     This gives a device independent image.
    62     This gives a device independent image.
    63     For display, a device representation is required, which can be
    63     For display, a device representation is required, which can be
    64     aquired by sending the 
    64     aquired by sending the
    65 	'onDevice:aDevice' 
    65 	'onDevice:aDevice'
    66     message to the image. This will create a (possibly dithered) device-form, 
    66     message to the image. This will create a (possibly dithered) device-form,
    67     representing the image using the currently available colors.
    67     representing the image using the currently available colors.
    68 
    68 
    69     In rare cases, an explicit monochrome representation of the image is needed 
    69     In rare cases, an explicit monochrome representation of the image is needed
    70     (X servers take monochrome icons only), this can be created by sending
    70     (X servers take monochrome icons only), this can be created by sending
    71     it the message 
    71     it the message
    72 	'monochromeOn:aDevice'.
    72 	'monochromeOn:aDevice'.
    73 
    73 
    74     Also, it is planned to generate another hi-color resolution version,
    74     Also, it is planned to generate another hi-color resolution version,
    75     which uses its own colormap and allows the use of all 256 colors on an 8bit display 
    75     which uses its own colormap and allows the use of all 256 colors on an 8bit display
    76     (this is not currently implemented).
    76     (this is not currently implemented).
    77 
    77 
    78     An images pixel interpretation is controlled by the photometric instance variable
    78     An images pixel interpretation is controlled by the photometric instance variable
    79     and (if that is #palette) a colorMap.
    79     and (if that is #palette) a colorMap.
    80     This is in contrast to the ST-80 way, where all of this info is in the colorMap
    80     This is in contrast to the ST-80 way, where all of this info is in the colorMap
    81     (and using specialized colorMaps for b&w / greyScale images).
    81     (and using specialized colorMaps for b&w / greyScale images).
    82     This may change in future versions for more application compatibility.
    82     This may change in future versions for more application compatibility.
    83 
    83 
    84     To convert pictures from/to external file-formats, image readers are used
    84     To convert pictures from/to external file-formats, image readers are used
    85     which have the file-format knowledge built in. 
    85     which have the file-format knowledge built in.
    86     There are readers for most common formats available 
    86     There are readers for most common formats available
    87     (see ImageReader and especially subclasses such as TIFFReader, GIFReader etc.).
    87     (see ImageReader and especially subclasses such as TIFFReader, GIFReader etc.).
    88 
    88 
    89     File formats are handled by subclasses of ImageReader, which understand
    89     File formats are handled by subclasses of ImageReader, which understand
    90     a specific format. You can add more readers, by adding an association
    90     a specific format. You can add more readers, by adding an association
    91     such as ('.jpg' -> JPEGReader) to the class variable 'FileFormats' 
    91     such as ('.jpg' -> JPEGReader) to the class variable 'FileFormats'
    92     (see the classes #initialize method, which sets up some default, and the
    92     (see the classes #initialize method, which sets up some default, and the
    93     patches/display.rc files, which add more).
    93     patches/display.rc files, which add more).
    94 
    94 
    95     Some algorithms used here (especially dithering & color allocation) are
    95     Some algorithms used here (especially dithering & color allocation) are
    96     experimental and far from being perfect (some are very slow). 
    96     experimental and far from being perfect (some are very slow).
    97     For now, the most common cases have been optimized and perform reasonably
    97     For now, the most common cases have been optimized and perform reasonably
    98     fast - however, with uncommon depth/visualType combinations, you may
    98     fast - however, with uncommon depth/visualType combinations, you may
    99     run into slower fallback methods ...
    99     run into slower fallback methods ...
   100 
   100 
   101     Much more work is needed if you plan to do heavy image processing and will
   101     Much more work is needed if you plan to do heavy image processing and will
   156 					    image was loaded - nil otherwise.
   156 					    image was loaded - nil otherwise.
   157 					    Useful for image save functions
   157 					    Useful for image save functions
   158 					    and for the UIPainter utility.
   158 					    and for the UIPainter utility.
   159 
   159 
   160 	imageSequence                       the imageSequence, of which the
   160 	imageSequence                       the imageSequence, of which the
   161 					    instance is a frame or nil, 
   161 					    instance is a frame or nil,
   162 					    if its not part of a sequence.
   162 					    if its not part of a sequence.
   163 
   163 
   164 	bitsPerPixel                        not used in ST/X
   164 	bitsPerPixel                        not used in ST/X
   165 	depth                               - these have been added in instVar-slots
   165 	depth                               - these have been added in instVar-slots
   166 	maxPixelValue                       - according to the ST-80's image class.
   166 	maxPixelValue                       - according to the ST-80's image class.
   188 					    Default is true.
   188 					    Default is true.
   189 
   189 
   190 	ImageNotFoundQuerySignal
   190 	ImageNotFoundQuerySignal
   191 			    <QuerySignal>   raised, if an image could not be loaded
   191 			    <QuerySignal>   raised, if an image could not be loaded
   192 					    from a file. The parameter is the images
   192 					    from a file. The parameter is the images
   193 					    fileName. 
   193 					    fileName.
   194 					    A handler may return a replacement
   194 					    A handler may return a replacement
   195 					    image or proceed with nil.
   195 					    image or proceed with nil.
   196 					    If unhandled, a nil is returned from the
   196 					    If unhandled, a nil is returned from the
   197 					    image creation.
   197 					    image creation.
   198 
   198 
   199 	BadImageFormatQuerySignal
   199 	BadImageFormatQuerySignal
   200 			    <QuerySignal>   raised, if an image could not be loaded
   200 			    <QuerySignal>   raised, if an image could not be loaded
   201 					    from a file due to a file error or
   201 					    from a file due to a file error or
   202 					    unsupported format. 
   202 					    unsupported format.
   203 					    A handler may return a replacement
   203 					    A handler may return a replacement
   204 					    image or proceed with nil.
   204 					    image or proceed with nil.
   205 					    If unhandled, a nil is returned from the
   205 					    If unhandled, a nil is returned from the
   206 					    image creation.
   206 					    image creation.
   207 
   207 
   314 
   314 
   315       a depth4 greyScale image:
   315       a depth4 greyScale image:
   316       (default photometric is #blackIs0)
   316       (default photometric is #blackIs0)
   317 									[exBegin]
   317 									[exBegin]
   318 	(Depth4Image
   318 	(Depth4Image
   319 	     width:8 
   319 	     width:8
   320 	     height:4
   320 	     height:4
   321 	     fromArray:#[ 
   321 	     fromArray:#[
   322 			    16r00 16r11 16r22 16r33
   322 			    16r00 16r11 16r22 16r33
   323 			    16r44 16r55 16r66 16r77
   323 			    16r44 16r55 16r66 16r77
   324 			    16r88 16r99 16raa 16rbb
   324 			    16r88 16r99 16raa 16rbb
   325 			    16rcc 16rdd 16ree 16rff 
   325 			    16rcc 16rdd 16ree 16rff
   326 			]) inspect
   326 			]) inspect
   327 									[exEnd]
   327 									[exEnd]
   328       the same, magnified:
   328       the same, magnified:
   329 									[exBegin]
   329 									[exBegin]
   330 	((Depth4Image
   330 	((Depth4Image
   331 	     width:4 
   331 	     width:4
   332 	     height:4
   332 	     height:4
   333 	     fromArray:#[ 
   333 	     fromArray:#[
   334 			    16r01 16r23
   334 			    16r01 16r23
   335 			    16r45 16r67
   335 			    16r45 16r67
   336 			    16r89 16rab
   336 			    16r89 16rab
   337 			    16rcd 16ref 
   337 			    16rcd 16ref
   338 			])
   338 			])
   339 	    magnifiedBy:30)
   339 	    magnifiedBy:30)
   340 		 inspect
   340 		 inspect
   341 									[exEnd]
   341 									[exEnd]
   342       the following has the same effect:
   342       the following has the same effect:
   343 									[exBegin]
   343 									[exBegin]
   344 	((Image
   344 	((Image
   345 	     width:4 
   345 	     width:4
   346 	     height:4
   346 	     height:4
   347 	     depth:4
   347 	     depth:4
   348 	     fromArray:#[ 
   348 	     fromArray:#[
   349 			    16r01 16r23
   349 			    16r01 16r23
   350 			    16r45 16r67
   350 			    16r45 16r67
   351 			    16r89 16rab
   351 			    16r89 16rab
   352 			    16rcd 16ref 
   352 			    16rcd 16ref
   353 			])
   353 			])
   354 	    magnifiedBy:30)
   354 	    magnifiedBy:30)
   355 		 inspect
   355 		 inspect
   356 									[exEnd]
   356 									[exEnd]
   357       with reverse grey-interpretation:
   357       with reverse grey-interpretation:
   358 									[exBegin]
   358 									[exBegin]
   359 	((Depth4Image
   359 	((Depth4Image
   360 	     width:4 
   360 	     width:4
   361 	     height:4
   361 	     height:4
   362 	     fromArray:#[ 
   362 	     fromArray:#[
   363 			    16r01 16r23
   363 			    16r01 16r23
   364 			    16r45 16r67
   364 			    16r45 16r67
   365 			    16r89 16rab
   365 			    16r89 16rab
   366 			    16rcd 16ref 
   366 			    16rcd 16ref
   367 			])
   367 			])
   368 	    photometric:#whiteIs0;
   368 	    photometric:#whiteIs0;
   369 	    magnifiedBy:30)
   369 	    magnifiedBy:30)
   370 		 inspect
   370 		 inspect
   371 									[exEnd]
   371 									[exEnd]
   372 
   372 
   373       with 1-bit-per-pixel rgb interpretation:
   373       with 1-bit-per-pixel rgb interpretation:
   374 									[exBegin]
   374 									[exBegin]
   375 	((Depth4Image
   375 	((Depth4Image
   376 	     width:4 
   376 	     width:4
   377 	     height:4
   377 	     height:4
   378 	     fromArray:#[ 
   378 	     fromArray:#[
   379 			    16r01 16r23
   379 			    16r01 16r23
   380 			    16r45 16r67
   380 			    16r45 16r67
   381 			    16r89 16rab
   381 			    16r89 16rab
   382 			    16rcd 16ref 
   382 			    16rcd 16ref
   383 			])
   383 			])
   384 	    photometric:#rgb;
   384 	    photometric:#rgb;
   385 	    samplesPerPixel:3;
   385 	    samplesPerPixel:3;
   386 	    bitsPerSample:#(1 1 1);
   386 	    bitsPerSample:#(1 1 1);
   387 	    magnifiedBy:30)
   387 	    magnifiedBy:30)
   389 									[exEnd]
   389 									[exEnd]
   390 
   390 
   391       with 1/2/1 rgb interpretation:
   391       with 1/2/1 rgb interpretation:
   392 									[exBegin]
   392 									[exBegin]
   393 	((Depth4Image
   393 	((Depth4Image
   394 	     width:4 
   394 	     width:4
   395 	     height:4
   395 	     height:4
   396 	     fromArray:#[ 
   396 	     fromArray:#[
   397 			    16r01 16r23
   397 			    16r01 16r23
   398 			    16r45 16r67
   398 			    16r45 16r67
   399 			    16r89 16rab
   399 			    16r89 16rab
   400 			    16rcd 16ref 
   400 			    16rcd 16ref
   401 			])
   401 			])
   402 	    photometric:#rgb;
   402 	    photometric:#rgb;
   403 	    samplesPerPixel:3;
   403 	    samplesPerPixel:3;
   404 	    bitsPerSample:#(1 2 1);
   404 	    bitsPerSample:#(1 2 1);
   405 	    magnifiedBy:30)
   405 	    magnifiedBy:30)
   447 
   447 
   448 
   448 
   449       a 2plane greyscale image:
   449       a 2plane greyscale image:
   450 									[exBegin]
   450 									[exBegin]
   451 	((Depth2Image
   451 	((Depth2Image
   452 	     width:4 
   452 	     width:4
   453 	     height:4
   453 	     height:4
   454 	     fromArray:#[ 
   454 	     fromArray:#[
   455 			    4r0123
   455 			    4r0123
   456 			    4r1230
   456 			    4r1230
   457 			    4r2301
   457 			    4r2301
   458 			    4r3012 
   458 			    4r3012
   459 			])
   459 			])
   460 	    magnifiedBy:30)
   460 	    magnifiedBy:30)
   461 		 inspect
   461 		 inspect
   462 									[exEnd]
   462 									[exEnd]
   463 
   463 
   464       with colors:
   464       with colors:
   465 									[exBegin]
   465 									[exBegin]
   466 	((Depth2Image
   466 	((Depth2Image
   467 	     width:4 
   467 	     width:4
   468 	     height:4
   468 	     height:4
   469 	     fromArray:#[ 
   469 	     fromArray:#[
   470 			    4r0123
   470 			    4r0123
   471 			    4r1230
   471 			    4r1230
   472 			    4r2301
   472 			    4r2301
   473 			    4r3012 
   473 			    4r3012
   474 			])
   474 			])
   475 	    colorMap:(Array with:(Color black)
   475 	    colorMap:(Array with:(Color black)
   476 			    with:(Color red)
   476 			    with:(Color red)
   477 			    with:(Color green)
   477 			    with:(Color green)
   478 			    with:(Color blue));
   478 			    with:(Color blue));
   481 									[exEnd]
   481 									[exEnd]
   482 
   482 
   483       depth8 image with 3/3/2 rgb interpretation:
   483       depth8 image with 3/3/2 rgb interpretation:
   484 									[exBegin]
   484 									[exBegin]
   485 	((Depth8Image
   485 	((Depth8Image
   486 	     width:16 
   486 	     width:16
   487 	     height:16
   487 	     height:16
   488 	     fromArray:(ByteArray withAll:(0 to:16rFF)))
   488 	     fromArray:(ByteArray withAll:(0 to:16rFF)))
   489 	    photometric:#rgb;
   489 	    photometric:#rgb;
   490 	    samplesPerPixel:3;
   490 	    samplesPerPixel:3;
   491 	    bitsPerSample:#(3 3 2);
   491 	    bitsPerSample:#(3 3 2);
   494 									[exEnd]
   494 									[exEnd]
   495 
   495 
   496       depth8 image with 2/2/2 rgb interpretation:
   496       depth8 image with 2/2/2 rgb interpretation:
   497 									[exBegin]
   497 									[exBegin]
   498 	((Depth8Image
   498 	((Depth8Image
   499 	     width:8 
   499 	     width:8
   500 	     height:8
   500 	     height:8
   501 	     fromArray:(ByteArray withAll:(0 to:16r3F)))
   501 	     fromArray:(ByteArray withAll:(0 to:16r3F)))
   502 	    photometric:#rgb;
   502 	    photometric:#rgb;
   503 	    samplesPerPixel:3;
   503 	    samplesPerPixel:3;
   504 	    bitsPerSample:#(2 2 2);
   504 	    bitsPerSample:#(2 2 2);
   507 									[exEnd]
   507 									[exEnd]
   508 
   508 
   509       trueColor image:
   509       trueColor image:
   510 									[exBegin]
   510 									[exBegin]
   511 	((Depth24Image
   511 	((Depth24Image
   512 	     width:4 
   512 	     width:4
   513 	     height:4
   513 	     height:4
   514 	     fromArray:#[ 
   514 	     fromArray:#[
   515 		    16rFF 16r00 16r00  16rFF 16r00 16r00  16rFF 16r00 16r00  16rFF 16r00 16r00
   515 		    16rFF 16r00 16r00  16rFF 16r00 16r00  16rFF 16r00 16r00  16rFF 16r00 16r00
   516 		    16r00 16rFF 16r00  16r00 16rFF 16r00  16r00 16rFF 16r00  16r00 16rFF 16r00
   516 		    16r00 16rFF 16r00  16r00 16rFF 16r00  16r00 16rFF 16r00  16r00 16rFF 16r00
   517 		    16r00 16r00 16rFF  16r00 16r00 16rFF  16r00 16r00 16rFF  16r00 16r00 16rFF 
   517 		    16r00 16r00 16rFF  16r00 16r00 16rFF  16r00 16r00 16rFF  16r00 16r00 16rFF
   518 		    16rFF 16rFF 16rFF  16rFF 16rFF 16rFF  16rFF 16rFF 16rFF  16rFF 16rFF 16rFF
   518 		    16rFF 16rFF 16rFF  16rFF 16rFF 16rFF  16rFF 16rFF 16rFF  16rFF 16rFF 16rFF
   519 			])
   519 			])
   520 	    photometric:#rgb;
   520 	    photometric:#rgb;
   521 	    samplesPerPixel:3;
   521 	    samplesPerPixel:3;
   522 	    bitsPerSample:#(8 8 8);
   522 	    bitsPerSample:#(8 8 8);
   533 	(Image fromFile:'myImage.tiff') inspect
   533 	(Image fromFile:'myImage.tiff') inspect
   534 									[exEnd]
   534 									[exEnd]
   535 
   535 
   536     magnifying (any factor):
   536     magnifying (any factor):
   537 									[exBegin]
   537 									[exBegin]
   538 	((Image fromFile:'goodies/bitmaps/gifImages/claus.gif') 
   538 	((Image fromFile:'goodies/bitmaps/gifImages/claus.gif')
   539 	    magnifiedTo:(48@48))
   539 	    magnifiedTo:(48@48))
   540 		inspect
   540 		inspect
   541 									[exEnd]
   541 									[exEnd]
   542 									[exBegin]
   542 									[exBegin]
   543 	((Image fromFile:'goodies/bitmaps/gifImages/claus.gif') 
   543 	((Image fromFile:'goodies/bitmaps/gifImages/claus.gif')
   544 	    magnifiedBy:0.7)
   544 	    magnifiedBy:0.7)
   545 		inspect
   545 		inspect
   546 									[exEnd]
   546 									[exEnd]
   547 
   547 
   548     rotating:
   548     rotating:
   549 									[exBegin]
   549 									[exBegin]
   550 	((Image fromFile:'goodies/bitmaps/gifImages/claus.gif') 
   550 	((Image fromFile:'goodies/bitmaps/gifImages/claus.gif')
   551 	    rotated:90)
   551 	    rotated:90)
   552 		inspect
   552 		inspect
   553 									[exEnd]
   553 									[exEnd]
   554 									[exBegin]
   554 									[exBegin]
   555 	(((Image fromFile:'goodies/bitmaps/gifImages/claus.gif') 
   555 	(((Image fromFile:'goodies/bitmaps/gifImages/claus.gif')
   556 	    magnifiedBy:0.3@0.7) rotated:270)
   556 	    magnifiedBy:0.3@0.7) rotated:270)
   557 		inspect
   557 		inspect
   558 									[exEnd]
   558 									[exEnd]
   559 									[exBegin]
   559 									[exBegin]
   560 	(((Image fromFile:'goodies/bitmaps/gifImages/claus.gif') 
   560 	(((Image fromFile:'goodies/bitmaps/gifImages/claus.gif')
   561 	    ) rotated:30)
   561 	    ) rotated:30)
   562 		inspect
   562 		inspect
   563 									[exEnd]
   563 									[exEnd]
   564     negative:
   564     negative:
   565 									[exBegin]
   565 									[exBegin]
   566 	((Image fromFile:'goodies/bitmaps/gifImages/claus.gif') 
   566 	((Image fromFile:'goodies/bitmaps/gifImages/claus.gif')
   567 	    negative)
   567 	    negative)
   568 		inspect
   568 		inspect
   569 									[exEnd]
   569 									[exEnd]
   570 "
   570 "
   571 ! !
   571 ! !
   627     "setup tracker of known pictures"
   627     "setup tracker of known pictures"
   628     Lobby isNil ifTrue:[
   628     Lobby isNil ifTrue:[
   629 	Lobby := Registry new.
   629 	Lobby := Registry new.
   630 	ObjectMemory addDependent:self.
   630 	ObjectMemory addDependent:self.
   631 
   631 
   632 	"/ define the algorithm to use for dithering - 
   632 	"/ define the algorithm to use for dithering -
   633 	"/ supported values are:
   633 	"/ supported values are:
   634 	"/      #threshold
   634 	"/      #threshold
   635 	"/      #ordered
   635 	"/      #ordered
   636 	"/      #floydSteinberg
   636 	"/      #floydSteinberg
   637 	"/      #burkes
   637 	"/      #burkes
   638 
   638 
   639 	DitherAlgorithm := #floydSteinberg.   
   639 	DitherAlgorithm := #floydSteinberg.
   640 
   640 
   641 	(Display notNil and:[Display hasGrayscales]) ifFalse:[
   641 	(Display notNil and:[Display hasGrayscales]) ifFalse:[
   642 	    NumberOfDitherColors := 64
   642 	    NumberOfDitherColors := 64
   643 	] ifTrue:[
   643 	] ifTrue:[
   644 	    "as far as I remember, this is about the number of grey values, the eye can distinguish"
   644 	    "as far as I remember, this is about the number of grey values, the eye can distinguish"
   689     "initialize a default table to map from file extension to reader class.
   689     "initialize a default table to map from file extension to reader class.
   690      The mapping here is a default needed for proper operation of ST/X;
   690      The mapping here is a default needed for proper operation of ST/X;
   691      see the 'smalltalk.rc'/'display.rc' startup files for a real (full) map."
   691      see the 'smalltalk.rc'/'display.rc' startup files for a real (full) map."
   692 
   692 
   693     MIMETypes notNil ifTrue:[
   693     MIMETypes notNil ifTrue:[
   694         MIMETypes imageReaderForSuffix:'xbm'  put:XBMReader.
   694 	MIMETypes imageReaderForSuffix:'xbm'  put:XBMReader.
   695         MIMETypes imageReaderForSuffix:'tiff' put:TIFFReader.
   695 	MIMETypes imageReaderForSuffix:'tiff' put:TIFFReader.
   696         MIMETypes imageReaderForSuffix:'gif'  put:GIFReader.
   696 	MIMETypes imageReaderForSuffix:'gif'  put:GIFReader.
   697     ].
   697     ].
   698 
   698 
   699     "
   699     "
   700      Image initializeFileFormatTable
   700      Image initializeFileFormatTable
   701     "
   701     "
   707     "initialize a default table to map from mime type to reader class.
   707     "initialize a default table to map from mime type to reader class.
   708      The mapping here is a default needed for proper operation of ST/X;
   708      The mapping here is a default needed for proper operation of ST/X;
   709      see the 'smalltalk.rc'/'display.rc' startup files for a real (full) map."
   709      see the 'smalltalk.rc'/'display.rc' startup files for a real (full) map."
   710 
   710 
   711     MIMETypes notNil ifTrue:[
   711     MIMETypes notNil ifTrue:[
   712         MIMETypes mimeTypeForSuffix:'gif'       put:'image/gif'.
   712 	MIMETypes mimeTypeForSuffix:'gif'       put:'image/gif'.
   713         MIMETypes mimeTypeForSuffix:'tiff'      put:'image/tiff'.
   713 	MIMETypes mimeTypeForSuffix:'tiff'      put:'image/tiff'.
   714         MIMETypes mimeTypeForSuffix:'tif'       put:'image/tiff'.
   714 	MIMETypes mimeTypeForSuffix:'tif'       put:'image/tiff'.
   715         MIMETypes mimeTypeForSuffix:'xbm'       put:'image/x-xbitmap'.
   715 	MIMETypes mimeTypeForSuffix:'xbm'       put:'image/x-xbitmap'.
   716         MIMETypes mimeTypeForSuffix:'xpm'       put:'image/x-xpixmap'.
   716 	MIMETypes mimeTypeForSuffix:'xpm'       put:'image/x-xpixmap'.
   717     ].
   717     ].
   718 
   718 
   719     "
   719     "
   720      Image initializeMIMETable
   720      Image initializeMIMETable
   721     "
   721     "
   735 ! !
   735 ! !
   736 
   736 
   737 !Image class methodsFor:'instance creation'!
   737 !Image class methodsFor:'instance creation'!
   738 
   738 
   739 extent:ext
   739 extent:ext
   740     "create a new image, given extent. 
   740     "create a new image, given extent.
   741      Assume a depth of 1, unless an explicit imageClass is the receiver."
   741      Assume a depth of 1, unless an explicit imageClass is the receiver."
   742 
   742 
   743     ^ self width:(ext x) height:(ext y)
   743     ^ self width:(ext x) height:(ext y)
   744 
   744 
   745     "Created: / 30.9.1998 / 22:31:26 / cg"
   745     "Created: / 30.9.1998 / 22:31:26 / cg"
   747 !
   747 !
   748 
   748 
   749 extent:ext depth:d
   749 extent:ext depth:d
   750     "ST-80 compatibility"
   750     "ST-80 compatibility"
   751 
   751 
   752     ^ self width:ext x height:ext y depth:d 
   752     ^ self width:ext x height:ext y depth:d
   753 !
   753 !
   754 
   754 
   755 extent:ext depth:d bits:bits
   755 extent:ext depth:d bits:bits
   756     "ST-80 compatibility; assume 32-bit padding"
   756     "ST-80 compatibility; assume 32-bit padding"
   757 
   757 
   876 
   876 
   877 fromImage:anImage photometric:photometricOrNil
   877 fromImage:anImage photometric:photometricOrNil
   878     "create & return an Image given another image. This can be used to
   878     "create & return an Image given another image. This can be used to
   879      convert an image to another depth."
   879      convert an image to another depth."
   880 
   880 
   881     (self == Image 
   881     (self == Image
   882     or:[anImage class == self 
   882     or:[anImage class == self
   883 	and:[photometricOrNil isNil or:[photometricOrNil == anImage photometric]]]) ifTrue:[^ anImage].
   883 	and:[photometricOrNil isNil or:[photometricOrNil == anImage photometric]]]) ifTrue:[^ anImage].
   884     ^ self new fromImage:anImage photometric:photometricOrNil.
   884     ^ self new fromImage:anImage photometric:photometricOrNil.
   885 
   885 
   886     "
   886     "
   887      |i1 i8|
   887      |i1 i8|
   944      (Image fromSubForm:(5@5 corner:10@10) in:f) inspect
   944      (Image fromSubForm:(5@5 corner:10@10) in:f) inspect
   945     "
   945     "
   946 !
   946 !
   947 
   947 
   948 fromSubImage:anImage in:aRectangle
   948 fromSubImage:anImage in:aRectangle
   949     "create & return an Image from a rectangular area in another image. 
   949     "create & return an Image from a rectangular area in another image.
   950      This can also be used to get a subimage in another depth."
   950      This can also be used to get a subimage in another depth."
   951 
   951 
   952     |cls newImage|
   952     |cls newImage|
   953 
   953 
   954     self == Image ifTrue:[
   954     self == Image ifTrue:[
   955         cls := (self implementorForDepth:anImage depth).
   955 	cls := (self implementorForDepth:anImage depth).
   956     ] ifFalse:[
   956     ] ifFalse:[
   957         cls := self.
   957 	cls := self.
   958     ].
   958     ].
   959     newImage := cls new.
   959     newImage := cls new.
   960     ^ newImage fromSubImage:anImage in:aRectangle.
   960     ^ newImage fromSubImage:anImage in:aRectangle.
   961 
   961 
   962     "
   962     "
  1033 width:w height:h depth:d fromArray:pixelData
  1033 width:w height:h depth:d fromArray:pixelData
  1034     "create a new image, given width, height, depth and data.
  1034     "create a new image, given width, height, depth and data.
  1035      Data must be a ByteArray containing correctly aligned bits for the specified
  1035      Data must be a ByteArray containing correctly aligned bits for the specified
  1036      depth (8-bit padded)."
  1036      depth (8-bit padded)."
  1037 
  1037 
  1038     ^ (self newForDepth:d) 
  1038     ^ (self newForDepth:d)
  1039 	width:w height:h depth:d fromArray:pixelData
  1039 	width:w height:h depth:d fromArray:pixelData
  1040 
  1040 
  1041     "
  1041     "
  1042      Image width:8 
  1042      Image width:8
  1043 	   height:8
  1043 	   height:8
  1044 	   depth:1
  1044 	   depth:1
  1045 	   fromArray:#[2r11001100
  1045 	   fromArray:#[2r11001100
  1046 		       2r00110011
  1046 		       2r00110011
  1047 		       2r11001100
  1047 		       2r11001100
  1051 		       2r11001100
  1051 		       2r11001100
  1052 		       2r00110011].
  1052 		       2r00110011].
  1053     "
  1053     "
  1054 
  1054 
  1055     "
  1055     "
  1056      Image width:8 
  1056      Image width:8
  1057 	   height:8
  1057 	   height:8
  1058 	   depth:2 
  1058 	   depth:2
  1059 	   fromArray:#[4r1100 4r1100
  1059 	   fromArray:#[4r1100 4r1100
  1060 		       4r0011 4r0011
  1060 		       4r0011 4r0011
  1061 		       4r1100 4r1100
  1061 		       4r1100 4r1100
  1062 		       4r0011 4r0011
  1062 		       4r0011 4r0011
  1063 		       4r1100 4r1100
  1063 		       4r1100 4r1100
  1065 		       4r1100 4r1100
  1065 		       4r1100 4r1100
  1066 		       4r0011 4r0011].
  1066 		       4r0011 4r0011].
  1067     "
  1067     "
  1068 
  1068 
  1069     "
  1069     "
  1070      Image width:8 
  1070      Image width:8
  1071 	   height:8
  1071 	   height:8
  1072 	   depth:4 
  1072 	   depth:4
  1073 	   fromArray:#[16r00 16r01 16rf0 16rf1
  1073 	   fromArray:#[16r00 16r01 16rf0 16rf1
  1074 		       16r02 16r03 16rf2 16rf3
  1074 		       16r02 16r03 16rf2 16rf3
  1075 		       16r04 16r05 16rf4 16rf5
  1075 		       16r04 16r05 16rf4 16rf5
  1076 		       16r06 16r07 16rf6 16rf7
  1076 		       16r06 16r07 16rf6 16rf7
  1077 		       16r08 16r09 16rf8 16rf9
  1077 		       16r08 16r09 16rf8 16rf9
  1086 width:w height:h depth:d fromArray:pixelData pad:padding
  1086 width:w height:h depth:d fromArray:pixelData pad:padding
  1087     "create a new image, given width, height, depth and data.
  1087     "create a new image, given width, height, depth and data.
  1088      Data must be a ByteArray containing correctly aligned bits for the specified
  1088      Data must be a ByteArray containing correctly aligned bits for the specified
  1089      depth."
  1089      depth."
  1090 
  1090 
  1091     |img newBits 
  1091     |img newBits
  1092      srcRowBytes "{ Class: SmallInteger }"
  1092      srcRowBytes "{ Class: SmallInteger }"
  1093      dstRowBytes "{ Class: SmallInteger }"
  1093      dstRowBytes "{ Class: SmallInteger }"
  1094      nextDstIndex "{ Class: SmallInteger }"
  1094      nextDstIndex "{ Class: SmallInteger }"
  1095      srcIndex "{ Class: SmallInteger }"
  1095      srcIndex "{ Class: SmallInteger }"
  1096      dstIndex "{ Class: SmallInteger }" |
  1096      dstIndex "{ Class: SmallInteger }" |
  1108 	srcIndex := 1.
  1108 	srcIndex := 1.
  1109 	dstIndex := 1.
  1109 	dstIndex := 1.
  1110 
  1110 
  1111 	1 to:h do:[:row |
  1111 	1 to:h do:[:row |
  1112 	    nextDstIndex := dstIndex + dstRowBytes.
  1112 	    nextDstIndex := dstIndex + dstRowBytes.
  1113 	    newBits replaceFrom:dstIndex 
  1113 	    newBits replaceFrom:dstIndex
  1114 			     to:(nextDstIndex - 1)
  1114 			     to:(nextDstIndex - 1)
  1115 			   with:pixelData
  1115 			   with:pixelData
  1116 		     startingAt:srcIndex.
  1116 		     startingAt:srcIndex.
  1117 	    srcIndex := srcIndex + srcRowBytes.
  1117 	    srcIndex := srcIndex + srcRowBytes.
  1118 	    dstIndex := nextDstIndex.
  1118 	    dstIndex := nextDstIndex.
  1151 	pixels := anArray
  1151 	pixels := anArray
  1152     ].
  1152     ].
  1153     ^ cls new width:w height:h depth:d fromArray:pixels
  1153     ^ cls new width:w height:h depth:d fromArray:pixels
  1154 
  1154 
  1155     "
  1155     "
  1156      Image width:8 
  1156      Image width:8
  1157 	   height:8 
  1157 	   height:8
  1158 	   fromArray:#[2r11001100
  1158 	   fromArray:#[2r11001100
  1159 		       2r00110011
  1159 		       2r00110011
  1160 		       2r11001100
  1160 		       2r11001100
  1161 		       2r00110011
  1161 		       2r00110011
  1162 		       2r11001100
  1162 		       2r11001100
  1264     "Created: 1.2.1997 / 14:40:29 / cg"
  1264     "Created: 1.2.1997 / 14:40:29 / cg"
  1265 ! !
  1265 ! !
  1266 
  1266 
  1267 !Image class methodsFor:'cleanup'!
  1267 !Image class methodsFor:'cleanup'!
  1268 
  1268 
  1269 releaseResourcesOnDevice:aDevice 
  1269 releaseResourcesOnDevice:aDevice
  1270     "this is sent when a display connection is closed,
  1270     "this is sent when a display connection is closed,
  1271      to release all cached Images from that device"
  1271      to release all cached Images from that device"
  1272     
  1272 
  1273     Lobby 
  1273     Lobby
  1274         unregisterAllForWhich:[:eachImage | 
  1274 	unregisterAllForWhich:[:eachImage |
  1275             |ok|
  1275 	    |ok|
  1276 
  1276 
  1277             ok := eachImage graphicsDevice == aDevice.
  1277 	    ok := eachImage graphicsDevice == aDevice.
  1278             ok ifTrue:[
  1278 	    ok ifTrue:[
  1279                 eachImage releaseFromDevice
  1279 		eachImage releaseFromDevice
  1280             ].
  1280 	    ].
  1281             ok
  1281 	    ok
  1282         ]
  1282 	]
  1283 
  1283 
  1284     "Created: 16.1.1997 / 19:30:44 / cg"
  1284     "Created: 16.1.1997 / 19:30:44 / cg"
  1285     "Modified: 16.1.1997 / 19:33:49 / cg"
  1285     "Modified: 16.1.1997 / 19:33:49 / cg"
  1286 ! !
  1286 ! !
  1287 
  1287 
  1296      separate directory, thereby overriding system bitmaps easily.
  1296      separate directory, thereby overriding system bitmaps easily.
  1297      If the file is unreadable or does not contain an appropriate image,
  1297      If the file is unreadable or does not contain an appropriate image,
  1298      the ImageNotFoundQuerySignal is raised, which may be handled to
  1298      the ImageNotFoundQuerySignal is raised, which may be handled to
  1299      proceed with some replacement image. If unhandled, nil is returned."
  1299      proceed with some replacement image. If unhandled, nil is returned."
  1300 
  1300 
  1301     |image name fn nm inStream suffix readerClass 
  1301     |image name fn nm inStream suffix readerClass
  1302      mustDecompress inPipe readersErrorMsg|
  1302      mustDecompress inPipe readersErrorMsg|
  1303 
  1303 
  1304     "before trying each reader, check if the file is readable"
  1304     "before trying each reader, check if the file is readable"
  1305 
  1305 
  1306     name := aFileName asFilename.
  1306     name := aFileName asFilename.
  1307 
  1307 
  1308     inStream := Smalltalk systemFileStreamFor:name.
  1308     inStream := Smalltalk systemFileStreamFor:name.
  1309     inStream isNil ifTrue:[
  1309     inStream isNil ifTrue:[
  1310         inStream := Smalltalk bitmapFileStreamFor:name.
  1310 	inStream := Smalltalk bitmapFileStreamFor:name.
  1311         inStream isNil ifTrue:[
  1311 	inStream isNil ifTrue:[
  1312             "this signal is a query - if noone seems to care, return nil.
  1312 	    "this signal is a query - if noone seems to care, return nil.
  1313              However, a handler may provide a replacement image."
  1313 	     However, a handler may provide a replacement image."
  1314             ^ ImageNotFoundQuerySignal
  1314 	    ^ ImageNotFoundQuerySignal
  1315                         raiseRequestWith:aFileName
  1315 			raiseRequestWith:aFileName
  1316                         errorString:('IMAGE [warning]: ''' , name pathName, ''' does not exist or is not readable').
  1316 			errorString:('IMAGE [warning]: ''' , name pathName, ''' does not exist or is not readable').
  1317         ].
  1317 	].
  1318     ].
  1318     ].
  1319     fn := inStream pathName asFilename.
  1319     fn := inStream pathName asFilename.
  1320     inStream close.
  1320     inStream close.
  1321 
  1321 
  1322     nm := fn name.
  1322     nm := fn name.
  1323     suffix := fn suffix.
  1323     suffix := fn suffix.
  1324 
  1324 
  1325     "handle compressed-suffix"
  1325     "handle compressed-suffix"
  1326     (#('Z' 'gz') includes:suffix) ifTrue:[
  1326     (#('Z' 'gz') includes:suffix) ifTrue:[
  1327         fn := fn withoutSuffix.
  1327 	fn := fn withoutSuffix.
  1328         nm := fn name.
  1328 	nm := fn name.
  1329         suffix := fn suffix.
  1329 	suffix := fn suffix.
  1330         mustDecompress := true.
  1330 	mustDecompress := true.
  1331     ].
  1331     ].
  1332     suffix isEmpty ifTrue:[
  1332     suffix isEmpty ifTrue:[
  1333         suffix := nm.
  1333 	suffix := nm.
  1334     ].
  1334     ].
  1335 
  1335 
  1336     "get the imageReader class from the files extension and ask it first"
  1336     "get the imageReader class from the files extension and ask it first"
  1337     readerClass := MIMETypes imageReaderForSuffix:suffix.
  1337     readerClass := MIMETypes imageReaderForSuffix:suffix.
  1338     readerClass notNil ifTrue:[
  1338     readerClass notNil ifTrue:[
  1339         mustDecompress == true ifTrue:[
  1339 	mustDecompress == true ifTrue:[
  1340             inPipe := PipeStream readingFrom:'gunzip <' , fn pathName.
  1340 	    inPipe := PipeStream readingFrom:'gunzip <' , fn pathName.
  1341             inPipe notNil ifTrue:[
  1341 	    inPipe notNil ifTrue:[
  1342                 [
  1342 		[
  1343                     image := readerClass fromStream:inPipe.
  1343 		    image := readerClass fromStream:inPipe.
  1344                 ] ensure:[
  1344 		] ensure:[
  1345                     inPipe close
  1345 		    inPipe close
  1346                 ].
  1346 		].
  1347             ]
  1347 	    ]
  1348         ] ifFalse:[
  1348 	] ifFalse:[
  1349             BadImageFormatQuerySignal handle:[:ex |
  1349 	    BadImageFormatQuerySignal handle:[:ex |
  1350                 Transcript showCR:(readersErrorMsg := ex description).
  1350 		Transcript showCR:(readersErrorMsg := ex description).
  1351                 image := nil.
  1351 		image := nil.
  1352                 ex return.
  1352 		ex return.
  1353             ] do:[
  1353 	    ] do:[
  1354                 image := readerClass fromFile:fn.
  1354 		image := readerClass fromFile:fn.
  1355             ].
  1355 	    ].
  1356         ].
  1356 	].
  1357         image notNil ifTrue:[^ image].
  1357 	image notNil ifTrue:[^ image].
  1358     ].
  1358     ].
  1359 
  1359 
  1360     (readerClass isNil or:[readersErrorMsg notNil]) ifTrue:[
  1360     (readerClass isNil or:[readersErrorMsg notNil]) ifTrue:[
  1361         "no known extension (or wrong extension)
  1361 	"no known extension (or wrong extension)
  1362          - ask all readers if they know this format ...
  1362 	 - ask all readers if they know this format ...
  1363          ... these look into the file, and investigate the header.
  1363 	 ... these look into the file, and investigate the header.
  1364          therefore, it takes a bit longer."
  1364 	 therefore, it takes a bit longer."
  1365 
  1365 
  1366         MIMETypes imageReaderClasses do:[:mimeReaderClass |
  1366 	MIMETypes imageReaderClasses do:[:mimeReaderClass |
  1367             (mimeReaderClass notNil 
  1367 	    (mimeReaderClass notNil
  1368             and:[mimeReaderClass ~~ readerClass]) ifTrue:[
  1368 	    and:[mimeReaderClass ~~ readerClass]) ifTrue:[
  1369                (mimeReaderClass isValidImageFile:name) ifTrue:[
  1369 	       (mimeReaderClass isValidImageFile:name) ifTrue:[
  1370                     image := mimeReaderClass fromFile:name.
  1370 		    image := mimeReaderClass fromFile:name.
  1371                     image notNil ifTrue:[
  1371 		    image notNil ifTrue:[
  1372                         ^ image
  1372 			^ image
  1373                     ]
  1373 		    ]
  1374                 ]
  1374 		]
  1375             ]
  1375 	    ]
  1376         ].
  1376 	].
  1377     ].
  1377     ].
  1378 
  1378 
  1379     "nope - unknown format
  1379     "nope - unknown format
  1380      this signal is a query - if noone seems to care, return nil.
  1380      this signal is a query - if noone seems to care, return nil.
  1381      However, a handler may provide a replacement image."
  1381      However, a handler may provide a replacement image."
  1382 
  1382 
  1383     ^ BadImageFormatQuerySignal
  1383     ^ BadImageFormatQuerySignal
  1384         raiseRequestWith:aFileName                                                                                            
  1384 	raiseRequestWith:aFileName
  1385         errorString:(readersErrorMsg ? ('IMAGE [warning]: unknown image file format: ''' , aFileName asFilename pathName , '''')).
  1385 	errorString:(readersErrorMsg ? ('IMAGE [warning]: unknown image file format: ''' , aFileName asFilename pathName , '''')).
  1386 
  1386 
  1387     "
  1387     "
  1388      Image fromFile:'goodies/bitmaps/gifImages/claus.gif'
  1388      Image fromFile:'goodies/bitmaps/gifImages/claus.gif'
  1389      Image fromFile:'goodies/bitmaps/gifImages/garfield.gif'
  1389      Image fromFile:'goodies/bitmaps/gifImages/garfield.gif'
  1390 
  1390 
  1398      Image fromFile:'fooBar'
  1398      Image fromFile:'fooBar'
  1399     "
  1399     "
  1400 
  1400 
  1401     "giving a message for non-existing images:
  1401     "giving a message for non-existing images:
  1402 
  1402 
  1403      Image imageNotFoundQuerySignal 
  1403      Image imageNotFoundQuerySignal
  1404      handle:[:ex |
  1404      handle:[:ex |
  1405         Transcript showCR:ex description.
  1405 	Transcript showCR:ex description.
  1406         ex proceedWith:nil
  1406 	ex proceedWith:nil
  1407      ] do:[
  1407      ] do:[
  1408          Image fromFile:'fooBar'
  1408 	 Image fromFile:'fooBar'
  1409      ]
  1409      ]
  1410     "
  1410     "
  1411 
  1411 
  1412     "giving a replacement for non-existing images:
  1412     "giving a replacement for non-existing images:
  1413 
  1413 
  1414      Image imageNotFoundQuerySignal 
  1414      Image imageNotFoundQuerySignal
  1415      answer:(Image fromFile:'libtool/bitmaps/SmalltalkX.xbm')
  1415      answer:(Image fromFile:'libtool/bitmaps/SmalltalkX.xbm')
  1416      do:[
  1416      do:[
  1417          Image fromFile:'fooBar'
  1417 	 Image fromFile:'fooBar'
  1418      ]
  1418      ]
  1419     "
  1419     "
  1420 
  1420 
  1421     "Modified: / 18.5.1999 / 15:48:20 / cg"
  1421     "Modified: / 18.5.1999 / 15:48:20 / cg"
  1422 !
  1422 !
  1442     "
  1442     "
  1443 !
  1443 !
  1444 
  1444 
  1445 fromFile:aFileName on:aDevice
  1445 fromFile:aFileName on:aDevice
  1446     "read an image from a file and prepare a device representation.
  1446     "read an image from a file and prepare a device representation.
  1447      Return nil (or whatever a handler returned), 
  1447      Return nil (or whatever a handler returned),
  1448      if the file is unreadable or does not contain an appropriate image."
  1448      if the file is unreadable or does not contain an appropriate image."
  1449 
  1449 
  1450     |img|
  1450     |img|
  1451 
  1451 
  1452     img := self fromFile:aFileName.
  1452     img := self fromFile:aFileName.
  1459 !
  1459 !
  1460 
  1460 
  1461 fromFile:aFileName resolution:res
  1461 fromFile:aFileName resolution:res
  1462     "read an image from a file and (if required) scale the image
  1462     "read an image from a file and (if required) scale the image
  1463      as appropriate (only req'd for very high resolution displays).
  1463      as appropriate (only req'd for very high resolution displays).
  1464      Return nil (or whatever a handler returned), 
  1464      Return nil (or whatever a handler returned),
  1465      if the file is unreadable or does not contain an appropriate image."
  1465      if the file is unreadable or does not contain an appropriate image."
  1466 
  1466 
  1467     ^ self fromFile:aFileName resolution:res on:nil
  1467     ^ self fromFile:aFileName resolution:res on:nil
  1468 
  1468 
  1469     "Created: 19.12.1996 / 14:02:13 / cg"
  1469     "Created: 19.12.1996 / 14:02:13 / cg"
  1472 
  1472 
  1473 fromFile:aFileName resolution:dpi on:aDevice
  1473 fromFile:aFileName resolution:dpi on:aDevice
  1474     "read an image from a file and (if required) scale the image
  1474     "read an image from a file and (if required) scale the image
  1475      as appropriate (only req'd with very high resolution displays).
  1475      as appropriate (only req'd with very high resolution displays).
  1476      Prepare a device representation.
  1476      Prepare a device representation.
  1477      Return nil (or whatever a handler returned), 
  1477      Return nil (or whatever a handler returned),
  1478      if the file is unreadable or does not contain an appropriate image."
  1478      if the file is unreadable or does not contain an appropriate image."
  1479 
  1479 
  1480     |img dev dpiH mag|
  1480     |img dev dpiH mag|
  1481 
  1481 
  1482     img := self fromFile:aFileName.
  1482     img := self fromFile:aFileName.
  1511 fromStream:aStream
  1511 fromStream:aStream
  1512     "read an image from a stream - this methods tries to find
  1512     "read an image from a stream - this methods tries to find
  1513      out the file format itself (by contents)
  1513      out the file format itself (by contents)
  1514      and lets the appropriate reader read the file.
  1514      and lets the appropriate reader read the file.
  1515      To do this, the stream must be positionable.
  1515      To do this, the stream must be positionable.
  1516      Return nil (or whatever a handler returned), 
  1516      Return nil (or whatever a handler returned),
  1517      if the stream does not contain an appropriate image."
  1517      if the stream does not contain an appropriate image."
  1518 
  1518 
  1519     |image|
  1519     |image|
  1520 
  1520 
  1521     "
  1521     "
  1522      ask all readers if they know
  1522      ask all readers if they know
  1523      this format ...
  1523      this format ...
  1524     "
  1524     "
  1525     MIMETypes imageReaderClasses do:[:readerClass |
  1525     MIMETypes imageReaderClasses do:[:readerClass |
  1526         readerClass notNil ifTrue:[
  1526 	readerClass notNil ifTrue:[
  1527             image := readerClass fromStream:aStream.
  1527 	    image := readerClass fromStream:aStream.
  1528             image notNil ifTrue:[^ image].
  1528 	    image notNil ifTrue:[^ image].
  1529         ]
  1529 	]
  1530     ].
  1530     ].
  1531 
  1531 
  1532     "
  1532     "
  1533      nope - unknown format
  1533      nope - unknown format
  1534     "
  1534     "
  1535 "/    'Image [info]: unknown image file format in stream: ' infoPrintCR.
  1535 "/    'Image [info]: unknown image file format in stream: ' infoPrintCR.
  1536 
  1536 
  1537     ^ ImageNotFoundQuerySignal
  1537     ^ ImageNotFoundQuerySignal
  1538                 raiseRequestWith:aStream
  1538 		raiseRequestWith:aStream
  1539                 errorString:('IMAGE [warning]: unknown image file format in stream').
  1539 		errorString:('IMAGE [warning]: unknown image file format in stream').
  1540 
  1540 
  1541     "
  1541     "
  1542      Image fromFile:'goodies/bitmaps/gifImages/claus.gif'
  1542      Image fromFile:'goodies/bitmaps/gifImages/claus.gif'
  1543      Image fromFile:'goodies/bitmaps/gifImages/garfield.gif'
  1543      Image fromFile:'goodies/bitmaps/gifImages/garfield.gif'
  1544 
  1544 
  1561 fromStream:aStream using:aReaderClass
  1561 fromStream:aStream using:aReaderClass
  1562     "read an image from a stream, given an imageReaderClass.
  1562     "read an image from a stream, given an imageReaderClass.
  1563      Use this, if you know the files format, but it has an invalid
  1563      Use this, if you know the files format, but it has an invalid
  1564      extension (or non-definite header), so #fromStream: could not
  1564      extension (or non-definite header), so #fromStream: could not
  1565      find out the images format.
  1565      find out the images format.
  1566      Return nil (or whatever a handler returned), 
  1566      Return nil (or whatever a handler returned),
  1567      if the stream does not contain an appropriate image."
  1567      if the stream does not contain an appropriate image."
  1568 
  1568 
  1569     |image|
  1569     |image|
  1570 
  1570 
  1571     image := aReaderClass fromStream:aStream.
  1571     image := aReaderClass fromStream:aStream.
  1585 ! !
  1585 ! !
  1586 
  1586 
  1587 !Image class methodsFor:'misc'!
  1587 !Image class methodsFor:'misc'!
  1588 
  1588 
  1589 ditherAlgorithm
  1589 ditherAlgorithm
  1590     "return the way we dither - 
  1590     "return the way we dither -
  1591 	#threshold, or nil        -> no dither
  1591 	#threshold, or nil        -> no dither
  1592 	#pattern, or #ordered     -> orderedDither (ugly, but fast)
  1592 	#pattern, or #ordered     -> orderedDither (ugly, but fast)
  1593 	#error or #floydSteinberg -> errorDiffusion; much better
  1593 	#error or #floydSteinberg -> errorDiffusion; much better
  1594 	#burkes                   -> errorDiffusion; even better."
  1594 	#burkes                   -> errorDiffusion; even better."
  1595 
  1595 
  1597 
  1597 
  1598     "Created: 17.6.1996 / 18:57:47 / cg"
  1598     "Created: 17.6.1996 / 18:57:47 / cg"
  1599 !
  1599 !
  1600 
  1600 
  1601 ditherAlgorithm:aSymbol
  1601 ditherAlgorithm:aSymbol
  1602     "define how to dither - 
  1602     "define how to dither -
  1603 	#threshold, or nil        -> no dither
  1603 	#threshold, or nil        -> no dither
  1604 	#pattern, or #ordered     -> orderedDither (ugly, but fast)
  1604 	#pattern, or #ordered     -> orderedDither (ugly, but fast)
  1605 	#error or #floydSteinberg -> errorDiffusion; much better
  1605 	#error or #floydSteinberg -> errorDiffusion; much better
  1606 	#burkes                   -> errorDiffusion; even better."
  1606 	#burkes                   -> errorDiffusion; even better."
  1607 
  1607 
  1626 !
  1626 !
  1627 
  1627 
  1628 orderedDitherMatrixOfSize:sz
  1628 orderedDitherMatrixOfSize:sz
  1629     sz == 2 ifTrue:[
  1629     sz == 2 ifTrue:[
  1630 	^ #[
  1630 	^ #[
  1631 		0 2 
  1631 		0 2
  1632 		3 1
  1632 		3 1
  1633 	   ].
  1633 	   ].
  1634     ].
  1634     ].
  1635 
  1635 
  1636     sz == 4 ifTrue:[
  1636     sz == 4 ifTrue:[
  1644 
  1644 
  1645     sz == 8 ifTrue:[
  1645     sz == 8 ifTrue:[
  1646 	^  #[
  1646 	^  #[
  1647 		0 32  8 40    2 34 10 42
  1647 		0 32  8 40    2 34 10 42
  1648 	       48 16 56 24   50 18 58 26
  1648 	       48 16 56 24   50 18 58 26
  1649 	       12 44  4 36   14 46  6 38    
  1649 	       12 44  4 36   14 46  6 38
  1650 	       60 28 52 20   62 30 54 22
  1650 	       60 28 52 20   62 30 54 22
  1651 
  1651 
  1652 		3 35 11 43    1 33  9 41
  1652 		3 35 11 43    1 33  9 41
  1653 	       51 19 59 27   49 17 57 25
  1653 	       51 19 59 27   49 17 57 25
  1654 	       15 47  7 39   13 45  5 37    
  1654 	       15 47  7 39   13 45  5 37
  1655 	       63 31 55 23   61 29 53 21
  1655 	       63 31 55 23   61 29 53 21
  1656 	    ].
  1656 	    ].
  1657     ].
  1657     ].
  1658 
  1658 
  1659     ^ nil
  1659     ^ nil
  1773      return it; return nil if unknown"
  1773      return it; return nil if unknown"
  1774 
  1774 
  1775     ^ MIMETypes mimeTypeForSuffix:suffix
  1775     ^ MIMETypes mimeTypeForSuffix:suffix
  1776 
  1776 
  1777     "
  1777     "
  1778      Image mimeTypeFromSuffix:'gif'      
  1778      Image mimeTypeFromSuffix:'gif'
  1779      Image mimeTypeFromSuffix:'tiff'    
  1779      Image mimeTypeFromSuffix:'tiff'
  1780      Image mimeTypeFromSuffix:'foobar'  
  1780      Image mimeTypeFromSuffix:'foobar'
  1781     "
  1781     "
  1782 
  1782 
  1783     "Modified: 1.7.1997 / 00:17:27 / cg"
  1783     "Modified: 1.7.1997 / 00:17:27 / cg"
  1784 ! !
  1784 ! !
  1785 
  1785 
  1792 	      (use #fromScreen:on:grab: with a false grabArg then)."
  1792 	      (use #fromScreen:on:grab: with a false grabArg then)."
  1793 
  1793 
  1794     |display|
  1794     |display|
  1795 
  1795 
  1796     display := Screen current.
  1796     display := Screen current.
  1797     ^ self 
  1797     ^ self
  1798 	fromScreen:(0@0 corner:(display width @ display height))
  1798 	fromScreen:(0@0 corner:(display width @ display height))
  1799 	on:display
  1799 	on:display
  1800 	grab:true
  1800 	grab:true
  1801 
  1801 
  1802     "
  1802     "
  1811     "return an image of a part of the screen.
  1811     "return an image of a part of the screen.
  1812      WARNING: this temporarily grabs the display
  1812      WARNING: this temporarily grabs the display
  1813 	      it may not work from within a buttonMotion
  1813 	      it may not work from within a buttonMotion
  1814 	      (use #fromScreen:on:grab: with a false grabArg then)."
  1814 	      (use #fromScreen:on:grab: with a false grabArg then)."
  1815 
  1815 
  1816     ^ self 
  1816     ^ self
  1817 	fromScreen:aRectangle 
  1817 	fromScreen:aRectangle
  1818 	on:Screen current
  1818 	on:Screen current
  1819 	grab:true
  1819 	grab:true
  1820 
  1820 
  1821     "
  1821     "
  1822      Image fromScreen:(0@0 corner:100@100)
  1822      Image fromScreen:(0@0 corner:100@100)
  1832      WARNING: this temporarily grabs the display
  1832      WARNING: this temporarily grabs the display
  1833 	      it may not work from within a buttonMotion
  1833 	      it may not work from within a buttonMotion
  1834 	      (use #fromScreen:on:grab: with a false grabArg then)."
  1834 	      (use #fromScreen:on:grab: with a false grabArg then)."
  1835 
  1835 
  1836     ^ self
  1836     ^ self
  1837 	fromScreen:aRectangle 
  1837 	fromScreen:aRectangle
  1838 	on:aDevice 
  1838 	on:aDevice
  1839 	grab:true
  1839 	grab:true
  1840 
  1840 
  1841     "
  1841     "
  1842      Image fromScreen:(0@0 corner:100@100)
  1842      Image fromScreen:(0@0 corner:100@100)
  1843     "
  1843     "
  1857     "return an image of a part of the screen, which may be on
  1857     "return an image of a part of the screen, which may be on
  1858      another Display. If the doGrab argument is true, the display
  1858      another Display. If the doGrab argument is true, the display
  1859      is grabbed (i.e. blocked for others) and a camera cursor is
  1859      is grabbed (i.e. blocked for others) and a camera cursor is
  1860      shown while the readout is done.
  1860      shown while the readout is done.
  1861      WARNING: with doGrab true, this temporarily grabs the display
  1861      WARNING: with doGrab true, this temporarily grabs the display
  1862               and it may not work from within a buttonMotion
  1862 	      and it may not work from within a buttonMotion
  1863               (use with a false grabArg then)."
  1863 	      (use with a false grabArg then)."
  1864 
  1864 
  1865     |depth vis img|
  1865     |depth vis img|
  1866 
  1866 
  1867     depth := aDisplay depth.
  1867     depth := aDisplay depth.
  1868 
  1868 
  1871     "/ (must do this for depth15 & depth16 displays, since
  1871     "/ (must do this for depth15 & depth16 displays, since
  1872     "/  Depth16Image has no way to specify r/g/b masks ...)
  1872     "/  Depth16Image has no way to specify r/g/b masks ...)
  1873     "/
  1873     "/
  1874     vis := aDisplay visualType.
  1874     vis := aDisplay visualType.
  1875     (vis == #TrueColor or:[vis == #DirectColor]) ifTrue:[
  1875     (vis == #TrueColor or:[vis == #DirectColor]) ifTrue:[
  1876         depth > 8 ifTrue:[
  1876 	depth > 8 ifTrue:[
  1877             depth := 24.
  1877 	    depth := 24.
  1878         ]
  1878 	]
  1879     ].
  1879     ].
  1880 
  1880 
  1881     img := self newForDepth:depth.
  1881     img := self newForDepth:depth.
  1882     ^ img fromScreen:aRectangle on:aDisplay grab:doGrab
  1882     ^ img fromScreen:aRectangle on:aDisplay grab:doGrab
  1883 
  1883 
  1884     "Modified: / 26.1.1998 / 22:23:08 / cg"
  1884     "Modified: / 26.1.1998 / 22:23:08 / cg"
  1885 !
  1885 !
  1886 
  1886 
  1887 fromScreenArea
  1887 fromScreenArea
  1888     "return an image of a part of the screen; 
  1888     "return an image of a part of the screen;
  1889      let user specify screen area.
  1889      let user specify screen area.
  1890      This is the same as #fromUser - kept for backward compatibility.
  1890      This is the same as #fromUser - kept for backward compatibility.
  1891      Use #fromUser for ST-80 compatibility.
  1891      Use #fromUser for ST-80 compatibility.
  1892      WARNING: this temporarily grabs the display
  1892      WARNING: this temporarily grabs the display
  1893 	      it may not work from within a buttonMotion
  1893 	      it may not work from within a buttonMotion
  1927 !
  1927 !
  1928 
  1928 
  1929 fromView:aView
  1929 fromView:aView
  1930     "return an image taken from a views contents as currently
  1930     "return an image taken from a views contents as currently
  1931      on the screen. The returned image has the same depth and photometric
  1931      on the screen. The returned image has the same depth and photometric
  1932      as the Display. 
  1932      as the Display.
  1933      Notice, that for invisible or partial covered views, 
  1933      Notice, that for invisible or partial covered views,
  1934      the returned Image is NOT correct. 
  1934      the returned Image is NOT correct.
  1935      You may want to raise the view before using this method.
  1935      You may want to raise the view before using this method.
  1936      WARNING: this temporarily grabs the display
  1936      WARNING: this temporarily grabs the display
  1937 	      it may not work from within a buttonMotion
  1937 	      it may not work from within a buttonMotion
  1938 	      (use #fromView:grab: with a false grabArg then)."
  1938 	      (use #fromView:grab: with a false grabArg then)."
  1939 
  1939 
  1940     ^ self
  1940     ^ self
  1941 	fromView:aView 
  1941 	fromView:aView
  1942 	grab:true
  1942 	grab:true
  1943 
  1943 
  1944     "
  1944     "
  1945      Image fromView:(Launcher allInstances first window topView)
  1945      Image fromView:(Launcher allInstances first window topView)
  1946      Image fromView:(BrowserView allInstances first topView)
  1946      Image fromView:(BrowserView allInstances first topView)
  1962     "return an image taken from a views contents as currently
  1962     "return an image taken from a views contents as currently
  1963      on the screen. If the doGrab argument is true, the display
  1963      on the screen. If the doGrab argument is true, the display
  1964      is grabbed (i.e. blocked for others) and a camera cursor is
  1964      is grabbed (i.e. blocked for others) and a camera cursor is
  1965      shown while the readout is done.
  1965      shown while the readout is done.
  1966      The returned image has the same depth and photometric
  1966      The returned image has the same depth and photometric
  1967      as the Display. 
  1967      as the Display.
  1968      Notice, that for invisible or partial covered views, 
  1968      Notice, that for invisible or partial covered views,
  1969      the returned Image is NOT correct. 
  1969      the returned Image is NOT correct.
  1970      You may want to raise the view before using this method.
  1970      You may want to raise the view before using this method.
  1971      WARNING: with doGrab true, this temporarily grabs the display
  1971      WARNING: with doGrab true, this temporarily grabs the display
  1972               and it may not work from within a buttonMotion
  1972 	      and it may not work from within a buttonMotion
  1973               (use with a false grabArg then)."
  1973 	      (use with a false grabArg then)."
  1974 
  1974 
  1975     ^ self fromView:aView grab:doGrab withDecoration:false
  1975     ^ self fromView:aView grab:doGrab withDecoration:false
  1976 
  1976 
  1977     "Created: / 26.3.1997 / 10:34:20 / cg"
  1977     "Created: / 26.3.1997 / 10:34:20 / cg"
  1978     "Modified: / 10.10.2001 / 14:13:29 / cg"
  1978     "Modified: / 10.10.2001 / 14:13:29 / cg"
  1979 !
  1979 !
  1980 
  1980 
  1981 fromView:aView grab:doGrab withDecoration:withDecoration
  1981 fromView:aView grab:doGrab withDecoration:withDecoration
  1982     "return an image taken from a views contents as currently
  1982     "return an image taken from a views contents as currently
  1983      on the screen, optionally with decoration included. 
  1983      on the screen, optionally with decoration included.
  1984      If the doGrab argument is true, the display
  1984      If the doGrab argument is true, the display
  1985      is grabbed (i.e. blocked for others) and a camera cursor is
  1985      is grabbed (i.e. blocked for others) and a camera cursor is
  1986      shown while the readout is done.
  1986      shown while the readout is done.
  1987      The returned image has the same depth and photometric
  1987      The returned image has the same depth and photometric
  1988      as the Display. 
  1988      as the Display.
  1989      Notice, that for invisible or partial covered views, 
  1989      Notice, that for invisible or partial covered views,
  1990      the returned Image is NOT correct. 
  1990      the returned Image is NOT correct.
  1991      You may want to raise the view before using this method.
  1991      You may want to raise the view before using this method.
  1992      WARNING: with doGrab true, this temporarily grabs the display
  1992      WARNING: with doGrab true, this temporarily grabs the display
  1993               and it may not work from within a buttonMotion
  1993 	      and it may not work from within a buttonMotion
  1994               (use with a false grabArg then)."
  1994 	      (use with a false grabArg then)."
  1995 
  1995 
  1996     |org ext device cH bW bH|
  1996     |org ext device cH bW bH|
  1997 
  1997 
  1998     device := aView graphicsDevice.
  1998     device := aView graphicsDevice.
  1999     org := device translatePoint:(0@0) fromView:aView toView:nil.
  1999     org := device translatePoint:(0@0) fromView:aView toView:nil.
  2000     ext := aView extent.
  2000     ext := aView extent.
  2001     withDecoration ifTrue:[
  2001     withDecoration ifTrue:[
  2002         device platformName = 'WIN32' ifTrue:[
  2002 	device platformName = 'WIN32' ifTrue:[
  2003             cH := device captionHeight.
  2003 	    cH := device captionHeight.
  2004             bW := (device getSystemMetrics: #SM_CXFRAME )
  2004 	    bW := (device getSystemMetrics: #SM_CXFRAME )
  2005                   "+ ( device getSystemMetrics: #borderFrameWidth )".
  2005 		  "+ ( device getSystemMetrics: #borderFrameWidth )".
  2006             bH := (device getSystemMetrics: #SM_CYFRAME )
  2006 	    bH := (device getSystemMetrics: #SM_CYFRAME )
  2007                   " + ( device getSystemMetrics: #borderFrameHeight )".
  2007 		  " + ( device getSystemMetrics: #borderFrameHeight )".
  2008             org := org - (bW @ (bH + cH)).
  2008 	    org := org - (bW @ (bH + cH)).
  2009             ext := ext + ((bW + bW) @ (bH+bH+cH)).
  2009 	    ext := ext + ((bW + bW) @ (bH+bH+cH)).
  2010         ].
  2010 	].
  2011     ].
  2011     ].
  2012     ^ self fromScreen:(org extent:ext) on:device grab:doGrab
  2012     ^ self fromScreen:(org extent:ext) on:device grab:doGrab
  2013 
  2013 
  2014     "
  2014     "
  2015      Transcript topView raise. (Image fromView:Transcript topView grab:false withDecoration:false) inspect   
  2015      Transcript topView raise. (Image fromView:Transcript topView grab:false withDecoration:false) inspect
  2016      Transcript topView raise. (Image fromView:Transcript topView grab:false withDecoration:true) inspect     
  2016      Transcript topView raise. (Image fromView:Transcript topView grab:false withDecoration:true) inspect
  2017     "
  2017     "
  2018 
  2018 
  2019     "Created: / 26-03-1997 / 10:34:20 / cg"
  2019     "Created: / 26-03-1997 / 10:34:20 / cg"
  2020     "Modified: / 08-09-2006 / 15:41:41 / cg"
  2020     "Modified: / 08-09-2006 / 15:41:41 / cg"
  2021 ! !
  2021 ! !
  2046 
  2046 
  2047     "
  2047     "
  2048      |img|
  2048      |img|
  2049      img := Image extent:100@100 depth:24.
  2049      img := Image extent:100@100 depth:24.
  2050      img photometric:#rgb.
  2050      img photometric:#rgb.
  2051      img data:(ByteArray new:100*100*3).   
  2051      img data:(ByteArray new:100*100*3).
  2052      img fillWhite:(0@0 corner:100@100).
  2052      img fillWhite:(0@0 corner:100@100).
  2053      img fillBlack:(10@10 corner:90@90).
  2053      img fillBlack:(10@10 corner:90@90).
  2054      img inspect.
  2054      img inspect.
  2055     "
  2055     "
  2056 !
  2056 !
  2068 
  2068 
  2069 !Image methodsFor:'Compatibility-VW'!
  2069 !Image methodsFor:'Compatibility-VW'!
  2070 
  2070 
  2071 asCachedImage
  2071 asCachedImage
  2072     "return the receiver associated to the current screens device.
  2072     "return the receiver associated to the current screens device.
  2073      For ST-80 compatibility 
  2073      For ST-80 compatibility
  2074      (ST/X uses Image for both device- and nonDevice-images)"
  2074      (ST/X uses Image for both device- and nonDevice-images)"
  2075 
  2075 
  2076     ^ self onDevice:Screen current
  2076     ^ self onDevice:Screen current
  2077 
  2077 
  2078     "Modified: 23.4.1996 / 11:10:32 / cg"
  2078     "Modified: 23.4.1996 / 11:10:32 / cg"
  2079 !
  2079 !
  2080 
  2080 
  2081 asRetainedMedium
  2081 asRetainedMedium
  2082     "return the receiver associated to the current screens device.
  2082     "return the receiver associated to the current screens device.
  2083      For ST-80 compatibility 
  2083      For ST-80 compatibility
  2084      (ST/X uses Image for both device- and nonDevice-images)"
  2084      (ST/X uses Image for both device- and nonDevice-images)"
  2085 
  2085 
  2086     ^ self onDevice:Screen current
  2086     ^ self onDevice:Screen current
  2087 
  2087 
  2088     "Modified: 23.4.1996 / 11:10:32 / cg"
  2088     "Modified: 23.4.1996 / 11:10:32 / cg"
  2152 
  2152 
  2153 tile:bounds from:origin in:tile rule:rule
  2153 tile:bounds from:origin in:tile rule:rule
  2154     |orgX orgY tW tH|
  2154     |orgX orgY tW tH|
  2155 
  2155 
  2156     origin ~= (0@0) ifTrue:[
  2156     origin ~= (0@0) ifTrue:[
  2157         self halt:'unimplemented'.
  2157 	self halt:'unimplemented'.
  2158     ].
  2158     ].
  2159     bounds ~= self bounds ifTrue:[
  2159     bounds ~= self bounds ifTrue:[
  2160         self halt:'unimplemented'.
  2160 	self halt:'unimplemented'.
  2161     ].
  2161     ].
  2162     rule ~= #over ifTrue:[
  2162     rule ~= #over ifTrue:[
  2163         self halt:'unimplemented'.
  2163 	self halt:'unimplemented'.
  2164     ].
  2164     ].
  2165 
  2165 
  2166     orgX := origin x.
  2166     orgX := origin x.
  2167     orgY := origin y.
  2167     orgY := origin y.
  2168     tW := tile width.
  2168     tW := tile width.
  2169     tH := tile height.
  2169     tH := tile height.
  2170     (bounds top) to:(bounds bottom) by:tH do:[:dstY |
  2170     (bounds top) to:(bounds bottom) by:tH do:[:dstY |
  2171         (bounds left) to:(bounds right) by:(tile width) do:[:dstX |
  2171 	(bounds left) to:(bounds right) by:(tile width) do:[:dstX |
  2172             self 
  2172 	    self
  2173                 copyFrom:tile 
  2173 		copyFrom:tile
  2174                 x:orgX y:orgY 
  2174 		x:orgX y:orgY
  2175                 toX:dstX y:dstY 
  2175 		toX:dstX y:dstY
  2176                 width:tW height:tH.
  2176 		width:tW height:tH.
  2177         ].
  2177 	].
  2178     ].
  2178     ].
  2179 !
  2179 !
  2180 
  2180 
  2181 valueAtPoint:aPoint put:aColorValue
  2181 valueAtPoint:aPoint put:aColorValue
  2182     aColorValue isInteger ifFalse:[
  2182     aColorValue isInteger ifFalse:[
  2183         self colorAtX:aPoint x y:aPoint y put:aColorValue
  2183 	self colorAtX:aPoint x y:aPoint y put:aColorValue
  2184     ] ifTrue:[
  2184     ] ifTrue:[
  2185         self pixelAtX:aPoint x y:aPoint y put:aColorValue
  2185 	self pixelAtX:aPoint x y:aPoint y put:aColorValue
  2186     ]
  2186     ]
  2187 ! !
  2187 ! !
  2188 
  2188 
  2189 !Image methodsFor:'accessing'!
  2189 !Image methodsFor:'accessing'!
  2190 
  2190 
  2408 
  2408 
  2409     monoDeviceForm isNil ifTrue:[^ nil].
  2409     monoDeviceForm isNil ifTrue:[^ nil].
  2410     ^ monoDeviceForm id
  2410     ^ monoDeviceForm id
  2411 !
  2411 !
  2412 
  2412 
  2413 palette 
  2413 palette
  2414     "return the colormap; ST-80 compatibility"
  2414     "return the colormap; ST-80 compatibility"
  2415 
  2415 
  2416     ^ colorMap
  2416     ^ colorMap
  2417 !
  2417 !
  2418 
  2418 
  2419 palette:aColormap 
  2419 palette:aColormap
  2420     "set the colormap; ST-80 compatibility"
  2420     "set the colormap; ST-80 compatibility"
  2421 
  2421 
  2422     self colorMap:aColormap
  2422     self colorMap:aColormap
  2423 
  2423 
  2424     "Created: 1.2.1996 / 15:09:25 / cg"
  2424     "Created: 1.2.1996 / 15:09:25 / cg"
  2456 ! !
  2456 ! !
  2457 
  2457 
  2458 !Image methodsFor:'accessing-pixels'!
  2458 !Image methodsFor:'accessing-pixels'!
  2459 
  2459 
  2460 at:aPoint
  2460 at:aPoint
  2461     "WARNING: for now, this returns a pixels color 
  2461     "WARNING: for now, this returns a pixels color
  2462      (backward compatibility with ST/X)
  2462      (backward compatibility with ST/X)
  2463      In the future, this will return a pixel value (ST-80 compatibility)
  2463      In the future, this will return a pixel value (ST-80 compatibility)
  2464      Use #colorAt: - for future compatibility.
  2464      Use #colorAt: - for future compatibility.
  2465 
  2465 
  2466      retrieve the pixel at aPoint; return a color.
  2466      retrieve the pixel at aPoint; return a color.
  2478     "Modified: / 21.6.1997 / 13:10:17 / cg"
  2478     "Modified: / 21.6.1997 / 13:10:17 / cg"
  2479     "Modified: / 9.1.1998 / 20:33:52 / stefan"
  2479     "Modified: / 9.1.1998 / 20:33:52 / stefan"
  2480 !
  2480 !
  2481 
  2481 
  2482 at:aPoint put:aColor
  2482 at:aPoint put:aColor
  2483     "WARNING: for now, this expects a pixels color 
  2483     "WARNING: for now, this expects a pixels color
  2484      (backward compatibility with ST/X)
  2484      (backward compatibility with ST/X)
  2485      In the future, this will expect a pixel value (ST-80 compatibility)
  2485      In the future, this will expect a pixel value (ST-80 compatibility)
  2486      Use #colorAt:put: - for future compatibility.
  2486      Use #colorAt:put: - for future compatibility.
  2487 
  2487 
  2488      set the pixel at aPoint to aColor.
  2488      set the pixel at aPoint to aColor.
  2507      otherwise to 1. Nil is treated like noColor.
  2507      otherwise to 1. Nil is treated like noColor.
  2508      (used by the bitmap editor)"
  2508      (used by the bitmap editor)"
  2509 
  2509 
  2510     |maskVal|
  2510     |maskVal|
  2511 
  2511 
  2512     (aColorOrPixelOrNil notNil and:[aColorOrPixelOrNil ~= Color noColor]) ifTrue:[   
  2512     (aColorOrPixelOrNil notNil and:[aColorOrPixelOrNil ~= Color noColor]) ifTrue:[
  2513 	maskVal := 1.
  2513 	maskVal := 1.
  2514 	aColorOrPixelOrNil isInteger ifTrue:[
  2514 	aColorOrPixelOrNil isInteger ifTrue:[
  2515 	    self pixelAt:aPoint put:aColorOrPixelOrNil.
  2515 	    self pixelAt:aPoint put:aColorOrPixelOrNil.
  2516 	] ifFalse:[
  2516 	] ifFalse:[
  2517 	    self colorAt:aPoint put:aColorOrPixelOrNil
  2517 	    self colorAt:aPoint put:aColorOrPixelOrNil
  2520 	maskVal := 0.
  2520 	maskVal := 0.
  2521 	self pixelAt:aPoint put:0.
  2521 	self pixelAt:aPoint put:0.
  2522     ].
  2522     ].
  2523     mask notNil ifTrue:[
  2523     mask notNil ifTrue:[
  2524 	mask pixelAt:aPoint put:maskVal
  2524 	mask pixelAt:aPoint put:maskVal
  2525     ].  
  2525     ].
  2526 
  2526 
  2527     "Modified: / 30.9.1998 / 22:42:44 / cg"
  2527     "Modified: / 30.9.1998 / 22:42:44 / cg"
  2528 !
  2528 !
  2529 
  2529 
  2530 atImageAndMask:aPoint putValue:aPixelValueOrNil
  2530 atImageAndMask:aPoint putValue:aPixelValueOrNil
  2533      otherwise to 1.
  2533      otherwise to 1.
  2534      (used by the bitmap editor)"
  2534      (used by the bitmap editor)"
  2535 
  2535 
  2536     |pixVal maskVal|
  2536     |pixVal maskVal|
  2537 
  2537 
  2538     aPixelValueOrNil notNil ifTrue:[   
  2538     aPixelValueOrNil notNil ifTrue:[
  2539 	pixVal := aPixelValueOrNil.
  2539 	pixVal := aPixelValueOrNil.
  2540 	maskVal := 1.
  2540 	maskVal := 1.
  2541     ] ifFalse:[
  2541     ] ifFalse:[
  2542 	pixVal := 0.
  2542 	pixVal := 0.
  2543 	maskVal := 0.
  2543 	maskVal := 0.
  2544     ].
  2544     ].
  2545     mask notNil ifTrue:[
  2545     mask notNil ifTrue:[
  2546 	mask pixelAt:aPoint put:maskVal
  2546 	mask pixelAt:aPoint put:maskVal
  2547     ].  
  2547     ].
  2548     self pixelAt:aPoint put:pixVal
  2548     self pixelAt:aPoint put:pixVal
  2549 
  2549 
  2550     "Modified: / 30.9.1998 / 22:42:44 / cg"
  2550     "Modified: / 30.9.1998 / 22:42:44 / cg"
  2551 !
  2551 !
  2552 
  2552 
  2565 
  2565 
  2566     "Modified: 24.4.1997 / 17:17:59 / cg"
  2566     "Modified: 24.4.1997 / 17:17:59 / cg"
  2567 !
  2567 !
  2568 
  2568 
  2569 atX:x y:y
  2569 atX:x y:y
  2570     "WARNING: for now, this returns a pixels color 
  2570     "WARNING: for now, this returns a pixels color
  2571      (backward compatibility with ST/X)
  2571      (backward compatibility with ST/X)
  2572      In the future, this will return a pixel value (ST-80 compatibility)
  2572      In the future, this will return a pixel value (ST-80 compatibility)
  2573      Use #colorAt: - for future compatibility.
  2573      Use #colorAt: - for future compatibility.
  2574 
  2574 
  2575      Retrieve a pixel at x/y; return a color.
  2575      Retrieve a pixel at x/y; return a color.
  2584 
  2584 
  2585     "Modified: 21.6.1997 / 13:10:32 / cg"
  2585     "Modified: 21.6.1997 / 13:10:32 / cg"
  2586 !
  2586 !
  2587 
  2587 
  2588 atX:x y:y put:aColor
  2588 atX:x y:y put:aColor
  2589     "WARNING: for now, this expects a pixels color 
  2589     "WARNING: for now, this expects a pixels color
  2590      (backward compatibility with ST/X)
  2590      (backward compatibility with ST/X)
  2591      In the future, this will expect a pixel value (ST-80 compatibility)
  2591      In the future, this will expect a pixel value (ST-80 compatibility)
  2592      Use #colorAt:put: - for future compatibility.
  2592      Use #colorAt:put: - for future compatibility.
  2593 
  2593 
  2594      set the pixel at x/y to aColor.
  2594      set the pixel at x/y to aColor.
  2598      (i.e. if the receiver is a palette image, the color must be present in there).
  2598      (i.e. if the receiver is a palette image, the color must be present in there).
  2599      You should not use this method for image-processing, it is very slow ...
  2599      You should not use this method for image-processing, it is very slow ...
  2600      (it is meant to access individual pixels - for example, in a bitmap editor)"
  2600      (it is meant to access individual pixels - for example, in a bitmap editor)"
  2601 
  2601 
  2602     aColor isInteger ifTrue:[
  2602     aColor isInteger ifTrue:[
  2603         'Image [warning]: the Image>>atX:y:put: will change semantics soon; use #colorAtX:y:put:' infoPrintCR.
  2603 	'Image [warning]: the Image>>atX:y:put: will change semantics soon; use #colorAtX:y:put:' infoPrintCR.
  2604         ^ self pixelAtX:x y:y put:aColor
  2604 	^ self pixelAtX:x y:y put:aColor
  2605     ].
  2605     ].
  2606     ^ self colorAtX:x y:y put:aColor
  2606     ^ self colorAtX:x y:y put:aColor
  2607 
  2607 
  2608     "Modified: 21.6.1997 / 13:10:44 / cg"
  2608     "Modified: 21.6.1997 / 13:10:44 / cg"
  2609 !
  2609 !
  2627 !
  2627 !
  2628 
  2628 
  2629 bits
  2629 bits
  2630     "return the raw image data; depending on the photometric,
  2630     "return the raw image data; depending on the photometric,
  2631      this has to be interpreted as monochrome, greyscale,
  2631      this has to be interpreted as monochrome, greyscale,
  2632      palette or rgb data. 
  2632      palette or rgb data.
  2633      It is also packed to be dense, so a 4 bitPerSample palette image 
  2633      It is also packed to be dense, so a 4 bitPerSample palette image
  2634      will store 2 pixels per byte, whereas a 2-bitPerPixel image will store
  2634      will store 2 pixels per byte, whereas a 2-bitPerPixel image will store
  2635      4 pixels per byte."
  2635      4 pixels per byte."
  2636 
  2636 
  2637     ^ bytes
  2637     ^ bytes
  2638 !
  2638 !
  2782      Pixels start at 0/0 for upper left pixel, and end at
  2782      Pixels start at 0/0 for upper left pixel, and end at
  2783      width-1@height-1 for lower right pixel.
  2783      width-1@height-1 for lower right pixel.
  2784      The returned numbers interpretation depends on the photometric
  2784      The returned numbers interpretation depends on the photometric
  2785      and the colormap. (see also Image>>at: and Image>>atX:y:)
  2785      and the colormap. (see also Image>>at: and Image>>atX:y:)
  2786      You should not use this method for image-processing of
  2786      You should not use this method for image-processing of
  2787      big images, its very slow ... 
  2787      big images, its very slow ...
  2788      (it is meant to access individual pixels - for example, in a bitmap editor)"
  2788      (it is meant to access individual pixels - for example, in a bitmap editor)"
  2789 
  2789 
  2790     ^ self subclassResponsibility
  2790     ^ self subclassResponsibility
  2791 
  2791 
  2792     "Created: 24.4.1997 / 16:06:56 / cg"
  2792     "Created: 24.4.1997 / 16:06:56 / cg"
  2908 
  2908 
  2909     "Modified: 24.4.1997 / 17:05:57 / cg"
  2909     "Modified: 24.4.1997 / 17:05:57 / cg"
  2910 !
  2910 !
  2911 
  2911 
  2912 valueAt:aPoint
  2912 valueAt:aPoint
  2913     "WARNING: for now, this returns a pixels value 
  2913     "WARNING: for now, this returns a pixels value
  2914      (backward compatibility with ST/X)
  2914      (backward compatibility with ST/X)
  2915      In the future, this will return a color (ST-80 compatibility)
  2915      In the future, this will return a color (ST-80 compatibility)
  2916      Use #pixelAt: - for future compatibility.
  2916      Use #pixelAt: - for future compatibility.
  2917 
  2917 
  2918      Retrieve the pixelValue at aPoint; return an integer number.
  2918      Retrieve the pixelValue at aPoint; return an integer number.
  2929 
  2929 
  2930     "Modified: 21.6.1997 / 13:11:19 / cg"
  2930     "Modified: 21.6.1997 / 13:11:19 / cg"
  2931 !
  2931 !
  2932 
  2932 
  2933 valueAtX:x y:y
  2933 valueAtX:x y:y
  2934     "WARNING: for now, this returns a pixels value 
  2934     "WARNING: for now, this returns a pixels value
  2935      (backward compatibility with ST/X)
  2935      (backward compatibility with ST/X)
  2936      In the future, this will return a color (ST-80 compatibility)
  2936      In the future, this will return a color (ST-80 compatibility)
  2937      Use #pixelAt: - for future compatibility.
  2937      Use #pixelAt: - for future compatibility.
  2938 
  2938 
  2939      Retrieve the pixelValue at aPoint; return an integer number.
  2939      Retrieve the pixelValue at aPoint; return an integer number.
  2940      Pixels start at 0/0 for upper left pixel, and end at
  2940      Pixels start at 0/0 for upper left pixel, and end at
  2941      width-1@height-1 for lower right pixel.
  2941      width-1@height-1 for lower right pixel.
  2942      The returned numbers interpretation depends on the photometric
  2942      The returned numbers interpretation depends on the photometric
  2943      and the colormap. (see also Image>>at: and Image>>atX:y:)
  2943      and the colormap. (see also Image>>at: and Image>>atX:y:)
  2944      You should not use this method for image-processing of
  2944      You should not use this method for image-processing of
  2945      big images, its very slow ... 
  2945      big images, its very slow ...
  2946      (it is meant to access individual pixels - for example, in a bitmap editor)"
  2946      (it is meant to access individual pixels - for example, in a bitmap editor)"
  2947 
  2947 
  2948     'Image [warning]: the Image>>valueAtX:y: will change semantics soon; use #pixelAtX:y' infoPrintCR.
  2948     'Image [warning]: the Image>>valueAtX:y: will change semantics soon; use #pixelAtX:y' infoPrintCR.
  2949     ^ self pixelAtX:x y:y
  2949     ^ self pixelAtX:x y:y
  2950 
  2950 
  2965 
  2965 
  2966     "Modified: 23.4.1996 / 11:08:28 / cg"
  2966     "Modified: 23.4.1996 / 11:08:28 / cg"
  2967 !
  2967 !
  2968 
  2968 
  2969 bitsPerSample:aCollection
  2969 bitsPerSample:aCollection
  2970     "set the number of bits per sample. 
  2970     "set the number of bits per sample.
  2971 
  2971 
  2972      This interface is only to be used when initializing
  2972      This interface is only to be used when initializing
  2973      instances or by image readers. Calling for a change of an
  2973      instances or by image readers. Calling for a change of an
  2974      existing image may confuse later pixel interpretation."
  2974      existing image may confuse later pixel interpretation."
  2975 
  2975 
  2986      existing image may confuse later pixel interpretation."
  2986      existing image may confuse later pixel interpretation."
  2987 
  2987 
  2988     depth := self depth.
  2988     depth := self depth.
  2989     bitsPerPixel := d.
  2989     bitsPerPixel := d.
  2990     d == 24 ifTrue:[
  2990     d == 24 ifTrue:[
  2991         samplesPerPixel := 3.
  2991 	samplesPerPixel := 3.
  2992         bitsPerSample := #[8 8 8]
  2992 	bitsPerSample := #[8 8 8]
  2993     ] ifFalse:[
  2993     ] ifFalse:[
  2994         samplesPerPixel := 1.
  2994 	samplesPerPixel := 1.
  2995         bitsPerSample := ByteArray with:d 
  2995 	bitsPerSample := ByteArray with:d
  2996     ]
  2996     ]
  2997 
  2997 
  2998     "Modified: 20.2.1997 / 14:39:10 / cg"
  2998     "Modified: 20.2.1997 / 14:39:10 / cg"
  2999 !
  2999 !
  3000 
  3000 
  3024 !
  3024 !
  3025 
  3025 
  3026 photometric:aSymbol
  3026 photometric:aSymbol
  3027     "set the photometric interpretation of the pixel values.
  3027     "set the photometric interpretation of the pixel values.
  3028      The argument, aSymbol is one of:
  3028      The argument, aSymbol is one of:
  3029         #blackIs0, #whiteIs0, #palette, #rgb
  3029 	#blackIs0, #whiteIs0, #palette, #rgb
  3030      See TIFF documentation, from which the photometric concept is borrowed.
  3030      See TIFF documentation, from which the photometric concept is borrowed.
  3031 
  3031 
  3032      This interface is only to be used when initializing
  3032      This interface is only to be used when initializing
  3033      instances or by image readers. Calling for a change of an
  3033      instances or by image readers. Calling for a change of an
  3034      existing image may confuse later pixel interpretation."
  3034      existing image may confuse later pixel interpretation."
  3035 
  3035 
  3036     |b|
  3036     |b|
  3037 
  3037 
  3038     photometric := aSymbol.
  3038     photometric := aSymbol.
  3039     bitsPerSample isNil ifTrue:[
  3039     bitsPerSample isNil ifTrue:[
  3040         photometric == #rgb ifTrue:[
  3040 	photometric == #rgb ifTrue:[
  3041             b := self class imageDepth // 3.
  3041 	    b := self class imageDepth // 3.
  3042             bitsPerSample := ByteArray with:b with:b with:b
  3042 	    bitsPerSample := ByteArray with:b with:b with:b
  3043         ] ifFalse:[
  3043 	] ifFalse:[
  3044             bitsPerSample := ByteArray with:(self class imageDepth)
  3044 	    bitsPerSample := ByteArray with:(self class imageDepth)
  3045         ].
  3045 	].
  3046     ].
  3046     ].
  3047     samplesPerPixel isNil ifTrue:[
  3047     samplesPerPixel isNil ifTrue:[
  3048         photometric == #rgb ifTrue:[
  3048 	photometric == #rgb ifTrue:[
  3049             samplesPerPixel := 3
  3049 	    samplesPerPixel := 3
  3050         ] ifFalse:[
  3050 	] ifFalse:[
  3051             samplesPerPixel := 1
  3051 	    samplesPerPixel := 1
  3052         ]
  3052 	]
  3053     ].
  3053     ].
  3054 
  3054 
  3055     "Modified: 10.6.1996 / 18:21:29 / cg"
  3055     "Modified: 10.6.1996 / 18:21:29 / cg"
  3056 !
  3056 !
  3057 
  3057 
  3077     width := aNumber
  3077     width := aNumber
  3078 
  3078 
  3079     "Modified: 23.4.1996 / 11:08:48 / cg"
  3079     "Modified: 23.4.1996 / 11:08:48 / cg"
  3080 !
  3080 !
  3081 
  3081 
  3082 width:w height:h 
  3082 width:w height:h
  3083     "set the width and height of the image.
  3083     "set the width and height of the image.
  3084 
  3084 
  3085      This interface is only to be used when initializing
  3085      This interface is only to be used when initializing
  3086      instances or by image readers. Calling for a change of an
  3086      instances or by image readers. Calling for a change of an
  3087      existing image may confuse later pixel interpretation."
  3087      existing image may confuse later pixel interpretation."
  3146      This interface is only to be used when initializing
  3146      This interface is only to be used when initializing
  3147      instances or by image readers. Calling for a change of an
  3147      instances or by image readers. Calling for a change of an
  3148      existing image may confuse later pixel interpretation."
  3148      existing image may confuse later pixel interpretation."
  3149 
  3149 
  3150     ^ self
  3150     ^ self
  3151 	width:w 
  3151 	width:w
  3152 	height:h 
  3152 	height:h
  3153 	photometric:p 
  3153 	photometric:p
  3154 	samplesPerPixel:spp 
  3154 	samplesPerPixel:spp
  3155 	bitsPerSample:bps 
  3155 	bitsPerSample:bps
  3156 	colorMap:cm 
  3156 	colorMap:cm
  3157 	bits:pixels 
  3157 	bits:pixels
  3158 	mask:nil
  3158 	mask:nil
  3159 
  3159 
  3160     "Modified: 20.6.1996 / 17:10:24 / cg"
  3160     "Modified: 20.6.1996 / 17:10:24 / cg"
  3161 !
  3161 !
  3162 
  3162 
  3269 
  3269 
  3270     "
  3270     "
  3271      |i|
  3271      |i|
  3272 
  3272 
  3273      i := Depth4Image
  3273      i := Depth4Image
  3274              width:4 
  3274 	     width:4
  3275              height:4
  3275 	     height:4
  3276              fromArray:#[ 
  3276 	     fromArray:#[
  3277                             16r01 16r23
  3277 			    16r01 16r23
  3278                             16r45 16r67
  3278 			    16r45 16r67
  3279                             16r89 16rab
  3279 			    16r89 16rab
  3280                             16rcd 16ref 
  3280 			    16rcd 16ref
  3281                         ].
  3281 			].
  3282      i := i magnifiedBy:30.
  3282      i := i magnifiedBy:30.
  3283      i inspect.
  3283      i inspect.
  3284      i asFloydSteinbergDitheredMonochromeImage inspect.
  3284      i asFloydSteinbergDitheredMonochromeImage inspect.
  3285      i asBurkesDitheredMonochromeImage inspect.
  3285      i asBurkesDitheredMonochromeImage inspect.
  3286      i asOrderedDitheredMonochromeImage inspect.
  3286      i asOrderedDitheredMonochromeImage inspect.
  3313 
  3313 
  3314 asErrorDitheredMonochromeImage
  3314 asErrorDitheredMonochromeImage
  3315     "return an error-diffusion dithered monochrome image from the receiver image."
  3315     "return an error-diffusion dithered monochrome image from the receiver image."
  3316 
  3316 
  3317     DitherAlgorithm == #burkes ifTrue:[
  3317     DitherAlgorithm == #burkes ifTrue:[
  3318         ^ self asBurkesDitheredMonochromeImage
  3318 	^ self asBurkesDitheredMonochromeImage
  3319     ].
  3319     ].
  3320     DitherAlgorithm == #stevensonArce ifTrue:[
  3320     DitherAlgorithm == #stevensonArce ifTrue:[
  3321         ^ self asStevensonArceDitheredMonochromeImage
  3321 	^ self asStevensonArceDitheredMonochromeImage
  3322     ].
  3322     ].
  3323     ^ self asFloydSteinbergDitheredMonochromeImage
  3323     ^ self asFloydSteinbergDitheredMonochromeImage
  3324 
  3324 
  3325     "
  3325     "
  3326      |i|
  3326      |i|
  3342 
  3342 
  3343     "
  3343     "
  3344      |i|
  3344      |i|
  3345 
  3345 
  3346      i := Depth4Image
  3346      i := Depth4Image
  3347              width:4 
  3347 	     width:4
  3348              height:4
  3348 	     height:4
  3349              fromArray:#[ 
  3349 	     fromArray:#[
  3350                             16r01 16r23
  3350 			    16r01 16r23
  3351                             16r45 16r67
  3351 			    16r45 16r67
  3352                             16r89 16rab
  3352 			    16r89 16rab
  3353                             16rcd 16ref 
  3353 			    16rcd 16ref
  3354                         ].
  3354 			].
  3355      i := i magnifiedBy:30.
  3355      i := i magnifiedBy:30.
  3356      i inspect.
  3356      i inspect.
  3357      i asErrorDitheredMonochromeImage inspect.
  3357      i asErrorDitheredMonochromeImage inspect.
  3358      i asOrderedDitheredMonochromeImage inspect.
  3358      i asOrderedDitheredMonochromeImage inspect.
  3359     "
  3359     "
  3360 
  3360 
  3361     "Modified: 10.6.1996 / 14:22:30 / cg"
  3361     "Modified: 10.6.1996 / 14:22:30 / cg"
  3362 !
  3362 !
  3363 
  3363 
  3364 asFloydSteinbergDitheredDepth8FormOn:aDevice colors:fixColors 
  3364 asFloydSteinbergDitheredDepth8FormOn:aDevice colors:fixColors
  3365     "return a floyd-steinberg dithered pseudoForm from the picture. 
  3365     "return a floyd-steinberg dithered pseudoForm from the picture.
  3366      Use the colors in the fixColors array.
  3366      Use the colors in the fixColors array.
  3367      By passing the ditherColors as extra array, this method can
  3367      By passing the ditherColors as extra array, this method can
  3368      also be used to dither an 8bit image into a smaller number of colors,
  3368      also be used to dither an 8bit image into a smaller number of colors,
  3369      for example to create dithered Depth4Images from Depth8Images."
  3369      for example to create dithered Depth4Images from Depth8Images."
  3370 
  3370 
  3371     |pseudoBits f deviceDepth map|
  3371     |pseudoBits f deviceDepth map|
  3372 
  3372 
  3373     deviceDepth := aDevice depth.
  3373     deviceDepth := aDevice depth.
  3374     deviceDepth == 8 ifFalse:[
  3374     deviceDepth == 8 ifFalse:[
  3375         (aDevice supportedImageFormatForDepth:8) isNil ifTrue:[
  3375 	(aDevice supportedImageFormatForDepth:8) isNil ifTrue:[
  3376             ^ nil.
  3376 	    ^ nil.
  3377         ]
  3377 	]
  3378     ].
  3378     ].
  3379 
  3379 
  3380     pseudoBits := self floydSteinbergDitheredDepth8BitsColors:fixColors.
  3380     pseudoBits := self floydSteinbergDitheredDepth8BitsColors:fixColors.
  3381     pseudoBits isNil ifTrue:[^ nil].
  3381     pseudoBits isNil ifTrue:[^ nil].
  3382 
  3382 
  3387     "/ have to create a funny colorMap, where
  3387     "/ have to create a funny colorMap, where
  3388     "/ color at:index == color colorId:index
  3388     "/ color at:index == color colorId:index
  3389     "/
  3389     "/
  3390     map := Array new:256.
  3390     map := Array new:256.
  3391     fixColors do:[:clr |
  3391     fixColors do:[:clr |
  3392         map at:clr colorId + 1 put:clr
  3392 	map at:clr colorId + 1 put:clr
  3393     ].
  3393     ].
  3394     f colorMap:map. 
  3394     f colorMap:map.
  3395     f initGC.
  3395     f initGC.
  3396     f bits:pseudoBits.
  3396     f bits:pseudoBits.
  3397     aDevice 
  3397     aDevice
  3398         drawBits:pseudoBits 
  3398 	drawBits:pseudoBits
  3399         bitsPerPixel:8 
  3399 	bitsPerPixel:8
  3400         depth:deviceDepth  
  3400 	depth:deviceDepth
  3401         padding:8
  3401 	padding:8
  3402         width:width height:height
  3402 	width:width height:height
  3403         x:0 y:0
  3403 	x:0 y:0
  3404         into:(f id) x:0 y:0 
  3404 	into:(f id) x:0 y:0
  3405         width:width height:height 
  3405 	width:width height:height
  3406         with:(f gcId).
  3406 	with:(f gcId).
  3407     ^ f
  3407     ^ f
  3408 
  3408 
  3409     "
  3409     "
  3410      example: 
  3410      example:
  3411         color reduction from Depth8 to Depth4 (dithering) can be done by:
  3411 	color reduction from Depth8 to Depth4 (dithering) can be done by:
  3412 
  3412 
  3413      |img8 reducedImg8 img4 map form|
  3413      |img8 reducedImg8 img4 map form|
  3414 
  3414 
  3415      map := #( 
  3415      map := #(
  3416                   (0     0   0)
  3416 		  (0     0   0)
  3417                   (0     0 100)
  3417 		  (0     0 100)
  3418                   (0    50   0)
  3418 		  (0    50   0)
  3419                   (0    50 100)
  3419 		  (0    50 100)
  3420                   (0   100   0)
  3420 		  (0   100   0)
  3421                   (0   100 100)
  3421 		  (0   100 100)
  3422                   (100   0   0)
  3422 		  (100   0   0)
  3423                   (100   0 100)
  3423 		  (100   0 100)
  3424                   (100  50   0)
  3424 		  (100  50   0)
  3425                   (100  50 100)
  3425 		  (100  50 100)
  3426                   (100 100   0)
  3426 		  (100 100   0)
  3427                   (100 100 100)) collect:[:rgb | (Color red:(rgb at:1)
  3427 		  (100 100 100)) collect:[:rgb | (Color red:(rgb at:1)
  3428                                                       green:(rgb at:2)
  3428 						      green:(rgb at:2)
  3429                                                        blue:(rgb at:3)) onDevice:Display].
  3429 						       blue:(rgb at:3)) onDevice:Display].
  3430 
  3430 
  3431      img8 := Image fromFile:'goodies/bitmaps/bf.im8'.
  3431      img8 := Image fromFile:'goodies/bitmaps/bf.im8'.
  3432      form := img8 paletteImageAsDitheredPseudoFormOn:Display 
  3432      form := img8 paletteImageAsDitheredPseudoFormOn:Display
  3433                       colors:map 
  3433 		      colors:map
  3434                         nRed:2
  3434 			nRed:2
  3435                       nGreen:3
  3435 		      nGreen:3
  3436                        nBlue:2.
  3436 		       nBlue:2.
  3437      img8 := Depth8Image fromForm:form.    'dithered version of original image'.
  3437      img8 := Depth8Image fromForm:form.    'dithered version of original image'.
  3438      img4 := Depth4Image fromImage:img8.
  3438      img4 := Depth4Image fromImage:img8.
  3439     "
  3439     "
  3440 
  3440 
  3441     "Modified: 14.6.1996 / 16:52:34 / cg"
  3441     "Modified: 14.6.1996 / 16:52:34 / cg"
  3442     "Created: 23.6.1997 / 15:25:37 / cg"
  3442     "Created: 23.6.1997 / 15:25:37 / cg"
  3443 !
  3443 !
  3444 
  3444 
  3445 asFloydSteinbergDitheredDepth8FormOn:aDevice colors:fixColors nRed:nRed nGreen:nGreen nBlue:nBlue 
  3445 asFloydSteinbergDitheredDepth8FormOn:aDevice colors:fixColors nRed:nRed nGreen:nGreen nBlue:nBlue
  3446     "return a floyd-steinberg dithered pseudoForm from the palette picture. 
  3446     "return a floyd-steinberg dithered pseudoForm from the palette picture.
  3447      Use the colors in the fixColors array, which must be fixR x fixG x fixB
  3447      Use the colors in the fixColors array, which must be fixR x fixG x fixB
  3448      colors assigned to aDevice, such as the preallocated colors of the
  3448      colors assigned to aDevice, such as the preallocated colors of the
  3449      Color class. 
  3449      Color class.
  3450      By passing the ditherColors as extra array, this method can
  3450      By passing the ditherColors as extra array, this method can
  3451      also be used to dither an 8bit image into a smaller number of colors,
  3451      also be used to dither an 8bit image into a smaller number of colors,
  3452      for example to create dithered Depth4Images from Depth8Images."
  3452      for example to create dithered Depth4Images from Depth8Images."
  3453 
  3453 
  3454     |pseudoBits f deviceDepth map|
  3454     |pseudoBits f deviceDepth map|
  3455 
  3455 
  3456     deviceDepth := aDevice depth.
  3456     deviceDepth := aDevice depth.
  3457     deviceDepth == 8 ifFalse:[
  3457     deviceDepth == 8 ifFalse:[
  3458         (aDevice supportedImageFormatForDepth:8) isNil ifTrue:[
  3458 	(aDevice supportedImageFormatForDepth:8) isNil ifTrue:[
  3459             ^ nil
  3459 	    ^ nil
  3460         ]
  3460 	]
  3461     ].
  3461     ].
  3462 
  3462 
  3463     pseudoBits := self floydSteinbergDitheredDepth8BitsColors:fixColors nRed:nRed nGreen:nGreen nBlue:nBlue.
  3463     pseudoBits := self floydSteinbergDitheredDepth8BitsColors:fixColors nRed:nRed nGreen:nGreen nBlue:nBlue.
  3464     pseudoBits isNil ifTrue:[^ nil].
  3464     pseudoBits isNil ifTrue:[^ nil].
  3465 
  3465 
  3470     "/ have to create a funny colorMap, where
  3470     "/ have to create a funny colorMap, where
  3471     "/ color at:index == color colorId:index
  3471     "/ color at:index == color colorId:index
  3472     "/
  3472     "/
  3473     map := Array new:256.
  3473     map := Array new:256.
  3474     fixColors do:[:clr |
  3474     fixColors do:[:clr |
  3475         map at:clr colorId + 1 put:clr
  3475 	map at:clr colorId + 1 put:clr
  3476     ].
  3476     ].
  3477     f colorMap:map. 
  3477     f colorMap:map.
  3478     f initGC.
  3478     f initGC.
  3479     f bits:pseudoBits.
  3479     f bits:pseudoBits.
  3480     aDevice 
  3480     aDevice
  3481         drawBits:pseudoBits 
  3481 	drawBits:pseudoBits
  3482         bitsPerPixel:8 
  3482 	bitsPerPixel:8
  3483         depth:deviceDepth  
  3483 	depth:deviceDepth
  3484         padding:8
  3484 	padding:8
  3485         width:width height:height
  3485 	width:width height:height
  3486         x:0 y:0
  3486 	x:0 y:0
  3487         into:(f id) x:0 y:0 
  3487 	into:(f id) x:0 y:0
  3488         width:width height:height 
  3488 	width:width height:height
  3489         with:(f gcId).
  3489 	with:(f gcId).
  3490     ^ f
  3490     ^ f
  3491 
  3491 
  3492     "
  3492     "
  3493      example: 
  3493      example:
  3494         color reduction from Depth8 to Depth4 (dithering) can be done by:
  3494 	color reduction from Depth8 to Depth4 (dithering) can be done by:
  3495 
  3495 
  3496      |img8 reducedImg8 img4 map form|
  3496      |img8 reducedImg8 img4 map form|
  3497 
  3497 
  3498      map := #( 
  3498      map := #(
  3499                   (0     0   0)
  3499 		  (0     0   0)
  3500                   (0     0 100)
  3500 		  (0     0 100)
  3501                   (0    50   0)
  3501 		  (0    50   0)
  3502                   (0    50 100)
  3502 		  (0    50 100)
  3503                   (0   100   0)
  3503 		  (0   100   0)
  3504                   (0   100 100)
  3504 		  (0   100 100)
  3505                   (100   0   0)
  3505 		  (100   0   0)
  3506                   (100   0 100)
  3506 		  (100   0 100)
  3507                   (100  50   0)
  3507 		  (100  50   0)
  3508                   (100  50 100)
  3508 		  (100  50 100)
  3509                   (100 100   0)
  3509 		  (100 100   0)
  3510                   (100 100 100)) collect:[:rgb | (Color red:(rgb at:1)
  3510 		  (100 100 100)) collect:[:rgb | (Color red:(rgb at:1)
  3511                                                       green:(rgb at:2)
  3511 						      green:(rgb at:2)
  3512                                                        blue:(rgb at:3)) onDevice:Display].
  3512 						       blue:(rgb at:3)) onDevice:Display].
  3513 
  3513 
  3514      img8 := Image fromFile:'goodies/bitmaps/bf.im8'.
  3514      img8 := Image fromFile:'goodies/bitmaps/bf.im8'.
  3515      form := img8 paletteImageAsDitheredPseudoFormOn:Display 
  3515      form := img8 paletteImageAsDitheredPseudoFormOn:Display
  3516                       colors:map 
  3516 		      colors:map
  3517                         nRed:2
  3517 			nRed:2
  3518                       nGreen:3
  3518 		      nGreen:3
  3519                        nBlue:2.
  3519 		       nBlue:2.
  3520      img8 := Depth8Image fromForm:form.    'dithered version of original image'.
  3520      img8 := Depth8Image fromForm:form.    'dithered version of original image'.
  3521      img4 := Depth4Image fromImage:img8.
  3521      img4 := Depth4Image fromImage:img8.
  3522     "
  3522     "
  3523 
  3523 
  3524     "Modified: 14.6.1996 / 16:52:34 / cg"
  3524     "Modified: 14.6.1996 / 16:52:34 / cg"
  3585 
  3585 
  3586     "
  3586     "
  3587      |i|
  3587      |i|
  3588 
  3588 
  3589      i := Depth24Image width:4 height:1
  3589      i := Depth24Image width:4 height:1
  3590 	  fromArray:#[ 
  3590 	  fromArray:#[
  3591 	    16rFF 16r00 16r00   16rFF 16r00 16r00  16rFF 16r00 16r00  16rFF 16r00 16r00
  3591 	    16rFF 16r00 16r00   16rFF 16r00 16r00  16rFF 16r00 16r00  16rFF 16r00 16r00
  3592 	    16rFF 16r00 16r00   16rFF 16r00 16r00  16rFF 16r00 16r00  16rFF 16r00 16r00
  3592 	    16rFF 16r00 16r00   16rFF 16r00 16r00  16rFF 16r00 16r00  16rFF 16r00 16r00
  3593 	    16rFF 16r00 16r00   16rFF 16r00 16r00  16rFF 16r00 16r00  16rFF 16r00 16r00
  3593 	    16rFF 16r00 16r00   16rFF 16r00 16r00  16rFF 16r00 16r00  16rFF 16r00 16r00
  3594 	    16rFF 16r00 16r00   16rFF 16r00 16r00  16rFF 16r00 16r00  16rFF 16r00 16r00].
  3594 	    16rFF 16r00 16r00   16rFF 16r00 16r00  16rFF 16r00 16r00  16rFF 16r00 16r00].
  3595      i := i magnifiedBy:4@1.
  3595      i := i magnifiedBy:4@1.
  3602 
  3602 
  3603     "
  3603     "
  3604      |i|
  3604      |i|
  3605 
  3605 
  3606      i := Depth24Image width:4 height:6
  3606      i := Depth24Image width:4 height:6
  3607 	  fromArray:#[ 
  3607 	  fromArray:#[
  3608 	    16r00 16r00 16r00   16r00 16r00 16r80  16r00 16r00 16rff  16r00 16r80 16r00
  3608 	    16r00 16r00 16r00   16r00 16r00 16r80  16r00 16r00 16rff  16r00 16r80 16r00
  3609 	    16r00 16r80 16r80   16r00 16rFF 16r00  16r00 16rFF 16r80  16r00 16rFF 16rFF
  3609 	    16r00 16r80 16r80   16r00 16rFF 16r00  16r00 16rFF 16r80  16r00 16rFF 16rFF
  3610 	    16r80 16r00 16r00   16r80 16r00 16r80  16r80 16r00 16rff  16r80 16r80 16r00
  3610 	    16r80 16r00 16r00   16r80 16r00 16r80  16r80 16r00 16rff  16r80 16r80 16r00
  3611 	    16r80 16r80 16r80   16r80 16rFF 16r00  16r80 16rFF 16r80  16r80 16rFF 16rFF
  3611 	    16r80 16r80 16r80   16r80 16rFF 16r00  16r80 16rFF 16r80  16r80 16rFF 16rFF
  3612 	    16rFF 16r00 16r00   16rFF 16r00 16r80  16rFF 16r00 16rff  16rFF 16r80 16r00
  3612 	    16rFF 16r00 16r00   16rFF 16r00 16r80  16rFF 16r00 16rff  16rFF 16r80 16r00
  3640 
  3640 
  3641     "
  3641     "
  3642      |i|
  3642      |i|
  3643 
  3643 
  3644      i := Depth4Image
  3644      i := Depth4Image
  3645 	     width:4 
  3645 	     width:4
  3646 	     height:4
  3646 	     height:4
  3647 	     fromArray:#[ 
  3647 	     fromArray:#[
  3648 			    16r01 16r23
  3648 			    16r01 16r23
  3649 			    16r45 16r67
  3649 			    16r45 16r67
  3650 			    16r89 16rab
  3650 			    16r89 16rab
  3651 			    16rcd 16ref 
  3651 			    16rcd 16ref
  3652 			].
  3652 			].
  3653      i := i magnifiedBy:30.
  3653      i := i magnifiedBy:30.
  3654      i inspect.
  3654      i inspect.
  3655      (i asFloydSteinbergDitheredGrayImageDepth:1) inspect.
  3655      (i asFloydSteinbergDitheredGrayImageDepth:1) inspect.
  3656      (i asFloydSteinbergDitheredGrayImageDepth:2) inspect.
  3656      (i asFloydSteinbergDitheredGrayImageDepth:2) inspect.
  3727 
  3727 
  3728     "
  3728     "
  3729      |i|
  3729      |i|
  3730 
  3730 
  3731      i := Depth4Image
  3731      i := Depth4Image
  3732 	     width:4 
  3732 	     width:4
  3733 	     height:4
  3733 	     height:4
  3734 	     fromArray:#[ 
  3734 	     fromArray:#[
  3735 			    16r01 16r23
  3735 			    16r01 16r23
  3736 			    16r45 16r67
  3736 			    16r45 16r67
  3737 			    16r89 16rab
  3737 			    16r89 16rab
  3738 			    16rcd 16ref 
  3738 			    16rcd 16ref
  3739 			].
  3739 			].
  3740      i := i magnifiedBy:30.
  3740      i := i magnifiedBy:30.
  3741      i inspect.
  3741      i inspect.
  3742      i asFloydSteinbergDitheredMonochromeImage inspect.
  3742      i asFloydSteinbergDitheredMonochromeImage inspect.
  3743      i asBurkesDitheredMonochromeImage inspect.
  3743      i asBurkesDitheredMonochromeImage inspect.
  3754 
  3754 
  3755     |pseudoBits pseudoBits8 f has8BitImage deviceDepth map d|
  3755     |pseudoBits pseudoBits8 f has8BitImage deviceDepth map d|
  3756 
  3756 
  3757     deviceDepth := aDevice depth.
  3757     deviceDepth := aDevice depth.
  3758     has8BitImage := (deviceDepth == 8)
  3758     has8BitImage := (deviceDepth == 8)
  3759                     or:[ (aDevice supportedImageFormatForDepth:8) notNil ].
  3759 		    or:[ (aDevice supportedImageFormatForDepth:8) notNil ].
  3760 
  3760 
  3761     has8BitImage ifFalse:[
  3761     has8BitImage ifFalse:[
  3762         deviceDepth == 4 ifFalse:[^ nil].
  3762 	deviceDepth == 4 ifFalse:[^ nil].
  3763 
  3763 
  3764         pseudoBits8 := self nfloydSteinbergDitheredDepth8BitsColors:colors.
  3764 	pseudoBits8 := self nfloydSteinbergDitheredDepth8BitsColors:colors.
  3765         pseudoBits8 isNil ifTrue:[^ nil].
  3765 	pseudoBits8 isNil ifTrue:[^ nil].
  3766         "/ convert to devices depth
  3766 	"/ convert to devices depth
  3767 
  3767 
  3768         pseudoBits := ByteArray new:(width*4+7//8 * height).
  3768 	pseudoBits := ByteArray new:(width*4+7//8 * height).
  3769         pseudoBits8 compressPixels:4 width:width height:height into:pseudoBits mapping:nil.
  3769 	pseudoBits8 compressPixels:4 width:width height:height into:pseudoBits mapping:nil.
  3770         d := 4.
  3770 	d := 4.
  3771     ] ifTrue:[
  3771     ] ifTrue:[
  3772         pseudoBits := self nfloydSteinbergDitheredDepth8BitsColors:colors.
  3772 	pseudoBits := self nfloydSteinbergDitheredDepth8BitsColors:colors.
  3773         pseudoBits isNil ifTrue:[^ nil].
  3773 	pseudoBits isNil ifTrue:[^ nil].
  3774         d := 8.
  3774 	d := 8.
  3775     ].
  3775     ].
  3776 
  3776 
  3777     f := Form width:width height:height depth:deviceDepth on:aDevice.
  3777     f := Form width:width height:height depth:deviceDepth on:aDevice.
  3778     f isNil ifTrue:[^ nil].
  3778     f isNil ifTrue:[^ nil].
  3779 
  3779 
  3781     "/ have to create a funny colorMap, where
  3781     "/ have to create a funny colorMap, where
  3782     "/ color at:index == color colorId:index
  3782     "/ color at:index == color colorId:index
  3783     "/
  3783     "/
  3784     map := Array new:256 withAll:0.
  3784     map := Array new:256 withAll:0.
  3785     colors do:[:clr |
  3785     colors do:[:clr |
  3786         clr notNil ifTrue:[
  3786 	clr notNil ifTrue:[
  3787             map at:clr colorId + 1 put:clr
  3787 	    map at:clr colorId + 1 put:clr
  3788         ]
  3788 	]
  3789     ].
  3789     ].
  3790     f colorMap:map. 
  3790     f colorMap:map.
  3791     f initGC.
  3791     f initGC.
  3792     f bits:pseudoBits.
  3792     f bits:pseudoBits.
  3793     aDevice 
  3793     aDevice
  3794         drawBits:pseudoBits 
  3794 	drawBits:pseudoBits
  3795         bitsPerPixel:d 
  3795 	bitsPerPixel:d
  3796         depth:deviceDepth  
  3796 	depth:deviceDepth
  3797         padding:8
  3797 	padding:8
  3798         width:width height:height
  3798 	width:width height:height
  3799         x:0 y:0
  3799 	x:0 y:0
  3800         into:(f id) x:0 y:0 
  3800 	into:(f id) x:0 y:0
  3801         width:width height:height 
  3801 	width:width height:height
  3802         with:(f gcId).
  3802 	with:(f gcId).
  3803     ^ f
  3803     ^ f
  3804 
  3804 
  3805     "
  3805     "
  3806      |i|
  3806      |i|
  3807 
  3807 
  3826     |form visual|
  3826     |form visual|
  3827 
  3827 
  3828     ((aDevice == device) and:[deviceForm notNil]) ifTrue:[^ deviceForm].
  3828     ((aDevice == device) and:[deviceForm notNil]) ifTrue:[^ deviceForm].
  3829 
  3829 
  3830     mask notNil ifTrue:[
  3830     mask notNil ifTrue:[
  3831         mask := mask onDevice:aDevice
  3831 	mask := mask onDevice:aDevice
  3832     ].
  3832     ].
  3833 
  3833 
  3834     (aDevice depth == 1
  3834     (aDevice depth == 1
  3835     or:[aDevice hasGrayscales not]) ifTrue:[
  3835     or:[aDevice hasGrayscales not]) ifTrue:[
  3836         form := self asMonochromeFormOn:aDevice.
  3836 	form := self asMonochromeFormOn:aDevice.
  3837     ] ifFalse:[
  3837     ] ifFalse:[
  3838         ((visual := aDevice visualType) == #StaticGray) ifTrue:[
  3838 	((visual := aDevice visualType) == #StaticGray) ifTrue:[
  3839             form := self asGrayFormOn:aDevice.
  3839 	    form := self asGrayFormOn:aDevice.
  3840         ] ifFalse:[
  3840 	] ifFalse:[
  3841             (visual == #PseudoColor
  3841 	    (visual == #PseudoColor
  3842              or:[visual == #StaticColor]) ifTrue:[
  3842 	     or:[visual == #StaticColor]) ifTrue:[
  3843                 form := self asPseudoFormQuickOn:aDevice.
  3843 		form := self asPseudoFormQuickOn:aDevice.
  3844             ].
  3844 	    ].
  3845         ]
  3845 	]
  3846     ].
  3846     ].
  3847 
  3847 
  3848     form isNil ifTrue:[
  3848     form isNil ifTrue:[
  3849         (photometric == #palette) ifTrue:[
  3849 	(photometric == #palette) ifTrue:[
  3850             form := self paletteImageAsFormOn:aDevice
  3850 	    form := self paletteImageAsFormOn:aDevice
  3851         ] ifFalse:[
  3851 	] ifFalse:[
  3852             (photometric == #rgb) ifTrue:[
  3852 	    (photometric == #rgb) ifTrue:[
  3853                 form := self rgbImageAsFormOn:aDevice
  3853 		form := self rgbImageAsFormOn:aDevice
  3854             ] ifFalse:[
  3854 	    ] ifFalse:[
  3855                 (photometric == #cmy or:[photometric == #cmyk]) ifTrue:[
  3855 		(photometric == #cmy or:[photometric == #cmyk]) ifTrue:[
  3856                     form := self rgbImageAsFormOn:aDevice
  3856 		    form := self rgbImageAsFormOn:aDevice
  3857                 ] ifFalse:[
  3857 		] ifFalse:[
  3858                     form := self greyImageAsFormOn:aDevice
  3858 		    form := self greyImageAsFormOn:aDevice
  3859                 ]
  3859 		]
  3860             ]
  3860 	    ]
  3861         ].
  3861 	].
  3862     ].
  3862     ].
  3863 
  3863 
  3864     (device isNil or:[aDevice == device]) ifTrue:[
  3864     (device isNil or:[aDevice == device]) ifTrue:[
  3865         "remember this form in the receiver ..."
  3865 	"remember this form in the receiver ..."
  3866 
  3866 
  3867         form notNil ifTrue:[
  3867 	form notNil ifTrue:[
  3868             form := form asImageForm.
  3868 	    form := form asImageForm.
  3869             deviceForm := form.
  3869 	    deviceForm := form.
  3870             maskedPixelsAre0 := nil.
  3870 	    maskedPixelsAre0 := nil.
  3871             device isNil ifTrue:[
  3871 	    device isNil ifTrue:[
  3872                 device := aDevice.
  3872 		device := aDevice.
  3873                 Lobby register:self
  3873 		Lobby register:self
  3874             ] ifFalse:[
  3874 	    ] ifFalse:[
  3875                 Lobby registerChange:self
  3875 		Lobby registerChange:self
  3876             ].
  3876 	    ].
  3877             "
  3877 	    "
  3878              can save space, by not keeping the images data-bits
  3878 	     can save space, by not keeping the images data-bits
  3879              twice (here and in the device form)
  3879 	     twice (here and in the device form)
  3880             "
  3880 	    "
  3881             form forgetBits
  3881 	    form forgetBits
  3882         ]
  3882 	]
  3883     ].
  3883     ].
  3884 
  3884 
  3885     ^ form
  3885     ^ form
  3886 
  3886 
  3887     "
  3887     "
  3939 
  3939 
  3940 asGrayImageDepth:depth
  3940 asGrayImageDepth:depth
  3941     "get a gray image from the receiver"
  3941     "get a gray image from the receiver"
  3942 
  3942 
  3943     (self colorMap notNil and:[depth == self depth]) ifTrue:[
  3943     (self colorMap notNil and:[depth == self depth]) ifTrue:[
  3944         ^ self copyWithColorMapProcessing:[:clr | Color brightness:(clr brightness)].
  3944 	^ self copyWithColorMapProcessing:[:clr | Color brightness:(clr brightness)].
  3945     ].
  3945     ].
  3946     ^ self asGrayImageDepth:depth dither:DitherAlgorithm.
  3946     ^ self asGrayImageDepth:depth dither:DitherAlgorithm.
  3947 
  3947 
  3948     "
  3948     "
  3949      |i|
  3949      |i|
  4005 
  4005 
  4006     |form|
  4006     |form|
  4007 
  4007 
  4008     ((aDevice == device) and:[monoDeviceForm notNil]) ifTrue:[^ monoDeviceForm].
  4008     ((aDevice == device) and:[monoDeviceForm notNil]) ifTrue:[^ monoDeviceForm].
  4009     self depth == 1 ifTrue:[
  4009     self depth == 1 ifTrue:[
  4010         ((aDevice == device) and:[deviceForm notNil]) ifTrue:[^ deviceForm].
  4010 	((aDevice == device) and:[deviceForm notNil]) ifTrue:[^ deviceForm].
  4011         ^ self asFormOn:aDevice
  4011 	^ self asFormOn:aDevice
  4012     ].
  4012     ].
  4013 
  4013 
  4014     form := self asMonochromeFormOn:aDevice dither:DitherAlgorithm.
  4014     form := self asMonochromeFormOn:aDevice dither:DitherAlgorithm.
  4015 
  4015 
  4016     (device isNil or:[aDevice == device]) ifTrue:[
  4016     (device isNil or:[aDevice == device]) ifTrue:[
  4017         "remember this form in the receiver ..."
  4017 	"remember this form in the receiver ..."
  4018 
  4018 
  4019         form notNil ifTrue:[
  4019 	form notNil ifTrue:[
  4020             form := form asImageForm.
  4020 	    form := form asImageForm.
  4021             monoDeviceForm := form.
  4021 	    monoDeviceForm := form.
  4022             device isNil ifTrue:[
  4022 	    device isNil ifTrue:[
  4023                 device := aDevice.
  4023 		device := aDevice.
  4024                 Lobby register:self
  4024 		Lobby register:self
  4025             ] ifFalse:[
  4025 	    ] ifFalse:[
  4026                 Lobby registerChange:self
  4026 		Lobby registerChange:self
  4027             ].
  4027 	    ].
  4028             "
  4028 	    "
  4029              can save space, by not keeping the images data-bits
  4029 	     can save space, by not keeping the images data-bits
  4030              twice (here and in the device form)
  4030 	     twice (here and in the device form)
  4031             "
  4031 	    "
  4032             form forgetBits
  4032 	    form forgetBits
  4033         ]
  4033 	]
  4034     ].
  4034     ].
  4035 
  4035 
  4036     ^ form
  4036     ^ form
  4037 
  4037 
  4038     "
  4038     "
  4076     ^ self makeDeviceMonochromeBitmapOn:aDevice fromArray:monoBits
  4076     ^ self makeDeviceMonochromeBitmapOn:aDevice fromArray:monoBits
  4077 
  4077 
  4078     "Modified: 10.6.1996 / 20:18:05 / cg"
  4078     "Modified: 10.6.1996 / 20:18:05 / cg"
  4079 !
  4079 !
  4080 
  4080 
  4081 asNearestPaintDepth8FormOn:aDevice colors:fixColors 
  4081 asNearestPaintDepth8FormOn:aDevice colors:fixColors
  4082     "return a nearest paint pseudoForm from the palette picture. 
  4082     "return a nearest paint pseudoForm from the palette picture.
  4083      Use the colors in the fixColors array. 
  4083      Use the colors in the fixColors array.
  4084      By passing the ditherColors as extra array, this method can
  4084      By passing the ditherColors as extra array, this method can
  4085      also be used to dither an 8bit image into a smaller number of colors,
  4085      also be used to dither an 8bit image into a smaller number of colors,
  4086      for example to create dithered Depth4Images from Depth8Images."
  4086      for example to create dithered Depth4Images from Depth8Images."
  4087 
  4087 
  4088     ^ self asNearestPaintDepth8FormOn:aDevice colors:fixColors nRed:nil nGreen:nil nBlue:nil.
  4088     ^ self asNearestPaintDepth8FormOn:aDevice colors:fixColors nRed:nil nGreen:nil nBlue:nil.
  4089 
  4089 
  4090     "
  4090     "
  4091      example: 
  4091      example:
  4092         color reduction from Depth8 to Depth4 can be done by:
  4092 	color reduction from Depth8 to Depth4 can be done by:
  4093 
  4093 
  4094      |img8 reducedImg8 img4 map form|
  4094      |img8 reducedImg8 img4 map form|
  4095 
  4095 
  4096      map := #( 
  4096      map := #(
  4097                   (0     0   0)
  4097 		  (0     0   0)
  4098                   (0     0 100)
  4098 		  (0     0 100)
  4099                   (0    50   0)
  4099 		  (0    50   0)
  4100                   (0    50 100)
  4100 		  (0    50 100)
  4101                   (0   100   0)
  4101 		  (0   100   0)
  4102                   (0   100 100)
  4102 		  (0   100 100)
  4103                   (100   0   0)
  4103 		  (100   0   0)
  4104                   (100   0 100)
  4104 		  (100   0 100)
  4105                   (100  50   0)
  4105 		  (100  50   0)
  4106                   (100  50 100)
  4106 		  (100  50 100)
  4107                   (100 100   0)
  4107 		  (100 100   0)
  4108                   (100 100 100)) collect:[:rgb | (Color red:(rgb at:1)
  4108 		  (100 100 100)) collect:[:rgb | (Color red:(rgb at:1)
  4109                                                       green:(rgb at:2)
  4109 						      green:(rgb at:2)
  4110                                                        blue:(rgb at:3)) onDevice:Display].
  4110 						       blue:(rgb at:3)) onDevice:Display].
  4111 
  4111 
  4112      img8 := Image fromFile:'goodies/bitmaps/claus.gif'.
  4112      img8 := Image fromFile:'goodies/bitmaps/claus.gif'.
  4113      form := img8 asNearestPaintDepth8FormOn:Display 
  4113      form := img8 asNearestPaintDepth8FormOn:Display
  4114                       colors:map 
  4114 		      colors:map
  4115                         nRed:2
  4115 			nRed:2
  4116                       nGreen:3
  4116 		      nGreen:3
  4117                        nBlue:2.
  4117 		       nBlue:2.
  4118      img8 := Depth8Image fromForm:form.    'dithered version of original image'.
  4118      img8 := Depth8Image fromForm:form.    'dithered version of original image'.
  4119      img4 := Depth4Image fromImage:img8.
  4119      img4 := Depth4Image fromImage:img8.
  4120     "
  4120     "
  4121 
  4121 
  4122     "Modified: 17.6.1996 / 18:52:47 / cg"
  4122     "Modified: 17.6.1996 / 18:52:47 / cg"
  4123     "Created: 23.6.1997 / 15:26:09 / cg"
  4123     "Created: 23.6.1997 / 15:26:09 / cg"
  4124 !
  4124 !
  4125 
  4125 
  4126 asNearestPaintDepth8FormOn:aDevice colors:fixColors nRed:nRed nGreen:nGreen nBlue:nBlue 
  4126 asNearestPaintDepth8FormOn:aDevice colors:fixColors nRed:nRed nGreen:nGreen nBlue:nBlue
  4127     "return a nearest paint pseudoForm from the palette picture. 
  4127     "return a nearest paint pseudoForm from the palette picture.
  4128      Use the colors in the fixColors array, which must be fixR x fixG x fixB
  4128      Use the colors in the fixColors array, which must be fixR x fixG x fixB
  4129      colors assigned to aDevice, such as the preallocated colors of the
  4129      colors assigned to aDevice, such as the preallocated colors of the
  4130      Color class. 
  4130      Color class.
  4131      By passing the ditherColors as extra array, this method can
  4131      By passing the ditherColors as extra array, this method can
  4132      also be used to dither an 8bit image into a smaller number of colors,
  4132      also be used to dither an 8bit image into a smaller number of colors,
  4133      for example to create dithered Depth4Images from Depth8Images."
  4133      for example to create dithered Depth4Images from Depth8Images."
  4134 
  4134 
  4135     |pseudoBits f deviceDepth map|
  4135     |pseudoBits f deviceDepth map|
  4136 
  4136 
  4137     deviceDepth := aDevice depth.
  4137     deviceDepth := aDevice depth.
  4138     deviceDepth == 8 ifFalse:[
  4138     deviceDepth == 8 ifFalse:[
  4139         (aDevice supportedImageFormatForDepth:8) isNil ifTrue:[
  4139 	(aDevice supportedImageFormatForDepth:8) isNil ifTrue:[
  4140             ^ nil
  4140 	    ^ nil
  4141         ]
  4141 	]
  4142     ].
  4142     ].
  4143 
  4143 
  4144     pseudoBits := self nearestPaintDepth8BitsColors:fixColors nRed:nRed nGreen:nGreen nBlue:nBlue.
  4144     pseudoBits := self nearestPaintDepth8BitsColors:fixColors nRed:nRed nGreen:nGreen nBlue:nBlue.
  4145     pseudoBits isNil ifTrue:[^ nil].
  4145     pseudoBits isNil ifTrue:[^ nil].
  4146 
  4146 
  4151     "/ have to create a funny colorMap, where
  4151     "/ have to create a funny colorMap, where
  4152     "/ color at:index == color colorId:index
  4152     "/ color at:index == color colorId:index
  4153     "/
  4153     "/
  4154     map := Array new:256.
  4154     map := Array new:256.
  4155     fixColors do:[:clr |
  4155     fixColors do:[:clr |
  4156         map at:clr colorId + 1 put:clr
  4156 	map at:clr colorId + 1 put:clr
  4157     ].
  4157     ].
  4158     f colorMap:map. 
  4158     f colorMap:map.
  4159     f initGC.
  4159     f initGC.
  4160     f bits:pseudoBits.
  4160     f bits:pseudoBits.
  4161     aDevice 
  4161     aDevice
  4162         drawBits:pseudoBits 
  4162 	drawBits:pseudoBits
  4163         bitsPerPixel:8 
  4163 	bitsPerPixel:8
  4164         depth:deviceDepth  
  4164 	depth:deviceDepth
  4165         padding:8
  4165 	padding:8
  4166         width:width height:height
  4166 	width:width height:height
  4167         x:0 y:0
  4167 	x:0 y:0
  4168         into:(f id) x:0 y:0 
  4168 	into:(f id) x:0 y:0
  4169         width:width height:height 
  4169 	width:width height:height
  4170         with:(f gcId).
  4170 	with:(f gcId).
  4171     ^ f
  4171     ^ f
  4172 
  4172 
  4173     "
  4173     "
  4174      example: 
  4174      example:
  4175         color reduction from Depth8 to Depth4 (dithering) can be done by:
  4175 	color reduction from Depth8 to Depth4 (dithering) can be done by:
  4176 
  4176 
  4177      |img8 reducedImg8 img4 map form|
  4177      |img8 reducedImg8 img4 map form|
  4178 
  4178 
  4179      map := #( 
  4179      map := #(
  4180                   (0     0   0)
  4180 		  (0     0   0)
  4181                   (0     0 100)
  4181 		  (0     0 100)
  4182                   (0    50   0)
  4182 		  (0    50   0)
  4183                   (0    50 100)
  4183 		  (0    50 100)
  4184                   (0   100   0)
  4184 		  (0   100   0)
  4185                   (0   100 100)
  4185 		  (0   100 100)
  4186                   (100   0   0)
  4186 		  (100   0   0)
  4187                   (100   0 100)
  4187 		  (100   0 100)
  4188                   (100  50   0)
  4188 		  (100  50   0)
  4189                   (100  50 100)
  4189 		  (100  50 100)
  4190                   (100 100   0)
  4190 		  (100 100   0)
  4191                   (100 100 100)) collect:[:rgb | (Color red:(rgb at:1)
  4191 		  (100 100 100)) collect:[:rgb | (Color red:(rgb at:1)
  4192                                                       green:(rgb at:2)
  4192 						      green:(rgb at:2)
  4193                                                        blue:(rgb at:3)) onDevice:Display].
  4193 						       blue:(rgb at:3)) onDevice:Display].
  4194 
  4194 
  4195      img8 := Image fromFile:'goodies/bitmaps/claus.gif'.
  4195      img8 := Image fromFile:'goodies/bitmaps/claus.gif'.
  4196      form := img8 asNearestPaintDepth8FormOn:Display 
  4196      form := img8 asNearestPaintDepth8FormOn:Display
  4197                       colors:map 
  4197 		      colors:map
  4198                         nRed:2
  4198 			nRed:2
  4199                       nGreen:3
  4199 		      nGreen:3
  4200                        nBlue:2.
  4200 		       nBlue:2.
  4201      img8 := Depth8Image fromForm:form.    'dithered version of original image'.
  4201      img8 := Depth8Image fromForm:form.    'dithered version of original image'.
  4202      img4 := Depth4Image fromImage:img8.
  4202      img4 := Depth4Image fromImage:img8.
  4203     "
  4203     "
  4204 
  4204 
  4205     "Created: 17.6.1996 / 18:47:46 / cg"
  4205     "Created: 17.6.1996 / 18:47:46 / cg"
  4206     "Modified: 17.6.1996 / 18:52:47 / cg"
  4206     "Modified: 17.6.1996 / 18:52:47 / cg"
  4207 !
  4207 !
  4208 
  4208 
  4209 asNearestPaintImageDepth:d colors:colors 
  4209 asNearestPaintImageDepth:d colors:colors
  4210     "return a threshold image from the receiver picture, using colors in colors."
  4210     "return a threshold image from the receiver picture, using colors in colors."
  4211 
  4211 
  4212     |newBits|
  4212     |newBits|
  4213 
  4213 
  4214     d ~~ 8 ifTrue:[
  4214     d ~~ 8 ifTrue:[
  4226      Uses an 8x8 dithermatrix."
  4226      Uses an 8x8 dithermatrix."
  4227 
  4227 
  4228     |depth bits|
  4228     |depth bits|
  4229 
  4229 
  4230     depth := aDevice depth.
  4230     depth := aDevice depth.
  4231     (depth == 1 
  4231     (depth == 1
  4232     or:[aDevice hasGrayscales not]) ifTrue:[
  4232     or:[aDevice hasGrayscales not]) ifTrue:[
  4233 	"/ for monochrome, there is highly specialized
  4233 	"/ for monochrome, there is highly specialized
  4234 	"/ monochrome dither code available
  4234 	"/ monochrome dither code available
  4235 
  4235 
  4236 	^ self asOrderedDitheredMonochromeFormOn:aDevice
  4236 	^ self asOrderedDitheredMonochromeFormOn:aDevice
  4260     |dither|
  4260     |dither|
  4261 
  4261 
  4262     dither := self class orderedDitherMatrixOfSize:8.
  4262     dither := self class orderedDitherMatrixOfSize:8.
  4263 
  4263 
  4264     (depth == 1) ifTrue:[
  4264     (depth == 1) ifTrue:[
  4265         "/ for monochrome, there is highly specialized
  4265 	"/ for monochrome, there is highly specialized
  4266         "/ monochrome dither code available
  4266 	"/ monochrome dither code available
  4267 
  4267 
  4268         ^ Depth1Image
  4268 	^ Depth1Image
  4269             width:width
  4269 	    width:width
  4270             height:height
  4270 	    height:height
  4271             fromArray:(
  4271 	    fromArray:(
  4272                 self
  4272 		self
  4273                     orderedDitheredMonochromeBitsWithDitherMatrix:dither
  4273 		    orderedDitheredMonochromeBitsWithDitherMatrix:dither
  4274                     ditherWidth:8)
  4274 		    ditherWidth:8)
  4275     ].
  4275     ].
  4276 
  4276 
  4277     ^ (self class implementorForDepth:depth)
  4277     ^ (self class implementorForDepth:depth)
  4278         width:width
  4278 	width:width
  4279         height:height
  4279 	height:height
  4280         fromArray:(
  4280 	fromArray:(
  4281             self
  4281 	    self
  4282                 orderedDitheredGrayBitsWithDitherMatrix:dither
  4282 		orderedDitheredGrayBitsWithDitherMatrix:dither
  4283                 ditherWidth:8
  4283 		ditherWidth:8
  4284                 depth:depth)
  4284 		depth:depth)
  4285 
  4285 
  4286     "
  4286     "
  4287      |i i1 i2 i4 i8|
  4287      |i i1 i2 i4 i8|
  4288 
  4288 
  4289      i := Image fromFile:'goodies/bitmaps/gifImages/claus.gif'.
  4289      i := Image fromFile:'goodies/bitmaps/gifImages/claus.gif'.
  4333     "/
  4333     "/
  4334     "/ could look at the image and decide upon the number of
  4334     "/ could look at the image and decide upon the number of
  4335     "/ distinct colors present. Use 8x8 for high-number,
  4335     "/ distinct colors present. Use 8x8 for high-number,
  4336     "/ 4x4 for small number of colors ...
  4336     "/ 4x4 for small number of colors ...
  4337 
  4337 
  4338     ^ self 
  4338     ^ self
  4339         asOrderedDitheredMonochromeFormOn:aDevice 
  4339 	asOrderedDitheredMonochromeFormOn:aDevice
  4340         ditherMatrix:(self class orderedDitherMatrixOfSize:4)
  4340 	ditherMatrix:(self class orderedDitherMatrixOfSize:4)
  4341         ditherWidth:4
  4341 	ditherWidth:4
  4342 
  4342 
  4343 "/    ^ self 
  4343 "/    ^ self
  4344 "/        asOrderedDitheredMonochromeFormOn:aDevice 
  4344 "/        asOrderedDitheredMonochromeFormOn:aDevice
  4345 "/        ditherMatrix:(self class orderedDitherMatrixOfSize:8)
  4345 "/        ditherMatrix:(self class orderedDitherMatrixOfSize:8)
  4346 "/        ditherWidth:8
  4346 "/        ditherWidth:8
  4347 
  4347 
  4348     "
  4348     "
  4349      |i f|
  4349      |i f|
  4423     "/
  4423     "/
  4424     "/ could look at the image and decide upon the number of
  4424     "/ could look at the image and decide upon the number of
  4425     "/ distinct colors present. Use 8x8 for high-number,
  4425     "/ distinct colors present. Use 8x8 for high-number,
  4426     "/ 4x4 for small number of colors ...
  4426     "/ 4x4 for small number of colors ...
  4427 
  4427 
  4428     ^ self 
  4428     ^ self
  4429         asOrderedDitheredMonochromeImageWithDitherMatrix:(self class orderedDitherMatrixOfSize:4)
  4429 	asOrderedDitheredMonochromeImageWithDitherMatrix:(self class orderedDitherMatrixOfSize:4)
  4430         ditherWidth:4
  4430 	ditherWidth:4
  4431 
  4431 
  4432 "/    ^ self 
  4432 "/    ^ self
  4433 "/        asOrderedDitheredMonochromeImageWithDitherMatrix:(self class orderedDitherMatrixOfSize:8)
  4433 "/        asOrderedDitheredMonochromeImageWithDitherMatrix:(self class orderedDitherMatrixOfSize:8)
  4434 "/        ditherWidth:8
  4434 "/        ditherWidth:8
  4435 
  4435 
  4436     "
  4436     "
  4437      |i|
  4437      |i|
  4481 
  4481 
  4482      |i|
  4482      |i|
  4483 
  4483 
  4484      i := Image fromFile:'goodies/bitmaps/gifImages/garfield.gif'.
  4484      i := Image fromFile:'goodies/bitmaps/gifImages/garfield.gif'.
  4485      i
  4485      i
  4486         asOrderedDitheredMonochromeImageWithDitherMatrix:(Image orderedDitherMatrixOfSize:4)
  4486 	asOrderedDitheredMonochromeImageWithDitherMatrix:(Image orderedDitherMatrixOfSize:4)
  4487         ditherWidth:4
  4487 	ditherWidth:4
  4488     "
  4488     "
  4489 
  4489 
  4490     "order-6 dither:
  4490     "order-6 dither:
  4491 
  4491 
  4492      |i|
  4492      |i|
  4493 
  4493 
  4494      i := Image fromFile:'goodies/bitmaps/gifImages/garfield.gif'.
  4494      i := Image fromFile:'goodies/bitmaps/gifImages/garfield.gif'.
  4495      i
  4495      i
  4496         asOrderedDitheredMonochromeImageWithDitherMatrix:(Image orderedDitherMatrixOfSize:8)
  4496 	asOrderedDitheredMonochromeImageWithDitherMatrix:(Image orderedDitherMatrixOfSize:8)
  4497         ditherWidth:8
  4497 	ditherWidth:8
  4498     "
  4498     "
  4499 
  4499 
  4500 
  4500 
  4501     "thresholding at:0.5 (all above 0.5 becomes white):
  4501     "thresholding at:0.5 (all above 0.5 becomes white):
  4502 
  4502 
  4503      |i|
  4503      |i|
  4504 
  4504 
  4505      i := Image fromFile:'goodies/bitmaps/gifImages/garfield.gif'.
  4505      i := Image fromFile:'goodies/bitmaps/gifImages/garfield.gif'.
  4506      i
  4506      i
  4507         asOrderedDitheredMonochromeImageWithDitherMatrix:(ByteArray new:16 withAll:8)
  4507 	asOrderedDitheredMonochromeImageWithDitherMatrix:(ByteArray new:16 withAll:8)
  4508         ditherWidth:4
  4508 	ditherWidth:4
  4509     "
  4509     "
  4510 
  4510 
  4511     "thresholding at: 0.25 (all above 0.25 becomes white):
  4511     "thresholding at: 0.25 (all above 0.25 becomes white):
  4512 
  4512 
  4513      |i|
  4513      |i|
  4514 
  4514 
  4515      i := Image fromFile:'goodies/bitmaps/gifImages/garfield.gif'.
  4515      i := Image fromFile:'goodies/bitmaps/gifImages/garfield.gif'.
  4516      i
  4516      i
  4517         asOrderedDitheredMonochromeImageWithDitherMatrix:(ByteArray new:16 withAll:3)
  4517 	asOrderedDitheredMonochromeImageWithDitherMatrix:(ByteArray new:16 withAll:3)
  4518         ditherWidth:4
  4518 	ditherWidth:4
  4519     "
  4519     "
  4520 
  4520 
  4521     "thresholding at: 0.75 (all above 0.75 becomes white):
  4521     "thresholding at: 0.75 (all above 0.75 becomes white):
  4522 
  4522 
  4523      |i|
  4523      |i|
  4524 
  4524 
  4525      i := Image fromFile:'goodies/bitmaps/gifImages/garfield.gif'.
  4525      i := Image fromFile:'goodies/bitmaps/gifImages/garfield.gif'.
  4526      i
  4526      i
  4527         asOrderedDitheredMonochromeImageWithDitherMatrix:(ByteArray new:16 withAll:11)
  4527 	asOrderedDitheredMonochromeImageWithDitherMatrix:(ByteArray new:16 withAll:11)
  4528         ditherWidth:4
  4528 	ditherWidth:4
  4529     "
  4529     "
  4530 
  4530 
  4531     "Modified: 7.6.1996 / 17:23:47 / cg"
  4531     "Modified: 7.6.1996 / 17:23:47 / cg"
  4532 !
  4532 !
  4533 
  4533 
  4534 asPseudoFormQuickOn:aDevice
  4534 asPseudoFormQuickOn:aDevice
  4535     "return a pseudo-deviceForm from the image.
  4535     "return a pseudo-deviceForm from the image.
  4536      Fail if any color is not available (i.e. do not dither)."
  4536      Fail if any color is not available (i.e. do not dither)."
  4537 
  4537 
  4538     |f d 
  4538     |f d
  4539      temp temp8 bits clr cMap idMap 
  4539      temp temp8 bits clr cMap idMap
  4540      w            "{ Class: SmallInteger }"
  4540      w            "{ Class: SmallInteger }"
  4541      h            "{ Class: SmallInteger }"
  4541      h            "{ Class: SmallInteger }"
  4542      dDev         "{ Class: SmallInteger }"
  4542      dDev         "{ Class: SmallInteger }"
  4543      nClr         "{ Class: SmallInteger }" 
  4543      nClr         "{ Class: SmallInteger }"
  4544      bytesPerLine "{ Class: SmallInteger }"
  4544      bytesPerLine "{ Class: SmallInteger }"
  4545      usedColors pix fmt bytes|
  4545      usedColors pix fmt bytes|
  4546 
  4546 
  4547     d := self depth.
  4547     d := self depth.
  4548     (d == 1
  4548     (d == 1
  4616 
  4616 
  4617     (d == 8 and:[dDev == 8]) ifTrue:[
  4617     (d == 8 and:[dDev == 8]) ifTrue:[
  4618 	"/ only translate
  4618 	"/ only translate
  4619 	temp := ByteArray uninitializedNew:(w * h).
  4619 	temp := ByteArray uninitializedNew:(w * h).
  4620 	bytes expandPixels:8         "xlate only"
  4620 	bytes expandPixels:8         "xlate only"
  4621 		    width:w 
  4621 		    width:w
  4622 		   height:h
  4622 		   height:h
  4623 		     into:temp
  4623 		     into:temp
  4624 		  mapping:idMap.
  4624 		  mapping:idMap.
  4625     ] ifFalse:[
  4625     ] ifFalse:[
  4626 	"/ stupid: expandPixels can only handle any-to-8
  4626 	"/ stupid: expandPixels can only handle any-to-8
  4631 	"/ then from 8 to the device depth.
  4631 	"/ then from 8 to the device depth.
  4632 
  4632 
  4633 	d ~~ 8 ifTrue:[
  4633 	d ~~ 8 ifTrue:[
  4634 	    temp8 := ByteArray uninitializedNew:(w * h).
  4634 	    temp8 := ByteArray uninitializedNew:(w * h).
  4635 
  4635 
  4636 	    bytes expandPixels:d      
  4636 	    bytes expandPixels:d
  4637 			 width:w 
  4637 			 width:w
  4638 			height:h
  4638 			height:h
  4639 			  into:temp8
  4639 			  into:temp8
  4640 		       mapping:idMap.
  4640 		       mapping:idMap.
  4641 	    idMap := nil.
  4641 	    idMap := nil.
  4642 	] ifFalse:[
  4642 	] ifFalse:[
  4644 	].
  4644 	].
  4645 
  4645 
  4646 	dDev ~~ 8 ifTrue:[
  4646 	dDev ~~ 8 ifTrue:[
  4647 	    temp := ByteArray uninitializedNew:(bytesPerLine * h).
  4647 	    temp := ByteArray uninitializedNew:(bytesPerLine * h).
  4648 
  4648 
  4649 	    temp8 compressPixels:dDev      
  4649 	    temp8 compressPixels:dDev
  4650 			 width:w 
  4650 			 width:w
  4651 			height:h
  4651 			height:h
  4652 			  into:temp
  4652 			  into:temp
  4653 		       mapping:idMap.
  4653 		       mapping:idMap.
  4654 	] ifFalse:[
  4654 	] ifFalse:[
  4655 	    temp := temp8
  4655 	    temp := temp8
  4657     ].
  4657     ].
  4658 
  4658 
  4659     f := Form width:w height:h depth:dDev on:aDevice.
  4659     f := Form width:w height:h depth:dDev on:aDevice.
  4660     f isNil ifTrue:[^ nil].
  4660     f isNil ifTrue:[^ nil].
  4661 
  4661 
  4662     f colorMap:cMap. 
  4662     f colorMap:cMap.
  4663     f initGC.
  4663     f initGC.
  4664 
  4664 
  4665     aDevice 
  4665     aDevice
  4666 	drawBits:temp 
  4666 	drawBits:temp
  4667 	depth:dDev 
  4667 	depth:dDev
  4668 	padding:8
  4668 	padding:8
  4669 	width:w 
  4669 	width:w
  4670 	height:h
  4670 	height:h
  4671 	x:0 y:0
  4671 	x:0 y:0
  4672 	into:(f id) x:0 y:0 
  4672 	into:(f id) x:0 y:0
  4673 	width:w 
  4673 	width:w
  4674 	height:h 
  4674 	height:h
  4675 	with:(f gcId).
  4675 	with:(f gcId).
  4676 
  4676 
  4677     ^ f
  4677     ^ f
  4678 
  4678 
  4679     "
  4679     "
  4680      (
  4680      (
  4681 	(((Depth4Image
  4681 	(((Depth4Image
  4682 	     width:4 
  4682 	     width:4
  4683 	     height:4
  4683 	     height:4
  4684 	     fromArray:#[ 
  4684 	     fromArray:#[
  4685 			    16r01 16r23
  4685 			    16r01 16r23
  4686 			    16r45 16r67
  4686 			    16r45 16r67
  4687 			    16r89 16rab
  4687 			    16r89 16rab
  4688 			    16rcd 16ref 
  4688 			    16rcd 16ref
  4689 			]))
  4689 			]))
  4690 	       magnifiedBy:30
  4690 	       magnifiedBy:30
  4691 	 )
  4691 	 )
  4692 	  asPseudoFormQuickOn:Display
  4692 	  asPseudoFormQuickOn:Display
  4693       ) inspect
  4693       ) inspect
  4732 
  4732 
  4733     "
  4733     "
  4734      |i|
  4734      |i|
  4735 
  4735 
  4736      i := Depth4Image
  4736      i := Depth4Image
  4737              width:4 
  4737 	     width:4
  4738              height:4
  4738 	     height:4
  4739              fromArray:#[ 
  4739 	     fromArray:#[
  4740                             16r01 16r23
  4740 			    16r01 16r23
  4741                             16r45 16r67
  4741 			    16r45 16r67
  4742                             16r89 16rab
  4742 			    16r89 16rab
  4743                             16rcd 16ref 
  4743 			    16rcd 16ref
  4744                         ].
  4744 			].
  4745      i := i magnifiedBy:30.
  4745      i := i magnifiedBy:30.
  4746      i inspect.
  4746      i inspect.
  4747      i asStevensonArceDitheredMonochromeImage inspect.
  4747      i asStevensonArceDitheredMonochromeImage inspect.
  4748      i asOrderedDitheredMonochromeImage inspect.
  4748      i asOrderedDitheredMonochromeImage inspect.
  4749     "
  4749     "
  4759 
  4759 
  4760     (depth := aDevice depth) == 1 ifTrue:[
  4760     (depth := aDevice depth) == 1 ifTrue:[
  4761 	^ self asThresholdMonochromeFormOn:aDevice
  4761 	^ self asThresholdMonochromeFormOn:aDevice
  4762     ].
  4762     ].
  4763 
  4763 
  4764     ^ self 
  4764     ^ self
  4765 	makeDeviceGrayPixmapOn:aDevice 
  4765 	makeDeviceGrayPixmapOn:aDevice
  4766 	depth:depth 
  4766 	depth:depth
  4767 	fromArray:(self
  4767 	fromArray:(self
  4768 			orderedDitheredGrayBitsWithDitherMatrix:#[8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8]
  4768 			orderedDitheredGrayBitsWithDitherMatrix:#[8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8]
  4769 			ditherWidth:4
  4769 			ditherWidth:4
  4770 			depth:depth)
  4770 			depth:depth)
  4771 
  4771 
  4830 !
  4830 !
  4831 
  4831 
  4832 asThresholdMonochromeFormOn:aDevice
  4832 asThresholdMonochromeFormOn:aDevice
  4833     "return a threshold monochrome form from the image."
  4833     "return a threshold monochrome form from the image."
  4834 
  4834 
  4835     ^ self 
  4835     ^ self
  4836 	asOrderedDitheredMonochromeFormOn:aDevice 
  4836 	asOrderedDitheredMonochromeFormOn:aDevice
  4837 	ditherMatrix:#[8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8]
  4837 	ditherMatrix:#[8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8]
  4838 	ditherWidth:4
  4838 	ditherWidth:4
  4839 
  4839 
  4840     "
  4840     "
  4841      |i|
  4841      |i|
  5041 !
  5041 !
  5042 
  5042 
  5043 fromImage:anImage
  5043 fromImage:anImage
  5044     "setup the receiver from another image.
  5044     "setup the receiver from another image.
  5045      Color precision may be lost, if conversion is from a higher depth
  5045      Color precision may be lost, if conversion is from a higher depth
  5046      image. 
  5046      image.
  5047      WARNING:
  5047      WARNING:
  5048      This implementation is a slow fallback (the loop over the
  5048      This implementation is a slow fallback (the loop over the
  5049      source pixels is very slow). If this method is used heavily, you
  5049      source pixels is very slow). If this method is used heavily, you
  5050      may want to redefine it in concrete subclasses for common source images."
  5050      may want to redefine it in concrete subclasses for common source images."
  5051 
  5051 
  5053 !
  5053 !
  5054 
  5054 
  5055 fromImage:anImage photometric:photometricOrNil
  5055 fromImage:anImage photometric:photometricOrNil
  5056     "setup the receiver from another image and optionally set the photometric.
  5056     "setup the receiver from another image and optionally set the photometric.
  5057      Color precision may be lost, if conversion is from a higher depth
  5057      Color precision may be lost, if conversion is from a higher depth
  5058      image. 
  5058      image.
  5059      WARNING:
  5059      WARNING:
  5060      This implementation is a slow fallback (the loop over the
  5060      This implementation is a slow fallback (the loop over the
  5061      source pixels is very slow). If this method is used heavily, you
  5061      source pixels is very slow). If this method is used heavily, you
  5062      may want to redefine it in concrete subclasses for common source images."
  5062      may want to redefine it in concrete subclasses for common source images."
  5063 
  5063 
  5185 
  5185 
  5186     ((photometric == anImage photometric)
  5186     ((photometric == anImage photometric)
  5187     and:[self bitsPerPixel = anImage bitsPerPixel
  5187     and:[self bitsPerPixel = anImage bitsPerPixel
  5188     and:[colorMap = anImage colorMap]]) ifTrue:[
  5188     and:[colorMap = anImage colorMap]]) ifTrue:[
  5189 	"/ can do it by value
  5189 	"/ can do it by value
  5190 	anImage 
  5190 	anImage
  5191 	    valuesFromX:xL y:yT toX:xR y:yB
  5191 	    valuesFromX:xL y:yT toX:xR y:yB
  5192 	    do:[:x :y :pixelValue |
  5192 	    do:[:x :y :pixelValue |
  5193 		    self pixelAtX:x-xL y:y-yT put:pixelValue.
  5193 		    self pixelAtX:x-xL y:y-yT put:pixelValue.
  5194 	       ]
  5194 	       ]
  5195     ] ifFalse:[
  5195     ] ifFalse:[
  5196 	"/ must do it by colors
  5196 	"/ must do it by colors
  5197 	anImage 
  5197 	anImage
  5198 	    colorsFromX:xL y:yT toX:xR y:yB
  5198 	    colorsFromX:xL y:yT toX:xR y:yB
  5199 	    do:[:x :y :clr |
  5199 	    do:[:x :y :clr |
  5200 		    self colorAtX:x-xL y:y-yT put:clr.
  5200 		    self colorAtX:x-xL y:y-yT put:clr.
  5201 	       ]
  5201 	       ]
  5202     ].
  5202     ].
  5205 	anImage mask depth == 1 ifTrue:[
  5205 	anImage mask depth == 1 ifTrue:[
  5206 	    maskClass := ImageMask
  5206 	    maskClass := ImageMask
  5207 	] ifFalse:[
  5207 	] ifFalse:[
  5208 	    maskClass := anImage mask class.
  5208 	    maskClass := anImage mask class.
  5209 	].
  5209 	].
  5210 	mask := maskClass new 
  5210 	mask := maskClass new
  5211 		    fromSubImage:anImage mask in:aRectangle
  5211 		    fromSubImage:anImage mask in:aRectangle
  5212     ].
  5212     ].
  5213 
  5213 
  5214     "
  5214     "
  5215      |i i2 i4 i8 i16 i24|
  5215      |i i2 i4 i8 i16 i24|
  5322 !
  5322 !
  5323 
  5323 
  5324 greyImageAsPseudoFormOn:aDevice
  5324 greyImageAsPseudoFormOn:aDevice
  5325     "return an 8-bit pseudo Form from the grey image"
  5325     "return an 8-bit pseudo Form from the grey image"
  5326 
  5326 
  5327     |wideBits pictureDepth f map  
  5327     |wideBits pictureDepth f map
  5328      colorMap usedColors nUsed aColor 
  5328      colorMap usedColors nUsed aColor
  5329      nColors "{ Class: SmallInteger }"
  5329      nColors "{ Class: SmallInteger }"
  5330      range id
  5330      range id
  5331      cube nR nG nB grayColors
  5331      cube nR nG nB grayColors
  5332      fit|
  5332      fit|
  5333 
  5333 
  5345 	 to avoid allocating too many colors"
  5345 	 to avoid allocating too many colors"
  5346 
  5346 
  5347 	(grayColors := aDevice fixGrayColors) notNil ifTrue:[
  5347 	(grayColors := aDevice fixGrayColors) notNil ifTrue:[
  5348 	    DitherAlgorithm == #floydSteinberg ifTrue:[
  5348 	    DitherAlgorithm == #floydSteinberg ifTrue:[
  5349 		f := self
  5349 		f := self
  5350 		       asFloydSteinbergDitheredDepth8FormOn:aDevice 
  5350 		       asFloydSteinbergDitheredDepth8FormOn:aDevice
  5351 		       colors:grayColors 
  5351 		       colors:grayColors
  5352 	    ].
  5352 	    ].
  5353 	    f notNil ifTrue:[^ f].
  5353 	    f notNil ifTrue:[^ f].
  5354 	].
  5354 	].
  5355 
  5355 
  5356 	(cube := aDevice fixColors) notNil ifTrue:[
  5356 	(cube := aDevice fixColors) notNil ifTrue:[
  5358 	    nG := aDevice numFixGreen.
  5358 	    nG := aDevice numFixGreen.
  5359 	    nB := aDevice numFixBlue.
  5359 	    nB := aDevice numFixBlue.
  5360 
  5360 
  5361 	    DitherAlgorithm == #floydSteinberg ifTrue:[
  5361 	    DitherAlgorithm == #floydSteinberg ifTrue:[
  5362 		f := self
  5362 		f := self
  5363 		       asFloydSteinbergDitheredDepth8FormOn:aDevice 
  5363 		       asFloydSteinbergDitheredDepth8FormOn:aDevice
  5364 		       colors:cube 
  5364 		       colors:cube
  5365 		       nRed:nR
  5365 		       nRed:nR
  5366 		       nGreen:nG
  5366 		       nGreen:nG
  5367 		       nBlue:nB.
  5367 		       nBlue:nB.
  5368 	    ] ifFalse:[
  5368 	    ] ifFalse:[
  5369 		f := self
  5369 		f := self
  5370 		       asNearestPaintDepth8FormOn:aDevice 
  5370 		       asNearestPaintDepth8FormOn:aDevice
  5371 		       colors:cube 
  5371 		       colors:cube
  5372 		       nRed:nR
  5372 		       nRed:nR
  5373 		       nGreen:nG
  5373 		       nGreen:nG
  5374 		       nBlue:nB.
  5374 		       nBlue:nB.
  5375 	    ].
  5375 	    ].
  5376 	    f notNil ifTrue:[^ f].
  5376 	    f notNil ifTrue:[^ f].
  5421 	"/ Must dither.
  5421 	"/ Must dither.
  5422 
  5422 
  5423     ].
  5423     ].
  5424 
  5424 
  5425     "expand & translate"
  5425     "expand & translate"
  5426     self bits 
  5426     self bits
  5427 	expandPixels:pictureDepth
  5427 	expandPixels:pictureDepth
  5428 	width:width height:height
  5428 	width:width height:height
  5429 	into:wideBits
  5429 	into:wideBits
  5430 	mapping:map.
  5430 	mapping:map.
  5431 
  5431 
  5432     f := Form width:width height:height depth:8 on:aDevice.
  5432     f := Form width:width height:height depth:8 on:aDevice.
  5433     f isNil ifTrue:[^ nil].
  5433     f isNil ifTrue:[^ nil].
  5434     f colorMap:colorMap. 
  5434     f colorMap:colorMap.
  5435     f initGC.
  5435     f initGC.
  5436     aDevice 
  5436     aDevice
  5437 	drawBits:wideBits 
  5437 	drawBits:wideBits
  5438 	depth:8 
  5438 	depth:8
  5439 	padding:8
  5439 	padding:8
  5440 	width:width height:height
  5440 	width:width height:height
  5441 	x:0 y:0
  5441 	x:0 y:0
  5442 	into:(f id) 
  5442 	into:(f id)
  5443 	x:0 y:0 
  5443 	x:0 y:0
  5444 	width:width height:height 
  5444 	width:width height:height
  5445 	with:(f gcId).
  5445 	with:(f gcId).
  5446     ^ f
  5446     ^ f
  5447 
  5447 
  5448     "Modified: 19.10.1997 / 05:19:44 / cg"
  5448     "Modified: 19.10.1997 / 05:19:44 / cg"
  5449 !
  5449 !
  5450 
  5450 
  5451 greyImageAsTrueColorFormOn:aDevice
  5451 greyImageAsTrueColorFormOn:aDevice
  5452     "return a true-color device-form for the grey-image receiver.
  5452     "return a true-color device-form for the grey-image receiver.
  5453      TODO: the pixel loops ought to be implemented as inline primitive code ..."
  5453      TODO: the pixel loops ought to be implemented as inline primitive code ..."
  5454 
  5454 
  5455     |depth  
  5455     |depth
  5456      myDepth    "{ Class: SmallInteger }"
  5456      myDepth    "{ Class: SmallInteger }"
  5457      nColors    "{ Class: SmallInteger }"
  5457      nColors    "{ Class: SmallInteger }"
  5458      colorValues
  5458      colorValues
  5459      scaleDown 
  5459      scaleDown
  5460      scaleRed   "{ Class: SmallInteger }"
  5460      scaleRed   "{ Class: SmallInteger }"
  5461      scaleGreen "{ Class: SmallInteger }"
  5461      scaleGreen "{ Class: SmallInteger }"
  5462      scaleBlue  "{ Class: SmallInteger }"
  5462      scaleBlue  "{ Class: SmallInteger }"
  5463      redShift   "{ Class: SmallInteger }"
  5463      redShift   "{ Class: SmallInteger }"
  5464      blueShift  "{ Class: SmallInteger }"
  5464      blueShift  "{ Class: SmallInteger }"
  5465      greenShift "{ Class: SmallInteger }"
  5465      greenShift "{ Class: SmallInteger }"
  5466      form bestFormat usedDeviceDepth usedDeviceBitsPerPixel imageBits 
  5466      form bestFormat usedDeviceDepth usedDeviceBitsPerPixel imageBits
  5467      greyValue  "{ Class: SmallInteger }"
  5467      greyValue  "{ Class: SmallInteger }"
  5468      h          "{ Class: SmallInteger }"
  5468      h          "{ Class: SmallInteger }"
  5469      w          "{ Class: SmallInteger }"
  5469      w          "{ Class: SmallInteger }"
  5470      pixelArray newPixelArray i|
  5470      pixelArray newPixelArray i|
  5471 
  5471 
  5542 
  5542 
  5543     form := Form width:width height:height depth:usedDeviceDepth on:aDevice.
  5543     form := Form width:width height:height depth:usedDeviceDepth on:aDevice.
  5544     form isNil ifTrue:[^ nil].
  5544     form isNil ifTrue:[^ nil].
  5545     form initGC.
  5545     form initGC.
  5546 
  5546 
  5547     form 
  5547     form
  5548 	copyBitsFrom:imageBits 
  5548 	copyBitsFrom:imageBits
  5549 	bitsPerPixel:usedDeviceBitsPerPixel 
  5549 	bitsPerPixel:usedDeviceBitsPerPixel
  5550 	depth:usedDeviceDepth 
  5550 	depth:usedDeviceDepth
  5551 	padding:8
  5551 	padding:8
  5552 	width:width height:height 
  5552 	width:width height:height
  5553 	x:0 y:0 
  5553 	x:0 y:0
  5554 	toX:0 y:0. 
  5554 	toX:0 y:0.
  5555 
  5555 
  5556     ^ form
  5556     ^ form
  5557 
  5557 
  5558     "Created: 20.10.1995 / 22:05:10 / cg"
  5558     "Created: 20.10.1995 / 22:05:10 / cg"
  5559     "Modified: 24.4.1997 / 23:11:16 / cg"
  5559     "Modified: 24.4.1997 / 23:11:16 / cg"
  5604     "return a pseudo-deviceForm from the palette image."
  5604     "return a pseudo-deviceForm from the palette image."
  5605 
  5605 
  5606     |tempImage d temp8|
  5606     |tempImage d temp8|
  5607 
  5607 
  5608     d := self depth.
  5608     d := self depth.
  5609     (#(1 2 4 8) includes:d) ifTrue:[ 
  5609     (#(1 2 4 8) includes:d) ifTrue:[
  5610 	"
  5610 	"
  5611 	 fallback code for some depth's:
  5611 	 fallback code for some depth's:
  5612 	 create a temporary Depth8Image and use its conversion method
  5612 	 create a temporary Depth8Image and use its conversion method
  5613 	"
  5613 	"
  5614 	temp8 := ByteArray uninitializedNew:(width * height).
  5614 	temp8 := ByteArray uninitializedNew:(width * height).
  5615 
  5615 
  5616 	self bits 
  5616 	self bits
  5617 	    expandPixels:d      
  5617 	    expandPixels:d
  5618 	    width:width height:height
  5618 	    width:width height:height
  5619 	    into:temp8
  5619 	    into:temp8
  5620 	    mapping:nil.
  5620 	    mapping:nil.
  5621 
  5621 
  5622 	tempImage := Image width:width height:height depth:8 fromArray:temp8.
  5622 	tempImage := Image width:width height:height depth:8 fromArray:temp8.
  5627 !
  5627 !
  5628 
  5628 
  5629 paletteImageAsTrueColorFormOn:aDevice
  5629 paletteImageAsTrueColorFormOn:aDevice
  5630     "return a true-color device-form for the palette-image receiver."
  5630     "return a true-color device-form for the palette-image receiver."
  5631 
  5631 
  5632     |depth 
  5632     |depth
  5633      nColors "{ Class: SmallInteger }"
  5633      nColors "{ Class: SmallInteger }"
  5634      h       "{ Class: SmallInteger }"
  5634      h       "{ Class: SmallInteger }"
  5635      pixel   "{ Class: SmallInteger }"
  5635      pixel   "{ Class: SmallInteger }"
  5636      colorValues 
  5636      colorValues
  5637      scaleRed scaleGreen scaleBlue redShift greenShift blueShift
  5637      scaleRed scaleGreen scaleBlue redShift greenShift blueShift
  5638      form imageBits bestFormat usedDeviceDepth usedDeviceBitsPerPixel 
  5638      form imageBits bestFormat usedDeviceDepth usedDeviceBitsPerPixel
  5639      i pixelArray newPixelArray
  5639      i pixelArray newPixelArray
  5640      clr r g b rv gv bv v "{ Class: SmallInteger }" |
  5640      clr r g b rv gv bv v "{ Class: SmallInteger }" |
  5641 
  5641 
  5642     "/ this is a slow fallback method; this ought to be
  5642     "/ this is a slow fallback method; this ought to be
  5643     "/ redefined in DepthxImage for more performance.
  5643     "/ redefined in DepthxImage for more performance.
  5645     depth := aDevice depth.
  5645     depth := aDevice depth.
  5646 
  5646 
  5647     bestFormat := self bestSupportedImageFormatFor:aDevice.
  5647     bestFormat := self bestSupportedImageFormatFor:aDevice.
  5648     usedDeviceDepth := bestFormat at:#depth.
  5648     usedDeviceDepth := bestFormat at:#depth.
  5649     usedDeviceDepth == 1 ifTrue:[
  5649     usedDeviceDepth == 1 ifTrue:[
  5650         ^ self asMonochromeFormOn:aDevice.
  5650 	^ self asMonochromeFormOn:aDevice.
  5651     ].
  5651     ].
  5652     usedDeviceBitsPerPixel := bestFormat at:#bitsPerPixel.
  5652     usedDeviceBitsPerPixel := bestFormat at:#bitsPerPixel.
  5653 
  5653 
  5654 
  5654 
  5655     scaleRed := ((1 bitShift:aDevice bitsRed) - 1) / 255.
  5655     scaleRed := ((1 bitShift:aDevice bitsRed) - 1) / 255.
  5659     greenShift := aDevice shiftGreen.
  5659     greenShift := aDevice shiftGreen.
  5660     blueShift := aDevice shiftBlue.
  5660     blueShift := aDevice shiftBlue.
  5661 
  5661 
  5662     nColors := colorMap size.
  5662     nColors := colorMap size.
  5663     nColors <= 4096 ifTrue:[
  5663     nColors <= 4096 ifTrue:[
  5664         "/ precompute scales to map from 0..100 into devices range
  5664 	"/ precompute scales to map from 0..100 into devices range
  5665         "/ (this may be different for the individual components)
  5665 	"/ (this may be different for the individual components)
  5666         colorValues := Array uninitializedNew:nColors.
  5666 	colorValues := Array uninitializedNew:nColors.
  5667 
  5667 
  5668         1 to:nColors do:[:index |
  5668 	1 to:nColors do:[:index |
  5669             r := colorMap redByteAt:index.
  5669 	    r := colorMap redByteAt:index.
  5670             g := colorMap greenByteAt:index.
  5670 	    g := colorMap greenByteAt:index.
  5671             b := colorMap blueByteAt:index.
  5671 	    b := colorMap blueByteAt:index.
  5672 "/        clr := colorMap at:index.
  5672 "/        clr := colorMap at:index.
  5673             true "clr notNil" ifTrue:[
  5673 	    true "clr notNil" ifTrue:[
  5674 "/            r := clr red.
  5674 "/            r := clr red.
  5675 "/            g := clr green.
  5675 "/            g := clr green.
  5676 "/            b := clr blue.
  5676 "/            b := clr blue.
  5677                 rv := (r * scaleRed) rounded.
  5677 		rv := (r * scaleRed) rounded.
  5678                 gv := (g * scaleGreen) rounded.
  5678 		gv := (g * scaleGreen) rounded.
  5679                 bv := (b * scaleBlue) rounded.
  5679 		bv := (b * scaleBlue) rounded.
  5680 
  5680 
  5681                 v := rv bitShift:redShift.
  5681 		v := rv bitShift:redShift.
  5682                 v := v bitOr:(gv bitShift:greenShift).
  5682 		v := v bitOr:(gv bitShift:greenShift).
  5683                 v := v bitOr:(bv bitShift:blueShift).
  5683 		v := v bitOr:(bv bitShift:blueShift).
  5684                 colorValues at:index put:v.
  5684 		colorValues at:index put:v.
  5685 "/ clr print. ' ' print.
  5685 "/ clr print. ' ' print.
  5686 "/ rv print. ' ' print. gv print. ' ' print. bv print. ' ' print.
  5686 "/ rv print. ' ' print. gv print. ' ' print. bv print. ' ' print.
  5687 "/ ' -> ' print. v printNL.
  5687 "/ ' -> ' print. v printNL.
  5688 
  5688 
  5689             ]
  5689 	    ]
  5690         ].
  5690 	].
  5691     ].
  5691     ].
  5692 
  5692 
  5693     "/ the temporary helper image is only needed to allow
  5693     "/ the temporary helper image is only needed to allow
  5694     "/ the rowAt:putAll: calls below.
  5694     "/ the rowAt:putAll: calls below.
  5695 
  5695 
  5704     h := height - 1.
  5704     h := height - 1.
  5705     pixelArray := self pixelArraySpecies new:width.
  5705     pixelArray := self pixelArraySpecies new:width.
  5706     newPixelArray := i pixelArraySpecies new:width.
  5706     newPixelArray := i pixelArraySpecies new:width.
  5707 
  5707 
  5708     colorValues notNil ifTrue:[
  5708     colorValues notNil ifTrue:[
  5709         0 to:h do:[:y |
  5709 	0 to:h do:[:y |
  5710             self rowAt:y into:pixelArray.
  5710 	    self rowAt:y into:pixelArray.
  5711             1 to:width do:[:x |
  5711 	    1 to:width do:[:x |
  5712                 pixel := pixelArray at:x.
  5712 		pixel := pixelArray at:x.
  5713                 newPixelArray at:x put:(colorValues at:pixel + 1).
  5713 		newPixelArray at:x put:(colorValues at:pixel + 1).
  5714             ].
  5714 	    ].
  5715             i rowAt:y putAll:newPixelArray.
  5715 	    i rowAt:y putAll:newPixelArray.
  5716         ].
  5716 	].
  5717     ] ifFalse:[
  5717     ] ifFalse:[
  5718         0 to:h do:[:y |
  5718 	0 to:h do:[:y |
  5719             self rowAt:y into:pixelArray.
  5719 	    self rowAt:y into:pixelArray.
  5720             1 to:width do:[:x |
  5720 	    1 to:width do:[:x |
  5721                 
  5721 
  5722                 pixel := pixelArray at:x.
  5722 		pixel := pixelArray at:x.
  5723                 clr := self colorFromValue:pixel.
  5723 		clr := self colorFromValue:pixel.
  5724                 r := clr redByte.
  5724 		r := clr redByte.
  5725                 g := clr greenByte.
  5725 		g := clr greenByte.
  5726                 b := clr blueByte.
  5726 		b := clr blueByte.
  5727 
  5727 
  5728                 rv := (r * scaleRed) rounded.
  5728 		rv := (r * scaleRed) rounded.
  5729                 gv := (g * scaleGreen) rounded.
  5729 		gv := (g * scaleGreen) rounded.
  5730                 bv := (b * scaleBlue) rounded.
  5730 		bv := (b * scaleBlue) rounded.
  5731 
  5731 
  5732                 v := rv bitShift:redShift.
  5732 		v := rv bitShift:redShift.
  5733                 v := v bitOr:(gv bitShift:greenShift).
  5733 		v := v bitOr:(gv bitShift:greenShift).
  5734                 v := v bitOr:(bv bitShift:blueShift).
  5734 		v := v bitOr:(bv bitShift:blueShift).
  5735 
  5735 
  5736                 newPixelArray at:x put:v.
  5736 		newPixelArray at:x put:v.
  5737             ].
  5737 	    ].
  5738             i rowAt:y putAll:newPixelArray.
  5738 	    i rowAt:y putAll:newPixelArray.
  5739         ].
  5739 	].
  5740     ].
  5740     ].
  5741 
  5741 
  5742     form := Form width:width height:height depth:usedDeviceDepth on:aDevice.
  5742     form := Form width:width height:height depth:usedDeviceDepth on:aDevice.
  5743     form isNil ifTrue:[^ nil].
  5743     form isNil ifTrue:[^ nil].
  5744     form initGC.
  5744     form initGC.
  5745 
  5745 
  5746     form 
  5746     form
  5747         copyBitsFrom:imageBits 
  5747 	copyBitsFrom:imageBits
  5748         bitsPerPixel:usedDeviceBitsPerPixel 
  5748 	bitsPerPixel:usedDeviceBitsPerPixel
  5749         depth:usedDeviceDepth 
  5749 	depth:usedDeviceDepth
  5750         padding:8
  5750 	padding:8
  5751         width:width height:height 
  5751 	width:width height:height
  5752         x:0 y:0 
  5752 	x:0 y:0
  5753         toX:0 y:0. 
  5753 	toX:0 y:0.
  5754 
  5754 
  5755     ^ form
  5755     ^ form
  5756 
  5756 
  5757     "Modified: / 24.7.1998 / 00:56:14 / cg"
  5757     "Modified: / 24.7.1998 / 00:56:14 / cg"
  5758 ! !
  5758 ! !
  5759 
  5759 
  5760 !Image methodsFor:'converting rgb images'!
  5760 !Image methodsFor:'converting rgb images'!
  5761 
  5761 
  5762 asDitheredTrueColor8FormOn:aDevice
  5762 asDitheredTrueColor8FormOn:aDevice
  5763     "convert an rgb image to a dithered depth8-form on aDevice.
  5763     "convert an rgb image to a dithered depth8-form on aDevice.
  5764      Return the device-form. 
  5764      Return the device-form.
  5765      This method is only valid for trueColor displays."
  5765      This method is only valid for trueColor displays."
  5766 
  5766 
  5767     |fixColors pixel
  5767     |fixColors pixel
  5768      dstIdx     "{ Class: SmallInteger }"
  5768      dstIdx     "{ Class: SmallInteger }"
  5769      shiftRed   "{ Class: SmallInteger }"
  5769      shiftRed   "{ Class: SmallInteger }"
  5795 	    ]
  5795 	    ]
  5796 	]
  5796 	]
  5797     ].
  5797     ].
  5798 
  5798 
  5799     ^ self
  5799     ^ self
  5800 	asFloydSteinbergDitheredDepth8FormOn:aDevice 
  5800 	asFloydSteinbergDitheredDepth8FormOn:aDevice
  5801 	colors:fixColors 
  5801 	colors:fixColors
  5802 	nRed:nRed nGreen:nGreen nBlue:nBlue
  5802 	nRed:nRed nGreen:nGreen nBlue:nBlue
  5803 
  5803 
  5804     "Created: 14.6.1996 / 17:23:52 / cg"
  5804     "Created: 14.6.1996 / 17:23:52 / cg"
  5805     "Modified: 23.6.1997 / 15:22:36 / cg"
  5805     "Modified: 23.6.1997 / 15:22:36 / cg"
  5806 !
  5806 !
  5887 	'Image [warning]: display bitmap creation failed' errorPrintCR.
  5887 	'Image [warning]: display bitmap creation failed' errorPrintCR.
  5888 	^ nil
  5888 	^ nil
  5889     ].
  5889     ].
  5890     form initGC.
  5890     form initGC.
  5891 
  5891 
  5892     form 
  5892     form
  5893 	copyBitsFrom:self bits 
  5893 	copyBitsFrom:self bits
  5894 	bitsPerPixel:usedDeviceBitsPerPixel 
  5894 	bitsPerPixel:usedDeviceBitsPerPixel
  5895 	depth:usedDeviceDepth 
  5895 	depth:usedDeviceDepth
  5896 	padding:8
  5896 	padding:8
  5897 	width:width height:height 
  5897 	width:width height:height
  5898 	x:0 y:0 
  5898 	x:0 y:0
  5899 	toX:0 y:0. 
  5899 	toX:0 y:0.
  5900 
  5900 
  5901     ^ form
  5901     ^ form
  5902 
  5902 
  5903     "Modified: 10.1.1997 / 17:53:23 / cg"
  5903     "Modified: 10.1.1997 / 17:53:23 / cg"
  5904 ! !
  5904 ! !
  6024      errorArray1
  6024      errorArray1
  6025      e t
  6025      e t
  6026      w               "{Class: SmallInteger }"
  6026      w               "{Class: SmallInteger }"
  6027      h               "{Class: SmallInteger }"
  6027      h               "{Class: SmallInteger }"
  6028      bitCnt          "{Class: SmallInteger }"
  6028      bitCnt          "{Class: SmallInteger }"
  6029      byte            "{Class: SmallInteger }" 
  6029      byte            "{Class: SmallInteger }"
  6030      grey|
  6030      grey|
  6031 
  6031 
  6032     self depth > 12 ifTrue:[
  6032     self depth > 12 ifTrue:[
  6033 	^ self floydSteinbergDitheredMonochromeBits
  6033 	^ self floydSteinbergDitheredMonochromeBits
  6034     ].
  6034     ].
  6046 
  6046 
  6047     "/ fetch scaled brightness values outside of loop into a table;
  6047     "/ fetch scaled brightness values outside of loop into a table;
  6048     "/ use table-value in loop
  6048     "/ use table-value in loop
  6049 
  6049 
  6050     greyValues := self greyMapForRange:(255*1024).
  6050     greyValues := self greyMapForRange:(255*1024).
  6051     
  6051 
  6052     0 to:(h-1) do:[:y |
  6052     0 to:(h-1) do:[:y |
  6053 	nextDst := dstIndex + bytesPerMonoRow.
  6053 	nextDst := dstIndex + bytesPerMonoRow.
  6054 	byte := 0.
  6054 	byte := 0.
  6055 	bitCnt := 8.
  6055 	bitCnt := 8.
  6056 
  6056 
  6059 	errorArray1 := t.
  6059 	errorArray1 := t.
  6060 
  6060 
  6061 	errorArray1 atAllPut:0.
  6061 	errorArray1 atAllPut:0.
  6062 
  6062 
  6063 	self valuesAtY:y from:0 to:(w-1) do:[:x :pixel |
  6063 	self valuesAtY:y from:0 to:(w-1) do:[:x :pixel |
  6064 	    |eP "{Class: SmallInteger }" 
  6064 	    |eP "{Class: SmallInteger }"
  6065 	     eD 
  6065 	     eD
  6066 	     eI "{Class: SmallInteger }" 
  6066 	     eI "{Class: SmallInteger }"
  6067 	     xE "{Class: SmallInteger }"
  6067 	     xE "{Class: SmallInteger }"
  6068 	     xN "{Class: SmallInteger }" |
  6068 	     xN "{Class: SmallInteger }" |
  6069 
  6069 
  6070 	    "/ get the colors grey value [0 .. 1]
  6070 	    "/ get the colors grey value [0 .. 1]
  6071 	    grey := greyValues at:(pixel + 1).
  6071 	    grey := greyValues at:(pixel + 1).
  6142     "Modified: 10.6.1996 / 13:16:33 / cg"
  6142     "Modified: 10.6.1996 / 13:16:33 / cg"
  6143 !
  6143 !
  6144 
  6144 
  6145 floydSteinbergDitheredDepth8BitsColors:colors
  6145 floydSteinbergDitheredDepth8BitsColors:colors
  6146     "return a floyd-steinberg dithered bitmap from the receiver picture,
  6146     "return a floyd-steinberg dithered bitmap from the receiver picture,
  6147      which must be a depth-8 image. 
  6147      which must be a depth-8 image.
  6148      This method expects an array of colors to be used for dithering
  6148      This method expects an array of colors to be used for dithering
  6149      (which need not be a colorCubes colors)."
  6149      (which need not be a colorCubes colors)."
  6150 
  6150 
  6151     ^ self floydSteinbergDitheredDepth8BitsColors:colors map:nil
  6151     ^ self floydSteinbergDitheredDepth8BitsColors:colors map:nil
  6152 
  6152 
  6153 !
  6153 !
  6154 
  6154 
  6155 floydSteinbergDitheredDepth8BitsColors:colors map:aMapOrNil
  6155 floydSteinbergDitheredDepth8BitsColors:colors map:aMapOrNil
  6156     "return a floyd-steinberg dithered bitmap from the receiver picture,
  6156     "return a floyd-steinberg dithered bitmap from the receiver picture,
  6157      which must be a depth-24 image. 
  6157      which must be a depth-24 image.
  6158      This method expects an array of colors to be used for dithering
  6158      This method expects an array of colors to be used for dithering
  6159      (which need not be a colorCubes colors)."
  6159      (which need not be a colorCubes colors)."
  6160 
  6160 
  6161     |pseudoBits  
  6161     |pseudoBits
  6162      ditherRGBBytes ditherColors
  6162      ditherRGBBytes ditherColors
  6163      w       "{Class: SmallInteger }"
  6163      w       "{Class: SmallInteger }"
  6164      h       "{Class: SmallInteger }"
  6164      h       "{Class: SmallInteger }"
  6165      index   "{Class: SmallInteger }"
  6165      index   "{Class: SmallInteger }"
  6166      ditherIds failed lastColor qScramble
  6166      ditherIds failed lastColor qScramble
  6242 	i := qScramble at:((r bitShift:-4) bitAnd:16r0F) + 1.
  6242 	i := qScramble at:((r bitShift:-4) bitAnd:16r0F) + 1.
  6243 	i := i + ((qScramble at:((g bitShift:-4) bitAnd:16r0F) + 1) bitShift:-1).
  6243 	i := i + ((qScramble at:((g bitShift:-4) bitAnd:16r0F) + 1) bitShift:-1).
  6244 	i := i + ((qScramble at:((b bitShift:-4) bitAnd:16r0F) + 1) bitShift:-2).
  6244 	i := i + ((qScramble at:((b bitShift:-4) bitAnd:16r0F) + 1) bitShift:-2).
  6245 	lookupPos := i.
  6245 	lookupPos := i.
  6246 
  6246 
  6247 	[index < lookupPos] whileTrue:[        
  6247 	[index < lookupPos] whileTrue:[
  6248 	    clrLookup at:(index+1) put:(clrPosition-1-1).
  6248 	    clrLookup at:(index+1) put:(clrPosition-1-1).
  6249 	    index := index + 1
  6249 	    index := index + 1
  6250 	]
  6250 	]
  6251     ].
  6251     ].
  6252     clrLookup from:index+1 to:4096 put:(ditherColors size - 1).
  6252     clrLookup from:index+1 to:4096 put:(ditherColors size - 1).
  6388 		 && (__wantG == __wG)
  6388 		 && (__wantG == __wG)
  6389 		 && (__wantB == __wB)) {
  6389 		 && (__wantB == __wB)) {
  6390 		    /*
  6390 		    /*
  6391 		     * same color again - reuse last bestMatch
  6391 		     * same color again - reuse last bestMatch
  6392 		     */
  6392 		     */
  6393 		} else 
  6393 		} else
  6394 #endif
  6394 #endif
  6395 		{
  6395 		{
  6396 		    __wR = __wantR;
  6396 		    __wR = __wantR;
  6397 		    __wG = __wantG;
  6397 		    __wG = __wantG;
  6398 		    __wB = __wantB;
  6398 		    __wB = __wantB;
  6423 			d = dp[0];
  6423 			d = dp[0];
  6424 			delta = (__wR - d) * RED_SCALE;
  6424 			delta = (__wR - d) * RED_SCALE;
  6425 			if (delta < 0) delta = -delta;
  6425 			if (delta < 0) delta = -delta;
  6426 
  6426 
  6427 			d = dp[1];
  6427 			d = dp[1];
  6428 			if (__wG > d) 
  6428 			if (__wG > d)
  6429 			    delta += (__wG - d) * GREEN_SCALE;
  6429 			    delta += (__wG - d) * GREEN_SCALE;
  6430 			else 
  6430 			else
  6431 			    delta += (d - __wG) * GREEN_SCALE;
  6431 			    delta += (d - __wG) * GREEN_SCALE;
  6432 			d = dp[2];
  6432 			d = dp[2];
  6433 			if (__wB > d) 
  6433 			if (__wB > d)
  6434 			    delta += (__wB - d) * BLUE_SCALE;
  6434 			    delta += (__wB - d) * BLUE_SCALE;
  6435 			else 
  6435 			else
  6436 			    delta += (d - __wB) * BLUE_SCALE;
  6436 			    delta += (d - __wB) * BLUE_SCALE;
  6437 
  6437 
  6438 			if (delta <= GOOD_DELTA) {
  6438 			if (delta <= GOOD_DELTA) {
  6439 			    goto foundBest;
  6439 			    goto foundBest;
  6440 			}
  6440 			}
  6448 			    idx--; dp -= 3;
  6448 			    idx--; dp -= 3;
  6449 			    d = dp[0];
  6449 			    d = dp[0];
  6450 			    delta = (__wR - d) * RED_SCALE;
  6450 			    delta = (__wR - d) * RED_SCALE;
  6451 			    if (delta < 0) delta = -delta;
  6451 			    if (delta < 0) delta = -delta;
  6452 			    d = dp[1];
  6452 			    d = dp[1];
  6453 			    if (__wG > d) 
  6453 			    if (__wG > d)
  6454 				delta += (__wG - d) * GREEN_SCALE;
  6454 				delta += (__wG - d) * GREEN_SCALE;
  6455 			    else 
  6455 			    else
  6456 				delta += (d - __wG) * GREEN_SCALE;
  6456 				delta += (d - __wG) * GREEN_SCALE;
  6457 			    d = dp[2];
  6457 			    d = dp[2];
  6458 			    if (__wB > d) 
  6458 			    if (__wB > d)
  6459 				delta += (__wB - d) * BLUE_SCALE;
  6459 				delta += (__wB - d) * BLUE_SCALE;
  6460 			    else 
  6460 			    else
  6461 				delta += (d - __wB) * BLUE_SCALE;
  6461 				delta += (d - __wB) * BLUE_SCALE;
  6462 
  6462 
  6463 			    if (delta < minDelta) {
  6463 			    if (delta < minDelta) {
  6464 				bestIdx = idx;
  6464 				bestIdx = idx;
  6465 				if (delta <= GOOD_DELTA) {
  6465 				if (delta <= GOOD_DELTA) {
  6477 			    dp += 3;
  6477 			    dp += 3;
  6478 			    d = dp[0];
  6478 			    d = dp[0];
  6479 			    delta = (__wR - d) * RED_SCALE;
  6479 			    delta = (__wR - d) * RED_SCALE;
  6480 			    if (delta < 0) delta = -delta;
  6480 			    if (delta < 0) delta = -delta;
  6481 			    d = dp[1];
  6481 			    d = dp[1];
  6482 			    if (__wG > d) 
  6482 			    if (__wG > d)
  6483 				delta += (__wG - d) * GREEN_SCALE;
  6483 				delta += (__wG - d) * GREEN_SCALE;
  6484 			    else 
  6484 			    else
  6485 				delta += (d - __wG) * GREEN_SCALE;
  6485 				delta += (d - __wG) * GREEN_SCALE;
  6486 			    d = dp[2];
  6486 			    d = dp[2];
  6487 			    if (__wB > d) 
  6487 			    if (__wB > d)
  6488 				delta += (__wB - d) * BLUE_SCALE;
  6488 				delta += (__wB - d) * BLUE_SCALE;
  6489 			    else 
  6489 			    else
  6490 				delta += (d - __wB) * BLUE_SCALE;
  6490 				delta += (d - __wB) * BLUE_SCALE;
  6491 
  6491 
  6492 			    if (delta < minDelta) {
  6492 			    if (delta < minDelta) {
  6493 				bestIdx = idx;
  6493 				bestIdx = idx;
  6494 				if (delta <= GOOD_DELTA) {
  6494 				if (delta <= GOOD_DELTA) {
  6521 			d = dp[0];
  6521 			d = dp[0];
  6522 			delta = (__wR - d) * RED_SCALE;
  6522 			delta = (__wR - d) * RED_SCALE;
  6523 			if (delta < 0) delta = -delta;
  6523 			if (delta < 0) delta = -delta;
  6524 			if (delta < minDelta) {
  6524 			if (delta < minDelta) {
  6525 			    d = dp[1];
  6525 			    d = dp[1];
  6526 			    if (__wG > d) 
  6526 			    if (__wG > d)
  6527 				delta += (__wG - d) * GREEN_SCALE;
  6527 				delta += (__wG - d) * GREEN_SCALE;
  6528 			    else 
  6528 			    else
  6529 				delta += (d - __wG) * GREEN_SCALE;
  6529 				delta += (d - __wG) * GREEN_SCALE;
  6530 			    if (delta < minDelta) {
  6530 			    if (delta < minDelta) {
  6531 				d = dp[2];
  6531 				d = dp[2];
  6532 				if (__wB > d) 
  6532 				if (__wB > d)
  6533 				    delta += (__wB - d) * BLUE_SCALE;
  6533 				    delta += (__wB - d) * BLUE_SCALE;
  6534 				else 
  6534 				else
  6535 				    delta += (d - __wB) * BLUE_SCALE;
  6535 				    delta += (d - __wB) * BLUE_SCALE;
  6536 
  6536 
  6537 				if (delta < minDelta) {
  6537 				if (delta < minDelta) {
  6538 				    bestIdx = idx;
  6538 				    bestIdx = idx;
  6539 				    if (delta <= GOOD_DELTA) {
  6539 				    if (delta <= GOOD_DELTA) {
  6552 		dR = dp[0];
  6552 		dR = dp[0];
  6553 		dG = dp[1];
  6553 		dG = dp[1];
  6554 		dB = dp[2];
  6554 		dB = dp[2];
  6555 
  6555 
  6556 /*
  6556 /*
  6557 printf("want: %d/%d/%d (%d/%d/%d) got: %d/%d/%d\n",
  6557 console_printf("want: %d/%d/%d (%d/%d/%d) got: %d/%d/%d\n",
  6558 		__wantR, __wantG, __wantB,
  6558 		__wantR, __wantG, __wantB,
  6559 		__wR, __wG, __wB,
  6559 		__wR, __wG, __wB,
  6560 		dR, dG, dB);
  6560 		dR, dG, dB);
  6561 */
  6561 */
  6562 		/*
  6562 		/*
  6565 		*dstP++ = idP[bestIdx];
  6565 		*dstP++ = idP[bestIdx];
  6566 
  6566 
  6567 		/*
  6567 		/*
  6568 		 * the new error & distribute the error
  6568 		 * the new error & distribute the error
  6569 		 */
  6569 		 */
  6570 		__eR = __wantR - dR; 
  6570 		__eR = __wantR - dR;
  6571 		if (__eR) {
  6571 		if (__eR) {
  6572 		    tR = __eR >> 4;  /* 16th of error */
  6572 		    tR = __eR >> 4;  /* 16th of error */
  6573 		    nR = eP[3] + (tR * 7);/* from accu: error for (x+1 / y) */
  6573 		    nR = eP[3] + (tR * 7);/* from accu: error for (x+1 / y) */
  6574 		    eP[0] = tR*5;         /* 5/16th for (x / y+1) */
  6574 		    eP[0] = tR*5;         /* 5/16th for (x / y+1) */
  6575 		    eP[-3] = tR*3;        /* 3/16th for (x-1 / y+1) */
  6575 		    eP[-3] = tR*3;        /* 3/16th for (x-1 / y+1) */
  6591 		} else {
  6591 		} else {
  6592 		    __eG = eP[4];
  6592 		    __eG = eP[4];
  6593 		    eP[1] = eP[-2] = eP[4] = 0;
  6593 		    eP[1] = eP[-2] = eP[4] = 0;
  6594 		}
  6594 		}
  6595 
  6595 
  6596 		__eB = __wantB - dB; 
  6596 		__eB = __wantB - dB;
  6597 		if (__eB) {
  6597 		if (__eB) {
  6598 		    tB = __eB >> 4;
  6598 		    tB = __eB >> 4;
  6599 		    nB = eP[5] + (tB * 7);
  6599 		    nB = eP[5] + (tB * 7);
  6600 		    eP[2] = tB*5;
  6600 		    eP[2] = tB*5;
  6601 		    eP[-1] = tB*3;
  6601 		    eP[-1] = tB*3;
  6617     ].
  6617     ].
  6618 
  6618 
  6619     ^ pseudoBits
  6619     ^ pseudoBits
  6620 !
  6620 !
  6621 
  6621 
  6622 floydSteinbergDitheredDepth8BitsColors:fixColors nRed:nRed nGreen:nGreen nBlue:nBlue 
  6622 floydSteinbergDitheredDepth8BitsColors:fixColors nRed:nRed nGreen:nGreen nBlue:nBlue
  6623     "return a floyd-steinberg dithered bitmap from the receiver picture,
  6623     "return a floyd-steinberg dithered bitmap from the receiver picture,
  6624      which must be a depth-8 image. 
  6624      which must be a depth-8 image.
  6625      This is a special-cased dither method for 8-bit palette images being displayed on
  6625      This is a special-cased dither method for 8-bit palette images being displayed on
  6626      an 8-bit pseudoColor display, AND fixColor dithering is used.
  6626      an 8-bit pseudoColor display, AND fixColor dithering is used.
  6627      Use the colors in the fixColors array, which must be fixR x fixG x fixB
  6627      Use the colors in the fixColors array, which must be fixR x fixG x fixB
  6628      colors assigned to aDevice, such as the preallocated colors of the
  6628      colors assigned to aDevice, such as the preallocated colors of the
  6629      Color class. 
  6629      Color class.
  6630      By passing the ditherColors as extra array, this method can
  6630      By passing the ditherColors as extra array, this method can
  6631      also be used to dither an 8bit image into a smaller number of colors,
  6631      also be used to dither an 8bit image into a smaller number of colors,
  6632      for example to create dithered Depth4Images from Depth8Images."
  6632      for example to create dithered Depth4Images from Depth8Images."
  6633 
  6633 
  6634     |pseudoBits  
  6634     |pseudoBits
  6635      rgbBytes
  6635      rgbBytes
  6636      w       "{Class: SmallInteger }"
  6636      w       "{Class: SmallInteger }"
  6637      h       "{Class: SmallInteger }"
  6637      h       "{Class: SmallInteger }"
  6638      index   "{Class: SmallInteger }"
  6638      index   "{Class: SmallInteger }"
  6639      fixR    "{Class: SmallInteger }"
  6639      fixR    "{Class: SmallInteger }"
  6640      fixG    "{Class: SmallInteger }"
  6640      fixG    "{Class: SmallInteger }"
  6641      fixB    "{Class: SmallInteger }"
  6641      fixB    "{Class: SmallInteger }"
  6642      fixGfixB
  6642      fixGfixB
  6643      fixIds failed map lastColor 
  6643      fixIds failed map lastColor
  6644      rgbIDX  "{Class: SmallInteger }"
  6644      rgbIDX  "{Class: SmallInteger }"
  6645      idxAndErrRBytes idxAndErrGBytes idxAndErrBBytes
  6645      idxAndErrRBytes idxAndErrGBytes idxAndErrBBytes
  6646      error clr|
  6646      error clr|
  6647 
  6647 
  6648     self depth ~~ 8 ifTrue:[^ nil].
  6648     self depth ~~ 8 ifTrue:[^ nil].
  6700 	rgbIDX := (i * (fixR-1) + 128) // 255. "red index rounded"
  6700 	rgbIDX := (i * (fixR-1) + 128) // 255. "red index rounded"
  6701 	idxAndErrRBytes at:index put:(rgbIDX * fixGfixB).
  6701 	idxAndErrRBytes at:index put:(rgbIDX * fixGfixB).
  6702 	idxAndErrRBytes at:index+1 put:i - (rgbIDX * 255 // (fixR-1)) + 128.
  6702 	idxAndErrRBytes at:index+1 put:i - (rgbIDX * 255 // (fixR-1)) + 128.
  6703 
  6703 
  6704 	rgbIDX := (i * (fixG-1) + 128) // 255. "green index rounded"
  6704 	rgbIDX := (i * (fixG-1) + 128) // 255. "green index rounded"
  6705 	idxAndErrGBytes at:index put:(rgbIDX * fixB). 
  6705 	idxAndErrGBytes at:index put:(rgbIDX * fixB).
  6706 	idxAndErrGBytes at:index+1 put:i - (rgbIDX * 255 // (fixG-1)) + 128.
  6706 	idxAndErrGBytes at:index+1 put:i - (rgbIDX * 255 // (fixG-1)) + 128.
  6707 
  6707 
  6708 	rgbIDX := (i * (fixB-1) + 128) // 255. "blue index rounded"
  6708 	rgbIDX := (i * (fixB-1) + 128) // 255. "blue index rounded"
  6709 	idxAndErrBBytes at:index put:(rgbIDX ).
  6709 	idxAndErrBBytes at:index put:(rgbIDX ).
  6710 	idxAndErrBBytes at:index+1 put:i - (rgbIDX * 255 // (fixB-1)) + 128.
  6710 	idxAndErrBBytes at:index+1 put:i - (rgbIDX * 255 // (fixB-1)) + 128.
  6772 		 */
  6772 		 */
  6773 		__want = rgbP[pix]   + __eR;
  6773 		__want = rgbP[pix]   + __eR;
  6774 		if (__want > 255) __want = 255;
  6774 		if (__want > 255) __want = 255;
  6775 		else if (__want < 0) __want = 0;
  6775 		else if (__want < 0) __want = 0;
  6776 		__want += __want;
  6776 		__want += __want;
  6777 		idx = __idxAndErrRBytes[__want];   
  6777 		idx = __idxAndErrRBytes[__want];
  6778 		__eR = __idxAndErrRBytes[__want+1]; 
  6778 		__eR = __idxAndErrRBytes[__want+1];
  6779 		__eR -= 128;
  6779 		__eR -= 128;
  6780 
  6780 
  6781 		__want = rgbP[pix+1] + __eG;
  6781 		__want = rgbP[pix+1] + __eG;
  6782 		if (__want > 255) __want = 255;
  6782 		if (__want > 255) __want = 255;
  6783 		else if (__want < 0) __want = 0;
  6783 		else if (__want < 0) __want = 0;
  6784 		__want += __want;
  6784 		__want += __want;
  6785 		idx += __idxAndErrGBytes[__want];   
  6785 		idx += __idxAndErrGBytes[__want];
  6786 		__eG = __idxAndErrGBytes[__want+1]; 
  6786 		__eG = __idxAndErrGBytes[__want+1];
  6787 		__eG -= 128;
  6787 		__eG -= 128;
  6788 
  6788 
  6789 		__want = rgbP[pix+2] + __eB;
  6789 		__want = rgbP[pix+2] + __eB;
  6790 		if (__want > 255) __want = 255;
  6790 		if (__want > 255) __want = 255;
  6791 		else if (__want < 0) __want = 0;
  6791 		else if (__want < 0) __want = 0;
  6792 		__want += __want;
  6792 		__want += __want;
  6793 		idx += __idxAndErrBBytes[__want];   
  6793 		idx += __idxAndErrBBytes[__want];
  6794 		__eB = __idxAndErrBBytes[__want+1]; 
  6794 		__eB = __idxAndErrBBytes[__want+1];
  6795 		__eB -= 128;
  6795 		__eB -= 128;
  6796 
  6796 
  6797 		/*
  6797 		/*
  6798 		 * store the corresponding dither colors colorId
  6798 		 * store the corresponding dither colors colorId
  6799 		 */
  6799 		 */
  6853 
  6853 
  6854 !
  6854 !
  6855 
  6855 
  6856 floydSteinbergDitheredGrayBitsDepth:depth
  6856 floydSteinbergDitheredGrayBitsDepth:depth
  6857     "return the bits for dithering a gray image from the image.
  6857     "return the bits for dithering a gray image from the image.
  6858      Works for any source depths / photometric, 
  6858      Works for any source depths / photometric,
  6859      but possibly slow since each pixel is processed individually.
  6859      but possibly slow since each pixel is processed individually.
  6860      Redefined by some subclasses for more performance (D8Image/D24Image)"
  6860      Redefined by some subclasses for more performance (D8Image/D24Image)"
  6861 
  6861 
  6862     |dstIndex        "{Class: SmallInteger }"
  6862     |dstIndex        "{Class: SmallInteger }"
  6863      nextDst         "{Class: SmallInteger }"
  6863      nextDst         "{Class: SmallInteger }"
  6867      nextErrorArray
  6867      nextErrorArray
  6868      t
  6868      t
  6869      w               "{Class: SmallInteger }"
  6869      w               "{Class: SmallInteger }"
  6870      h               "{Class: SmallInteger }"
  6870      h               "{Class: SmallInteger }"
  6871      bitCnt          "{Class: SmallInteger }"
  6871      bitCnt          "{Class: SmallInteger }"
  6872      byte            "{Class: SmallInteger }" 
  6872      byte            "{Class: SmallInteger }"
  6873      grey
  6873      grey
  6874      eR eRB eB eLB |
  6874      eR eRB eB eLB |
  6875 
  6875 
  6876     depth > 8 ifTrue:[
  6876     depth > 8 ifTrue:[
  6877 	self error:'unimplemented conversion'.
  6877 	self error:'unimplemented conversion'.
  6926 	    self valuesAtY:y from:0 to:(w-1) do:[:x :value |
  6926 	    self valuesAtY:y from:0 to:(w-1) do:[:x :value |
  6927 		|e     "{ Class: SmallInteger }"
  6927 		|e     "{ Class: SmallInteger }"
  6928 		 pixel "{ Class: SmallInteger }"
  6928 		 pixel "{ Class: SmallInteger }"
  6929 		 error "{ Class: SmallInteger }"
  6929 		 error "{ Class: SmallInteger }"
  6930 		 e16   "{ Class: SmallInteger }"
  6930 		 e16   "{ Class: SmallInteger }"
  6931 		 xE    "{ Class: SmallInteger }" 
  6931 		 xE    "{ Class: SmallInteger }"
  6932 		 xN    "{ Class: SmallInteger }" |
  6932 		 xN    "{ Class: SmallInteger }" |
  6933 
  6933 
  6934 		pixel := greyPixels at:(value + 1).
  6934 		pixel := greyPixels at:(value + 1).
  6935 
  6935 
  6936 		"/ adjust error
  6936 		"/ adjust error
  6937 		xE := x + 2.
  6937 		xE := x + 2.
  6938 		error := (greyErrors at:(value + 1)) + (errorArray at:xE).
  6938 		error := (greyErrors at:(value + 1)) + (errorArray at:xE).
  6939 
  6939 
  6940 		byte := byte bitShift:depth.
  6940 		byte := byte bitShift:depth.
  6941 		error > 512 "0.5" ifTrue:[
  6941 		error > 512 "0.5" ifTrue:[
  6942 		    pixel := pixel + 1.      
  6942 		    pixel := pixel + 1.
  6943 		    e := error - 1024 "1.0"
  6943 		    e := error - 1024 "1.0"
  6944 		] ifFalse:[
  6944 		] ifFalse:[
  6945 		    e := error              
  6945 		    e := error
  6946 		].
  6946 		].
  6947 		byte := byte bitOr:pixel.
  6947 		byte := byte bitOr:pixel.
  6948 
  6948 
  6949 		e ~= 0 ifTrue:[
  6949 		e ~= 0 ifTrue:[
  6950 		    e16 := e // 16.
  6950 		    e16 := e // 16.
  7001 	    self colorsAtY:y from:0 to:(w-1) do:[:x :clr |
  7001 	    self colorsAtY:y from:0 to:(w-1) do:[:x :clr |
  7002 		|e     "{ Class: SmallInteger }"
  7002 		|e     "{ Class: SmallInteger }"
  7003 		 pixel "{ Class: SmallInteger }"
  7003 		 pixel "{ Class: SmallInteger }"
  7004 		 error "{ Class: SmallInteger }"
  7004 		 error "{ Class: SmallInteger }"
  7005 		 e16   "{ Class: SmallInteger }"
  7005 		 e16   "{ Class: SmallInteger }"
  7006 		 xE    "{ Class: SmallInteger }" 
  7006 		 xE    "{ Class: SmallInteger }"
  7007 		 xN    "{ Class: SmallInteger }" |
  7007 		 xN    "{ Class: SmallInteger }" |
  7008 
  7008 
  7009 		grey := (clr brightness * greyLevels).
  7009 		grey := (clr brightness * greyLevels).
  7010 		pixel := grey truncated.
  7010 		pixel := grey truncated.
  7011 		error := ((grey - pixel) * 1024) truncated.
  7011 		error := ((grey - pixel) * 1024) truncated.
  7014 		xE := x + 2.
  7014 		xE := x + 2.
  7015 		error := error + (errorArray at:xE).
  7015 		error := error + (errorArray at:xE).
  7016 
  7016 
  7017 		byte := byte bitShift:depth.
  7017 		byte := byte bitShift:depth.
  7018 		error > 512 "0.5" ifTrue:[
  7018 		error > 512 "0.5" ifTrue:[
  7019 		    pixel := pixel + 1.      
  7019 		    pixel := pixel + 1.
  7020 		    e := error - 1024 "1.0"
  7020 		    e := error - 1024 "1.0"
  7021 		] ifFalse:[
  7021 		] ifFalse:[
  7022 		    e := error              
  7022 		    e := error
  7023 		].
  7023 		].
  7024 
  7024 
  7025 		byte := byte bitOr:pixel.
  7025 		byte := byte bitOr:pixel.
  7026 
  7026 
  7027 		e ~= 0 ifTrue:[
  7027 		e ~= 0 ifTrue:[
  7073     "Modified: 11.6.1996 / 00:13:38 / cg"
  7073     "Modified: 11.6.1996 / 00:13:38 / cg"
  7074 !
  7074 !
  7075 
  7075 
  7076 floydSteinbergDitheredMonochromeBits
  7076 floydSteinbergDitheredMonochromeBits
  7077     "return the bitmap for a dithered monochrome bitmap from the image.
  7077     "return the bitmap for a dithered monochrome bitmap from the image.
  7078      Works for any source depths / photometric, 
  7078      Works for any source depths / photometric,
  7079      but very very slow since each pixel is processed individually.
  7079      but very very slow since each pixel is processed individually.
  7080      Redefined by some subclasses for more performance (D8Image)"
  7080      Redefined by some subclasses for more performance (D8Image)"
  7081 
  7081 
  7082     |dstIndex        "{Class: SmallInteger }"
  7082     |dstIndex        "{Class: SmallInteger }"
  7083      nextDst         "{Class: SmallInteger }"
  7083      nextDst         "{Class: SmallInteger }"
  7087      nextErrorArray
  7087      nextErrorArray
  7088      e eD t
  7088      e eD t
  7089      w               "{Class: SmallInteger }"
  7089      w               "{Class: SmallInteger }"
  7090      h               "{Class: SmallInteger }"
  7090      h               "{Class: SmallInteger }"
  7091      bitCnt          "{Class: SmallInteger }"
  7091      bitCnt          "{Class: SmallInteger }"
  7092      byte            "{Class: SmallInteger }" 
  7092      byte            "{Class: SmallInteger }"
  7093      grey  
  7093      grey
  7094      eR eRB eB eLB |
  7094      eR eRB eB eLB |
  7095 
  7095 
  7096     w := width.
  7096     w := width.
  7097     h := height.
  7097     h := height.
  7098 
  7098 
  7134 		int __eR, __eB, __eRB, __eLB, __eI;
  7134 		int __eR, __eB, __eRB, __eLB, __eI;
  7135 		int __bitCnt = __intVal(bitCnt);
  7135 		int __bitCnt = __intVal(bitCnt);
  7136 
  7136 
  7137 		__grey = __intVal(__ArrayInstPtr(greyValues)->a_element[__intVal(pixel)]);
  7137 		__grey = __intVal(__ArrayInstPtr(greyValues)->a_element[__intVal(pixel)]);
  7138 		__grey += __intVal(__errorArray[__x+1]);
  7138 		__grey += __intVal(__errorArray[__x+1]);
  7139                 
  7139 
  7140 		__byte <<= 1;
  7140 		__byte <<= 1;
  7141 		if (__grey > 127*1024) {
  7141 		if (__grey > 127*1024) {
  7142 		    __e = __grey - (255*1024);
  7142 		    __e = __grey - (255*1024);
  7143 		    __byte |= 1;
  7143 		    __byte |= 1;
  7144 		} else {
  7144 		} else {
  7145 		    __e = __grey;
  7145 		    __e = __grey;
  7146 		}
  7146 		}
  7147 		if (__e) {
  7147 		if (__e) {
  7148 		    __eI = __e >> 4;
  7148 		    __eI = __e >> 4;
  7149 		    __eR  = __eI * 7;            
  7149 		    __eR  = __eI * 7;
  7150 		    __eRB = __eI * 1;            
  7150 		    __eRB = __eI * 1;
  7151 		    __eB  = __eI * 5;            
  7151 		    __eB  = __eI * 5;
  7152 		    __eLB = __e - __eR - __eRB - __eB;
  7152 		    __eLB = __e - __eR - __eRB - __eB;
  7153 		    __errorArray[__x+2] = __MKSMALLINT(__intVal(__errorArray[__x+2]) + __eR);
  7153 		    __errorArray[__x+2] = __MKSMALLINT(__intVal(__errorArray[__x+2]) + __eR);
  7154 		    __nextErrorArray[__x+2] = __MKSMALLINT(__intVal(__nextErrorArray[__x+2]) + __eRB);
  7154 		    __nextErrorArray[__x+2] = __MKSMALLINT(__intVal(__nextErrorArray[__x+2]) + __eRB);
  7155 		    __nextErrorArray[__x+1] = __MKSMALLINT(__intVal(__nextErrorArray[__x+1]) + __eB);
  7155 		    __nextErrorArray[__x+1] = __MKSMALLINT(__intVal(__nextErrorArray[__x+1]) + __eB);
  7156 		    __nextErrorArray[__x  ] = __MKSMALLINT(__intVal(__nextErrorArray[__x  ]) + __eLB);
  7156 		    __nextErrorArray[__x  ] = __MKSMALLINT(__intVal(__nextErrorArray[__x  ]) + __eLB);
  7167 		}
  7167 		}
  7168 		byte = __MKSMALLINT(__byte);
  7168 		byte = __MKSMALLINT(__byte);
  7169 		bitCnt = __MKSMALLINT(__bitCnt);
  7169 		bitCnt = __MKSMALLINT(__bitCnt);
  7170 %}.
  7170 %}.
  7171 
  7171 
  7172 "/                |eI "{ Class: SmallInteger }" 
  7172 "/                |eI "{ Class: SmallInteger }"
  7173 "/                 xE "{ Class: SmallInteger }" 
  7173 "/                 xE "{ Class: SmallInteger }"
  7174 "/                 xN "{ Class: SmallInteger }" |
  7174 "/                 xN "{ Class: SmallInteger }" |
  7175 "/
  7175 "/
  7176 "/                "/ get the colors grey value [0 .. 1]
  7176 "/                "/ get the colors grey value [0 .. 1]
  7177 "/                grey := greyValues at:(pixel + 1).
  7177 "/                grey := greyValues at:(pixel + 1).
  7178 "/
  7178 "/
  7241 	    nextErrorArray := t.
  7241 	    nextErrorArray := t.
  7242 
  7242 
  7243 	    nextErrorArray atAllPut:0.
  7243 	    nextErrorArray atAllPut:0.
  7244 
  7244 
  7245 	    self colorsAtY:y from:0 to:(w-1) do:[:x :clr |
  7245 	    self colorsAtY:y from:0 to:(w-1) do:[:x :clr |
  7246 		|eI "{ Class: SmallInteger }" 
  7246 		|eI "{ Class: SmallInteger }"
  7247 		 xE "{ Class: SmallInteger }" 
  7247 		 xE "{ Class: SmallInteger }"
  7248 		 xN "{ Class: SmallInteger }" |
  7248 		 xN "{ Class: SmallInteger }" |
  7249 
  7249 
  7250 		"/ get the colors grey value [0 .. 1]
  7250 		"/ get the colors grey value [0 .. 1]
  7251 		grey := (clr brightness * 255).
  7251 		grey := (clr brightness * 255).
  7252 
  7252 
  7310 
  7310 
  7311     "Created: 8.6.1996 / 16:39:46 / cg"
  7311     "Created: 8.6.1996 / 16:39:46 / cg"
  7312     "Modified: 10.6.1996 / 15:12:11 / cg"
  7312     "Modified: 10.6.1996 / 15:12:11 / cg"
  7313 !
  7313 !
  7314 
  7314 
  7315 nearestPaintDepth8BitsColors:fixColors nRed:nRed nGreen:nGreen nBlue:nBlue 
  7315 nearestPaintDepth8BitsColors:fixColors nRed:nRed nGreen:nGreen nBlue:nBlue
  7316     "return a nearest paint bitmap from the receiver picture,
  7316     "return a nearest paint bitmap from the receiver picture,
  7317      which must be a depth-8 image. 
  7317      which must be a depth-8 image.
  7318      This is a special-cased dither method for 8-bit palette images being displayed on
  7318      This is a special-cased dither method for 8-bit palette images being displayed on
  7319      an 8-bit pseudoColor display, AND fixColor dithering is used.
  7319      an 8-bit pseudoColor display, AND fixColor dithering is used.
  7320      Use the colors in the fixColors array, which must be fixR x fixG x fixB
  7320      Use the colors in the fixColors array, which must be fixR x fixG x fixB
  7321      colors assigned to aDevice, such as the preallocated colors of the
  7321      colors assigned to aDevice, such as the preallocated colors of the
  7322      Color class."
  7322      Color class."
  7323 
  7323 
  7324     |pseudoBits  
  7324     |pseudoBits
  7325      fixR    "{Class: SmallInteger }"
  7325      fixR    "{Class: SmallInteger }"
  7326      fixG    "{Class: SmallInteger }"
  7326      fixG    "{Class: SmallInteger }"
  7327      fixB    "{Class: SmallInteger }"
  7327      fixB    "{Class: SmallInteger }"
  7328      fixGfixB 
  7328      fixGfixB
  7329      r       "{Class: SmallInteger }"
  7329      r       "{Class: SmallInteger }"
  7330      g       "{Class: SmallInteger }"
  7330      g       "{Class: SmallInteger }"
  7331      b       "{Class: SmallInteger }"
  7331      b       "{Class: SmallInteger }"
  7332      idx     "{Class: SmallInteger }"
  7332      idx     "{Class: SmallInteger }"
  7333      idMap lastColor 
  7333      idMap lastColor
  7334      clr|
  7334      clr|
  7335 
  7335 
  7336     self depth ~~ 8 ifTrue:[^ nil].
  7336     self depth ~~ 8 ifTrue:[^ nil].
  7337 
  7337 
  7338     photometric == #palette ifTrue:[
  7338     photometric == #palette ifTrue:[
  7396     "Modified: 18.6.1996 / 09:18:09 / cg"
  7396     "Modified: 18.6.1996 / 09:18:09 / cg"
  7397 !
  7397 !
  7398 
  7398 
  7399 nfloydSteinbergDitheredDepth8BitsColors:colors
  7399 nfloydSteinbergDitheredDepth8BitsColors:colors
  7400     "return a floyd-steinberg dithered bitmap from the receiver picture,
  7400     "return a floyd-steinberg dithered bitmap from the receiver picture,
  7401      which must be a depth-8 image. 
  7401      which must be a depth-8 image.
  7402      This method expects an array of colors to be used for dithering
  7402      This method expects an array of colors to be used for dithering
  7403      (which need not be a colorCubes colors)."
  7403      (which need not be a colorCubes colors)."
  7404 
  7404 
  7405     |pseudoBits  
  7405     |pseudoBits
  7406      rgbBytes 
  7406      rgbBytes
  7407      ditherRGBBytes ditherColors
  7407      ditherRGBBytes ditherColors
  7408      w       "{Class: SmallInteger }"
  7408      w       "{Class: SmallInteger }"
  7409      h       "{Class: SmallInteger }"
  7409      h       "{Class: SmallInteger }"
  7410      index   "{Class: SmallInteger }"
  7410      index   "{Class: SmallInteger }"
  7411      numR    "{Class: SmallInteger }"
  7411      numR    "{Class: SmallInteger }"
  7427      dG  "{Class: SmallInteger }"
  7427      dG  "{Class: SmallInteger }"
  7428      dB  "{Class: SmallInteger }"
  7428      dB  "{Class: SmallInteger }"
  7429      iR    "{Class: SmallInteger }"
  7429      iR    "{Class: SmallInteger }"
  7430      iRG   "{Class: SmallInteger }"
  7430      iRG   "{Class: SmallInteger }"
  7431      iRGB  "{Class: SmallInteger }"
  7431      iRGB  "{Class: SmallInteger }"
  7432      clr 
  7432      clr
  7433      rI  "{Class: SmallInteger }"
  7433      rI  "{Class: SmallInteger }"
  7434      gI  "{Class: SmallInteger }"
  7434      gI  "{Class: SmallInteger }"
  7435      bI  "{Class: SmallInteger }"
  7435      bI  "{Class: SmallInteger }"
  7436      maxIDX  "{Class: SmallInteger }"
  7436      maxIDX  "{Class: SmallInteger }"
  7437      subCubeColorCollection
  7437      subCubeColorCollection
  7438      error 
  7438      error
  7439      dl "{Class: SmallInteger }"|
  7439      dl "{Class: SmallInteger }"|
  7440 
  7440 
  7441     self depth ~~ 8 ifTrue:[^ nil].
  7441     self depth ~~ 8 ifTrue:[^ nil].
  7442 
  7442 
  7443     "/
  7443     "/
  7535 "/    cube keysAndValuesDo:[:i :indices |
  7535 "/    cube keysAndValuesDo:[:i :indices |
  7536 "/        indices notNil ifTrue:[
  7536 "/        indices notNil ifTrue:[
  7537 "/            nCube at:i put:(indices asByteArray)
  7537 "/            nCube at:i put:(indices asByteArray)
  7538 "/        ] ifFalse:[
  7538 "/        ] ifFalse:[
  7539 "/            "/ find nearest color
  7539 "/            "/ find nearest color
  7540 "/        
  7540 "/
  7541 "/            dl := 1.
  7541 "/            dl := 1.
  7542 "/            [dl < maxBits] whileTrue:[
  7542 "/            [dl < maxBits] whileTrue:[
  7543 "/                dR := dl negated.
  7543 "/                dR := dl negated.
  7544 "/                [dR <= dl] whileTrue:[
  7544 "/                [dR <= dl] whileTrue:[
  7545 "/                    iR := i + (dR * shR).
  7545 "/                    iR := i + (dR * shR).
  7546 "/                    (iR > 0 and:[iR < maxIDX]) ifTrue:[    
  7546 "/                    (iR > 0 and:[iR < maxIDX]) ifTrue:[
  7547 "/                        dG := dl negated.
  7547 "/                        dG := dl negated.
  7548 "/                        [dG < dl] whileTrue:[
  7548 "/                        [dG < dl] whileTrue:[
  7549 "/                            iRG := iR + (dG * shG).
  7549 "/                            iRG := iR + (dG * shG).
  7550 "/                            (iRG > 0 and:[iRG < maxIDX]) ifTrue:[
  7550 "/                            (iRG > 0 and:[iRG < maxIDX]) ifTrue:[
  7551 "/                                dB := dl negated.
  7551 "/                                dB := dl negated.
  7570 "/        ]
  7570 "/        ]
  7571 "/    ].
  7571 "/    ].
  7572 "/self halt.
  7572 "/self halt.
  7573 
  7573 
  7574     "/ now, cube contains collections of colors which are
  7574     "/ now, cube contains collections of colors which are
  7575     "/ positioned in a subCube; quickly accessed by a lookup 
  7575     "/ positioned in a subCube; quickly accessed by a lookup
  7576 
  7576 
  7577     pseudoBits := ByteArray uninitializedNew:(width * height).
  7577     pseudoBits := ByteArray uninitializedNew:(width * height).
  7578 
  7578 
  7579     w := width.
  7579     w := width.
  7580     h := height.
  7580     h := height.
  7648 		int tR, tG, tB;
  7648 		int tR, tG, tB;
  7649 		int nR, nG, nB;
  7649 		int nR, nG, nB;
  7650 		int __dR, __dG, __dB;
  7650 		int __dR, __dG, __dB;
  7651 		int minDelta, bestIdx;
  7651 		int minDelta, bestIdx;
  7652 		int __iR, __iG, __iB;
  7652 		int __iR, __iG, __iB;
  7653 		int cR, cG, cB;   
  7653 		int cR, cG, cB;
  7654 		int delta;
  7654 		int delta;
  7655 		OBJ subCubeColors;
  7655 		OBJ subCubeColors;
  7656 
  7656 
  7657 		pix = *srcP++;
  7657 		pix = *srcP++;
  7658 
  7658 
  7806 #endif
  7806 #endif
  7807 		} else {
  7807 		} else {
  7808 #ifdef REMEMBER_SEARCH
  7808 #ifdef REMEMBER_SEARCH
  7809 		    if (__isSmallInteger(subCubeColors)) {
  7809 		    if (__isSmallInteger(subCubeColors)) {
  7810 			bestIdx = __intVal(subCubeColors);
  7810 			bestIdx = __intVal(subCubeColors);
  7811 		    } else 
  7811 		    } else
  7812 #endif
  7812 #endif
  7813 		    {
  7813 		    {
  7814 			bestIdx = __ByteArrayInstPtr(subCubeColors)->ba_element[0];
  7814 			bestIdx = __ByteArrayInstPtr(subCubeColors)->ba_element[0];
  7815 		    }
  7815 		    }
  7816 		}
  7816 		}
  7817                 
  7817 
  7818 		/*
  7818 		/*
  7819 		 * ok, now, we have found a collection of nearby
  7819 		 * ok, now, we have found a collection of nearby
  7820 		 * colors in subCubeColors.
  7820 		 * colors in subCubeColors.
  7821 		 *
  7821 		 *
  7822 		 * since the error is at most 1/16 (i.e. roughly 6%),
  7822 		 * since the error is at most 1/16 (i.e. roughly 6%),
  7841 		    __dB = dp[2];
  7841 		    __dB = dp[2];
  7842 		}
  7842 		}
  7843 #endif
  7843 #endif
  7844 
  7844 
  7845 /*
  7845 /*
  7846 printf("want: %d/%d/%d (%d/%d/%d) got: %d/%d/%d\n",
  7846 console_printf("want: %d/%d/%d (%d/%d/%d) got: %d/%d/%d\n",
  7847 		__wantR, __wantG, __wantB,
  7847 		__wantR, __wantG, __wantB,
  7848 		__wR, __wG, __wB,
  7848 		__wR, __wG, __wB,
  7849 		__dR, __dG, __dB);
  7849 		__dR, __dG, __dB);
  7850 */
  7850 */
  7851 		/*
  7851 		/*
  7855 
  7855 
  7856 #ifndef NO_FLOYD_STEINBERG
  7856 #ifndef NO_FLOYD_STEINBERG
  7857 		/*
  7857 		/*
  7858 		 * the new error & distribute the error
  7858 		 * the new error & distribute the error
  7859 		 */
  7859 		 */
  7860 		__eR = __wantR - __dR; 
  7860 		__eR = __wantR - __dR;
  7861 		if (__eR) {
  7861 		if (__eR) {
  7862 		    tR = __eR >> 4;  /* 16th of error */
  7862 		    tR = __eR >> 4;  /* 16th of error */
  7863 		    nR = eP[3] + (tR * 7);/* from accu: error for (x+1 / y) */
  7863 		    nR = eP[3] + (tR * 7);/* from accu: error for (x+1 / y) */
  7864 		    eP[0] = tR*5;         /* 5/16th for (x / y+1) */
  7864 		    eP[0] = tR*5;         /* 5/16th for (x / y+1) */
  7865 		    eP[-3] = tR*3;        /* 3/16th for (x-1 / y+1) */
  7865 		    eP[-3] = tR*3;        /* 3/16th for (x-1 / y+1) */
  7881 		} else {
  7881 		} else {
  7882 		    __eG = eP[4];
  7882 		    __eG = eP[4];
  7883 		    eP[1] = eP[-2] = eP[4] = 0;
  7883 		    eP[1] = eP[-2] = eP[4] = 0;
  7884 		}
  7884 		}
  7885 
  7885 
  7886 		__eB = __wantB - __dB; 
  7886 		__eB = __wantB - __dB;
  7887 		if (__eB) {
  7887 		if (__eB) {
  7888 		    tB = __eB >> 4;
  7888 		    tB = __eB >> 4;
  7889 		    nB = eP[5] + (tB * 7);
  7889 		    nB = eP[5] + (tB * 7);
  7890 		    eP[2] = tB*5;
  7890 		    eP[2] = tB*5;
  7891 		    eP[-1] = tB*3;
  7891 		    eP[-1] = tB*3;
  7941 !
  7941 !
  7942 
  7942 
  7943 orderedDitheredGrayBitsWithDitherMatrix:ditherMatrix ditherWidth:dW depth:depth
  7943 orderedDitheredGrayBitsWithDitherMatrix:ditherMatrix ditherWidth:dW depth:depth
  7944     "return the bitmap for a dithered depth-bitmap from the image;
  7944     "return the bitmap for a dithered depth-bitmap from the image;
  7945      with a constant ditherMatrix, this can be used for thresholding.
  7945      with a constant ditherMatrix, this can be used for thresholding.
  7946      Works for any source depths / photometric, 
  7946      Works for any source depths / photometric,
  7947      but very very slow since each pixel is processed individually.
  7947      but very very slow since each pixel is processed individually.
  7948      Redefined by some subclasses for more performance (D8Image)"
  7948      Redefined by some subclasses for more performance (D8Image)"
  7949 
  7949 
  7950     |dH nDither   
  7950     |dH nDither
  7951      greyLevels greyValues greyPixels greyErrors
  7951      greyLevels greyValues greyPixels greyErrors
  7952      dstIndex        "{Class: SmallInteger }"
  7952      dstIndex        "{Class: SmallInteger }"
  7953      nextDst         
  7953      nextDst
  7954      bytesPerOutRow  "{Class: SmallInteger }"
  7954      bytesPerOutRow  "{Class: SmallInteger }"
  7955      pixelsPerByte   "{Class: SmallInteger }"
  7955      pixelsPerByte   "{Class: SmallInteger }"
  7956      outBits
  7956      outBits
  7957      w               "{Class: SmallInteger }"
  7957      w               "{Class: SmallInteger }"
  7958      h               "{Class: SmallInteger }"
  7958      h               "{Class: SmallInteger }"
  8015 
  8015 
  8016 		__pixel = __greyPixels[__value];
  8016 		__pixel = __greyPixels[__value];
  8017 		__grey = __greyErrors[__value];
  8017 		__grey = __greyErrors[__value];
  8018 
  8018 
  8019 		__dT = __ByteArrayInstPtr(ditherMatrix)
  8019 		__dT = __ByteArrayInstPtr(ditherMatrix)
  8020 			    ->ba_element[__intVal(x) % __dW 
  8020 			    ->ba_element[__intVal(x) % __dW
  8021 					 + (__intVal(y) % __intVal(dH)) * __dW];
  8021 					 + (__intVal(y) % __intVal(dH)) * __dW];
  8022 
  8022 
  8023 		if (__grey > __dT) {
  8023 		if (__grey > __dT) {
  8024 		    __pixel++;
  8024 		    __pixel++;
  8025 		}
  8025 		}
  8054 	    byte := 0.
  8054 	    byte := 0.
  8055 	    bitCnt := 8.
  8055 	    bitCnt := 8.
  8056 
  8056 
  8057 	    "/ this is the representaion independent (but slow)
  8057 	    "/ this is the representaion independent (but slow)
  8058 	    "/ inner loop - it extracts colors from the receiver
  8058 	    "/ inner loop - it extracts colors from the receiver
  8059             
  8059 
  8060 	    self colorsAtY:y from:0 to:(w-1) do:[:x :clr |
  8060 	    self colorsAtY:y from:0 to:(w-1) do:[:x :clr |
  8061 		|dstClr grey dT pixel|
  8061 		|dstClr grey dT pixel|
  8062 
  8062 
  8063 		"/ get the colors grey value [0 .. 1]
  8063 		"/ get the colors grey value [0 .. 1]
  8064 		grey := clr brightness.
  8064 		grey := clr brightness.
  8065 
  8065 
  8066 		"/ remap into [0 .. greyLevels-1]
  8066 		"/ remap into [0 .. greyLevels-1]
  8067 		grey := grey * (greyLevels-1).
  8067 		grey := grey * (greyLevels-1).
  8068             
  8068 
  8069 		"/ get threshold pixel [0 .. greyLevels-1]
  8069 		"/ get threshold pixel [0 .. greyLevels-1]
  8070 
  8070 
  8071 		pixel := grey truncated.  
  8071 		pixel := grey truncated.
  8072 
  8072 
  8073 		"/ compute the error [0..1]
  8073 		"/ compute the error [0..1]
  8074 		grey := grey - pixel.
  8074 		grey := grey - pixel.
  8075 
  8075 
  8076 		"/ map into dither space [0 .. nDither]
  8076 		"/ map into dither space [0 .. nDither]
  8083 		int __dstIdx;
  8083 		int __dstIdx;
  8084 		int __pixel;
  8084 		int __pixel;
  8085 		int __bitCnt = __intVal(bitCnt);
  8085 		int __bitCnt = __intVal(bitCnt);
  8086 
  8086 
  8087 		__dT = __ByteArrayInstPtr(ditherMatrix)
  8087 		__dT = __ByteArrayInstPtr(ditherMatrix)
  8088 			    ->ba_element[__intVal(x) % __dW 
  8088 			    ->ba_element[__intVal(x) % __dW
  8089 					 + (__intVal(y) % __intVal(dH)) * __dW];
  8089 					 + (__intVal(y) % __intVal(dH)) * __dW];
  8090 
  8090 
  8091 		__pixel = __intVal(pixel);
  8091 		__pixel = __intVal(pixel);
  8092 
  8092 
  8093 		if (__intVal(grey) > __dT) {
  8093 		if (__intVal(grey) > __dT) {
  8094 		    __pixel++;
  8094 		    __pixel++;
  8095 		}
  8095 		}
  8096 		__byte = (__byte << __intVal(depth)) | __pixel;
  8096 		__byte = (__byte << __intVal(depth)) | __pixel;
  8097             
  8097 
  8098 		__bitCnt = __bitCnt - __intVal(depth);
  8098 		__bitCnt = __bitCnt - __intVal(depth);
  8099 		if (__bitCnt == 0) {
  8099 		if (__bitCnt == 0) {
  8100 		    __dstIdx = __intVal(dstIndex);
  8100 		    __dstIdx = __intVal(dstIndex);
  8101 		    __ByteArrayInstPtr(outBits)->ba_element[__dstIdx-1] = __byte;
  8101 		    __ByteArrayInstPtr(outBits)->ba_element[__dstIdx-1] = __byte;
  8102 		    __dstIdx = __dstIdx + 1;
  8102 		    __dstIdx = __dstIdx + 1;
  8132 !
  8132 !
  8133 
  8133 
  8134 orderedDitheredMonochromeBitsWithDitherMatrix:ditherMatrix ditherWidth:dW
  8134 orderedDitheredMonochromeBitsWithDitherMatrix:ditherMatrix ditherWidth:dW
  8135     "return the bitmap for a dithered monochrome bitmap from the image;
  8135     "return the bitmap for a dithered monochrome bitmap from the image;
  8136      with a constant ditherMatrix, this can be used for thresholding.
  8136      with a constant ditherMatrix, this can be used for thresholding.
  8137      Works for any source depths / photometric, 
  8137      Works for any source depths / photometric,
  8138      but very very slow since each pixel is processed individually.
  8138      but very very slow since each pixel is processed individually.
  8139      Redefined by some subclasses for more performance (D8Image)"
  8139      Redefined by some subclasses for more performance (D8Image)"
  8140 
  8140 
  8141     |dH nDither   
  8141     |dH nDither
  8142      greyValues
  8142      greyValues
  8143      dstIndex        "{Class: SmallInteger }"
  8143      dstIndex        "{Class: SmallInteger }"
  8144      nextDst         "{Class: SmallInteger }"
  8144      nextDst         "{Class: SmallInteger }"
  8145      bytesPerMonoRow "{Class: SmallInteger }"
  8145      bytesPerMonoRow "{Class: SmallInteger }"
  8146      monoBits
  8146      monoBits
  8181 		unsigned char *__greyValues = __ByteArrayInstPtr(greyValues)->ba_element;
  8181 		unsigned char *__greyValues = __ByteArrayInstPtr(greyValues)->ba_element;
  8182 
  8182 
  8183 		__grey = __greyValues[__intVal(value)];
  8183 		__grey = __greyValues[__intVal(value)];
  8184 
  8184 
  8185 		__dT = __ByteArrayInstPtr(ditherMatrix)
  8185 		__dT = __ByteArrayInstPtr(ditherMatrix)
  8186 			    ->ba_element[__intVal(x) % __dW 
  8186 			    ->ba_element[__intVal(x) % __dW
  8187 					 + (__intVal(y) % __intVal(dH)) * __dW];
  8187 					 + (__intVal(y) % __intVal(dH)) * __dW];
  8188 
  8188 
  8189 		__byte = __byte << 1;
  8189 		__byte = __byte << 1;
  8190 		if (__grey > __dT) {
  8190 		if (__grey > __dT) {
  8191 		    __byte = __byte | 1;            /* white */
  8191 		    __byte = __byte | 1;            /* white */
  8232 		int __dT;
  8232 		int __dT;
  8233 		int __dstIdx;
  8233 		int __dstIdx;
  8234 		int __bitCnt = __intVal(bitCnt);
  8234 		int __bitCnt = __intVal(bitCnt);
  8235 
  8235 
  8236 		__dT = __ByteArrayInstPtr(ditherMatrix)
  8236 		__dT = __ByteArrayInstPtr(ditherMatrix)
  8237 			    ->ba_element[__intVal(x) % __dW 
  8237 			    ->ba_element[__intVal(x) % __dW
  8238 					 + (__intVal(y) % __intVal(dH)) * __dW];
  8238 					 + (__intVal(y) % __intVal(dH)) * __dW];
  8239 
  8239 
  8240 		__byte = __byte << 1;
  8240 		__byte = __byte << 1;
  8241 		if (__intVal(grey) > __dT) {
  8241 		if (__intVal(grey) > __dT) {
  8242 		    __byte = __byte | 1;            /* white */
  8242 		    __byte = __byte | 1;            /* white */
  8254 		bitCnt = __MKSMALLINT(__bitCnt);
  8254 		bitCnt = __MKSMALLINT(__bitCnt);
  8255 %}.
  8255 %}.
  8256 		0
  8256 		0
  8257 
  8257 
  8258 "/                dT := ditherMatrix at:(x \\ dW) + (y \\ dH * dW) + 1.
  8258 "/                dT := ditherMatrix at:(x \\ dW) + (y \\ dH * dW) + 1.
  8259 "/     
  8259 "/
  8260 "/                byte := byte bitShift:1.
  8260 "/                byte := byte bitShift:1.
  8261 "/                grey < dT ifTrue:[
  8261 "/                grey < dT ifTrue:[
  8262 "/                    byte := byte bitOr:1.
  8262 "/                    byte := byte bitOr:1.
  8263 "/                ].
  8263 "/                ].
  8264 "/                bitCnt := bitCnt - 1.
  8264 "/                bitCnt := bitCnt - 1.
  8292      errorArray1 errorArray2 errorArray3
  8292      errorArray1 errorArray2 errorArray3
  8293      e t
  8293      e t
  8294      w               "{Class: SmallInteger }"
  8294      w               "{Class: SmallInteger }"
  8295      h               "{Class: SmallInteger }"
  8295      h               "{Class: SmallInteger }"
  8296      bitCnt          "{Class: SmallInteger }"
  8296      bitCnt          "{Class: SmallInteger }"
  8297      byte            "{Class: SmallInteger }" 
  8297      byte            "{Class: SmallInteger }"
  8298      grey
  8298      grey
  8299      xE              "{Class: SmallInteger }" |
  8299      xE              "{Class: SmallInteger }" |
  8300 
  8300 
  8301     self depth > 12 ifTrue:[
  8301     self depth > 12 ifTrue:[
  8302 	^ self floydSteinbergDitheredMonochromeBits
  8302 	^ self floydSteinbergDitheredMonochromeBits
  8317 
  8317 
  8318     "/ fetch scaled brightness values outside of loop into a table;
  8318     "/ fetch scaled brightness values outside of loop into a table;
  8319     "/ use table-value in loop
  8319     "/ use table-value in loop
  8320 
  8320 
  8321     greyValues := self greyMapForRange:(255 * 1024).
  8321     greyValues := self greyMapForRange:(255 * 1024).
  8322     
  8322 
  8323     0 to:(h-1) do:[:y |
  8323     0 to:(h-1) do:[:y |
  8324 	nextDst := dstIndex + bytesPerMonoRow.
  8324 	nextDst := dstIndex + bytesPerMonoRow.
  8325 	byte := 0.
  8325 	byte := 0.
  8326 	bitCnt := 8.
  8326 	bitCnt := 8.
  8327 
  8327 
  8427     "draw a rectangle with some pixel value.
  8427     "draw a rectangle with some pixel value.
  8428      By using #atImageAndMask:put: it also works on images with mono masks."
  8428      By using #atImageAndMask:put: it also works on images with mono masks."
  8429 
  8429 
  8430     |xI "{ Class: SmallInteger }"
  8430     |xI "{ Class: SmallInteger }"
  8431      yI "{ Class: SmallInteger }"
  8431      yI "{ Class: SmallInteger }"
  8432      wI "{ Class: SmallInteger }" 
  8432      wI "{ Class: SmallInteger }"
  8433      hI "{ Class: SmallInteger }"|
  8433      hI "{ Class: SmallInteger }"|
  8434 
  8434 
  8435     xI := aRectangle left.
  8435     xI := aRectangle left.
  8436     yI := aRectangle top.
  8436     yI := aRectangle top.
  8437     wI := aRectangle width.
  8437     wI := aRectangle width.
  8453     "draw a rectangle with some pixel value.
  8453     "draw a rectangle with some pixel value.
  8454     By using #atImageAndMask:put: it also works on images with mono masks."
  8454     By using #atImageAndMask:put: it also works on images with mono masks."
  8455 
  8455 
  8456     |xI "{ Class: SmallInteger }"
  8456     |xI "{ Class: SmallInteger }"
  8457      yI "{ Class: SmallInteger }"
  8457      yI "{ Class: SmallInteger }"
  8458      wI "{ Class: SmallInteger }" 
  8458      wI "{ Class: SmallInteger }"
  8459      hI "{ Class: SmallInteger }"|
  8459      hI "{ Class: SmallInteger }"|
  8460 
  8460 
  8461     xI := aRectangle left.
  8461     xI := aRectangle left.
  8462     yI := aRectangle top.
  8462     yI := aRectangle top.
  8463     wI := aRectangle width.
  8463     wI := aRectangle width.
  8482     "fill a rectangular area with some pixel value.
  8482     "fill a rectangular area with some pixel value.
  8483      May be redefined in concrete subclasses for more performance, if req'd."
  8483      May be redefined in concrete subclasses for more performance, if req'd."
  8484 
  8484 
  8485     |xI "{ Class: SmallInteger }"
  8485     |xI "{ Class: SmallInteger }"
  8486      yI "{ Class: SmallInteger }"
  8486      yI "{ Class: SmallInteger }"
  8487      wI "{ Class: SmallInteger }" 
  8487      wI "{ Class: SmallInteger }"
  8488      hI "{ Class: SmallInteger }"|
  8488      hI "{ Class: SmallInteger }"|
  8489 
  8489 
  8490     xI := x.
  8490     xI := x.
  8491     yI := y.
  8491     yI := y.
  8492     wI := w.
  8492     wI := w.
  8511      toDo idx pixel w h|
  8511      toDo idx pixel w h|
  8512 
  8512 
  8513     w := self width.
  8513     w := self width.
  8514     h := self height.
  8514     h := self height.
  8515 
  8515 
  8516     surroundingPixelsOfDo := 
  8516     surroundingPixelsOfDo :=
  8517         [:pX :pY :fn |
  8517 	[:pX :pY :fn |
  8518             |nX nY|
  8518 	    |nX nY|
  8519 
  8519 
  8520             nX := pX + 1.
  8520 	    nX := pX + 1.
  8521             nY := pY + 1.
  8521 	    nY := pY + 1.
  8522             (nY < h) ifTrue: [fn value:pX value:nY].
  8522 	    (nY < h) ifTrue: [fn value:pX value:nY].
  8523             (pY > 0) ifTrue: [fn value:pX value:(pY - 1)].
  8523 	    (pY > 0) ifTrue: [fn value:pX value:(pY - 1)].
  8524             (nX < w) ifTrue: [fn value:nX value:pY].
  8524 	    (nX < w) ifTrue: [fn value:nX value:pY].
  8525             (pX > 0) ifTrue: [fn value:(pX - 1) value:pY].
  8525 	    (pX > 0) ifTrue: [fn value:(pX - 1) value:pY].
  8526         ].
  8526 	].
  8527 
  8527 
  8528     enumerateDetectedPixelsAndDo := 
  8528     enumerateDetectedPixelsAndDo :=
  8529         [:detectedPixels :action |
  8529 	[:detectedPixels :action |
  8530             |idx|
  8530 	    |idx|
  8531 
  8531 
  8532             idx := 1.
  8532 	    idx := 1.
  8533             0 to:h-1 do:[:y |
  8533 	    0 to:h-1 do:[:y |
  8534                 0 to:w-1 do:[:x |
  8534 		0 to:w-1 do:[:x |
  8535                     (detectedPixels at:idx) ifTrue:[ 
  8535 		    (detectedPixels at:idx) ifTrue:[
  8536                         action value:x value:y
  8536 			action value:x value:y
  8537                     ].
  8537 		    ].
  8538                     idx := idx + 1.
  8538 		    idx := idx + 1.
  8539                 ].
  8539 		].
  8540             ].
  8540 	    ].
  8541         ].
  8541 	].
  8542 
  8542 
  8543     processPixelToFill := [:spX :spY |
  8543     processPixelToFill := [:spX :spY |
  8544             |sp idx|
  8544 	    |sp idx|
  8545 
  8545 
  8546             ((self pixelAtX:spX y:spY) == detectedPixel and: [mask isNil or:[(mask pixelAtX:spX y:spY) == 1]])
  8546 	    ((self pixelAtX:spX y:spY) == detectedPixel and: [mask isNil or:[(mask pixelAtX:spX y:spY) == 1]])
  8547             ifTrue: [
  8547 	    ifTrue: [
  8548                 idx := 1 + spX + (spY * w).
  8548 		idx := 1 + spX + (spY * w).
  8549                 (allDetectedPixelCoordinates at:idx) ifFalse:[
  8549 		(allDetectedPixelCoordinates at:idx) ifFalse:[
  8550                     allDetectedPixelCoordinates at:idx put:true.
  8550 		    allDetectedPixelCoordinates at:idx put:true.
  8551                     toDo add:spX @ spY.
  8551 		    toDo add:spX @ spY.
  8552                 ].
  8552 		].
  8553             ]
  8553 	    ]
  8554         ].
  8554 	].
  8555 
  8555 
  8556     (mask notNil and: [(mask pixelAt:aPoint) == 0]) ifTrue:[
  8556     (mask notNil and: [(mask pixelAt:aPoint) == 0]) ifTrue:[
  8557         allDetectedPixelCoordinates := mask floodFillAt: aPoint withColor: Color white.
  8557 	allDetectedPixelCoordinates := mask floodFillAt: aPoint withColor: Color white.
  8558         enumerateDetectedPixelsAndDo
  8558 	enumerateDetectedPixelsAndDo
  8559                 value:allDetectedPixelCoordinates
  8559 		value:allDetectedPixelCoordinates
  8560                 value:[:x :y | self atImageAndMask:(x@y) put: aColor].
  8560 		value:[:x :y | self atImageAndMask:(x@y) put: aColor].
  8561         ^ allDetectedPixelCoordinates
  8561 	^ allDetectedPixelCoordinates
  8562     ].
  8562     ].
  8563 
  8563 
  8564     detectedPixel := self pixelAt: aPoint.
  8564     detectedPixel := self pixelAt: aPoint.
  8565 
  8565 
  8566     allDetectedPixelCoordinates := BooleanArray new:(w * h). 
  8566     allDetectedPixelCoordinates := BooleanArray new:(w * h).
  8567     toDo := OrderedCollection new:1000.
  8567     toDo := OrderedCollection new:1000.
  8568     allDetectedPixelCoordinates at:(1 + aPoint x + (aPoint y * w)) put:true.
  8568     allDetectedPixelCoordinates at:(1 + aPoint x + (aPoint y * w)) put:true.
  8569     toDo add:aPoint.
  8569     toDo add:aPoint.
  8570 
  8570 
  8571     [toDo notEmpty] whileTrue:[
  8571     [toDo notEmpty] whileTrue:[
  8572         |p|
  8572 	|p|
  8573 
  8573 
  8574         p := toDo removeFirst.
  8574 	p := toDo removeFirst.
  8575         surroundingPixelsOfDo value:p x value:p y value:processPixelToFill.
  8575 	surroundingPixelsOfDo value:p x value:p y value:processPixelToFill.
  8576     ].
  8576     ].
  8577 
  8577 
  8578     idx := 1.
  8578     idx := 1.
  8579     aColor redByte notNil ifTrue:[
  8579     aColor redByte notNil ifTrue:[
  8580         pixel := self valueFromColor:aColor.
  8580 	pixel := self valueFromColor:aColor.
  8581     ].
  8581     ].
  8582 
  8582 
  8583     pixel isNil ifTrue:[
  8583     pixel isNil ifTrue:[
  8584         enumerateDetectedPixelsAndDo
  8584 	enumerateDetectedPixelsAndDo
  8585                 value:allDetectedPixelCoordinates
  8585 		value:allDetectedPixelCoordinates
  8586                 value:[:x :y | mask pixelAtX:x y:y put:0].
  8586 		value:[:x :y | mask pixelAtX:x y:y put:0].
  8587     ] ifFalse:[
  8587     ] ifFalse:[
  8588         enumerateDetectedPixelsAndDo
  8588 	enumerateDetectedPixelsAndDo
  8589                 value:allDetectedPixelCoordinates
  8589 		value:allDetectedPixelCoordinates
  8590                 value:[:x :y | self pixelAtX:x y:y put:pixel].
  8590 		value:[:x :y | self pixelAtX:x y:y put:pixel].
  8591     ].
  8591     ].
  8592     ^ allDetectedPixelCoordinates
  8592     ^ allDetectedPixelCoordinates
  8593 
  8593 
  8594     "Modified: / 29.7.1998 / 03:09:16 / cg"
  8594     "Modified: / 29.7.1998 / 03:09:16 / cg"
  8595 !
  8595 !
  8657      yR|
  8657      yR|
  8658 
  8658 
  8659     yS := yStart.
  8659     yS := yStart.
  8660     yE := yEnd.
  8660     yE := yEnd.
  8661 
  8661 
  8662     yS to:yE do:[:yRun |    
  8662     yS to:yE do:[:yRun |
  8663 	yR := yRun.
  8663 	yR := yRun.
  8664 	self colorsAtY:yRun from:xStart to:xEnd do:[:xRun :color |
  8664 	self colorsAtY:yRun from:xStart to:xEnd do:[:xRun :color |
  8665 	    aBlock value:xRun value:yR value:color 
  8665 	    aBlock value:xRun value:yR value:color
  8666 	]
  8666 	]
  8667     ]
  8667     ]
  8668 
  8668 
  8669     "Modified: 11.7.1996 / 19:50:47 / cg"
  8669     "Modified: 11.7.1996 / 19:50:47 / cg"
  8670 !
  8670 !
  8680 
  8680 
  8681     "Modified: 7.6.1996 / 19:11:06 / cg"
  8681     "Modified: 7.6.1996 / 19:11:06 / cg"
  8682 !
  8682 !
  8683 
  8683 
  8684 valuesAtY:y from:x1 to:x2 do:aBlock
  8684 valuesAtY:y from:x1 to:x2 do:aBlock
  8685     "WARNING: for now, this enumerates pixel values 
  8685     "WARNING: for now, this enumerates pixel values
  8686      (backward compatibility with ST/X)
  8686      (backward compatibility with ST/X)
  8687      In the future, this will enumerate colors 
  8687      In the future, this will enumerate colors
  8688      Use #pixelAtT:from:to:do: - for future compatibility.
  8688      Use #pixelAtT:from:to:do: - for future compatibility.
  8689 
  8689 
  8690      perform aBlock for each pixelValue from x1 to x2 in row y.
  8690      perform aBlock for each pixelValue from x1 to x2 in row y.
  8691      Notice, that x and y coordinates start at 0@0 for the upper left corner.
  8691      Notice, that x and y coordinates start at 0@0 for the upper left corner.
  8692      The block is passed the x coordinate and the pixelValue at each pixel.
  8692      The block is passed the x coordinate and the pixelValue at each pixel.
  8719     |xS "{Class: SmallInteger }"
  8719     |xS "{Class: SmallInteger }"
  8720      xE "{Class: SmallInteger }"|
  8720      xE "{Class: SmallInteger }"|
  8721 
  8721 
  8722     xS := xStart.
  8722     xS := xStart.
  8723     xE := xEnd.
  8723     xE := xEnd.
  8724     yStart to:yEnd do:[:yRun |    
  8724     yStart to:yEnd do:[:yRun |
  8725 	self valuesAtY:yRun from:xStart to:xEnd do:[:xRun :pixel |
  8725 	self valuesAtY:yRun from:xStart to:xEnd do:[:xRun :pixel |
  8726 	    aBlock value:xRun value:yRun value:pixel
  8726 	    aBlock value:xRun value:yRun value:pixel
  8727 	]
  8727 	]
  8728     ]
  8728     ]
  8729 
  8729 
  8743     "some Image has been collected - nothing to do"
  8743     "some Image has been collected - nothing to do"
  8744 ! !
  8744 ! !
  8745 
  8745 
  8746 !Image methodsFor:'image manipulations'!
  8746 !Image methodsFor:'image manipulations'!
  8747 
  8747 
  8748 applyPixelValuesTo:pixelFunctionBlock in:aRectangle into:newImage 
  8748 applyPixelValuesTo:pixelFunctionBlock in:aRectangle into:newImage
  8749     "helper for withPixelFunctionAppliedToValues:
  8749     "helper for withPixelFunctionAppliedToValues:
  8750      enumerate pixelValues and evaluate the block for each.
  8750      enumerate pixelValues and evaluate the block for each.
  8751      Could be redefined by subclasses for better performance."
  8751      Could be redefined by subclasses for better performance."
  8752 
  8752 
  8753     |w   "{Class: SmallInteger }"
  8753     |w   "{Class: SmallInteger }"
  8805 
  8805 
  8806 applyPixelValuesTo:pixelFunctionBlock into:newImage
  8806 applyPixelValuesTo:pixelFunctionBlock into:newImage
  8807     "helper for withPixelFunctionAppliedToValues:
  8807     "helper for withPixelFunctionAppliedToValues:
  8808      enumerate pixelValues and evaluate the block for each."
  8808      enumerate pixelValues and evaluate the block for each."
  8809 
  8809 
  8810     ^ self 
  8810     ^ self
  8811 	applyPixelValuesTo:pixelFunctionBlock 
  8811 	applyPixelValuesTo:pixelFunctionBlock
  8812 	in:(0@0 corner:width@height) 
  8812 	in:(0@0 corner:width@height)
  8813 	into:newImage
  8813 	into:newImage
  8814 !
  8814 !
  8815 
  8815 
  8816 blendWith:aColor
  8816 blendWith:aColor
  8817     "return a new image which is blended with some color.
  8817     "return a new image which is blended with some color.
  8818      The receiver must be a palette image (currently).
  8818      The receiver must be a palette image (currently).
  8819      CAVEAT: this only works with palette images (i.e. not for rgb or greyScale).
  8819      CAVEAT: this only works with palette images (i.e. not for rgb or greyScale).
  8820      CAVEAT: Need an argument, which specifies by how much it should be lighter."
  8820      CAVEAT: Need an argument, which specifies by how much it should be lighter."
  8821 
  8821 
  8822      ^ self 
  8822      ^ self
  8823 	copyWithColorMapProcessing:[:clr | clr blendWith:aColor]
  8823 	copyWithColorMapProcessing:[:clr | clr blendWith:aColor]
  8824 
  8824 
  8825     "
  8825     "
  8826      (Smalltalk bitmapFromFileNamed:'gifImages/claus.gif' inPackage:'stx:goodies') inspect
  8826      (Smalltalk bitmapFromFileNamed:'gifImages/claus.gif' inPackage:'stx:goodies') inspect
  8827      ((Smalltalk bitmapFromFileNamed:'gifImages/claus.gif' inPackage:'stx:goodies') blendWith:Color red) inspect
  8827      ((Smalltalk bitmapFromFileNamed:'gifImages/claus.gif' inPackage:'stx:goodies') blendWith:Color red) inspect
  8832     "Modified: 24.4.1997 / 18:31:23 / cg"
  8832     "Modified: 24.4.1997 / 18:31:23 / cg"
  8833 !
  8833 !
  8834 
  8834 
  8835 colorMapProcessing:aBlock
  8835 colorMapProcessing:aBlock
  8836     "a helper for all kinds of colormap manipulations.
  8836     "a helper for all kinds of colormap manipulations.
  8837      The argument, aBlock is called for every colormap entry, 
  8837      The argument, aBlock is called for every colormap entry,
  8838      and the returned value will replace the original entry in the map.
  8838      and the returned value will replace the original entry in the map.
  8839      This will fail for non-palette images.
  8839      This will fail for non-palette images.
  8840      See examples in Image>>copyWithColorMapProcessing:"
  8840      See examples in Image>>copyWithColorMapProcessing:"
  8841 
  8841 
  8842     |nColors "{ Class: SmallInteger }"|
  8842     |nColors "{ Class: SmallInteger }"|
  8870      CAVEAT: this only works with palette images (i.e. not for rgb or greyScale)"
  8870      CAVEAT: this only works with palette images (i.e. not for rgb or greyScale)"
  8871 
  8871 
  8872     |newImage|
  8872     |newImage|
  8873 
  8873 
  8874     self colorMap isNil ifTrue:[
  8874     self colorMap isNil ifTrue:[
  8875         ^ self withPixelFunctionApplied:[:orig :clr :x :y | aBlock  value:clr]
  8875 	^ self withPixelFunctionApplied:[:orig :clr :x :y | aBlock  value:clr]
  8876 "/        self error:'no colormap in image'.
  8876 "/        self error:'no colormap in image'.
  8877 "/        ^ nil
  8877 "/        ^ nil
  8878     ].
  8878     ].
  8879 
  8879 
  8880     "
  8880     "
  8886     ^ newImage
  8886     ^ newImage
  8887 
  8887 
  8888     "
  8888     "
  8889      leave red component only:
  8889      leave red component only:
  8890 
  8890 
  8891      (Image fromFile:'goodies/bitmaps/gifImages/claus.gif') 
  8891      (Image fromFile:'goodies/bitmaps/gifImages/claus.gif')
  8892         copyWithColorMapProcessing:[:clr | Color red:(clr red) green:0 blue:0] 
  8892 	copyWithColorMapProcessing:[:clr | Color red:(clr red) green:0 blue:0]
  8893     "
  8893     "
  8894 
  8894 
  8895     "
  8895     "
  8896      make it reddish:
  8896      make it reddish:
  8897 
  8897 
  8898      (Image fromFile:'bitmaps/gifImages/claus.gif') 
  8898      (Image fromFile:'bitmaps/gifImages/claus.gif')
  8899         copyWithColorMapProcessing:[:clr | Color red:((clr red * 2) min:100) green:clr green blue:clr blue] 
  8899 	copyWithColorMapProcessing:[:clr | Color red:((clr red * 2) min:100) green:clr green blue:clr blue]
  8900     "
  8900     "
  8901 
  8901 
  8902     "
  8902     "
  8903      invert:
  8903      invert:
  8904 
  8904 
  8905      (Image fromFile:'bitmaps/gifImages/claus.gif') 
  8905      (Image fromFile:'bitmaps/gifImages/claus.gif')
  8906         copyWithColorMapProcessing:[:clr | Color red:(100 - clr red) green:(100 - clr green) blue:(100 - clr green)] 
  8906 	copyWithColorMapProcessing:[:clr | Color red:(100 - clr red) green:(100 - clr green) blue:(100 - clr green)]
  8907     "
  8907     "
  8908 
  8908 
  8909     "
  8909     "
  8910      lighter:
  8910      lighter:
  8911 
  8911 
  8912      (Image fromFile:'bitmaps/gifImages/claus.gif') 
  8912      (Image fromFile:'bitmaps/gifImages/claus.gif')
  8913         copyWithColorMapProcessing:[:clr | |r g b|
  8913 	copyWithColorMapProcessing:[:clr | |r g b|
  8914                                                 r := clr red.  g := clr green.  b := clr blue.
  8914 						r := clr red.  g := clr green.  b := clr blue.
  8915                                                 Color red:(r + (100-r//2)) 
  8915 						Color red:(r + (100-r//2))
  8916                                                       green:(g + (100-g//2)) 
  8916 						      green:(g + (100-g//2))
  8917                                                       blue:(b + (100-b//2))]
  8917 						      blue:(b + (100-b//2))]
  8918     "
  8918     "
  8919 
  8919 
  8920     "
  8920     "
  8921      darker:
  8921      darker:
  8922 
  8922 
  8923      (Image fromFile:'bitmaps/gifImages/claus.gif') 
  8923      (Image fromFile:'bitmaps/gifImages/claus.gif')
  8924         copyWithColorMapProcessing:[:clr | Color red:(clr red//2) green:(clr green // 2) blue:(clr blue // 2)] 
  8924 	copyWithColorMapProcessing:[:clr | Color red:(clr red//2) green:(clr green // 2) blue:(clr blue // 2)]
  8925     "
  8925     "
  8926 
  8926 
  8927     "Modified: 24.4.1997 / 18:28:05 / cg"
  8927     "Modified: 24.4.1997 / 18:28:05 / cg"
  8928 !
  8928 !
  8929 
  8929 
  8941     "return a new image which is slightly darker than the receiver.
  8941     "return a new image which is slightly darker than the receiver.
  8942      The receiver must be a palette image (currently).
  8942      The receiver must be a palette image (currently).
  8943      CAVEAT: this only works with palette images (i.e. not for rgb or greyScale).
  8943      CAVEAT: this only works with palette images (i.e. not for rgb or greyScale).
  8944      CAVEAT: Need an argument, which specifies by how much it should be darker."
  8944      CAVEAT: Need an argument, which specifies by how much it should be darker."
  8945 
  8945 
  8946      ^ self 
  8946      ^ self
  8947 	copyWithColorMapProcessing:[:clr | clr darkened]
  8947 	copyWithColorMapProcessing:[:clr | clr darkened]
  8948 
  8948 
  8949     "
  8949     "
  8950      (Smalltalk bitmapFromFileNamed:'gifImages/claus.gif' inPackage:'stx:goodies') inspect
  8950      (Smalltalk bitmapFromFileNamed:'gifImages/claus.gif' inPackage:'stx:goodies') inspect
  8951      (Smalltalk bitmapFromFileNamed:'gifImages/claus.gif' inPackage:'stx:goodies') darkened inspect
  8951      (Smalltalk bitmapFromFileNamed:'gifImages/claus.gif' inPackage:'stx:goodies') darkened inspect
  9037 flipVertical
  9037 flipVertical
  9038     "inplace vertical flip"
  9038     "inplace vertical flip"
  9039 
  9039 
  9040     |h           "{Class: SmallInteger }"
  9040     |h           "{Class: SmallInteger }"
  9041      bytesPerRow "{Class: SmallInteger }"
  9041      bytesPerRow "{Class: SmallInteger }"
  9042      buffer 
  9042      buffer
  9043      indexLow    "{Class: SmallInteger }"
  9043      indexLow    "{Class: SmallInteger }"
  9044      indexHi     "{Class: SmallInteger }"
  9044      indexHi     "{Class: SmallInteger }"
  9045      bytes|
  9045      bytes|
  9046 
  9046 
  9047     bytes := self bits.
  9047     bytes := self bits.
  9088 hardMagnifiedBy:scalePoint
  9088 hardMagnifiedBy:scalePoint
  9089     "return a new image magnified by scalePoint, aPoint.
  9089     "return a new image magnified by scalePoint, aPoint.
  9090      This is the general magnification method, handling non-integral values.
  9090      This is the general magnification method, handling non-integral values.
  9091      It is slower than the integral magnification method."
  9091      It is slower than the integral magnification method."
  9092 
  9092 
  9093     |mX        
  9093     |mX
  9094      mY        
  9094      mY
  9095      newWidth  "{ Class: SmallInteger }"
  9095      newWidth  "{ Class: SmallInteger }"
  9096      newHeight "{ Class: SmallInteger }"
  9096      newHeight "{ Class: SmallInteger }"
  9097      w         "{ Class: SmallInteger }"
  9097      w         "{ Class: SmallInteger }"
  9098      h         "{ Class: SmallInteger }"
  9098      h         "{ Class: SmallInteger }"
  9099      newImage newBits bitsPerPixel newBytesPerRow newMask
  9099      newImage newBits bitsPerPixel newBytesPerRow newMask
  9100      value 
  9100      value
  9101      srcRow pixelArray|
  9101      srcRow pixelArray|
  9102 
  9102 
  9103     mX := scalePoint x.
  9103     mX := scalePoint x.
  9104     mY := scalePoint y.
  9104     mY := scalePoint y.
  9105     ((mX < 0) or:[mY < 0]) ifTrue:[^ nil].
  9105     ((mX < 0) or:[mY < 0]) ifTrue:[^ nil].
  9115     mask notNil ifTrue:[
  9115     mask notNil ifTrue:[
  9116 	newMask := (mask magnifiedBy:scalePoint)
  9116 	newMask := (mask magnifiedBy:scalePoint)
  9117     ].
  9117     ].
  9118 
  9118 
  9119     newImage := self species new.
  9119     newImage := self species new.
  9120     newImage 
  9120     newImage
  9121 	width:newWidth 
  9121 	width:newWidth
  9122 	height:newHeight 
  9122 	height:newHeight
  9123 	photometric:photometric 
  9123 	photometric:photometric
  9124 	samplesPerPixel:samplesPerPixel 
  9124 	samplesPerPixel:samplesPerPixel
  9125 	bitsPerSample:bitsPerSample 
  9125 	bitsPerSample:bitsPerSample
  9126 	colorMap:colorMap copy
  9126 	colorMap:colorMap copy
  9127 	bits:newBits
  9127 	bits:newBits
  9128 	mask:newMask.
  9128 	mask:newMask.
  9129 
  9129 
  9130     "walk over destination image fetching pixels from source image"
  9130     "walk over destination image fetching pixels from source image"
  9156     "Modified: 24.4.1997 / 18:30:24 / cg"
  9156     "Modified: 24.4.1997 / 18:30:24 / cg"
  9157 !
  9157 !
  9158 
  9158 
  9159 hardRotated:degrees
  9159 hardRotated:degrees
  9160     "return a new image from the old one, by rotating the image
  9160     "return a new image from the old one, by rotating the image
  9161      degrees clockwise. 
  9161      degrees clockwise.
  9162      Warning: the returned image will be larger than the original image."
  9162      Warning: the returned image will be larger than the original image."
  9163 
  9163 
  9164     |p r a aN p1 p2 p3 p4 maxX minX maxY minY
  9164     |p r a aN p1 p2 p3 p4 maxX minX maxY minY
  9165      newImage 
  9165      newImage
  9166      newWidth  "{ Class: SmallInteger }"
  9166      newWidth  "{ Class: SmallInteger }"
  9167      newHeight "{ Class: SmallInteger }"
  9167      newHeight "{ Class: SmallInteger }"
  9168      newBytesPerRow newBits
  9168      newBytesPerRow newBits
  9169      blackPixel halfW halfH radians m t bad
  9169      blackPixel halfW halfH radians m t bad
  9170      bytesPerRow myDepth maskBits
  9170      bytesPerRow myDepth maskBits
  9171      pX pY srcX srcY pix nX nY 
  9171      pX pY srcX srcY pix nX nY
  9172      sinRot cosRot sinPY cosPY|
  9172      sinRot cosRot sinPY cosPY|
  9173 
  9173 
  9174     radians := degrees degreesToRadians.
  9174     radians := degrees degreesToRadians.
  9175 
  9175 
  9176     "/ placing the image at the origin,
  9176     "/ placing the image at the origin,
  9178 
  9178 
  9179     p := (width - 1 / 2) @ (height - 1 / 2).
  9179     p := (width - 1 / 2) @ (height - 1 / 2).
  9180     r := p r.
  9180     r := p r.
  9181     a := p theta.
  9181     a := p theta.
  9182 
  9182 
  9183     "/ add the rotation 
  9183     "/ add the rotation
  9184     "/ (sight - subtract, we defined things clockwise ... 
  9184     "/ (sight - subtract, we defined things clockwise ...
  9185     "/  ... in contrast to point which thinks counter-clockwise)
  9185     "/  ... in contrast to point which thinks counter-clockwise)
  9186 
  9186 
  9187     aN := a - radians.
  9187     aN := a - radians.
  9188 
  9188 
  9189     "/ compute new corner points
  9189     "/ compute new corner points
  9194 
  9194 
  9195     "/ compute the boundary of the new image
  9195     "/ compute the boundary of the new image
  9196 
  9196 
  9197     maxX := minX := p1 x.
  9197     maxX := minX := p1 x.
  9198     (t := p2 x) > maxX ifTrue:[
  9198     (t := p2 x) > maxX ifTrue:[
  9199         maxX := t
  9199 	maxX := t
  9200     ] ifFalse:[
  9200     ] ifFalse:[
  9201         t < minX ifTrue:[minX := t].
  9201 	t < minX ifTrue:[minX := t].
  9202     ].
  9202     ].
  9203     (t := p3 x) > maxX ifTrue:[
  9203     (t := p3 x) > maxX ifTrue:[
  9204         maxX := t
  9204 	maxX := t
  9205     ] ifFalse:[
  9205     ] ifFalse:[
  9206         t < minX ifTrue:[minX := t].
  9206 	t < minX ifTrue:[minX := t].
  9207     ].
  9207     ].
  9208     (t := p4 x) > maxX ifTrue:[
  9208     (t := p4 x) > maxX ifTrue:[
  9209         maxX := t
  9209 	maxX := t
  9210     ] ifFalse:[
  9210     ] ifFalse:[
  9211         t < minX ifTrue:[minX := t].
  9211 	t < minX ifTrue:[minX := t].
  9212     ].
  9212     ].
  9213 
  9213 
  9214     maxY := minY := p1 y.
  9214     maxY := minY := p1 y.
  9215     (t := p2 y) > maxY ifTrue:[
  9215     (t := p2 y) > maxY ifTrue:[
  9216         maxY := t
  9216 	maxY := t
  9217     ] ifFalse:[
  9217     ] ifFalse:[
  9218         t < minY ifTrue:[minY := t].
  9218 	t < minY ifTrue:[minY := t].
  9219     ].
  9219     ].
  9220     (t := p3 y) > maxY ifTrue:[
  9220     (t := p3 y) > maxY ifTrue:[
  9221         maxY := t
  9221 	maxY := t
  9222     ] ifFalse:[
  9222     ] ifFalse:[
  9223         t < minY ifTrue:[minY := t].
  9223 	t < minY ifTrue:[minY := t].
  9224     ].
  9224     ].
  9225     (t := p4 y) > maxY ifTrue:[
  9225     (t := p4 y) > maxY ifTrue:[
  9226         maxY := t
  9226 	maxY := t
  9227     ] ifFalse:[
  9227     ] ifFalse:[
  9228         t < minY ifTrue:[minY := t].
  9228 	t < minY ifTrue:[minY := t].
  9229     ].
  9229     ].
  9230 
  9230 
  9231 
  9231 
  9232     newWidth := (maxX - minX) rounded + 1.
  9232     newWidth := (maxX - minX) rounded + 1.
  9233     newHeight := (maxY - minY) rounded + 1.
  9233     newHeight := (maxY - minY) rounded + 1.
  9242     newImage samplesPerPixel:samplesPerPixel.
  9242     newImage samplesPerPixel:samplesPerPixel.
  9243     newImage bitsPerSample:bitsPerSample.
  9243     newImage bitsPerSample:bitsPerSample.
  9244     newImage colorMap:colorMap copy.
  9244     newImage colorMap:colorMap copy.
  9245     newImage maskedPixelsAre0:maskedPixelsAre0.
  9245     newImage maskedPixelsAre0:maskedPixelsAre0.
  9246     mask notNil ifTrue:[
  9246     mask notNil ifTrue:[
  9247         newImage mask:(mask rotated:degrees)
  9247 	newImage mask:(mask rotated:degrees)
  9248     ] ifFalse:[
  9248     ] ifFalse:[
  9249         self isMask ifFalse:[
  9249 	self isMask ifFalse:[
  9250             self depth ~~ 1 ifTrue:[
  9250 	    self depth ~~ 1 ifTrue:[
  9251                 m := ImageMask width:width height:height.
  9251 		m := ImageMask width:width height:height.
  9252                 m bits:(maskBits := ByteArray new:(m bytesPerRow * height)).
  9252 		m bits:(maskBits := ByteArray new:(m bytesPerRow * height)).
  9253                 maskBits atAllPut:16rFF.
  9253 		maskBits atAllPut:16rFF.
  9254                 newImage mask:(m rotated:degrees)
  9254 		newImage mask:(m rotated:degrees)
  9255             ]
  9255 	    ]
  9256         ]
  9256 	]
  9257     ].
  9257     ].
  9258 
  9258 
  9259     maskedPixelsAre0 ifTrue:[
  9259     maskedPixelsAre0 ifTrue:[
  9260         blackPixel := 0.
  9260 	blackPixel := 0.
  9261     ] ifFalse:[
  9261     ] ifFalse:[
  9262         blackPixel := self valueFromColor:Color black.
  9262 	blackPixel := self valueFromColor:Color black.
  9263         blackPixel isNil ifTrue:[
  9263 	blackPixel isNil ifTrue:[
  9264             blackPixel := self valueFromColor:Color white.
  9264 	    blackPixel := self valueFromColor:Color white.
  9265             blackPixel isNil ifTrue:[
  9265 	    blackPixel isNil ifTrue:[
  9266                 blackPixel := 0.
  9266 		blackPixel := 0.
  9267             ]
  9267 	    ]
  9268         ]
  9268 	]
  9269     ].
  9269     ].
  9270     self isMask ifTrue:[
  9270     self isMask ifTrue:[
  9271         blackPixel := 0.
  9271 	blackPixel := 0.
  9272     ].
  9272     ].
  9273 
  9273 
  9274     myDepth := self depth.
  9274     myDepth := self depth.
  9275     newBits atAllPut:0.
  9275     newBits atAllPut:0.
  9276 
  9276 
  9277     "/ now, walk over destination pixels,
  9277     "/ now, walk over destination pixels,
  9278     "/ fetching from source. 
  9278     "/ fetching from source.
  9279     "/ (if we walked over the source, we could get holes
  9279     "/ (if we walked over the source, we could get holes
  9280     "/  in the destination image ...)
  9280     "/  in the destination image ...)
  9281 
  9281 
  9282     halfW := (width - 1) / 2.0.
  9282     halfW := (width - 1) / 2.0.
  9283     halfH := (height - 1) / 2.0.
  9283     halfH := (height - 1) / 2.0.
  9303     double sin(), cos();
  9303     double sin(), cos();
  9304 #   define Float_PI 3.14159
  9304 #   define Float_PI 3.14159
  9305 
  9305 
  9306     bad = true;
  9306     bad = true;
  9307     if (1
  9307     if (1
  9308      && __isFloat(minX) 
  9308      && __isFloat(minX)
  9309      && __isFloat(minY)
  9309      && __isFloat(minY)
  9310      && __isFloat(radians)
  9310      && __isFloat(radians)
  9311      && __isFloat(halfW)
  9311      && __isFloat(halfW)
  9312      && __isFloat(halfH)
  9312      && __isFloat(halfH)
  9313      && __isByteArray(newBits)
  9313      && __isByteArray(newBits)
  9314      && __isByteArray(__INST(bytes))) {
  9314      && __isByteArray(__INST(bytes))) {
  9315         __srcBytes = __ByteArrayInstPtr(__INST(bytes))->ba_element;
  9315 	__srcBytes = __ByteArrayInstPtr(__INST(bytes))->ba_element;
  9316         __dstBytes = __ByteArrayInstPtr(newBits)->ba_element;
  9316 	__dstBytes = __ByteArrayInstPtr(newBits)->ba_element;
  9317         __nSrcBytes = __byteArraySize(__INST(bytes));
  9317 	__nSrcBytes = __byteArraySize(__INST(bytes));
  9318         __nDstBytes = __byteArraySize(newBits);
  9318 	__nDstBytes = __byteArraySize(newBits);
  9319         __blackPixel = __intVal(blackPixel);
  9319 	__blackPixel = __intVal(blackPixel);
  9320 
  9320 
  9321         __radians = __floatVal(radians);
  9321 	__radians = __floatVal(radians);
  9322         __radians = -__radians; /* sigh: clock-wise */
  9322 	__radians = -__radians; /* sigh: clock-wise */
  9323         __sin = sin(__radians);
  9323 	__sin = sin(__radians);
  9324         __cos = cos(__radians);
  9324 	__cos = cos(__radians);
  9325         __minX = __floatVal(minX);
  9325 	__minX = __floatVal(minX);
  9326         __minY = __floatVal(minY);
  9326 	__minY = __floatVal(minY);
  9327         __halfW = __floatVal(halfW);
  9327 	__halfW = __floatVal(halfW);
  9328         __halfH = __floatVal(halfH);
  9328 	__halfH = __floatVal(halfH);
  9329 
  9329 
  9330         __dstRowPtr = __dstBytes;
  9330 	__dstRowPtr = __dstBytes;
  9331         __dstEndPtr = __dstBytes + __nDstBytes;
  9331 	__dstEndPtr = __dstBytes + __nDstBytes;
  9332 
  9332 
  9333 #       define EARLY_OUT
  9333 #       define EARLY_OUT
  9334 #       define FAST_ADVANCE 5
  9334 #       define FAST_ADVANCE 5
  9335 #       define FAST_ADVANCE2
  9335 #       define FAST_ADVANCE2
  9336 
  9336 
  9337         switch (__depth) {
  9337 	switch (__depth) {
  9338             case 8:
  9338 	    case 8:
  9339                 for (__dstY = 0; __dstY < __newHeight; __dstY++) {
  9339 		for (__dstY = 0; __dstY < __newHeight; __dstY++) {
  9340                     double __pY, __sinPY, __cosPY;
  9340 		    double __pY, __sinPY, __cosPY;
  9341 #ifdef EARLY_OUT
  9341 #ifdef EARLY_OUT
  9342                     int didFetchInRow = 0;
  9342 		    int didFetchInRow = 0;
  9343 #endif
  9343 #endif
  9344                     __pY = (double)(__dstY + __minY);
  9344 		    __pY = (double)(__dstY + __minY);
  9345 
  9345 
  9346                     __sinPY = __sin * __pY;
  9346 		    __sinPY = __sin * __pY;
  9347                     __cosPY = __cos * __pY;
  9347 		    __cosPY = __cos * __pY;
  9348 
  9348 
  9349                     __dstPtr = __dstRowPtr;
  9349 		    __dstPtr = __dstRowPtr;
  9350                     __dstRowPtr += __dstBytesPerRow;
  9350 		    __dstRowPtr += __dstBytesPerRow;
  9351 
  9351 
  9352                     for (__dstX = 0; __dstX < __newWidth; __dstX++) {
  9352 		    for (__dstX = 0; __dstX < __newWidth; __dstX++) {
  9353                         double __pX, __nX;
  9353 			double __pX, __nX;
  9354                         unsigned __pix;
  9354 			unsigned __pix;
  9355 
  9355 
  9356                         /* translate X in destination (center to 0/0) */
  9356 			/* translate X in destination (center to 0/0) */
  9357                         __pX = (double)(__dstX + __minX);
  9357 			__pX = (double)(__dstX + __minX);
  9358                         /* rotate X */
  9358 			/* rotate X */
  9359                         __nX = (__cos * __pX) - __sinPY;
  9359 			__nX = (__cos * __pX) - __sinPY;
  9360 
  9360 
  9361                         /* translate X in source (origin to 0/0) */
  9361 			/* translate X in source (origin to 0/0) */
  9362                         __nX = __nX + __halfW + 0.5;
  9362 			__nX = __nX + __halfW + 0.5;
  9363 
  9363 
  9364                         /* inside ? */
  9364 			/* inside ? */
  9365                         if (__nX < 0) {
  9365 			if (__nX < 0) {
  9366 #ifdef EARLY_OUT
  9366 #ifdef EARLY_OUT
  9367                             if (didFetchInRow) {
  9367 			    if (didFetchInRow) {
  9368                                 break;
  9368 				break;
  9369                             }
  9369 			    }
  9370 #endif
  9370 #endif
  9371 #ifdef FAST_ADVANCE
  9371 #ifdef FAST_ADVANCE
  9372                             if (__blackPixel == 0) {
  9372 			    if (__blackPixel == 0) {
  9373                                 do {
  9373 				do {
  9374                                     /* try advance by FAST_ADVANCE pixels ... */
  9374 				    /* try advance by FAST_ADVANCE pixels ... */
  9375                                     __dstX += FAST_ADVANCE; __dstPtr += FAST_ADVANCE;
  9375 				    __dstX += FAST_ADVANCE; __dstPtr += FAST_ADVANCE;
  9376                                     if (__dstX >= __newWidth) {
  9376 				    if (__dstX >= __newWidth) {
  9377                                         break;
  9377 					break;
  9378                                     }
  9378 				    }
  9379                                     __pX = (double)(__dstX + __minX);
  9379 				    __pX = (double)(__dstX + __minX);
  9380                                     __nX = (__cos * __pX) - __sinPY;
  9380 				    __nX = (__cos * __pX) - __sinPY;
  9381                                     __nX = __nX + __halfW + 0.5;
  9381 				    __nX = __nX + __halfW + 0.5;
  9382                                 } while (__nX < 0);
  9382 				} while (__nX < 0);
  9383                                 __dstX -= FAST_ADVANCE; __dstPtr -= FAST_ADVANCE;
  9383 				__dstX -= FAST_ADVANCE; __dstPtr -= FAST_ADVANCE;
  9384                             }
  9384 			    }
  9385 #endif
  9385 #endif
  9386                             __pix = __blackPixel;
  9386 			    __pix = __blackPixel;
  9387                         } else {
  9387 			} else {
  9388                             int __srcX;
  9388 			    int __srcX;
  9389 
  9389 
  9390                             __srcX = (int)__nX;
  9390 			    __srcX = (int)__nX;
  9391                             /* inside ? */
  9391 			    /* inside ? */
  9392                             if (__srcX >= __width) {
  9392 			    if (__srcX >= __width) {
  9393 #ifdef EARLY_OUT
  9393 #ifdef EARLY_OUT
  9394                                 if (didFetchInRow) {
  9394 				if (didFetchInRow) {
  9395                                     break;
  9395 				    break;
  9396                                 }
  9396 				}
  9397 #endif
  9397 #endif
  9398 #ifdef FAST_ADVANCE2
  9398 #ifdef FAST_ADVANCE2
  9399                                 if (__blackPixel == 0) {
  9399 				if (__blackPixel == 0) {
  9400                                     do {
  9400 				    do {
  9401                                         /* try advance by FAST_ADVANCE pixels ... */
  9401 					/* try advance by FAST_ADVANCE pixels ... */
  9402                                         __dstX += FAST_ADVANCE; __dstPtr += FAST_ADVANCE;
  9402 					__dstX += FAST_ADVANCE; __dstPtr += FAST_ADVANCE;
  9403                                         if (__dstX >= __newWidth) {
  9403 					if (__dstX >= __newWidth) {
  9404                                             break;
  9404 					    break;
  9405                                         }
  9405 					}
  9406                                         __pX = (double)(__dstX + __minX);
  9406 					__pX = (double)(__dstX + __minX);
  9407                                         __nX = (__cos * __pX) - __sinPY;
  9407 					__nX = (__cos * __pX) - __sinPY;
  9408                                         __nX = __nX + __halfW + 0.5;
  9408 					__nX = __nX + __halfW + 0.5;
  9409                                         __srcX = (int)__nX;
  9409 					__srcX = (int)__nX;
  9410                                     } while (__srcX >= __width);
  9410 				    } while (__srcX >= __width);
  9411                                     __dstX -= FAST_ADVANCE; __dstPtr -= FAST_ADVANCE;
  9411 				    __dstX -= FAST_ADVANCE; __dstPtr -= FAST_ADVANCE;
  9412                                 }
  9412 				}
  9413 #endif
  9413 #endif
  9414                                 __pix = __blackPixel;
  9414 				__pix = __blackPixel;
  9415                             } else {
  9415 			    } else {
  9416                                 double __nY;
  9416 				double __nY;
  9417 
  9417 
  9418                                 /* rotate Y */
  9418 				/* rotate Y */
  9419                                 __nY = (__sin * __pX) + __cosPY;
  9419 				__nY = (__sin * __pX) + __cosPY;
  9420                                 /* translate Y in source (origin to 0/0) */
  9420 				/* translate Y in source (origin to 0/0) */
  9421                                 __nY = __nY + __halfH + 0.5;
  9421 				__nY = __nY + __halfH + 0.5;
  9422 
  9422 
  9423                                 /* inside ? */
  9423 				/* inside ? */
  9424                                 if (__nY < 0) {
  9424 				if (__nY < 0) {
  9425 #ifdef EARLY_OUT
  9425 #ifdef EARLY_OUT
  9426                                     if (didFetchInRow) {
  9426 				    if (didFetchInRow) {
  9427                                         break;
  9427 					break;
  9428                                     }
  9428 				    }
  9429 #endif
  9429 #endif
  9430 #ifdef FAST_ADVANCE2
  9430 #ifdef FAST_ADVANCE2
  9431                                     if (__blackPixel == 0) {
  9431 				    if (__blackPixel == 0) {
  9432                                         do {
  9432 					do {
  9433                                             /* try advance by FAST_ADVANCE pixels ... */
  9433 					    /* try advance by FAST_ADVANCE pixels ... */
  9434                                             __dstX += FAST_ADVANCE; __dstPtr += FAST_ADVANCE;
  9434 					    __dstX += FAST_ADVANCE; __dstPtr += FAST_ADVANCE;
  9435                                             if (__dstX >= __newWidth) {
  9435 					    if (__dstX >= __newWidth) {
  9436                                                 break;
  9436 						break;
  9437                                             }
  9437 					    }
  9438                                             __pX = (double)(__dstX + __minX);
  9438 					    __pX = (double)(__dstX + __minX);
  9439                                             __nY = (__sin * __pX) + __cosPY;
  9439 					    __nY = (__sin * __pX) + __cosPY;
  9440                                             __nY = __nY + __halfH + 0.5;
  9440 					    __nY = __nY + __halfH + 0.5;
  9441                                         } while (__nY < 0);
  9441 					} while (__nY < 0);
  9442                                         __dstX -= FAST_ADVANCE; __dstPtr -= FAST_ADVANCE;
  9442 					__dstX -= FAST_ADVANCE; __dstPtr -= FAST_ADVANCE;
  9443                                     }
  9443 				    }
  9444 #endif
  9444 #endif
  9445                                     __pix = __blackPixel;
  9445 				    __pix = __blackPixel;
  9446                                 } else {
  9446 				} else {
  9447                                     int __srcY;
  9447 				    int __srcY;
  9448 
  9448 
  9449                                     __srcY = (int)__nY;
  9449 				    __srcY = (int)__nY;
  9450                                     /* inside ? */
  9450 				    /* inside ? */
  9451                                     if (__srcY >= __height) {
  9451 				    if (__srcY >= __height) {
  9452 #ifdef EARLY_OUT
  9452 #ifdef EARLY_OUT
  9453                                         if (didFetchInRow) {
  9453 					if (didFetchInRow) {
  9454                                             break;
  9454 					    break;
  9455                                         }
  9455 					}
  9456 #endif
  9456 #endif
  9457 #ifdef FAST_ADVANCE
  9457 #ifdef FAST_ADVANCE
  9458                                         if (__blackPixel == 0) {
  9458 					if (__blackPixel == 0) {
  9459                                             do {
  9459 					    do {
  9460                                                 /* try advance by FAST_ADVANCE pixels ... */
  9460 						/* try advance by FAST_ADVANCE pixels ... */
  9461                                                 __dstX += FAST_ADVANCE; __dstPtr += FAST_ADVANCE;
  9461 						__dstX += FAST_ADVANCE; __dstPtr += FAST_ADVANCE;
  9462                                                 if (__dstX >= __newWidth) {
  9462 						if (__dstX >= __newWidth) {
  9463                                                     break;
  9463 						    break;
  9464                                                 }
  9464 						}
  9465                                                 __pX = (double)(__dstX + __minX);
  9465 						__pX = (double)(__dstX + __minX);
  9466                                                 __nY = (__sin * __pX) + __cosPY;
  9466 						__nY = (__sin * __pX) + __cosPY;
  9467                                                 __nY = __nY + __halfH + 0.5;
  9467 						__nY = __nY + __halfH + 0.5;
  9468                                                 __srcY = (int)__nY;
  9468 						__srcY = (int)__nY;
  9469                                             } while (__srcY >= __height);
  9469 					    } while (__srcY >= __height);
  9470                                             __dstX -= FAST_ADVANCE; __dstPtr -= FAST_ADVANCE;
  9470 					    __dstX -= FAST_ADVANCE; __dstPtr -= FAST_ADVANCE;
  9471                                         }
  9471 					}
  9472 #endif
  9472 #endif
  9473                                         __pix = __blackPixel;
  9473 					__pix = __blackPixel;
  9474                                     } else {
  9474 				    } else {
  9475                                         /* fetch source pixel */
  9475 					/* fetch source pixel */
  9476 
  9476 
  9477                                         int idx;
  9477 					int idx;
  9478 #ifdef EARLY_OUT
  9478 #ifdef EARLY_OUT
  9479                                         didFetchInRow = 1;
  9479 					didFetchInRow = 1;
  9480 #endif
  9480 #endif
  9481                                         idx = __srcY * __srcBytesPerRow + __srcX;
  9481 					idx = __srcY * __srcBytesPerRow + __srcX;
  9482                                         if ((unsigned)idx < __nSrcBytes) {
  9482 					if ((unsigned)idx < __nSrcBytes) {
  9483                                             __pix = __srcBytes[idx];
  9483 					    __pix = __srcBytes[idx];
  9484                                         } else {
  9484 					} else {
  9485                                             __pix = __blackPixel;
  9485 					    __pix = __blackPixel;
  9486                                         }
  9486 					}
  9487                                     }
  9487 				    }
  9488                                 }
  9488 				}
  9489                             }
  9489 			    }
  9490                         }
  9490 			}
  9491 
  9491 
  9492                         if (__pix != 0) {
  9492 			if (__pix != 0) {
  9493                             *__dstPtr = __pix;
  9493 			    *__dstPtr = __pix;
  9494                         }
  9494 			}
  9495                         __dstPtr++;
  9495 			__dstPtr++;
  9496                     }
  9496 		    }
  9497                 }
  9497 		}
  9498                 break;
  9498 		break;
  9499 
  9499 
  9500             case 1:
  9500 	    case 1:
  9501                 for (__dstY = 0; __dstY < __newHeight; __dstY++) {
  9501 		for (__dstY = 0; __dstY < __newHeight; __dstY++) {
  9502                     double __pY, __sinPY, __cosPY;
  9502 		    double __pY, __sinPY, __cosPY;
  9503 #ifdef EARLY_OUT
  9503 #ifdef EARLY_OUT
  9504                     int didFetchInRow = 0;
  9504 		    int didFetchInRow = 0;
  9505 #endif
  9505 #endif
  9506                     __pY = (double)(__dstY + __minY);
  9506 		    __pY = (double)(__dstY + __minY);
  9507 
  9507 
  9508                     __sinPY = __sin * __pY;
  9508 		    __sinPY = __sin * __pY;
  9509                     __cosPY = __cos * __pY;
  9509 		    __cosPY = __cos * __pY;
  9510 
  9510 
  9511                     __dstPtr = __dstRowPtr;
  9511 		    __dstPtr = __dstRowPtr;
  9512                     __dstMask = 0x80;
  9512 		    __dstMask = 0x80;
  9513                     __dstRowPtr += __dstBytesPerRow;
  9513 		    __dstRowPtr += __dstBytesPerRow;
  9514 
  9514 
  9515                     for (__dstX = 0; __dstX < __newWidth; __dstX++) {
  9515 		    for (__dstX = 0; __dstX < __newWidth; __dstX++) {
  9516                         double __pX, __nX;
  9516 			double __pX, __nX;
  9517                         int __pix;
  9517 			int __pix;
  9518 
  9518 
  9519                         /* translate X in destination (center to 0/0) */
  9519 			/* translate X in destination (center to 0/0) */
  9520                         __pX = (double)(__dstX + __minX);
  9520 			__pX = (double)(__dstX + __minX);
  9521                         /* rotate X */
  9521 			/* rotate X */
  9522                         __nX = (__cos * __pX) - __sinPY;
  9522 			__nX = (__cos * __pX) - __sinPY;
  9523 
  9523 
  9524                         /* translate X in source (origin to 0/0) */
  9524 			/* translate X in source (origin to 0/0) */
  9525                         __nX = __nX + __halfW + 0.5;
  9525 			__nX = __nX + __halfW + 0.5;
  9526 
  9526 
  9527                         /* inside ? */
  9527 			/* inside ? */
  9528                         if (__nX < 0) {
  9528 			if (__nX < 0) {
  9529 #ifdef EARLY_OUT
  9529 #ifdef EARLY_OUT
  9530                             if (didFetchInRow) {
  9530 			    if (didFetchInRow) {
  9531                                 break;
  9531 				break;
  9532                             }
  9532 			    }
  9533 #endif
  9533 #endif
  9534 #ifdef FAST_ADVANCE
  9534 #ifdef FAST_ADVANCE
  9535                             if (__blackPixel == 0) {
  9535 			    if (__blackPixel == 0) {
  9536                                 do {
  9536 				do {
  9537                                     /* try advance by 8 pixels ... */
  9537 				    /* try advance by 8 pixels ... */
  9538                                     __dstX += 8; __dstPtr ++;
  9538 				    __dstX += 8; __dstPtr ++;
  9539                                     if (__dstX >= __newWidth) {
  9539 				    if (__dstX >= __newWidth) {
  9540                                         break;
  9540 					break;
  9541                                     }
  9541 				    }
  9542                                     __pX = (double)(__dstX + __minX);
  9542 				    __pX = (double)(__dstX + __minX);
  9543                                     __nX = (__cos * __pX) - __sinPY;
  9543 				    __nX = (__cos * __pX) - __sinPY;
  9544                                     __nX = __nX + __halfW + 0.5;
  9544 				    __nX = __nX + __halfW + 0.5;
  9545                                 } while (__nX < 0);
  9545 				} while (__nX < 0);
  9546                                 __dstX -= 8; __dstPtr--;
  9546 				__dstX -= 8; __dstPtr--;
  9547                             }
  9547 			    }
  9548 #endif
  9548 #endif
  9549                             __pix = __blackPixel;
  9549 			    __pix = __blackPixel;
  9550                         } else {
  9550 			} else {
  9551                             int __srcX;
  9551 			    int __srcX;
  9552 
  9552 
  9553                             __srcX = (int)__nX;
  9553 			    __srcX = (int)__nX;
  9554                             /* inside ? */
  9554 			    /* inside ? */
  9555                             if (__srcX >= __width) {
  9555 			    if (__srcX >= __width) {
  9556 #ifdef EARLY_OUT
  9556 #ifdef EARLY_OUT
  9557                                 if (didFetchInRow) {
  9557 				if (didFetchInRow) {
  9558                                     break;
  9558 				    break;
  9559                                 }
  9559 				}
  9560 #endif
  9560 #endif
  9561 #ifdef FAST_ADVANCE2
  9561 #ifdef FAST_ADVANCE2
  9562                                 if (__blackPixel == 0) {
  9562 				if (__blackPixel == 0) {
  9563                                     do {
  9563 				    do {
  9564                                         /* try advance by 8 pixels ... */
  9564 					/* try advance by 8 pixels ... */
  9565                                         __dstX += 8; __dstPtr++;
  9565 					__dstX += 8; __dstPtr++;
  9566                                         if (__dstX >= __newWidth) {
  9566 					if (__dstX >= __newWidth) {
  9567                                             break;
  9567 					    break;
  9568                                         }
  9568 					}
  9569                                         __pX = (double)(__dstX + __minX);
  9569 					__pX = (double)(__dstX + __minX);
  9570                                         __nX = (__cos * __pX) - __sinPY;
  9570 					__nX = (__cos * __pX) - __sinPY;
  9571                                         __nX = __nX + __halfW + 0.5;
  9571 					__nX = __nX + __halfW + 0.5;
  9572                                         __srcX = (int)__nX;
  9572 					__srcX = (int)__nX;
  9573                                     } while (__srcX >= __width);
  9573 				    } while (__srcX >= __width);
  9574                                     __dstX -= 8; __dstPtr--;
  9574 				    __dstX -= 8; __dstPtr--;
  9575                                 }
  9575 				}
  9576 #endif
  9576 #endif
  9577                                 __pix = __blackPixel;
  9577 				__pix = __blackPixel;
  9578                             } else {
  9578 			    } else {
  9579                                 double __nY;
  9579 				double __nY;
  9580 
  9580 
  9581                                 /* rotate Y */
  9581 				/* rotate Y */
  9582                                 __nY = (__sin * __pX) + __cosPY;
  9582 				__nY = (__sin * __pX) + __cosPY;
  9583                                 /* translate Y in source (origin to 0/0) */
  9583 				/* translate Y in source (origin to 0/0) */
  9584                                 __nY = __nY + __halfH + 0.5;
  9584 				__nY = __nY + __halfH + 0.5;
  9585 
  9585 
  9586                                 /* inside ? */
  9586 				/* inside ? */
  9587                                 if (__nY < 0) {
  9587 				if (__nY < 0) {
  9588 #ifdef EARLY_OUT
  9588 #ifdef EARLY_OUT
  9589                                     if (didFetchInRow) {
  9589 				    if (didFetchInRow) {
  9590                                         break;
  9590 					break;
  9591                                     }
  9591 				    }
  9592 #endif
  9592 #endif
  9593 #ifdef FAST_ADVANCE2
  9593 #ifdef FAST_ADVANCE2
  9594                                     if (__blackPixel == 0) {
  9594 				    if (__blackPixel == 0) {
  9595                                         do {
  9595 					do {
  9596                                             /* try advance by 8 pixels ... */
  9596 					    /* try advance by 8 pixels ... */
  9597                                             __dstX += 8; __dstPtr++;
  9597 					    __dstX += 8; __dstPtr++;
  9598                                             if (__dstX >= __newWidth) {
  9598 					    if (__dstX >= __newWidth) {
  9599                                                 break;
  9599 						break;
  9600                                             }
  9600 					    }
  9601                                             __pX = (double)(__dstX + __minX);
  9601 					    __pX = (double)(__dstX + __minX);
  9602                                             __nY = (__sin * __pX) + __cosPY;
  9602 					    __nY = (__sin * __pX) + __cosPY;
  9603                                             __nY = __nY + __halfH + 0.5;
  9603 					    __nY = __nY + __halfH + 0.5;
  9604                                         } while (__nY < 0);
  9604 					} while (__nY < 0);
  9605                                         __dstX -= 8; __dstPtr--;
  9605 					__dstX -= 8; __dstPtr--;
  9606                                     }
  9606 				    }
  9607 #endif
  9607 #endif
  9608                                     __pix = __blackPixel;
  9608 				    __pix = __blackPixel;
  9609                                 } else {
  9609 				} else {
  9610                                     int __srcY;
  9610 				    int __srcY;
  9611 
  9611 
  9612                                     __srcY = (int)__nY;
  9612 				    __srcY = (int)__nY;
  9613                                     /* inside ? */
  9613 				    /* inside ? */
  9614                                     if (__srcY >= __height) {
  9614 				    if (__srcY >= __height) {
  9615 #ifdef EARLY_OUT
  9615 #ifdef EARLY_OUT
  9616                                         if (didFetchInRow) {
  9616 					if (didFetchInRow) {
  9617                                             break;
  9617 					    break;
  9618                                         }
  9618 					}
  9619 #endif
  9619 #endif
  9620 #ifdef FAST_ADVANCE
  9620 #ifdef FAST_ADVANCE
  9621                                         if (__blackPixel == 0) {
  9621 					if (__blackPixel == 0) {
  9622                                             do {
  9622 					    do {
  9623                                                 /* try advance by 8 pixels ... */
  9623 						/* try advance by 8 pixels ... */
  9624                                                 __dstX += 8; __dstPtr++;
  9624 						__dstX += 8; __dstPtr++;
  9625                                                 if (__dstX >= __newWidth) {
  9625 						if (__dstX >= __newWidth) {
  9626                                                     break;
  9626 						    break;
  9627                                                 }
  9627 						}
  9628                                                 __pX = (double)(__dstX + __minX);
  9628 						__pX = (double)(__dstX + __minX);
  9629                                                 __nY = (__sin * __pX) + __cosPY;
  9629 						__nY = (__sin * __pX) + __cosPY;
  9630                                                 __nY = __nY + __halfH + 0.5;
  9630 						__nY = __nY + __halfH + 0.5;
  9631                                                 __srcY = (int)__nY;
  9631 						__srcY = (int)__nY;
  9632                                             } while (__srcY >= __height);
  9632 					    } while (__srcY >= __height);
  9633                                             __dstX -= 8; __dstPtr--;
  9633 					    __dstX -= 8; __dstPtr--;
  9634                                         }
  9634 					}
  9635 #endif
  9635 #endif
  9636                                         __pix = __blackPixel;
  9636 					__pix = __blackPixel;
  9637                                     } else {
  9637 				    } else {
  9638                                         /* fetch source pixel */
  9638 					/* fetch source pixel */
  9639 
  9639 
  9640                                         int idx, pV;
  9640 					int idx, pV;
  9641 #ifdef EARLY_OUT
  9641 #ifdef EARLY_OUT
  9642                                         didFetchInRow = 1;
  9642 					didFetchInRow = 1;
  9643 #endif
  9643 #endif
  9644                                         idx = __srcY * __srcBytesPerRow + (__srcX >> 3);
  9644 					idx = __srcY * __srcBytesPerRow + (__srcX >> 3);
  9645                                         if ((unsigned)idx < __nSrcBytes) {
  9645 					if ((unsigned)idx < __nSrcBytes) {
  9646                                             pV = __srcBytes[idx];
  9646 					    pV = __srcBytes[idx];
  9647                                             __pix = (pV & (0x80 >> (__srcX & 7))) ? 1 : 0;
  9647 					    __pix = (pV & (0x80 >> (__srcX & 7))) ? 1 : 0;
  9648                                         } else {
  9648 					} else {
  9649                                             __pix = __blackPixel;
  9649 					    __pix = __blackPixel;
  9650                                         }
  9650 					}
  9651                                     }
  9651 				    }
  9652                                 }
  9652 				}
  9653                             }
  9653 			    }
  9654                         }
  9654 			}
  9655 
  9655 
  9656                         /* store pixel */
  9656 			/* store pixel */
  9657                         if (__pix != 0) {
  9657 			if (__pix != 0) {
  9658                             *__dstPtr |= __dstMask;
  9658 			    *__dstPtr |= __dstMask;
  9659                         }
  9659 			}
  9660                         __dstMask >>= 1;
  9660 			__dstMask >>= 1;
  9661                         if (__dstMask == 0) {
  9661 			if (__dstMask == 0) {
  9662                             __dstMask = 0x80;
  9662 			    __dstMask = 0x80;
  9663                             __dstPtr++;
  9663 			    __dstPtr++;
  9664                         }
  9664 			}
  9665                     }
  9665 		    }
  9666                 }
  9666 		}
  9667                 break;
  9667 		break;
  9668 
  9668 
  9669             case 24:
  9669 	    case 24:
  9670                 for (__dstY = 0; __dstY < __newHeight; __dstY++) {
  9670 		for (__dstY = 0; __dstY < __newHeight; __dstY++) {
  9671                     double __pY, __sinPY, __cosPY;
  9671 		    double __pY, __sinPY, __cosPY;
  9672 #ifdef EARLY_OUT
  9672 #ifdef EARLY_OUT
  9673                     int didFetchInRow = 0;
  9673 		    int didFetchInRow = 0;
  9674 #endif
  9674 #endif
  9675                     __pY = (double)(__dstY + __minY);
  9675 		    __pY = (double)(__dstY + __minY);
  9676 
  9676 
  9677                     __sinPY = __sin * __pY;
  9677 		    __sinPY = __sin * __pY;
  9678                     __cosPY = __cos * __pY;
  9678 		    __cosPY = __cos * __pY;
  9679 
  9679 
  9680                     __dstPtr = __dstRowPtr;
  9680 		    __dstPtr = __dstRowPtr;
  9681                     __dstRowPtr += __dstBytesPerRow;
  9681 		    __dstRowPtr += __dstBytesPerRow;
  9682 
  9682 
  9683                     for (__dstX = 0; __dstX < __newWidth; __dstX++) {
  9683 		    for (__dstX = 0; __dstX < __newWidth; __dstX++) {
  9684                         double __pX, __nX;
  9684 			double __pX, __nX;
  9685                         unsigned __pix;
  9685 			unsigned __pix;
  9686 
  9686 
  9687                         /* translate X in destination (center to 0/0) */
  9687 			/* translate X in destination (center to 0/0) */
  9688                         __pX = (double)(__dstX + __minX);
  9688 			__pX = (double)(__dstX + __minX);
  9689                         /* rotate X */
  9689 			/* rotate X */
  9690                         __nX = (__cos * __pX) - __sinPY;
  9690 			__nX = (__cos * __pX) - __sinPY;
  9691 
  9691 
  9692                         /* translate X in source (origin to 0/0) */
  9692 			/* translate X in source (origin to 0/0) */
  9693                         __nX = __nX + __halfW + 0.5;
  9693 			__nX = __nX + __halfW + 0.5;
  9694 
  9694 
  9695                         /* inside ? */
  9695 			/* inside ? */
  9696                         if (__nX < 0) {
  9696 			if (__nX < 0) {
  9697 #ifdef EARLY_OUT
  9697 #ifdef EARLY_OUT
  9698                             if (didFetchInRow) {
  9698 			    if (didFetchInRow) {
  9699                                 break;
  9699 				break;
  9700                             }
  9700 			    }
  9701 #endif
  9701 #endif
  9702                             __pix = __blackPixel;
  9702 			    __pix = __blackPixel;
  9703                         } else {
  9703 			} else {
  9704                             int __srcX;
  9704 			    int __srcX;
  9705 
  9705 
  9706                             __srcX = (int)__nX;
  9706 			    __srcX = (int)__nX;
  9707                             /* inside ? */
  9707 			    /* inside ? */
  9708                             if (__srcX >= __width) {
  9708 			    if (__srcX >= __width) {
  9709 #ifdef EARLY_OUT
  9709 #ifdef EARLY_OUT
  9710                                 if (didFetchInRow) {
  9710 				if (didFetchInRow) {
  9711                                     break;
  9711 				    break;
  9712                                 }
  9712 				}
  9713 #endif
  9713 #endif
  9714                                 __pix = __blackPixel;
  9714 				__pix = __blackPixel;
  9715                             } else {
  9715 			    } else {
  9716                                 double __nY;
  9716 				double __nY;
  9717 
  9717 
  9718                                 /* rotate Y */
  9718 				/* rotate Y */
  9719                                 __nY = (__sin * __pX) + __cosPY;
  9719 				__nY = (__sin * __pX) + __cosPY;
  9720                                 /* translate Y in source (origin to 0/0) */
  9720 				/* translate Y in source (origin to 0/0) */
  9721                                 __nY = __nY + __halfH + 0.5;
  9721 				__nY = __nY + __halfH + 0.5;
  9722 
  9722 
  9723                                 /* inside ? */
  9723 				/* inside ? */
  9724                                 if (__nY < 0) {
  9724 				if (__nY < 0) {
  9725 #ifdef EARLY_OUT
  9725 #ifdef EARLY_OUT
  9726                                     if (didFetchInRow) {
  9726 				    if (didFetchInRow) {
  9727                                         break;
  9727 					break;
  9728                                     }
  9728 				    }
  9729 #endif
  9729 #endif
  9730                                     __pix = __blackPixel;
  9730 				    __pix = __blackPixel;
  9731                                 } else {
  9731 				} else {
  9732                                     int __srcY;
  9732 				    int __srcY;
  9733 
  9733 
  9734                                     __srcY = (int)__nY;
  9734 				    __srcY = (int)__nY;
  9735                                     /* inside ? */
  9735 				    /* inside ? */
  9736                                     if (__srcY >= __height) {
  9736 				    if (__srcY >= __height) {
  9737 #ifdef EARLY_OUT
  9737 #ifdef EARLY_OUT
  9738                                         if (didFetchInRow) {
  9738 					if (didFetchInRow) {
  9739                                             break;
  9739 					    break;
  9740                                         }
  9740 					}
  9741 #endif
  9741 #endif
  9742                                         __pix = __blackPixel;
  9742 					__pix = __blackPixel;
  9743                                     } else {
  9743 				    } else {
  9744                                         /* fetch source pixel */
  9744 					/* fetch source pixel */
  9745 
  9745 
  9746                                         int idx;
  9746 					int idx;
  9747 #ifdef EARLY_OUT
  9747 #ifdef EARLY_OUT
  9748                                         didFetchInRow = 1;
  9748 					didFetchInRow = 1;
  9749 #endif
  9749 #endif
  9750                                         idx = __srcY * __srcBytesPerRow + __srcX + __srcX + __srcX;
  9750 					idx = __srcY * __srcBytesPerRow + __srcX + __srcX + __srcX;
  9751                                         if ((unsigned)idx < __nSrcBytes) {
  9751 					if ((unsigned)idx < __nSrcBytes) {
  9752                                             __pix = __srcBytes[idx];
  9752 					    __pix = __srcBytes[idx];
  9753                                             __pix = (__pix<<8) | __srcBytes[idx+1];
  9753 					    __pix = (__pix<<8) | __srcBytes[idx+1];
  9754                                             __pix = (__pix<<8) | __srcBytes[idx+2];
  9754 					    __pix = (__pix<<8) | __srcBytes[idx+2];
  9755                                         } else {
  9755 					} else {
  9756                                             __pix = __blackPixel;
  9756 					    __pix = __blackPixel;
  9757                                         }
  9757 					}
  9758                                     }
  9758 				    }
  9759                                 }
  9759 				}
  9760                             }
  9760 			    }
  9761                         }
  9761 			}
  9762 
  9762 
  9763                         /* store pixel */
  9763 			/* store pixel */
  9764                         if (__pix != 0) {
  9764 			if (__pix != 0) {
  9765                             __dstPtr[0] = (__pix >> 16 & 0xFF);
  9765 			    __dstPtr[0] = (__pix >> 16 & 0xFF);
  9766                             __dstPtr[1] = (__pix >> 8) & 0xFF;
  9766 			    __dstPtr[1] = (__pix >> 8) & 0xFF;
  9767                             __dstPtr[2] = __pix & 0xFF;
  9767 			    __dstPtr[2] = __pix & 0xFF;
  9768                         }
  9768 			}
  9769                         __dstPtr += 3;
  9769 			__dstPtr += 3;
  9770                     }
  9770 		    }
  9771                 }
  9771 		}
  9772                 break;
  9772 		break;
  9773 
  9773 
  9774             default:
  9774 	    default:
  9775                 for (__dstY = 0; __dstY < __newHeight; __dstY++) {
  9775 		for (__dstY = 0; __dstY < __newHeight; __dstY++) {
  9776                     double __pY, __sinPY, __cosPY;
  9776 		    double __pY, __sinPY, __cosPY;
  9777 #ifdef EARLY_OUT
  9777 #ifdef EARLY_OUT
  9778                     int didFetchInRow = 0;
  9778 		    int didFetchInRow = 0;
  9779 #endif
  9779 #endif
  9780                     __pY = (double)(__dstY + __minY);
  9780 		    __pY = (double)(__dstY + __minY);
  9781 
  9781 
  9782                     __sinPY = __sin * __pY;
  9782 		    __sinPY = __sin * __pY;
  9783                     __cosPY = __cos * __pY;
  9783 		    __cosPY = __cos * __pY;
  9784 
  9784 
  9785                     __dstPtr = __dstRowPtr;
  9785 		    __dstPtr = __dstRowPtr;
  9786                     __dstMask = 0x80;
  9786 		    __dstMask = 0x80;
  9787                     __dstRowPtr += __dstBytesPerRow;
  9787 		    __dstRowPtr += __dstBytesPerRow;
  9788 
  9788 
  9789                     for (__dstX = 0; __dstX < __newWidth; __dstX++) {
  9789 		    for (__dstX = 0; __dstX < __newWidth; __dstX++) {
  9790                         double __pX, __nX;
  9790 			double __pX, __nX;
  9791                         OBJ __pix;
  9791 			OBJ __pix;
  9792 
  9792 
  9793                         /* translate X in destination (center to 0/0) */
  9793 			/* translate X in destination (center to 0/0) */
  9794                         __pX = (double)(__dstX + __minX);
  9794 			__pX = (double)(__dstX + __minX);
  9795                         /* rotate X */
  9795 			/* rotate X */
  9796                         __nX = (__cos * __pX) - __sinPY;
  9796 			__nX = (__cos * __pX) - __sinPY;
  9797 
  9797 
  9798                         /* translate X in source (origin to 0/0) */
  9798 			/* translate X in source (origin to 0/0) */
  9799                         __nX = __nX + __halfW + 0.5;
  9799 			__nX = __nX + __halfW + 0.5;
  9800 
  9800 
  9801                         /* inside ? */
  9801 			/* inside ? */
  9802                         if (__nX < 0) {
  9802 			if (__nX < 0) {
  9803 #ifdef EARLY_OUT
  9803 #ifdef EARLY_OUT
  9804                             if (didFetchInRow) {
  9804 			    if (didFetchInRow) {
  9805                                 break;
  9805 				break;
  9806                             }
  9806 			    }
  9807 #endif
  9807 #endif
  9808                             __pix = blackPixel;
  9808 			    __pix = blackPixel;
  9809                         } else {
  9809 			} else {
  9810                             int __srcX;
  9810 			    int __srcX;
  9811 
  9811 
  9812                             __srcX = (int)__nX;
  9812 			    __srcX = (int)__nX;
  9813                             /* inside ? */
  9813 			    /* inside ? */
  9814                             if (__srcX >= __width) {
  9814 			    if (__srcX >= __width) {
  9815 #ifdef EARLY_OUT
  9815 #ifdef EARLY_OUT
  9816                                 if (didFetchInRow) {
  9816 				if (didFetchInRow) {
  9817                                     break;
  9817 				    break;
  9818                                 }
  9818 				}
  9819 #endif
  9819 #endif
  9820                                 __pix = blackPixel;
  9820 				__pix = blackPixel;
  9821                             } else {
  9821 			    } else {
  9822                                 double __nY;
  9822 				double __nY;
  9823 
  9823 
  9824                                 /* rotate Y */
  9824 				/* rotate Y */
  9825                                 __nY = (__sin * __pX) + __cosPY;
  9825 				__nY = (__sin * __pX) + __cosPY;
  9826                                 /* translate Y in source (origin to 0/0) */
  9826 				/* translate Y in source (origin to 0/0) */
  9827                                 __nY = __nY + __halfH + 0.5;
  9827 				__nY = __nY + __halfH + 0.5;
  9828 
  9828 
  9829                                 /* inside ? */
  9829 				/* inside ? */
  9830                                 if (__nY < 0) {
  9830 				if (__nY < 0) {
  9831 #ifdef EARLY_OUT
  9831 #ifdef EARLY_OUT
  9832                                     if (didFetchInRow) {
  9832 				    if (didFetchInRow) {
  9833                                         break;
  9833 					break;
  9834                                     }
  9834 				    }
  9835 #endif
  9835 #endif
  9836                                     __pix = blackPixel;
  9836 				    __pix = blackPixel;
  9837                                 } else {
  9837 				} else {
  9838                                     int __srcY;
  9838 				    int __srcY;
  9839 
  9839 
  9840                                     __srcY = (int)__nY;
  9840 				    __srcY = (int)__nY;
  9841                                     /* inside ? */
  9841 				    /* inside ? */
  9842                                     if (__srcY >= __height) {
  9842 				    if (__srcY >= __height) {
  9843 #ifdef EARLY_OUT
  9843 #ifdef EARLY_OUT
  9844                                         if (didFetchInRow) {
  9844 					if (didFetchInRow) {
  9845                                             break;
  9845 					    break;
  9846                                         }
  9846 					}
  9847 #endif
  9847 #endif
  9848                                         __pix = blackPixel;
  9848 					__pix = blackPixel;
  9849                                     } else {
  9849 				    } else {
  9850                                         /* fetch source pixel */
  9850 					/* fetch source pixel */
  9851 
  9851 
  9852                                         static struct inlineCache valAt = _ILC2;
  9852 					static struct inlineCache valAt = _ILC2;
  9853 #ifdef EARLY_OUT
  9853 #ifdef EARLY_OUT
  9854                                         didFetchInRow = 1;
  9854 					didFetchInRow = 1;
  9855 #endif
  9855 #endif
  9856                                         __pix = (*valAt.ilc_func)(self,
  9856 					__pix = (*valAt.ilc_func)(self,
  9857                                                               @symbol(pixelAtX:y:),
  9857 							      @symbol(pixelAtX:y:),
  9858                                                               nil, &valAt,
  9858 							      nil, &valAt,
  9859                                                               __MKSMALLINT(__srcX),
  9859 							      __MKSMALLINT(__srcX),
  9860                                                               __MKSMALLINT(__srcY));
  9860 							      __MKSMALLINT(__srcY));
  9861                                     }
  9861 				    }
  9862                                 }
  9862 				}
  9863                             }
  9863 			    }
  9864                         }
  9864 			}
  9865 
  9865 
  9866                         /* store pixel */
  9866 			/* store pixel */
  9867                         {
  9867 			{
  9868                             static struct inlineCache atPutVal = _ILC3;
  9868 			    static struct inlineCache atPutVal = _ILC3;
  9869 
  9869 
  9870                             if (__pix != __MKSMALLINT(0)) {
  9870 			    if (__pix != __MKSMALLINT(0)) {
  9871                                 (*atPutVal.ilc_func)(newImage,
  9871 				(*atPutVal.ilc_func)(newImage,
  9872                                                       @symbol(pixelAtX:y:put:),
  9872 						      @symbol(pixelAtX:y:put:),
  9873                                                       nil, &atPutVal,
  9873 						      nil, &atPutVal,
  9874                                                       __MKSMALLINT(__dstX),
  9874 						      __MKSMALLINT(__dstX),
  9875                                                       __MKSMALLINT(__dstY),
  9875 						      __MKSMALLINT(__dstY),
  9876                                                       __pix
  9876 						      __pix
  9877                                                      );
  9877 						     );
  9878                             }
  9878 			    }
  9879                         }
  9879 			}
  9880                     }
  9880 		    }
  9881                 }
  9881 		}
  9882                 break;
  9882 		break;
  9883         }
  9883 	}
  9884 
  9884 
  9885         bad = false;
  9885 	bad = false;
  9886     }
  9886     }
  9887 %}.
  9887 %}.
  9888 
  9888 
  9889     bad ifTrue:[
  9889     bad ifTrue:[
  9890         "/ should not happen
  9890 	"/ should not happen
  9891         self primitiveFailed
  9891 	self primitiveFailed
  9892 
  9892 
  9893 "/        sinRot := radians negated sin.
  9893 "/        sinRot := radians negated sin.
  9894 "/        cosRot := radians negated cos.
  9894 "/        cosRot := radians negated cos.
  9895 "/
  9895 "/
  9896 "/        0 to:newHeight-1 do:[:dstY |
  9896 "/        0 to:newHeight-1 do:[:dstY |
  9917 "/
  9917 "/
  9918 "/                    "/ inside ?
  9918 "/                    "/ inside ?
  9919 "/                    (srcY >= 0 and:[srcY < height]) ifTrue:[
  9919 "/                    (srcY >= 0 and:[srcY < height]) ifTrue:[
  9920 "/                        pix := self pixelAtX:srcX y:srcY
  9920 "/                        pix := self pixelAtX:srcX y:srcY
  9921 "/                    ] ifFalse:[
  9921 "/                    ] ifFalse:[
  9922 "/                        pix := blackPixel.        
  9922 "/                        pix := blackPixel.
  9923 "/                    ].
  9923 "/                    ].
  9924 "/                ] ifFalse:[
  9924 "/                ] ifFalse:[
  9925 "/                    pix := blackPixel.        
  9925 "/                    pix := blackPixel.
  9926 "/                ].
  9926 "/                ].
  9927 "/                pix ~~ blackPixel ifTrue:[
  9927 "/                pix ~~ blackPixel ifTrue:[
  9928 "/                    newImage pixelAtX:dstX y:dstY put:pix.        
  9928 "/                    newImage pixelAtX:dstX y:dstY put:pix.
  9929 "/                ]
  9929 "/                ]
  9930 "/            ].
  9930 "/            ].
  9931 "/        ].
  9931 "/        ].
  9932     ].
  9932     ].
  9933 
  9933 
  9953     "
  9953     "
  9954      |i|
  9954      |i|
  9955 
  9955 
  9956      i := Smalltalk imageFromFileNamed:'bitmaps/gifImages/garfield.gif' inPackage:'stx:goodies'.
  9956      i := Smalltalk imageFromFileNamed:'bitmaps/gifImages/garfield.gif' inPackage:'stx:goodies'.
  9957      Transcript showCR:(
  9957      Transcript showCR:(
  9958         Time millisecondsToRun:[
  9958 	Time millisecondsToRun:[
  9959            i rotated:45.
  9959 	   i rotated:45.
  9960         ]
  9960 	]
  9961      ).
  9961      ).
  9962     "
  9962     "
  9963     "
  9963     "
  9964      |v i rI rot|
  9964      |v i rI rot|
  9965 
  9965 
  9966      i := Smalltalk imageFromFileNamed:'bitmaps/xpmBitmaps/misc_icons/BOOK.xpm' inPackage:'stx:goodies'.
  9966      i := Smalltalk imageFromFileNamed:'bitmaps/xpmBitmaps/misc_icons/BOOK.xpm' inPackage:'stx:goodies'.
  9967      v := View new extent:(i width max:100)@(i height max:100).
  9967      v := View new extent:(i width max:100)@(i height max:100).
  9968      v openAndWait.
  9968      v openAndWait.
  9969      rot := 0.
  9969      rot := 0.
  9970      [true] whileTrue:[
  9970      [true] whileTrue:[
  9971         rI := i rotated:rot.
  9971 	rI := i rotated:rot.
  9972         rI := rI onDevice:v device.
  9972 	rI := rI onDevice:v device.
  9973         v clear.
  9973 	v clear.
  9974         v displayForm:rI x:v width//2-(rI width//2) y:v height//2-(rI height // 2).
  9974 	v displayForm:rI x:v width//2-(rI width//2) y:v height//2-(rI height // 2).
  9975         rot := rot + 5.
  9975 	rot := rot + 5.
  9976         rI close.
  9976 	rI close.
  9977      ]
  9977      ]
  9978     "
  9978     "
  9979     "
  9979     "
  9980      |v i rI rot|
  9980      |v i rI rot|
  9981 
  9981 
  9982      i := Smalltalk imageFromFileNamed:'bitmaps/gifImages/claus.gif' inPackage:'stx:goodies'.
  9982      i := Smalltalk imageFromFileNamed:'bitmaps/gifImages/claus.gif' inPackage:'stx:goodies'.
  9983      v := View new extent:400@400.
  9983      v := View new extent:400@400.
  9984      v openAndWait.
  9984      v openAndWait.
  9985      rot := 0.
  9985      rot := 0.
  9986      [true] whileTrue:[
  9986      [true] whileTrue:[
  9987         rI := i rotated:rot.
  9987 	rI := i rotated:rot.
  9988         rI := rI onDevice:v device.
  9988 	rI := rI onDevice:v device.
  9989         v clear.
  9989 	v clear.
  9990         v displayForm:rI x:v width//2-(rI width//2) y:v height//2-(rI height // 2).
  9990 	v displayForm:rI x:v width//2-(rI width//2) y:v height//2-(rI height // 2).
  9991         rot := rot + 5.
  9991 	rot := rot + 5.
  9992         rI close.
  9992 	rI close.
  9993      ]
  9993      ]
  9994     "
  9994     "
  9995 
  9995 
  9996     "Modified: 22.4.1997 / 17:36:37 / cg"
  9996     "Modified: 22.4.1997 / 17:36:37 / cg"
  9997 !
  9997 !
 10000     "return a new image which is slightly brighter than the receiver.
 10000     "return a new image which is slightly brighter than the receiver.
 10001      The receiver must be a palette image (currently).
 10001      The receiver must be a palette image (currently).
 10002      CAVEAT: this only works with palette images (i.e. not for rgb or greyScale).
 10002      CAVEAT: this only works with palette images (i.e. not for rgb or greyScale).
 10003      CAVEAT: Need an argument, which specifies by how much it should be lighter."
 10003      CAVEAT: Need an argument, which specifies by how much it should be lighter."
 10004 
 10004 
 10005     ^ self 
 10005     ^ self
 10006         copyWithColorMapProcessing:[:clr | clr lightened]
 10006 	copyWithColorMapProcessing:[:clr | clr lightened]
 10007 
 10007 
 10008     "
 10008     "
 10009      (Smalltalk bitmapFromFileNamed:'gifImages/claus.gif' inPackage:'stx:goodies') inspect
 10009      (Smalltalk bitmapFromFileNamed:'gifImages/claus.gif' inPackage:'stx:goodies') inspect
 10010      (Smalltalk bitmapFromFileNamed:'gifImages/claus.gif' inPackage:'stx:goodies') lightened inspect
 10010      (Smalltalk bitmapFromFileNamed:'gifImages/claus.gif' inPackage:'stx:goodies') lightened inspect
 10011      (Smalltalk bitmapFromFileNamed:'gifImages/claus.gif' inPackage:'stx:goodies') darkened inspect
 10011      (Smalltalk bitmapFromFileNamed:'gifImages/claus.gif' inPackage:'stx:goodies') darkened inspect
 10059     mask notNil ifTrue:[
 10059     mask notNil ifTrue:[
 10060 	newMask := (mask magnifiedBy:scalePoint)
 10060 	newMask := (mask magnifiedBy:scalePoint)
 10061     ].
 10061     ].
 10062 
 10062 
 10063     newImage := self species new.
 10063     newImage := self species new.
 10064     newImage 
 10064     newImage
 10065 	width:newWidth 
 10065 	width:newWidth
 10066 	height:newHeight 
 10066 	height:newHeight
 10067 	photometric:photometric 
 10067 	photometric:photometric
 10068 	samplesPerPixel:samplesPerPixel 
 10068 	samplesPerPixel:samplesPerPixel
 10069 	bitsPerSample:bitsPerSample 
 10069 	bitsPerSample:bitsPerSample
 10070 	colorMap:colorMap copy
 10070 	colorMap:colorMap copy
 10071 	bits:newBits
 10071 	bits:newBits
 10072 	mask:newMask.
 10072 	mask:newMask.
 10073 
 10073 
 10074     mX = 1 ifTrue:[
 10074     mX = 1 ifTrue:[
 10076 	srcOffset := 1.
 10076 	srcOffset := 1.
 10077 	dstOffset := 1.
 10077 	dstOffset := 1.
 10078 
 10078 
 10079 	1 to:h do:[:row |
 10079 	1 to:h do:[:row |
 10080 	    1 to:magY do:[:i |
 10080 	    1 to:magY do:[:i |
 10081 		newBits replaceFrom:dstOffset 
 10081 		newBits replaceFrom:dstOffset
 10082 			to:(dstOffset + oldBytesPerRow - 1)
 10082 			to:(dstOffset + oldBytesPerRow - 1)
 10083 			with:bytes 
 10083 			with:bytes
 10084 			startingAt:srcOffset.
 10084 			startingAt:srcOffset.
 10085 		dstOffset := dstOffset + newBytesPerRow
 10085 		dstOffset := dstOffset + newBytesPerRow
 10086 	    ].
 10086 	    ].
 10087 	    srcOffset := srcOffset + oldBytesPerRow.
 10087 	    srcOffset := srcOffset + oldBytesPerRow.
 10088 	].
 10088 	].
 10090 	"expand cols"
 10090 	"expand cols"
 10091 	(mX > 1) ifTrue:[
 10091 	(mX > 1) ifTrue:[
 10092 	    dstOffset := 1.
 10092 	    dstOffset := 1.
 10093 	    srcOffset := 1.
 10093 	    srcOffset := 1.
 10094 	    1 to:h do:[:row |
 10094 	    1 to:h do:[:row |
 10095 		self magnifyRowFrom:bytes 
 10095 		self magnifyRowFrom:bytes
 10096 		     offset:srcOffset  
 10096 		     offset:srcOffset
 10097 		     into:newBits 
 10097 		     into:newBits
 10098 		     offset:dstOffset 
 10098 		     offset:dstOffset
 10099 		     factor:mX.
 10099 		     factor:mX.
 10100 
 10100 
 10101 		first := dstOffset.
 10101 		first := dstOffset.
 10102 		dstOffset := dstOffset + newBytesPerRow.
 10102 		dstOffset := dstOffset + newBytesPerRow.
 10103 		" and copy for row expansion "
 10103 		" and copy for row expansion "
 10104 		2 to:magY do:[:i |
 10104 		2 to:magY do:[:i |
 10105 		    newBits replaceFrom:dstOffset 
 10105 		    newBits replaceFrom:dstOffset
 10106 			    to:(dstOffset + newBytesPerRow - 1)
 10106 			    to:(dstOffset + newBytesPerRow - 1)
 10107 			    with:newBits 
 10107 			    with:newBits
 10108 			    startingAt:first.
 10108 			    startingAt:first.
 10109 		    dstOffset := dstOffset + newBytesPerRow
 10109 		    dstOffset := dstOffset + newBytesPerRow
 10110 		].
 10110 		].
 10111 		srcOffset := srcOffset + oldBytesPerRow.
 10111 		srcOffset := srcOffset + oldBytesPerRow.
 10112 	    ].
 10112 	    ].
 10119     "
 10119     "
 10120 
 10120 
 10121     "Modified: 24.4.1997 / 18:32:04 / cg"
 10121     "Modified: 24.4.1997 / 18:32:04 / cg"
 10122 !
 10122 !
 10123 
 10123 
 10124 magnifiedPreservingRatioTo:anExtent 
 10124 magnifiedPreservingRatioTo:anExtent
 10125     "return a new image magnified to fit into anExtent,
 10125     "return a new image magnified to fit into anExtent,
 10126      preserving the receivers width/height ratio.
 10126      preserving the receivers width/height ratio.
 10127      (i.e. not distorting the image).
 10127      (i.e. not distorting the image).
 10128      See also #magnifiedTo: and #magnifiedBy:"
 10128      See also #magnifiedTo: and #magnifiedBy:"
 10129 
 10129 
 10142     "
 10142     "
 10143 
 10143 
 10144     "Modified: 22.4.1997 / 12:33:46 / cg"
 10144     "Modified: 22.4.1997 / 12:33:46 / cg"
 10145 !
 10145 !
 10146 
 10146 
 10147 magnifiedTo:anExtent 
 10147 magnifiedTo:anExtent
 10148     "return a new image magnified to have the size specified by extent.
 10148     "return a new image magnified to have the size specified by extent.
 10149      This may distort the image if the arguments ratio is not the images ratio.
 10149      This may distort the image if the arguments ratio is not the images ratio.
 10150      See also #magnifiedPreservingRatioTo: and #magnifiedBy:"
 10150      See also #magnifiedPreservingRatioTo: and #magnifiedBy:"
 10151 
 10151 
 10152     ^ self magnifiedBy:(anExtent / self extent)
 10152     ^ self magnifiedBy:(anExtent / self extent)
 10159      ((Image fromFile:'goodies/bitmaps/gifImages/garfield.gif') magnifiedPreservingRatioTo:100@100)
 10159      ((Image fromFile:'goodies/bitmaps/gifImages/garfield.gif') magnifiedPreservingRatioTo:100@100)
 10160     "
 10160     "
 10161 !
 10161 !
 10162 
 10162 
 10163 mixed:amount with:aColor
 10163 mixed:amount with:aColor
 10164     "return a new image which is blended with some color; 
 10164     "return a new image which is blended with some color;
 10165      amount determines how much of the blending color is applied (0..)
 10165      amount determines how much of the blending color is applied (0..)
 10166      where 0 means: blending color pure.
 10166      where 0 means: blending color pure.
 10167      The receiver must be a palette image (currently).
 10167      The receiver must be a palette image (currently).
 10168      CAVEAT: this only works with palette images (i.e. not for rgb or greyScale).
 10168      CAVEAT: this only works with palette images (i.e. not for rgb or greyScale).
 10169      CAVEAT: Need an argument, which specifies by how much it should be lighter."
 10169      CAVEAT: Need an argument, which specifies by how much it should be lighter."
 10170 
 10170 
 10171      ^ self 
 10171      ^ self
 10172 	copyWithColorMapProcessing:[:clr | clr mixed:amount with:aColor]
 10172 	copyWithColorMapProcessing:[:clr | clr mixed:amount with:aColor]
 10173 
 10173 
 10174     "
 10174     "
 10175      (Smalltalk bitmapFromFileNamed:'gifImages/claus.gif' inPackage:'stx:goodies') inspect
 10175      (Smalltalk bitmapFromFileNamed:'gifImages/claus.gif' inPackage:'stx:goodies') inspect
 10176      ((Smalltalk bitmapFromFileNamed:'gifImages/claus.gif' inPackage:'stx:goodies') mixed:0.0 with:Color red) inspect
 10176      ((Smalltalk bitmapFromFileNamed:'gifImages/claus.gif' inPackage:'stx:goodies') mixed:0.0 with:Color red) inspect
 10203 	    ^ newImage
 10203 	    ^ newImage
 10204 	].
 10204 	].
 10205 	^ nil
 10205 	^ nil
 10206     ].
 10206     ].
 10207 
 10207 
 10208      ^ self 
 10208      ^ self
 10209 	copyWithColorMapProcessing:[:clr | 
 10209 	copyWithColorMapProcessing:[:clr |
 10210 		|newColor|
 10210 		|newColor|
 10211 
 10211 
 10212 		newColor := Color
 10212 		newColor := Color
 10213 				redByte:(255 - clr redByte)
 10213 				redByte:(255 - clr redByte)
 10214 				greenByte:(255 - clr greenByte)
 10214 				greenByte:(255 - clr greenByte)
 10297 
 10297 
 10298     |xMax yMax r g b nR nG nB clr pix map revMap n_clr n_pix mask anyChange
 10298     |xMax yMax r g b nR nG nB clr pix map revMap n_clr n_pix mask anyChange
 10299      newColors newColorArray newImage extMask extBits newPixelValue|
 10299      newColors newColorArray newImage extMask extBits newPixelValue|
 10300 
 10300 
 10301     numBits > 7 ifTrue:[
 10301     numBits > 7 ifTrue:[
 10302         ^ nil
 10302 	^ nil
 10303     ].
 10303     ].
 10304     mask := (16rFF bitShift:numBits) bitAnd:16rFF.
 10304     mask := (16rFF bitShift:numBits) bitAnd:16rFF.
 10305     extMask := (1 bitShift:numBits).
 10305     extMask := (1 bitShift:numBits).
 10306     extBits := extMask - 1.
 10306     extBits := extMask - 1.
 10307 
 10307 
 10319     newImage mask:(self mask copy).
 10319     newImage mask:(self mask copy).
 10320 
 10320 
 10321     xMax := width - 1.
 10321     xMax := width - 1.
 10322     yMax := height - 1.
 10322     yMax := height - 1.
 10323 
 10323 
 10324     newPixelValue := 
 10324     newPixelValue :=
 10325         [:image :pixelValue |
 10325 	[:image :pixelValue |
 10326             |r g b nR nG nB|
 10326 	    |r g b nR nG nB|
 10327 
 10327 
 10328             r := image redBitsOf:pixelValue.
 10328 	    r := image redBitsOf:pixelValue.
 10329             g := image greenBitsOf:pixelValue.
 10329 	    g := image greenBitsOf:pixelValue.
 10330             b := image blueBitsOf:pixelValue.
 10330 	    b := image blueBitsOf:pixelValue.
 10331             nR := r bitAnd:mask. (nR bitAnd:extMask)~~0 ifTrue:[nR := nR bitOr:extBits].
 10331 	    nR := r bitAnd:mask. (nR bitAnd:extMask)~~0 ifTrue:[nR := nR bitOr:extBits].
 10332             nG := g bitAnd:mask. (nG bitAnd:extMask)~~0 ifTrue:[nG := nG bitOr:extBits].
 10332 	    nG := g bitAnd:mask. (nG bitAnd:extMask)~~0 ifTrue:[nG := nG bitOr:extBits].
 10333             nB := b bitAnd:mask. (nB bitAnd:extMask)~~0 ifTrue:[nB := nB bitOr:extBits].
 10333 	    nB := b bitAnd:mask. (nB bitAnd:extMask)~~0 ifTrue:[nB := nB bitOr:extBits].
 10334             image valueFromRedBits:nR greenBits:nG blueBits:nB.
 10334 	    image valueFromRedBits:nR greenBits:nG blueBits:nB.
 10335         ].
 10335 	].
 10336 
 10336 
 10337 
 10337 
 10338     photometric == #palette ifFalse:[
 10338     photometric == #palette ifFalse:[
 10339         "/ direct manipulation of the pixels
 10339 	"/ direct manipulation of the pixels
 10340         0 to:yMax do:[:y |
 10340 	0 to:yMax do:[:y |
 10341             0 to:xMax do:[:x |
 10341 	    0 to:xMax do:[:x |
 10342                 pix := self pixelAtX:x y:y.
 10342 		pix := self pixelAtX:x y:y.
 10343                 n_pix := newPixelValue value:self value:pix.
 10343 		n_pix := newPixelValue value:self value:pix.
 10344                 n_pix ~= pix ifTrue:[
 10344 		n_pix ~= pix ifTrue:[
 10345                     newImage pixelAtX:x y:y put:n_pix.
 10345 		    newImage pixelAtX:x y:y put:n_pix.
 10346                     anyChange := true.
 10346 		    anyChange := true.
 10347                 ]
 10347 		]
 10348             ]
 10348 	    ]
 10349         ].
 10349 	].
 10350         anyChange ifFalse:[
 10350 	anyChange ifFalse:[
 10351             ^ nil
 10351 	    ^ nil
 10352         ].
 10352 	].
 10353     ] ifTrue:[
 10353     ] ifTrue:[
 10354         "/ manipulate the colormap
 10354 	"/ manipulate the colormap
 10355         0 to:yMax do:[:y |
 10355 	0 to:yMax do:[:y |
 10356             0 to:xMax do:[:x |
 10356 	    0 to:xMax do:[:x |
 10357                 pix := self pixelAtX:x y:y.
 10357 		pix := self pixelAtX:x y:y.
 10358                 (n_pix := map at:pix+1) isNil ifTrue:[
 10358 		(n_pix := map at:pix+1) isNil ifTrue:[
 10359                     clr := self colorAtX:x y:y.
 10359 		    clr := self colorAtX:x y:y.
 10360 
 10360 
 10361                     r := clr redByte.
 10361 		    r := clr redByte.
 10362                     g := clr greenByte.
 10362 		    g := clr greenByte.
 10363                     b := clr blueByte.
 10363 		    b := clr blueByte.
 10364                     nR := r bitAnd:mask. (nR bitAnd:extMask)~~0 ifTrue:[nR := nR bitOr:extBits].
 10364 		    nR := r bitAnd:mask. (nR bitAnd:extMask)~~0 ifTrue:[nR := nR bitOr:extBits].
 10365                     nG := g bitAnd:mask. (nR bitAnd:extMask)~~0 ifTrue:[nR := nR bitOr:extBits].
 10365 		    nG := g bitAnd:mask. (nR bitAnd:extMask)~~0 ifTrue:[nR := nR bitOr:extBits].
 10366                     nB := b bitAnd:mask. (nR bitAnd:extMask)~~0 ifTrue:[nR := nR bitOr:extBits].
 10366 		    nB := b bitAnd:mask. (nR bitAnd:extMask)~~0 ifTrue:[nR := nR bitOr:extBits].
 10367                     n_clr := Color redByte:nR greenByte:nG blueByte:nB.
 10367 		    n_clr := Color redByte:nR greenByte:nG blueByte:nB.
 10368                     (newColors includes:n_clr) ifFalse:[
 10368 		    (newColors includes:n_clr) ifFalse:[
 10369                         newColors add:n_clr.
 10369 			newColors add:n_clr.
 10370                         newColorArray add:n_clr.
 10370 			newColorArray add:n_clr.
 10371                         revMap add:pix.
 10371 			revMap add:pix.
 10372                         map at:pix+1 put:(n_pix := revMap size - 1).
 10372 			map at:pix+1 put:(n_pix := revMap size - 1).
 10373                     ] ifTrue:[
 10373 		    ] ifTrue:[
 10374                         "/ mhmh - multiple pixels mapped to the same color
 10374 			"/ mhmh - multiple pixels mapped to the same color
 10375                         n_pix := (newColorArray indexOf:n_clr) - 1.
 10375 			n_pix := (newColorArray indexOf:n_clr) - 1.
 10376                         map at:pix+1 put:n_pix.
 10376 			map at:pix+1 put:n_pix.
 10377                     ]
 10377 		    ]
 10378                 ].
 10378 		].
 10379                 newImage pixelAtX:x y:y put:n_pix.
 10379 		newImage pixelAtX:x y:y put:n_pix.
 10380             ]
 10380 	    ]
 10381         ].
 10381 	].
 10382         revMap size == self colorMap size ifTrue:[
 10382 	revMap size == self colorMap size ifTrue:[
 10383             revMap = (0 to:revMap size-1) ifTrue:[
 10383 	    revMap = (0 to:revMap size-1) ifTrue:[
 10384                 ^ nil
 10384 		^ nil
 10385             ]
 10385 	    ]
 10386         ].
 10386 	].
 10387 
 10387 
 10388         newImage colorMap:(MappedPalette withColors:newColorArray).
 10388 	newImage colorMap:(MappedPalette withColors:newColorArray).
 10389     ].
 10389     ].
 10390 
 10390 
 10391     ^ newImage
 10391     ^ newImage
 10392 !
 10392 !
 10393 
 10393 
 10396      on the pixel colors.
 10396      on the pixel colors.
 10397      Notice: this method is very slow - either apply pixel values
 10397      Notice: this method is very slow - either apply pixel values
 10398      (#withPixelFunctionAppliedToPixels:) or redefine this method in
 10398      (#withPixelFunctionAppliedToPixels:) or redefine this method in
 10399      a concrete subclass.
 10399      a concrete subclass.
 10400      (read `Beyond photography, by Gerard J. Holzmann;
 10400      (read `Beyond photography, by Gerard J. Holzmann;
 10401            ISBM 0-13-074410-7)
 10401 	   ISBM 0-13-074410-7)
 10402      See blurred / oilPointed as examples ...)"
 10402      See blurred / oilPointed as examples ...)"
 10403 
 10403 
 10404     |w  "{Class: SmallInteger }"
 10404     |w  "{Class: SmallInteger }"
 10405      h  "{Class: SmallInteger }"
 10405      h  "{Class: SmallInteger }"
 10406      newImage "newBits newBytesPerRow"|
 10406      newImage "newBits newBytesPerRow"|
 10419 
 10419 
 10420     w := width - 1.
 10420     w := width - 1.
 10421     h := height - 1.
 10421     h := height - 1.
 10422 
 10422 
 10423     0 to:h do:[:y |
 10423     0 to:h do:[:y |
 10424         0 to:w do:[:x |
 10424 	0 to:w do:[:x |
 10425             newImage colorAtX:x y:y put:(pixelFunctionBlock
 10425 	    newImage colorAtX:x y:y put:(pixelFunctionBlock
 10426                                                 value:self
 10426 						value:self
 10427                                                 value:(self colorAtX:x y:y)
 10427 						value:(self colorAtX:x y:y)
 10428                                                 value:x
 10428 						value:x
 10429                                                 value:y)
 10429 						value:y)
 10430         ]
 10430 	]
 10431     ].
 10431     ].
 10432     ^ newImage
 10432     ^ newImage
 10433 
 10433 
 10434     "black out everything except for some rectangle:
 10434     "black out everything except for some rectangle:
 10435 
 10435 
 10438      i := Image fromFile:'goodies/bitmaps/gifImages/claus.gif'.
 10438      i := Image fromFile:'goodies/bitmaps/gifImages/claus.gif'.
 10439      i inspect.
 10439      i inspect.
 10440 
 10440 
 10441      black := Color black.
 10441      black := Color black.
 10442      (i withPixelFunctionApplied:[:oldImage :oldColor :x :y |
 10442      (i withPixelFunctionApplied:[:oldImage :oldColor :x :y |
 10443                         ((x between:100 and:200) 
 10443 			((x between:100 and:200)
 10444                         and:[y between:100 and:200]) ifTrue:[
 10444 			and:[y between:100 and:200]) ifTrue:[
 10445                             oldColor
 10445 			    oldColor
 10446                         ] ifFalse:[
 10446 			] ifFalse:[
 10447                             black.
 10447 			    black.
 10448                         ]
 10448 			]
 10449                      ]) inspect.
 10449 		     ]) inspect.
 10450     "
 10450     "
 10451     "brighten a frame:
 10451     "brighten a frame:
 10452 
 10452 
 10453      |i black w h|
 10453      |i black w h|
 10454 
 10454 
 10456      i inspect.
 10456      i inspect.
 10457 
 10457 
 10458      w := i width.
 10458      w := i width.
 10459      h := i height.
 10459      h := i height.
 10460      (i withPixelFunctionApplied:[:oldImage :oldColor :x :y |
 10460      (i withPixelFunctionApplied:[:oldImage :oldColor :x :y |
 10461                         ((x between:0 and:10) 
 10461 			((x between:0 and:10)
 10462                         or:[(y between:0 and:10)
 10462 			or:[(y between:0 and:10)
 10463                         or:[(x between:w-10 and:w)
 10463 			or:[(x between:w-10 and:w)
 10464                         or:[y between:h-10 and:h]]]) ifTrue:[
 10464 			or:[y between:h-10 and:h]]]) ifTrue:[
 10465                             oldColor lightened nearestIn:i colorMap
 10465 			    oldColor lightened nearestIn:i colorMap
 10466                         ] ifFalse:[
 10466 			] ifFalse:[
 10467                             oldColor.
 10467 			    oldColor.
 10468                         ]
 10468 			]
 10469                      ]) inspect.
 10469 		     ]) inspect.
 10470     "
 10470     "
 10471 
 10471 
 10472     "Modified: 24.4.1997 / 18:36:59 / cg"
 10472     "Modified: 24.4.1997 / 18:36:59 / cg"
 10473 !
 10473 !
 10474 
 10474 
 10477      on the pixel values.
 10477      on the pixel values.
 10478      (read `Beyond photography, by Gerard J. Holzmann;
 10478      (read `Beyond photography, by Gerard J. Holzmann;
 10479 	   ISBM 0-13-074410-7)
 10479 	   ISBM 0-13-074410-7)
 10480      See blurred / oilPointed as examples ...)"
 10480      See blurred / oilPointed as examples ...)"
 10481 
 10481 
 10482     ^ self 
 10482     ^ self
 10483 	withPixelFunctionAppliedToPixels:pixelFunctionBlock 
 10483 	withPixelFunctionAppliedToPixels:pixelFunctionBlock
 10484 	in:(0@0 corner:width@height)
 10484 	in:(0@0 corner:width@height)
 10485 
 10485 
 10486     "oil painting effect:
 10486     "oil painting effect:
 10487 
 10487 
 10488      |i w h|
 10488      |i w h|
 10588 
 10588 
 10589 withPixelFunctionAppliedToPixels:pixelFunctionBlock in:aRectangle
 10589 withPixelFunctionAppliedToPixels:pixelFunctionBlock in:aRectangle
 10590     "return a new image from the old one, by applying a pixel processor
 10590     "return a new image from the old one, by applying a pixel processor
 10591      on the pixel values.
 10591      on the pixel values.
 10592      (read `Beyond photography, by Gerard J. Holzmann;
 10592      (read `Beyond photography, by Gerard J. Holzmann;
 10593            ISBM 0-13-074410-7)
 10593 	   ISBM 0-13-074410-7)
 10594      See blurred / oilPointed as examples ...)"
 10594      See blurred / oilPointed as examples ...)"
 10595 
 10595 
 10596     |newImage "newBits newBytesPerRow"|
 10596     |newImage "newBits newBytesPerRow"|
 10597 
 10597 
 10598     newImage := self species new.
 10598     newImage := self species new.
 10617      i := Image fromFile:'goodies/bitmaps/gifImages/claus.gif'.
 10617      i := Image fromFile:'goodies/bitmaps/gifImages/claus.gif'.
 10618      i inspect.
 10618      i inspect.
 10619      w := i width - 1.
 10619      w := i width - 1.
 10620      h := i height - 1.
 10620      h := i height - 1.
 10621      (i withPixelFunctionAppliedToPixels:[:oldImage :oldPixel :x :y |
 10621      (i withPixelFunctionAppliedToPixels:[:oldImage :oldPixel :x :y |
 10622                         |b p max xMin xMax yMin yMax|
 10622 			|b p max xMin xMax yMin yMax|
 10623 
 10623 
 10624                         b := Bag identityNew:10.
 10624 			b := Bag identityNew:10.
 10625                         xMin := x-3 max:0.
 10625 			xMin := x-3 max:0.
 10626                         xMax := x+3 min:w.
 10626 			xMax := x+3 min:w.
 10627                         yMin := y-3 max:0.
 10627 			yMin := y-3 max:0.
 10628                         yMax := y+3 min:h.
 10628 			yMax := y+3 min:h.
 10629                         xMin to:xMax do:[:tx|
 10629 			xMin to:xMax do:[:tx|
 10630                           yMin to:yMax do:[:ty|
 10630 			  yMin to:yMax do:[:ty|
 10631                             b add:(oldImage pixelAtX:tx y:ty)
 10631 			    b add:(oldImage pixelAtX:tx y:ty)
 10632                           ]
 10632 			  ]
 10633                         ].
 10633 			].
 10634                         max := 0.
 10634 			max := 0.
 10635                         b contents keysAndValuesDo:[:pixel :n |
 10635 			b contents keysAndValuesDo:[:pixel :n |
 10636                             n > max ifTrue:[
 10636 			    n > max ifTrue:[
 10637                                 p := pixel.
 10637 				p := pixel.
 10638                                 max := n
 10638 				max := n
 10639                             ]
 10639 			    ]
 10640                         ].
 10640 			].
 10641                         p
 10641 			p
 10642                      ]) inspect.
 10642 		     ]) inspect.
 10643     "
 10643     "
 10644 
 10644 
 10645     "fisheye effect:
 10645     "fisheye effect:
 10646 
 10646 
 10647      |i w h w2 h2 R white|
 10647      |i w h w2 h2 R white|
 10653      w2 := w // 2.
 10653      w2 := w // 2.
 10654      h2 := h // 2.
 10654      h2 := h // 2.
 10655      R := w2.
 10655      R := w2.
 10656      white := i valueFromColor:Color white.
 10656      white := i valueFromColor:Color white.
 10657      (i withPixelFunctionAppliedToPixels:[:oldImage :oldPixel :x :y |
 10657      (i withPixelFunctionAppliedToPixels:[:oldImage :oldPixel :x :y |
 10658                         |p r a nR nP nX nY|
 10658 			|p r a nR nP nX nY|
 10659 
 10659 
 10660                         p := (x-w2)@(y-h2).
 10660 			p := (x-w2)@(y-h2).
 10661                         r := p r.
 10661 			r := p r.
 10662                         a := p theta.
 10662 			a := p theta.
 10663                         nR := r * r / R.
 10663 			nR := r * r / R.
 10664                         nP := Point r:nR theta:a.
 10664 			nP := Point r:nR theta:a.
 10665                         nX := ((nP x+w2) rounded max:0) min:w.
 10665 			nX := ((nP x+w2) rounded max:0) min:w.
 10666                         nY := ((nP y+h2) rounded max:0) min:h.
 10666 			nY := ((nP y+h2) rounded max:0) min:h.
 10667                         (nX > w or:[nX < 0]) ifTrue:[
 10667 			(nX > w or:[nX < 0]) ifTrue:[
 10668                             white
 10668 			    white
 10669                         ] ifFalse:[
 10669 			] ifFalse:[
 10670                             (nY > h or:[nY < 0]) ifTrue:[
 10670 			    (nY > h or:[nY < 0]) ifTrue:[
 10671                                 white
 10671 				white
 10672                             ] ifFalse:[
 10672 			    ] ifFalse:[
 10673                                 oldImage pixelAtX:nX y:nY
 10673 				oldImage pixelAtX:nX y:nY
 10674                             ]
 10674 			    ]
 10675                         ]
 10675 			]
 10676                      ]) inspect.
 10676 		     ]) inspect.
 10677     "
 10677     "
 10678     "fisheye effect:
 10678     "fisheye effect:
 10679 
 10679 
 10680      |i w h w2 h2 R white|
 10680      |i w h w2 h2 R white|
 10681 
 10681 
 10686      w2 := w // 2.
 10686      w2 := w // 2.
 10687      h2 := h // 2.
 10687      h2 := h // 2.
 10688      R := w2.
 10688      R := w2.
 10689      white := i valueFromColor:Color white.
 10689      white := i valueFromColor:Color white.
 10690      (i withPixelFunctionAppliedToPixels:[:oldImage :oldPixel :x :y |
 10690      (i withPixelFunctionAppliedToPixels:[:oldImage :oldPixel :x :y |
 10691                         |p r a nR nP nX nY|
 10691 			|p r a nR nP nX nY|
 10692 
 10692 
 10693                         p := (x-w2)@(y-h2).
 10693 			p := (x-w2)@(y-h2).
 10694                         r := p r.
 10694 			r := p r.
 10695                         a := p theta.
 10695 			a := p theta.
 10696                         nR := r * r / R.
 10696 			nR := r * r / R.
 10697                         nP := Point r:nR theta:a.
 10697 			nP := Point r:nR theta:a.
 10698                         nX := (nP x+w2) rounded.
 10698 			nX := (nP x+w2) rounded.
 10699                         nY := (nP y+h2) rounded.
 10699 			nY := (nP y+h2) rounded.
 10700                         (nX > w or:[nX < 0]) ifTrue:[
 10700 			(nX > w or:[nX < 0]) ifTrue:[
 10701                             white
 10701 			    white
 10702                         ] ifFalse:[
 10702 			] ifFalse:[
 10703                             (nY > h or:[nY < 0]) ifTrue:[
 10703 			    (nY > h or:[nY < 0]) ifTrue:[
 10704                                 white
 10704 				white
 10705                             ] ifFalse:[
 10705 			    ] ifFalse:[
 10706                                 oldImage pixelAtX:nX y:nY
 10706 				oldImage pixelAtX:nX y:nY
 10707                             ]
 10707 			    ]
 10708                         ]
 10708 			]
 10709                      ]) inspect.
 10709 		     ]) inspect.
 10710     "
 10710     "
 10711 
 10711 
 10712     "Created: 24.4.1997 / 18:37:17 / cg"
 10712     "Created: 24.4.1997 / 18:37:17 / cg"
 10713     "Modified: 24.4.1997 / 18:40:02 / cg"
 10713     "Modified: 24.4.1997 / 18:40:02 / cg"
 10714 ! !
 10714 ! !
 10803 applyPixelValuesTo:pixelFunctionBlock into:newImage in:aRectangle
 10803 applyPixelValuesTo:pixelFunctionBlock into:newImage in:aRectangle
 10804     "helper for withPixelFunctionAppliedToValues:
 10804     "helper for withPixelFunctionAppliedToValues:
 10805      enumerate pixelValues and evaluate the block for each.
 10805      enumerate pixelValues and evaluate the block for each.
 10806      To be redefined by subclasses for better performance."
 10806      To be redefined by subclasses for better performance."
 10807 
 10807 
 10808     ^ self applyPixelValuesTo:pixelFunctionBlock in:aRectangle into:newImage 
 10808     ^ self applyPixelValuesTo:pixelFunctionBlock in:aRectangle into:newImage
 10809 !
 10809 !
 10810 
 10810 
 10811 magnifyBy:scale
 10811 magnifyBy:scale
 10812     "obsolete: has been renamed to magnifiedBy: for ST-80 compatibility
 10812     "obsolete: has been renamed to magnifiedBy: for ST-80 compatibility
 10813      and name consistency ..."
 10813      and name consistency ..."
 10824      colorMap - otherwise, an error will be reported.
 10824      colorMap - otherwise, an error will be reported.
 10825 
 10825 
 10826      WARNING:
 10826      WARNING:
 10827        This implementation is a very slow fallback general algorithm
 10827        This implementation is a very slow fallback general algorithm
 10828        (the loop over the source pixels is very slow).
 10828        (the loop over the source pixels is very slow).
 10829        If this method is used heavily, you may want to redefine it in 
 10829        If this method is used heavily, you may want to redefine it in
 10830        concrete subclasses for the common case of of copying from an Image 
 10830        concrete subclasses for the common case of of copying from an Image
 10831        with the same depth & palette.
 10831        with the same depth & palette.
 10832        If you do heavy image processing, specialized versions are even req'd 
 10832        If you do heavy image processing, specialized versions are even req'd
 10833        for other cases, rewriting the inner loops as inline C-code."
 10833        for other cases, rewriting the inner loops as inline C-code."
 10834 
 10834 
 10835     |dX dY|
 10835     |dX dY|
 10836 
 10836 
 10837     dX := srcX-dstX.
 10837     dX := srcX-dstX.
 10838     dY := srcY-dstY.
 10838     dY := srcY-dstY.
 10839 
 10839 
 10840     ((photometric == anImage photometric)
 10840     ((photometric == anImage photometric)
 10841      and:[self bitsPerPixel == anImage bitsPerPixel
 10841      and:[self bitsPerPixel == anImage bitsPerPixel
 10842      and:[colorMap = anImage colorMap]]) ifTrue:[
 10842      and:[colorMap = anImage colorMap]]) ifTrue:[
 10843         "/ can loop over values
 10843 	"/ can loop over values
 10844         anImage valuesFromX:srcX  y:srcY 
 10844 	anImage valuesFromX:srcX  y:srcY
 10845                         toX:srcX+w-1 y:srcY+h-1  
 10845 			toX:srcX+w-1 y:srcY+h-1
 10846                          do:[:x :y :pixelValue |
 10846 			 do:[:x :y :pixelValue |
 10847             self pixelAtX:x-dX y:y-dY put:pixelValue.
 10847 	    self pixelAtX:x-dX y:y-dY put:pixelValue.
 10848         ]
 10848 	]
 10849     ] ifFalse:[
 10849     ] ifFalse:[
 10850         "/ must loop over colors - horribly slow
 10850 	"/ must loop over colors - horribly slow
 10851         anImage colorsFromX:srcX  y:srcY 
 10851 	anImage colorsFromX:srcX  y:srcY
 10852                         toX:srcX+w-1 y:srcY+h-1  
 10852 			toX:srcX+w-1 y:srcY+h-1
 10853                          do:[:x :y :clr |
 10853 			 do:[:x :y :clr |
 10854             self colorAtX:x-dX y:y-dY put:clr.
 10854 	    self colorAtX:x-dX y:y-dY put:clr.
 10855         ]
 10855 	]
 10856     ].
 10856     ].
 10857 
 10857 
 10858     (mask isNil and:[anImage mask notNil]) ifTrue:[
 10858     (mask isNil and:[anImage mask notNil]) ifTrue:[
 10859         "/ I have no mask; copied image has
 10859 	"/ I have no mask; copied image has
 10860         self createMask.
 10860 	self createMask.
 10861     ].
 10861     ].
 10862 
 10862 
 10863     mask notNil ifTrue:[
 10863     mask notNil ifTrue:[
 10864         anImage mask notNil ifTrue:[
 10864 	anImage mask notNil ifTrue:[
 10865             "/ both have a mask
 10865 	    "/ both have a mask
 10866             mask copyFrom:anImage mask x:srcX y:srcY toX:dstX y:dstY width:w height:h
 10866 	    mask copyFrom:anImage mask x:srcX y:srcY toX:dstX y:dstY width:w height:h
 10867         ] ifFalse:[
 10867 	] ifFalse:[
 10868             "/ I have a mask - copied image has not
 10868 	    "/ I have a mask - copied image has not
 10869             mask fillRectangleX:dstX y:dstY width:w height:h withValue:1
 10869 	    mask fillRectangleX:dstX y:dstY width:w height:h withValue:1
 10870         ]
 10870 	]
 10871 "/    ] ifFalse:[
 10871 "/    ] ifFalse:[
 10872 "/        anImage mask notNil ifTrue:[
 10872 "/        anImage mask notNil ifTrue:[
 10873 "/            "/ I have no mask; copied image has (already handled)
 10873 "/            "/ I have no mask; copied image has (already handled)
 10874 "/        ] ifFalse:[
 10874 "/        ] ifFalse:[
 10875 "/            "/ none has a mask - nothing to do.
 10875 "/            "/ none has a mask - nothing to do.
 10921     aStream nextPutAll:'(' , self class name , ' new)'.
 10921     aStream nextPutAll:'(' , self class name , ' new)'.
 10922     aStream nextPutAll:' width: '. width storeOn:aStream.
 10922     aStream nextPutAll:' width: '. width storeOn:aStream.
 10923     aStream nextPutAll:'; height: '. height storeOn:aStream.
 10923     aStream nextPutAll:'; height: '. height storeOn:aStream.
 10924     aStream nextPutAll:'; photometric:('. photometric storeOn:aStream.
 10924     aStream nextPutAll:'; photometric:('. photometric storeOn:aStream.
 10925     aStream nextPutAll:'); bitsPerSample:('. bitsPerSample storeOn:aStream.
 10925     aStream nextPutAll:'); bitsPerSample:('. bitsPerSample storeOn:aStream.
 10926     aStream nextPutAll:'); samplesPerPixel:('. samplesPerPixel storeOn:aStream. 
 10926     aStream nextPutAll:'); samplesPerPixel:('. samplesPerPixel storeOn:aStream.
 10927     aStream nextPutAll:'); bits:(ByteArray fromPackedString:'. self bits asPackedString storeOn:aStream. aStream nextPutAll:') '.
 10927     aStream nextPutAll:'); bits:(ByteArray fromPackedString:'. self bits asPackedString storeOn:aStream. aStream nextPutAll:') '.
 10928 
 10928 
 10929     colorMap notNil ifTrue:[
 10929     colorMap notNil ifTrue:[
 10930         self depth <= 8 ifTrue:[
 10930 	self depth <= 8 ifTrue:[
 10931             "/ cut off unused colors ...
 10931 	    "/ cut off unused colors ...
 10932             usedValues := self usedValues.
 10932 	    usedValues := self usedValues.
 10933             colors := colorMap copyFrom:1 to:((usedValues max+1) min:colorMap size).
 10933 	    colors := colorMap copyFrom:1 to:((usedValues max+1) min:colorMap size).
 10934 
 10934 
 10935             colorMapArray := OrderedCollection new.
 10935 	    colorMapArray := OrderedCollection new.
 10936             colors do:[:clr| colorMapArray add:(clr redByte); add:(clr greenByte); add:(clr blueByte)].
 10936 	    colors do:[:clr| colorMapArray add:(clr redByte); add:(clr greenByte); add:(clr blueByte)].
 10937             aStream nextPutAll:'; colorMapFromArray:'.
 10937 	    aStream nextPutAll:'; colorMapFromArray:'.
 10938             colorMapArray asByteArray storeOn:aStream.
 10938 	    colorMapArray asByteArray storeOn:aStream.
 10939         ] ifFalse:[
 10939 	] ifFalse:[
 10940             aStream nextPutAll:'; colorMap:('.
 10940 	    aStream nextPutAll:'; colorMap:('.
 10941             colorMap storeOn:aStream.
 10941 	    colorMap storeOn:aStream.
 10942             aStream nextPutAll:')'
 10942 	    aStream nextPutAll:')'
 10943         ]
 10943 	]
 10944     ].  
 10944     ].
 10945     mask notNil ifTrue:[
 10945     mask notNil ifTrue:[
 10946         aStream nextPutAll:'; mask:('.
 10946 	aStream nextPutAll:'; mask:('.
 10947         mask storeOn:aStream.
 10947 	mask storeOn:aStream.
 10948         aStream nextPutAll:')'.
 10948 	aStream nextPutAll:')'.
 10949     ].
 10949     ].
 10950     aStream nextPutAll:'; yourself'
 10950     aStream nextPutAll:'; yourself'
 10951 
 10951 
 10952     "Modified: / 22.8.1998 / 12:55:21 / cg"
 10952     "Modified: / 22.8.1998 / 12:55:21 / cg"
 10953 ! !
 10953 ! !
 10960      on it. The best format is the one with the same number or more bits per
 10960      on it. The best format is the one with the same number or more bits per
 10961      pixel. Here, the smallest format found which can represent enough pixels is taken."
 10961      pixel. Here, the smallest format found which can represent enough pixels is taken."
 10962 
 10962 
 10963     |bestDeviceDepth
 10963     |bestDeviceDepth
 10964      bestDeviceBitsPerPixel "{ Class: SmallInteger }"
 10964      bestDeviceBitsPerPixel "{ Class: SmallInteger }"
 10965      "maxDepth" 
 10965      "maxDepth"
 10966      bestInfo maxInfo 
 10966      bestInfo maxInfo
 10967      myDepth                "{ Class: SmallInteger }"
 10967      myDepth                "{ Class: SmallInteger }"
 10968      maxBitsPerPixel        "{ Class: SmallInteger }"|
 10968      maxBitsPerPixel        "{ Class: SmallInteger }"|
 10969 
 10969 
 10970     myDepth := self bitsPerPixel.
 10970     myDepth := self bitsPerPixel.
 10971     maxBitsPerPixel := 0.
 10971     maxBitsPerPixel := 0.
 10979 
 10979 
 10980 	"/ for now, ignore all depth's which are neither 1 nor the
 10980 	"/ for now, ignore all depth's which are neither 1 nor the
 10981 	"/ devices depth.
 10981 	"/ devices depth.
 10982 	"/ (actually, many devices can handle other pixMap formats,
 10982 	"/ (actually, many devices can handle other pixMap formats,
 10983 	"/ but I dont know (yet) how to pass the correct color info
 10983 	"/ but I dont know (yet) how to pass the correct color info
 10984         
 10984 
 10985 	((deviceImageDepth == 1) or:[deviceImageDepth == aDevice depth]) ifTrue:[
 10985 	((deviceImageDepth == 1) or:[deviceImageDepth == aDevice depth]) ifTrue:[
 10986 
 10986 
 10987 	    deviceImageBitsPerPixel > maxBitsPerPixel ifTrue:[
 10987 	    deviceImageBitsPerPixel > maxBitsPerPixel ifTrue:[
 10988 		maxInfo := entry.
 10988 		maxInfo := entry.
 10989     "/            maxBitsPerPixel := deviceImageBitsPerPixel.
 10989     "/            maxBitsPerPixel := deviceImageBitsPerPixel.
 11006 		     or:[deviceImageBitsPerPixel < bestDeviceBitsPerPixel]) ifTrue:[
 11006 		     or:[deviceImageBitsPerPixel < bestDeviceBitsPerPixel]) ifTrue:[
 11007 			bestInfo := entry.
 11007 			bestInfo := entry.
 11008 			bestDeviceDepth := deviceImageDepth.
 11008 			bestDeviceDepth := deviceImageDepth.
 11009 			bestDeviceBitsPerPixel := deviceImageBitsPerPixel.
 11009 			bestDeviceBitsPerPixel := deviceImageBitsPerPixel.
 11010 		    ]
 11010 		    ]
 11011 		]    
 11011 		]
 11012 	    ].
 11012 	    ].
 11013 	].
 11013 	].
 11014     ].
 11014     ].
 11015 
 11015 
 11016     bestDeviceDepth isNil ifTrue:[
 11016     bestDeviceDepth isNil ifTrue:[
 11062 	].
 11062 	].
 11063 	photometric == #palette ifTrue:[
 11063 	photometric == #palette ifTrue:[
 11064 	    self setColorMap:(anImage colorMap copy).
 11064 	    self setColorMap:(anImage colorMap copy).
 11065 	    "
 11065 	    "
 11066 	     must generate/compress the colormap, if source image has higher depth
 11066 	     must generate/compress the colormap, if source image has higher depth
 11067 	     than myself. 
 11067 	     than myself.
 11068 	    "
 11068 	    "
 11069 	    (colorMap isNil
 11069 	    (colorMap isNil
 11070 	    or:[anImage bitsPerPixel > self bitsPerPixel]) ifTrue:[
 11070 	    or:[anImage bitsPerPixel > self bitsPerPixel]) ifTrue:[
 11071 		"
 11071 		"
 11072 		 get used colors are extracted into our colorMap
 11072 		 get used colors are extracted into our colorMap
 11093     "Modified: 10.1.1997 / 17:52:21 / cg"
 11093     "Modified: 10.1.1997 / 17:52:21 / cg"
 11094 !
 11094 !
 11095 
 11095 
 11096 greyByteMapForRange:range
 11096 greyByteMapForRange:range
 11097     "return a collection to map from pixelValues to greyLevels
 11097     "return a collection to map from pixelValues to greyLevels
 11098      in the range 0..range. 
 11098      in the range 0..range.
 11099      Range must be < 256 (for elements to fit into a ByteArray).
 11099      Range must be < 256 (for elements to fit into a ByteArray).
 11100      The values are rounded towards the nearest pixel."
 11100      The values are rounded towards the nearest pixel."
 11101 
 11101 
 11102     |d clr val greyMap r
 11102     |d clr val greyMap r
 11103      n "{ Class: SmallInteger }"|
 11103      n "{ Class: SmallInteger }"|
 11232     "
 11232     "
 11233 
 11233 
 11234     "Modified: 1.3.1997 / 15:48:49 / cg"
 11234     "Modified: 1.3.1997 / 15:48:49 / cg"
 11235 !
 11235 !
 11236 
 11236 
 11237 magnifyRowFrom:srcBytes offset:srcStart  
 11237 magnifyRowFrom:srcBytes offset:srcStart
 11238 	  into:dstBytes offset:dstStart factor:mX
 11238 	  into:dstBytes offset:dstStart factor:mX
 11239 
 11239 
 11240     "magnify a single pixel row - can only magnify by integer factors,
 11240     "magnify a single pixel row - can only magnify by integer factors,
 11241      can only magnify 1,2,4,8 and 24 bit-per-pixel images. But this is done fast."
 11241      can only magnify 1,2,4,8 and 24 bit-per-pixel images. But this is done fast."
 11242 
 11242 
 11243     ^ self subclassResponsibility
 11243     ^ self subclassResponsibility
 11244 !
 11244 !
 11245 
 11245 
 11246 makeDeviceGrayPixmapOn:aDevice depth:depth fromArray:bits
 11246 makeDeviceGrayPixmapOn:aDevice depth:depth fromArray:bits
 11247     "given the bits of a grey/color bitmap, 8-bit padded and
 11247     "given the bits of a grey/color bitmap, 8-bit padded and
 11248      pixels interpreted as greyValues, 0 is black,  
 11248      pixels interpreted as greyValues, 0 is black,
 11249      create a device form for it"
 11249      create a device form for it"
 11250 
 11250 
 11251     |f|
 11251     |f|
 11252 
 11252 
 11253     f := Form width:width height:height depth:depth on:aDevice.
 11253     f := Form width:width height:height depth:depth on:aDevice.
 11258 
 11258 
 11259     (aDevice blackpixel ~~ 0) ifTrue:[
 11259     (aDevice blackpixel ~~ 0) ifTrue:[
 11260 	"/ have to invert bits
 11260 	"/ have to invert bits
 11261 	f function:#copyInverted
 11261 	f function:#copyInverted
 11262     ].
 11262     ].
 11263     aDevice 
 11263     aDevice
 11264 	drawBits:bits 
 11264 	drawBits:bits
 11265 	depth:depth
 11265 	depth:depth
 11266 	padding:8
 11266 	padding:8
 11267 	width:width height:height
 11267 	width:width height:height
 11268 	x:0 y:0
 11268 	x:0 y:0
 11269 	into:(f id) 
 11269 	into:(f id)
 11270 	x:0 y:0 
 11270 	x:0 y:0
 11271 	width:width height:height 
 11271 	width:width height:height
 11272 	with:(f gcId).
 11272 	with:(f gcId).
 11273     ^ f
 11273     ^ f
 11274 
 11274 
 11275     "Created: 10.6.1996 / 20:10:31 / cg"
 11275     "Created: 10.6.1996 / 20:10:31 / cg"
 11276 !
 11276 !
 11287     "Modified: 17.4.1997 / 01:07:38 / cg"
 11287     "Modified: 17.4.1997 / 01:07:38 / cg"
 11288 !
 11288 !
 11289 
 11289 
 11290 makeDevicePixmapOn:aDevice depth:depth fromArray:bits
 11290 makeDevicePixmapOn:aDevice depth:depth fromArray:bits
 11291     "given the bits of a grey/color bitmap, 8-bit padded and
 11291     "given the bits of a grey/color bitmap, 8-bit padded and
 11292      pixels interpreted as in the devices colormap, 
 11292      pixels interpreted as in the devices colormap,
 11293      create a device form for it"
 11293      create a device form for it"
 11294 
 11294 
 11295     |f|
 11295     |f|
 11296 
 11296 
 11297     f := Form width:width height:height depth:depth on:aDevice.
 11297     f := Form width:width height:height depth:depth on:aDevice.
 11298     f isNil ifTrue:[^ nil].
 11298     f isNil ifTrue:[^ nil].
 11299 
 11299 
 11300     f bits:bits.
 11300     f bits:bits.
 11301     f initGC.
 11301     f initGC.
 11302 
 11302 
 11303     aDevice 
 11303     aDevice
 11304 	drawBits:bits 
 11304 	drawBits:bits
 11305 	depth:depth
 11305 	depth:depth
 11306 	padding:8
 11306 	padding:8
 11307 	width:width height:height
 11307 	width:width height:height
 11308 	x:0 y:0
 11308 	x:0 y:0
 11309 	into:(f id) 
 11309 	into:(f id)
 11310 	x:0 y:0 
 11310 	x:0 y:0
 11311 	width:width height:height 
 11311 	width:width height:height
 11312 	with:(f gcId).
 11312 	with:(f gcId).
 11313     ^ f
 11313     ^ f
 11314 
 11314 
 11315     "Created: 10.6.1996 / 17:56:08 / cg"
 11315     "Created: 10.6.1996 / 17:56:08 / cg"
 11316     "Modified: 10.6.1996 / 20:11:27 / cg"
 11316     "Modified: 10.6.1996 / 20:11:27 / cg"
 11380 
 11380 
 11381 averageColor
 11381 averageColor
 11382     "return the average color of the image.
 11382     "return the average color of the image.
 11383      This usually only makes sense for textures and patterns
 11383      This usually only makes sense for textures and patterns
 11384      (i.e. to compute shadow & light colors for viewBackgrounds).
 11384      (i.e. to compute shadow & light colors for viewBackgrounds).
 11385      Notice, that for the above purpose, it is usually ok to process 
 11385      Notice, that for the above purpose, it is usually ok to process
 11386      a subImage - i.e. use Image>>averageColorIn: on a smaller rectangle"
 11386      a subImage - i.e. use Image>>averageColorIn: on a smaller rectangle"
 11387 
 11387 
 11388     ^ self averageColorIn:(0@0 corner:(width-1)@(height-1))
 11388     ^ self averageColorIn:(0@0 corner:(width-1)@(height-1))
 11389 !
 11389 !
 11390 
 11390 
 11391 averageColorIn:aRectangle
 11391 averageColorIn:aRectangle
 11392     "return the images average color in an area.
 11392     "return the images average color in an area.
 11393      The implementation below is slow - so you may want to
 11393      The implementation below is slow - so you may want to
 11394      create tuned versions for DepthXImage if you plan to do
 11394      create tuned versions for DepthXImage if you plan to do
 11395      heavy image processing ... 
 11395      heavy image processing ...
 11396      (also, creating tuned versions of the enumeration messages helps a lot)"
 11396      (also, creating tuned versions of the enumeration messages helps a lot)"
 11397 
 11397 
 11398     |x0 "{ Class:SmallInteger }"
 11398     |x0 "{ Class:SmallInteger }"
 11399      y0 "{ Class:SmallInteger }"
 11399      y0 "{ Class:SmallInteger }"
 11400      x1 "{ Class:SmallInteger }"
 11400      x1 "{ Class:SmallInteger }"
 11401      y1 "{ Class:SmallInteger }"
 11401      y1 "{ Class:SmallInteger }"
 11402      sumRed sumGreen sumBlue n|
 11402      sumRed sumGreen sumBlue n|
 11403 
 11403 
 11404     sumRed := sumGreen := sumBlue := 0.    
 11404     sumRed := sumGreen := sumBlue := 0.
 11405     y0 := aRectangle top.
 11405     y0 := aRectangle top.
 11406     y1 := aRectangle bottom.
 11406     y1 := aRectangle bottom.
 11407     x0 := aRectangle left.
 11407     x0 := aRectangle left.
 11408     x1 := aRectangle right.
 11408     x1 := aRectangle right.
 11409 
 11409 
 11410     n := (x1 - x0 + 1) * (y1 - y0 + 1).    
 11410     n := (x1 - x0 + 1) * (y1 - y0 + 1).
 11411     mask isNil ifTrue:[
 11411     mask isNil ifTrue:[
 11412 	self colorsFromX:x0 y:y0 toX:x1 y:y1 do:[:x :y :colorAtXY |
 11412 	self colorsFromX:x0 y:y0 toX:x1 y:y1 do:[:x :y :colorAtXY |
 11413 	    sumRed := sumRed + colorAtXY red.
 11413 	    sumRed := sumRed + colorAtXY red.
 11414 	    sumGreen := sumGreen + colorAtXY green.
 11414 	    sumGreen := sumGreen + colorAtXY green.
 11415 	    sumBlue := sumBlue + colorAtXY blue.
 11415 	    sumBlue := sumBlue + colorAtXY blue.
 11585 
 11585 
 11586     |p maxPixel clr r g b c m y k|
 11586     |p maxPixel clr r g b c m y k|
 11587 
 11587 
 11588     p := photometric.
 11588     p := photometric.
 11589     p isNil ifTrue:[
 11589     p isNil ifTrue:[
 11590         colorMap notNil ifTrue:[
 11590 	colorMap notNil ifTrue:[
 11591             p := #palette
 11591 	    p := #palette
 11592         ] ifFalse:[
 11592 	] ifFalse:[
 11593 "/            'Image [warning]: no photometric - assume greyscale' infoPrintCR
 11593 "/            'Image [warning]: no photometric - assume greyscale' infoPrintCR
 11594             p := #blackIs0
 11594 	    p := #blackIs0
 11595         ]
 11595 	]
 11596     ].
 11596     ].
 11597 
 11597 
 11598     p == #blackIs0 ifTrue:[
 11598     p == #blackIs0 ifTrue:[
 11599         maxPixel := (1 bitShift:self bitsPerPixel) - 1.
 11599 	maxPixel := (1 bitShift:self bitsPerPixel) - 1.
 11600         ^ Color gray:(pixelValue * (100 / maxPixel)).
 11600 	^ Color gray:(pixelValue * (100 / maxPixel)).
 11601     ].
 11601     ].
 11602 
 11602 
 11603     p == #whiteIs0 ifTrue:[
 11603     p == #whiteIs0 ifTrue:[
 11604         maxPixel := (1 bitShift:self bitsPerPixel) - 1.
 11604 	maxPixel := (1 bitShift:self bitsPerPixel) - 1.
 11605         ^ Color gray:100 - (pixelValue * (100 / maxPixel)).
 11605 	^ Color gray:100 - (pixelValue * (100 / maxPixel)).
 11606     ].
 11606     ].
 11607 
 11607 
 11608     p == #palette ifTrue:[
 11608     p == #palette ifTrue:[
 11609         pixelValue >= colorMap size ifTrue:[
 11609 	pixelValue >= colorMap size ifTrue:[
 11610             ^ Color black
 11610 	    ^ Color black
 11611         ].
 11611 	].
 11612         clr := colorMap at:(pixelValue + 1).
 11612 	clr := colorMap at:(pixelValue + 1).
 11613         clr isNil ifTrue:[
 11613 	clr isNil ifTrue:[
 11614             ^ Color black.
 11614 	    ^ Color black.
 11615         ].
 11615 	].
 11616         ^ clr.
 11616 	^ clr.
 11617     ].
 11617     ].
 11618 
 11618 
 11619     p == #rgb ifTrue:[
 11619     p == #rgb ifTrue:[
 11620         r := self redBitsOf:pixelValue.
 11620 	r := self redBitsOf:pixelValue.
 11621         g := self greenBitsOf:pixelValue.
 11621 	g := self greenBitsOf:pixelValue.
 11622         b := self blueBitsOf:pixelValue.
 11622 	b := self blueBitsOf:pixelValue.
 11623         "/ must scale to byte value...
 11623 	"/ must scale to byte value...
 11624         r := r bitShift:(8 - (bitsPerSample at:1)).
 11624 	r := r bitShift:(8 - (bitsPerSample at:1)).
 11625         g := g bitShift:(8 - (bitsPerSample at:2)).
 11625 	g := g bitShift:(8 - (bitsPerSample at:2)).
 11626         b := b bitShift:(8 - (bitsPerSample at:3)).
 11626 	b := b bitShift:(8 - (bitsPerSample at:3)).
 11627         ^ Color redByte:r greenByte:g blueByte:b
 11627 	^ Color redByte:r greenByte:g blueByte:b
 11628     ].
 11628     ].
 11629 
 11629 
 11630     p == #cmyk ifTrue:[
 11630     p == #cmyk ifTrue:[
 11631         c := self cyanComponentOfCMYK:pixelValue.
 11631 	c := self cyanComponentOfCMYK:pixelValue.
 11632         m := self magentaComponentOfCMYK:pixelValue.
 11632 	m := self magentaComponentOfCMYK:pixelValue.
 11633         y := self yellowComponentOfCMYK:pixelValue.
 11633 	y := self yellowComponentOfCMYK:pixelValue.
 11634         k := self blackComponentOfCMYK:pixelValue.
 11634 	k := self blackComponentOfCMYK:pixelValue.
 11635         ^ Color cyan:c magenta:m yellow:y black:k.
 11635 	^ Color cyan:c magenta:m yellow:y black:k.
 11636     ].
 11636     ].
 11637 
 11637 
 11638     p == #cmy ifTrue:[
 11638     p == #cmy ifTrue:[
 11639         c := self cyanComponentOfCMY:pixelValue.
 11639 	c := self cyanComponentOfCMY:pixelValue.
 11640         m := self magentaComponentOfCMY:pixelValue.
 11640 	m := self magentaComponentOfCMY:pixelValue.
 11641         y := self yellowComponentOfCMY:pixelValue.
 11641 	y := self yellowComponentOfCMY:pixelValue.
 11642         ^ Color cyan:c magenta:m yellow:y.
 11642 	^ Color cyan:c magenta:m yellow:y.
 11643     ].
 11643     ].
 11644 
 11644 
 11645     self error:'invalid (unsupported) photometric'
 11645     self error:'invalid (unsupported) photometric'
 11646 
 11646 
 11647     "Created: 8.6.1996 / 08:46:18 / cg"
 11647     "Created: 8.6.1996 / 08:46:18 / cg"
 11746     "return the shift amount used with translation from pixelValues to greenBits"
 11746     "return the shift amount used with translation from pixelValues to greenBits"
 11747 
 11747 
 11748     |greenBits|
 11748     |greenBits|
 11749 
 11749 
 11750     samplesPerPixel >= 3 ifTrue:[
 11750     samplesPerPixel >= 3 ifTrue:[
 11751         greenBits := bitsPerSample at:3.
 11751 	greenBits := bitsPerSample at:3.
 11752         ^ greenBits negated
 11752 	^ greenBits negated
 11753     ].
 11753     ].
 11754 
 11754 
 11755     self subclassResponsibility
 11755     self subclassResponsibility
 11756 !
 11756 !
 11757 
 11757 
 11844     "Modified: 24.4.1997 / 15:34:34 / cg"
 11844     "Modified: 24.4.1997 / 15:34:34 / cg"
 11845 !
 11845 !
 11846 
 11846 
 11847 realColorMap
 11847 realColorMap
 11848     "return a collection usable as a real colormap of the image.
 11848     "return a collection usable as a real colormap of the image.
 11849      For palette images, this is the internal colormap; 
 11849      For palette images, this is the internal colormap;
 11850      for other photometrics (which do not have a real colormap), synthesize one.
 11850      for other photometrics (which do not have a real colormap), synthesize one.
 11851      This is different from #colorMap, which returns nil for non palette images."
 11851      This is different from #colorMap, which returns nil for non palette images."
 11852 
 11852 
 11853     |d nEntries "{ Class: SmallInteger }"
 11853     |d nEntries "{ Class: SmallInteger }"
 11854      colorArray|
 11854      colorArray|
 11898 
 11898 
 11899     |set last|
 11899     |set last|
 11900 
 11900 
 11901     set := IdentitySet new.
 11901     set := IdentitySet new.
 11902     self valuesFromX:0 y:0 toX:(self width-1) y:(self height-1) do:[:x :y :pixel |
 11902     self valuesFromX:0 y:0 toX:(self width-1) y:(self height-1) do:[:x :y :pixel |
 11903         pixel ~~ last ifTrue:[
 11903 	pixel ~~ last ifTrue:[
 11904             set add:pixel.
 11904 	    set add:pixel.
 11905             last := pixel.
 11905 	    last := pixel.
 11906         ]
 11906 	]
 11907     ].
 11907     ].
 11908     ^ set
 11908     ^ set
 11909 
 11909 
 11910     "
 11910     "
 11911      (Image fromFile:'goodies/bitmaps/gifImages/garfield.gif') usedValues
 11911      (Image fromFile:'goodies/bitmaps/gifImages/garfield.gif') usedValues
 11958 	greenBits := bitsPerSample at:2.
 11958 	greenBits := bitsPerSample at:2.
 11959 	blueBits := bitsPerSample at:3.
 11959 	blueBits := bitsPerSample at:3.
 11960 
 11960 
 11961 	s := (1 bitShift:redBits) - 1.
 11961 	s := (1 bitShift:redBits) - 1.
 11962 
 11962 
 11963 	^ 100.0 / s * 
 11963 	^ 100.0 / s *
 11964 	  ((pixel bitShift:(greenBits + blueBits) negated)
 11964 	  ((pixel bitShift:(greenBits + blueBits) negated)
 11965 	   bitAnd:(1 bitShift:redBits)-1)
 11965 	   bitAnd:(1 bitShift:redBits)-1)
 11966     ].
 11966     ].
 11967 
 11967 
 11968     self subclassResponsibility
 11968     self subclassResponsibility
 12010 
 12010 
 12011     |p maxPixel clr r g b c m y k|
 12011     |p maxPixel clr r g b c m y k|
 12012 
 12012 
 12013     p := photometric.
 12013     p := photometric.
 12014     p isNil ifTrue:[
 12014     p isNil ifTrue:[
 12015         colorMap notNil ifTrue:[
 12015 	colorMap notNil ifTrue:[
 12016             p := #palette
 12016 	    p := #palette
 12017         ] ifFalse:[
 12017 	] ifFalse:[
 12018 "/            'Image [warning]: no photometric - assume greyscale' infoPrintCR
 12018 "/            'Image [warning]: no photometric - assume greyscale' infoPrintCR
 12019             p := #blackIs0
 12019 	    p := #blackIs0
 12020         ]
 12020 	]
 12021     ].
 12021     ].
 12022 
 12022 
 12023     p == #blackIs0 ifTrue:[
 12023     p == #blackIs0 ifTrue:[
 12024         maxPixel := (1 bitShift:self bitsPerPixel) - 1.
 12024 	maxPixel := (1 bitShift:self bitsPerPixel) - 1.
 12025         b := pixelValue * 255 // maxPixel.
 12025 	b := pixelValue * 255 // maxPixel.
 12026         ^ (((b bitShift:8) bitOr:b) bitShift:8) bitOr:b
 12026 	^ (((b bitShift:8) bitOr:b) bitShift:8) bitOr:b
 12027     ].
 12027     ].
 12028 
 12028 
 12029     p == #whiteIs0 ifTrue:[
 12029     p == #whiteIs0 ifTrue:[
 12030         maxPixel := (1 bitShift:self bitsPerPixel) - 1.
 12030 	maxPixel := (1 bitShift:self bitsPerPixel) - 1.
 12031         b := 255 - (pixelValue * 255 // maxPixel).
 12031 	b := 255 - (pixelValue * 255 // maxPixel).
 12032         ^ (((b bitShift:8) bitOr:b) bitShift:8) bitOr:b
 12032 	^ (((b bitShift:8) bitOr:b) bitShift:8) bitOr:b
 12033     ].
 12033     ].
 12034 
 12034 
 12035     p == #palette ifTrue:[
 12035     p == #palette ifTrue:[
 12036         pixelValue >= colorMap size ifTrue:[
 12036 	pixelValue >= colorMap size ifTrue:[
 12037             ^ 0 "/ black
 12037 	    ^ 0 "/ black
 12038         ].
 12038 	].
 12039         clr := colorMap at:(pixelValue + 1).
 12039 	clr := colorMap at:(pixelValue + 1).
 12040         clr isNil ifTrue:[
 12040 	clr isNil ifTrue:[
 12041             ^ 0 "/ black
 12041 	    ^ 0 "/ black
 12042         ].
 12042 	].
 12043         ^ clr rgbValue.
 12043 	^ clr rgbValue.
 12044     ].
 12044     ].
 12045 
 12045 
 12046     p == #rgb ifTrue:[
 12046     p == #rgb ifTrue:[
 12047         r := self redBitsOf:pixelValue.
 12047 	r := self redBitsOf:pixelValue.
 12048         g := self greenBitsOf:pixelValue.
 12048 	g := self greenBitsOf:pixelValue.
 12049         b := self blueBitsOf:pixelValue.
 12049 	b := self blueBitsOf:pixelValue.
 12050         "/ must scale to byte value...
 12050 	"/ must scale to byte value...
 12051         r := r bitShift:(8 - (bitsPerSample at:1)).
 12051 	r := r bitShift:(8 - (bitsPerSample at:1)).
 12052         g := g bitShift:(8 - (bitsPerSample at:2)).
 12052 	g := g bitShift:(8 - (bitsPerSample at:2)).
 12053         b := b bitShift:(8 - (bitsPerSample at:3)).
 12053 	b := b bitShift:(8 - (bitsPerSample at:3)).
 12054         ^ (((r bitShift:8) bitOr:g) bitShift:8) bitOr:b
 12054 	^ (((r bitShift:8) bitOr:g) bitShift:8) bitOr:b
 12055     ].
 12055     ].
 12056 
 12056 
 12057     p == #cmyk ifTrue:[
 12057     p == #cmyk ifTrue:[
 12058         c := self cyanComponentOfCMYK:pixelValue.
 12058 	c := self cyanComponentOfCMYK:pixelValue.
 12059         m := self magentaComponentOfCMYK:pixelValue.
 12059 	m := self magentaComponentOfCMYK:pixelValue.
 12060         y := self yellowComponentOfCMYK:pixelValue.
 12060 	y := self yellowComponentOfCMYK:pixelValue.
 12061         k := self blackComponentOfCMYK:pixelValue.
 12061 	k := self blackComponentOfCMYK:pixelValue.
 12062         ^ (Color cyan:c magenta:m yellow:y black:k) rgbValue.
 12062 	^ (Color cyan:c magenta:m yellow:y black:k) rgbValue.
 12063     ].
 12063     ].
 12064 
 12064 
 12065     p == #cmy ifTrue:[
 12065     p == #cmy ifTrue:[
 12066         c := self cyanComponentOfCMY:pixelValue.
 12066 	c := self cyanComponentOfCMY:pixelValue.
 12067         m := self magentaComponentOfCMY:pixelValue.
 12067 	m := self magentaComponentOfCMY:pixelValue.
 12068         y := self yellowComponentOfCMY:pixelValue.
 12068 	y := self yellowComponentOfCMY:pixelValue.
 12069         ^ (Color cyan:c magenta:m yellow:y) rgbValue.
 12069 	^ (Color cyan:c magenta:m yellow:y) rgbValue.
 12070     ].
 12070     ].
 12071 
 12071 
 12072     self error:'invalid (unsupported) photometric'
 12072     self error:'invalid (unsupported) photometric'
 12073 !
 12073 !
 12074 
 12074 
 12079 
 12079 
 12080     |colors|
 12080     |colors|
 12081 
 12081 
 12082     colors := self usedColorsMax:4096.
 12082     colors := self usedColorsMax:4096.
 12083     colors isNil ifTrue:[
 12083     colors isNil ifTrue:[
 12084         self error:'too many colors in image'.
 12084 	self error:'too many colors in image'.
 12085     ].
 12085     ].
 12086     ^ colors
 12086     ^ colors
 12087 
 12087 
 12088     "
 12088     "
 12089      (Image fromFile:'goodies/bitmaps/gifImages/garfield.gif') usedColors
 12089      (Image fromFile:'goodies/bitmaps/gifImages/garfield.gif') usedColors
 12101      (useful when searching rgb images)."
 12101      (useful when searching rgb images)."
 12102 
 12102 
 12103     |usedValues max colors|
 12103     |usedValues max colors|
 12104 
 12104 
 12105     photometric == #rgb ifTrue:[
 12105     photometric == #rgb ifTrue:[
 12106         usedValues := IdentitySet new.
 12106 	usedValues := IdentitySet new.
 12107         self valuesFromX:0 y:0 toX:(width-1) y:(height-1)
 12107 	self valuesFromX:0 y:0 toX:(width-1) y:(height-1)
 12108           do:[:x :y :pixel |
 12108 	  do:[:x :y :pixel |
 12109             usedValues add:pixel.
 12109 	    usedValues add:pixel.
 12110             usedValues size > nMax ifTrue:[
 12110 	    usedValues size > nMax ifTrue:[
 12111                 "/ too many to be returned here (think of the mass of
 12111 		"/ too many to be returned here (think of the mass of
 12112                 "/ data to be returned by a 24bit image ... ;-)
 12112 		"/ data to be returned by a 24bit image ... ;-)
 12113                 ^ nil
 12113 		^ nil
 12114             ]
 12114 	    ]
 12115         ].
 12115 	].
 12116         "/ code below is slightly faster ...
 12116 	"/ code below is slightly faster ...
 12117         "/ colors := usedValues collect:[:pixel | self colorFromValue:pixel].
 12117 	"/ colors := usedValues collect:[:pixel | self colorFromValue:pixel].
 12118         colors := usedValues collect:[:pixel | |r g b|
 12118 	colors := usedValues collect:[:pixel | |r g b|
 12119                                         r := self redBitsOf:pixel.
 12119 					r := self redBitsOf:pixel.
 12120                                         g := self greenBitsOf:pixel.
 12120 					g := self greenBitsOf:pixel.
 12121                                         b := self blueBitsOf:pixel.
 12121 					b := self blueBitsOf:pixel.
 12122                                         "/ must scale to byte value...
 12122 					"/ must scale to byte value...
 12123                                         r := r bitShift:(8 - (bitsPerSample at:1)).
 12123 					r := r bitShift:(8 - (bitsPerSample at:1)).
 12124                                         g := g bitShift:(8 - (bitsPerSample at:2)).
 12124 					g := g bitShift:(8 - (bitsPerSample at:2)).
 12125                                         b := b bitShift:(8 - (bitsPerSample at:3)).
 12125 					b := b bitShift:(8 - (bitsPerSample at:3)).
 12126                                         Color redByte:r greenByte:g blueByte:b
 12126 					Color redByte:r greenByte:g blueByte:b
 12127                                      ].
 12127 				     ].
 12128         ^ colors.                
 12128 	^ colors.
 12129     ].
 12129     ].
 12130 
 12130 
 12131     usedValues := self usedValues asArray.
 12131     usedValues := self usedValues asArray.
 12132     photometric == #palette ifTrue:[
 12132     photometric == #palette ifTrue:[
 12133         colors := usedValues collect:[:val | (colorMap at:val+1 ifAbsent:[Color black])].
 12133 	colors := usedValues collect:[:val | (colorMap at:val+1 ifAbsent:[Color black])].
 12134     ] ifFalse:[
 12134     ] ifFalse:[
 12135         "/ (photometric == #blackIs0 or:[photometric == #whiteIs0])
 12135 	"/ (photometric == #blackIs0 or:[photometric == #whiteIs0])
 12136 
 12136 
 12137         max := (1 bitShift:self depth) - 1.
 12137 	max := (1 bitShift:self depth) - 1.
 12138         colors :=  usedValues collect:[:val | (Color gray:(100 * val / max ))].
 12138 	colors :=  usedValues collect:[:val | (Color gray:(100 * val / max ))].
 12139     ].
 12139     ].
 12140     ^ colors asSet
 12140     ^ colors asSet
 12141 
 12141 
 12142     "
 12142     "
 12143      (Image fromFile:'goodies/bitmaps/gifImages/garfield.gif') usedColors
 12143      (Image fromFile:'goodies/bitmaps/gifImages/garfield.gif') usedColors
 12195     photometric == #rgb ifTrue:[
 12195     photometric == #rgb ifTrue:[
 12196 	samplesPerPixel >= 3 ifTrue:[
 12196 	samplesPerPixel >= 3 ifTrue:[
 12197 	    redBits := bitsPerSample at:1.
 12197 	    redBits := bitsPerSample at:1.
 12198 	    greenBits := bitsPerSample at:2.
 12198 	    greenBits := bitsPerSample at:2.
 12199 	    blueBits := bitsPerSample at:3.
 12199 	    blueBits := bitsPerSample at:3.
 12200         
 12200 
 12201 	    "/ map r/g/b to 0..255
 12201 	    "/ map r/g/b to 0..255
 12202 	    r := (color red / 100.0 * ((1 bitShift:redBits)-1)) rounded.
 12202 	    r := (color red / 100.0 * ((1 bitShift:redBits)-1)) rounded.
 12203 	    g := (color green / 100.0 * ((1 bitShift:greenBits)-1)) rounded.
 12203 	    g := (color green / 100.0 * ((1 bitShift:greenBits)-1)) rounded.
 12204 	    b := (color blue / 100.0 * ((1 bitShift:blueBits)-1)) rounded.
 12204 	    b := (color blue / 100.0 * ((1 bitShift:blueBits)-1)) rounded.
 12205 	    pixel := (((r bitShift:greenBits) + g) bitShift:blueBits) + b.
 12205 	    pixel := (((r bitShift:greenBits) + g) bitShift:blueBits) + b.
 12222 
 12222 
 12223     photometric == #rgb ifTrue:[
 12223     photometric == #rgb ifTrue:[
 12224 	samplesPerPixel >= 3 ifTrue:[
 12224 	samplesPerPixel >= 3 ifTrue:[
 12225 	    numGreenBits := bitsPerSample at:2.
 12225 	    numGreenBits := bitsPerSample at:2.
 12226 	    numBlueBits := bitsPerSample at:3.
 12226 	    numBlueBits := bitsPerSample at:3.
 12227         
 12227 
 12228 	    pixel := (((redBits bitShift:numGreenBits) + greenBits) bitShift:numBlueBits) + blueBits.
 12228 	    pixel := (((redBits bitShift:numGreenBits) + greenBits) bitShift:numBlueBits) + blueBits.
 12229 	    ^ pixel
 12229 	    ^ pixel
 12230 	]
 12230 	]
 12231     ].
 12231     ].
 12232 
 12232 
 12281 ! !
 12281 ! !
 12282 
 12282 
 12283 !Image methodsFor:'saving on file'!
 12283 !Image methodsFor:'saving on file'!
 12284 
 12284 
 12285 saveOn:aFileName
 12285 saveOn:aFileName
 12286     "save the image in aFileName. The suffix of the filename controls the format. 
 12286     "save the image in aFileName. The suffix of the filename controls the format.
 12287      Currently, not all formats may be supported
 12287      Currently, not all formats may be supported
 12288      (see ImageReader subclasses implementing save:onFile:).
 12288      (see ImageReader subclasses implementing save:onFile:).
 12289      May raise a signal, if the image cannot be written by the reader."
 12289      May raise a signal, if the image cannot be written by the reader."
 12290 
 12290 
 12291     |suffix readerClass|
 12291     |suffix readerClass|
 12320 
 12320 
 12321     "Modified: 30.6.1997 / 22:06:34 / cg"
 12321     "Modified: 30.6.1997 / 22:06:34 / cg"
 12322 !
 12322 !
 12323 
 12323 
 12324 saveOn:aFileName using:readerClass
 12324 saveOn:aFileName using:readerClass
 12325     "save the receiver using the representation class 
 12325     "save the receiver using the representation class
 12326      (which is usually a concrete subclasses of ImageReader).
 12326      (which is usually a concrete subclasses of ImageReader).
 12327      May raise a signal, if the image cannot be written by the reader."
 12327      May raise a signal, if the image cannot be written by the reader."
 12328 
 12328 
 12329     ^ readerClass save:self onFile:aFileName
 12329     ^ readerClass save:self onFile:aFileName
 12330 
 12330 
 12378      If its a view or rootView, it must be completely visible (or have
 12378      If its a view or rootView, it must be completely visible (or have
 12379      the backingStore option turned on). Otherwise, only the clipped contents
 12379      the backingStore option turned on). Otherwise, only the clipped contents
 12380      is returned. This is a common helper for form-to-image conversion,
 12380      is returned. This is a common helper for form-to-image conversion,
 12381      and to read hardcopy images from the screen."
 12381      and to read hardcopy images from the screen."
 12382 
 12382 
 12383     | visType 
 12383     | visType
 12384      x        "{ Class: SmallInteger }"
 12384      x        "{ Class: SmallInteger }"
 12385      y        "{ Class: SmallInteger }"
 12385      y        "{ Class: SmallInteger }"
 12386      w        "{ Class: SmallInteger }"
 12386      w        "{ Class: SmallInteger }"
 12387      h        "{ Class: SmallInteger }"
 12387      h        "{ Class: SmallInteger }"
 12388      dstIndex "{ Class: SmallInteger }" 
 12388      dstIndex "{ Class: SmallInteger }"
 12389      srcIndex "{ Class: SmallInteger }" 
 12389      srcIndex "{ Class: SmallInteger }"
 12390      srcRow   "{ Class: SmallInteger }"
 12390      srcRow   "{ Class: SmallInteger }"
 12391      dstRow   "{ Class: SmallInteger }"
 12391      dstRow   "{ Class: SmallInteger }"
 12392      inData tmpData usedPixels mapSize 
 12392      inData tmpData usedPixels mapSize
 12393      map bytesPerLine 
 12393      map bytesPerLine
 12394      bitOrder spaceBitsPerPixel
 12394      bitOrder spaceBitsPerPixel
 12395      info bitsPerPixelIn bytesPerLineIn 
 12395      info bitsPerPixelIn bytesPerLineIn
 12396      bitsR "{ Class: SmallInteger }"
 12396      bitsR "{ Class: SmallInteger }"
 12397      bitsG "{ Class: SmallInteger }"
 12397      bitsG "{ Class: SmallInteger }"
 12398      bitsB "{ Class: SmallInteger }"
 12398      bitsB "{ Class: SmallInteger }"
 12399      maskR "{ Class: SmallInteger }"
 12399      maskR "{ Class: SmallInteger }"
 12400      maskG "{ Class: SmallInteger }"
 12400      maskG "{ Class: SmallInteger }"
 12407      shB2 "{ Class: SmallInteger }"
 12407      shB2 "{ Class: SmallInteger }"
 12408      r "{ Class: SmallInteger }"
 12408      r "{ Class: SmallInteger }"
 12409      g "{ Class: SmallInteger }"
 12409      g "{ Class: SmallInteger }"
 12410      b "{ Class: SmallInteger }"
 12410      b "{ Class: SmallInteger }"
 12411      word "{ Class: SmallInteger }"
 12411      word "{ Class: SmallInteger }"
 12412      lword 
 12412      lword
 12413      device ddepth isMSB|
 12413      device ddepth isMSB|
 12414 
 12414 
 12415     depth := self depth.
 12415     depth := self depth.
 12416     bitsPerPixel := self bitsPerPixel.
 12416     bitsPerPixel := self bitsPerPixel.
 12417 
 12417 
 12418     device := aDrawable graphicsDevice.
 12418     device := aDrawable graphicsDevice.
 12419 
 12419 
 12420     (aDrawable isForm and:[aDrawable depth == 1]) ifTrue:[
 12420     (aDrawable isForm and:[aDrawable depth == 1]) ifTrue:[
 12421         "/ a monochrome bitmap ?
 12421 	"/ a monochrome bitmap ?
 12422         visType := #StaticGray.
 12422 	visType := #StaticGray.
 12423         ddepth := 1.
 12423 	ddepth := 1.
 12424     ] ifFalse:[
 12424     ] ifFalse:[
 12425         (aDrawable isForm) ifFalse:[
 12425 	(aDrawable isForm) ifFalse:[
 12426             "
 12426 	    "
 12427              get some attributes of the display device
 12427 	     get some attributes of the display device
 12428             "
 12428 	    "
 12429             visType := device visualType.
 12429 	    visType := device visualType.
 12430             ddepth := device depth.
 12430 	    ddepth := device depth.
 12431         ] ifTrue:[
 12431 	] ifTrue:[
 12432             ddepth := aDrawable depth.
 12432 	    ddepth := aDrawable depth.
 12433             visType := aDrawable photometric
 12433 	    visType := aDrawable photometric
 12434         ].
 12434 	].
 12435     ].
 12435     ].
 12436 
 12436 
 12437     "/ kludge for 15bit XFree server
 12437     "/ kludge for 15bit XFree server
 12438     ddepth == 15 ifTrue:[
 12438     ddepth == 15 ifTrue:[
 12439         ddepth := 16
 12439 	ddepth := 16
 12440     ].
 12440     ].
 12441 
 12441 
 12442     aDrawable isForm ifTrue:[
 12442     aDrawable isForm ifTrue:[
 12443         photometric := aDrawable photometric.
 12443 	photometric := aDrawable photometric.
 12444         samplesPerPixel := ddepth == 24 ifTrue:3 ifFalse:1.
 12444 	samplesPerPixel := ddepth == 24 ifTrue:3 ifFalse:1.
 12445         bitsPerSample := ddepth == 24 ifTrue:#[8 8 8 ] ifFalse:[ByteArray with:bitsPerPixel].
 12445 	bitsPerSample := ddepth == 24 ifTrue:#[8 8 8 ] ifFalse:[ByteArray with:bitsPerPixel].
 12446     ] ifFalse:[
 12446     ] ifFalse:[
 12447         (visType == #StaticGray) ifTrue:[
 12447 	(visType == #StaticGray) ifTrue:[
 12448             (device blackpixel == 0) ifTrue:[
 12448 	    (device blackpixel == 0) ifTrue:[
 12449                 photometric := #blackIs0
 12449 		photometric := #blackIs0
 12450             ] ifFalse:[
 12450 	    ] ifFalse:[
 12451                 photometric := #whiteIs0
 12451 		photometric := #whiteIs0
 12452             ].
 12452 	    ].
 12453             samplesPerPixel := 1.
 12453 	    samplesPerPixel := 1.
 12454             bitsPerPixel := ddepth.
 12454 	    bitsPerPixel := ddepth.
 12455             bitsPerSample := ByteArray with:bitsPerPixel.
 12455 	    bitsPerSample := ByteArray with:bitsPerPixel.
 12456         ] ifFalse:[
 12456 	] ifFalse:[
 12457             ((visType == #PseudoColor) or:[(visType == #StaticColor) or:[visType == #GrayScale]]) ifTrue:[
 12457 	    ((visType == #PseudoColor) or:[(visType == #StaticColor) or:[visType == #GrayScale]]) ifTrue:[
 12458                 photometric := #palette.
 12458 		photometric := #palette.
 12459                 samplesPerPixel := 1.
 12459 		samplesPerPixel := 1.
 12460                 bitsPerPixel := ddepth.
 12460 		bitsPerPixel := ddepth.
 12461                 bitsPerSample := ByteArray with:bitsPerPixel.
 12461 		bitsPerSample := ByteArray with:bitsPerPixel.
 12462             ] ifFalse:[
 12462 	    ] ifFalse:[
 12463                 ((visType == #TrueColor) or:[visType == #DirectColor]) ifTrue:[
 12463 		((visType == #TrueColor) or:[visType == #DirectColor]) ifTrue:[
 12464                     photometric := #rgb.
 12464 		    photometric := #rgb.
 12465                     samplesPerPixel := 3.
 12465 		    samplesPerPixel := 3.
 12466     "/                bitsPerPixel := depth.
 12466     "/                bitsPerPixel := depth.
 12467     "/                bitsPerSample := ByteArray with:device bitsRed
 12467     "/                bitsPerSample := ByteArray with:device bitsRed
 12468     "/                                       with:device bitsGreen
 12468     "/                                       with:device bitsGreen
 12469     "/                                       with:device bitsBlue
 12469     "/                                       with:device bitsBlue
 12470                     bitsPerPixel := 24.
 12470 		    bitsPerPixel := 24.
 12471                     bitsPerSample := #(8 8 8).
 12471 		    bitsPerSample := #(8 8 8).
 12472                 ] ifFalse:[
 12472 		] ifFalse:[
 12473                     self error:'screen visual not supported'.
 12473 		    self error:'screen visual not supported'.
 12474                     ^ nil
 12474 		    ^ nil
 12475                 ]
 12475 		]
 12476             ]
 12476 	    ]
 12477         ].
 12477 	].
 12478     ].
 12478     ].
 12479 
 12479 
 12480     "
 12480     "
 12481      dont know yet, how the display pads; assume worst case, 
 12481      dont know yet, how the display pads; assume worst case,
 12482      offering enough space for 32 bit padding
 12482      offering enough space for 32 bit padding
 12483     "
 12483     "
 12484     w := width := aRectangle width.
 12484     w := width := aRectangle width.
 12485     h := height := aRectangle height.
 12485     h := height := aRectangle height.
 12486     x := aRectangle left.
 12486     x := aRectangle left.
 12490      a kludge: we dont know in advance how much we are going to need
 12490      a kludge: we dont know in advance how much we are going to need
 12491      (its too late when info is present ...)
 12491      (its too late when info is present ...)
 12492     "
 12492     "
 12493     spaceBitsPerPixel := bitsPerPixel.
 12493     spaceBitsPerPixel := bitsPerPixel.
 12494     (bitsPerPixel > 8) ifTrue:[
 12494     (bitsPerPixel > 8) ifTrue:[
 12495         spaceBitsPerPixel := 16.
 12495 	spaceBitsPerPixel := 16.
 12496         (bitsPerPixel > 16) ifTrue:[
 12496 	(bitsPerPixel > 16) ifTrue:[
 12497             spaceBitsPerPixel := 32.
 12497 	    spaceBitsPerPixel := 32.
 12498             (bitsPerPixel > 32) ifTrue:[
 12498 	    (bitsPerPixel > 32) ifTrue:[
 12499                 spaceBitsPerPixel := bitsPerPixel.
 12499 		spaceBitsPerPixel := bitsPerPixel.
 12500             ]
 12500 	    ]
 12501         ]
 12501 	]
 12502     ].
 12502     ].
 12503 
 12503 
 12504     bytesPerLine := (w * spaceBitsPerPixel + 31) // 32 * 4.
 12504     bytesPerLine := (w * spaceBitsPerPixel + 31) // 32 * 4.
 12505     "/ inData := ByteArray uninitializedNew:(bytesPerLine * height).
 12505     "/ inData := ByteArray uninitializedNew:(bytesPerLine * height).
 12506     inData := ByteArray new:(bytesPerLine * height).
 12506     inData := ByteArray new:(bytesPerLine * height).
 12507 
 12507 
 12508     "
 12508     "
 12509      get the pixels
 12509      get the pixels
 12510     "
 12510     "
 12511     aDrawable isForm ifTrue:[
 12511     aDrawable isForm ifTrue:[
 12512         info := device getBitsFromPixmapId:aDrawable id x:x y:y width:w height:h into:inData. 
 12512 	info := device getBitsFromPixmapId:aDrawable id x:x y:y width:w height:h into:inData.
 12513     ] ifFalse:[
 12513     ] ifFalse:[
 12514         info := device getBitsFromViewId:aDrawable id x:x y:y width:w height:h into:inData. 
 12514 	info := device getBitsFromViewId:aDrawable id x:x y:y width:w height:h into:inData.
 12515     ].
 12515     ].
 12516 
 12516 
 12517     bitsPerPixelIn := info at:#bitsPerPixel.
 12517     bitsPerPixelIn := info at:#bitsPerPixel.
 12518 
 12518 
 12519     isMSB := ((info at:#byteOrder) == #msbFirst).
 12519     isMSB := ((info at:#byteOrder) == #msbFirst).
 12522     "/ check if bitorder is what I like (msbFirst)
 12522     "/ check if bitorder is what I like (msbFirst)
 12523     "/
 12523     "/
 12524     "/ mhmh - thats not needed
 12524     "/ mhmh - thats not needed
 12525 
 12525 
 12526     bitsPerPixelIn < 8 ifTrue:[
 12526     bitsPerPixelIn < 8 ifTrue:[
 12527         bitOrder := info at:#bitOrder.
 12527 	bitOrder := info at:#bitOrder.
 12528         bitOrder ~~ #msbFirst ifTrue:[
 12528 	bitOrder ~~ #msbFirst ifTrue:[
 12529             inData 
 12529 	    inData
 12530                 expandPixels:8 
 12530 		expandPixels:8
 12531                 width:(inData size)
 12531 		width:(inData size)
 12532                 height:1 
 12532 		height:1
 12533                 into:inData
 12533 		into:inData
 12534                 mapping:(ImageReader reverseBits "TODO: reverseBitsForDepth:bitsPerPixelIn").
 12534 		mapping:(ImageReader reverseBits "TODO: reverseBitsForDepth:bitsPerPixelIn").
 12535         ].
 12535 	].
 12536     ].
 12536     ].
 12537 
 12537 
 12538     "
 12538     "
 12539      check, if the devices padding is different ..
 12539      check, if the devices padding is different ..
 12540      or if the bitsPerPixels are different
 12540      or if the bitsPerPixels are different
 12544 
 12544 
 12545     maskR := info at:#redMask ifAbsent:0.
 12545     maskR := info at:#redMask ifAbsent:0.
 12546     maskG := info at:#greenMask ifAbsent:0.
 12546     maskG := info at:#greenMask ifAbsent:0.
 12547     maskB := info at:#blueMask ifAbsent:0.
 12547     maskB := info at:#blueMask ifAbsent:0.
 12548 
 12548 
 12549     ((bytesPerLine ~~ bytesPerLineIn) 
 12549     ((bytesPerLine ~~ bytesPerLineIn)
 12550     or:[bitsPerPixelIn ~~ bitsPerPixel]) ifTrue:[
 12550     or:[bitsPerPixelIn ~~ bitsPerPixel]) ifTrue:[
 12551         tmpData := inData.
 12551 	tmpData := inData.
 12552         inData := ByteArray uninitializedNew:(bytesPerLine * height).
 12552 	inData := ByteArray uninitializedNew:(bytesPerLine * height).
 12553 
 12553 
 12554         srcRow := 1.
 12554 	srcRow := 1.
 12555         dstRow := 1.
 12555 	dstRow := 1.
 12556 
 12556 
 12557         bitsPerPixelIn ~~ bitsPerPixel ifTrue:[
 12557 	bitsPerPixelIn ~~ bitsPerPixel ifTrue:[
 12558             "/ for now, only 32 -> 24 is supported
 12558 	    "/ for now, only 32 -> 24 is supported
 12559                 
 12559 
 12560             maskR == 0 ifTrue:[
 12560 	    maskR == 0 ifTrue:[
 12561                 bitsR := device bitsRed.
 12561 		bitsR := device bitsRed.
 12562                 bitsG := device bitsGreen.
 12562 		bitsG := device bitsGreen.
 12563                 bitsB := device bitsBlue.
 12563 		bitsB := device bitsBlue.
 12564                 maskR := (1 bitShift:bitsR) - 1.
 12564 		maskR := (1 bitShift:bitsR) - 1.
 12565                 maskG := (1 bitShift:bitsG) - 1.
 12565 		maskG := (1 bitShift:bitsG) - 1.
 12566                 maskB := (1 bitShift:bitsB) - 1.
 12566 		maskB := (1 bitShift:bitsB) - 1.
 12567                 shR := device shiftRed negated.
 12567 		shR := device shiftRed negated.
 12568                 shG := device shiftGreen negated.
 12568 		shG := device shiftGreen negated.
 12569                 shB := device shiftBlue negated.
 12569 		shB := device shiftBlue negated.
 12570             ] ifFalse:[
 12570 	    ] ifFalse:[
 12571                 shR := (maskR lowBit - 1) negated.
 12571 		shR := (maskR lowBit - 1) negated.
 12572                 bitsR := maskR highBit - maskR lowBit + 1.
 12572 		bitsR := maskR highBit - maskR lowBit + 1.
 12573                 maskR := maskR bitShift:shR.
 12573 		maskR := maskR bitShift:shR.
 12574                 shG := (maskG lowBit - 1) negated.
 12574 		shG := (maskG lowBit - 1) negated.
 12575                 bitsG := maskG highBit - maskG lowBit + 1.
 12575 		bitsG := maskG highBit - maskG lowBit + 1.
 12576                 maskG := maskG bitShift:shG.
 12576 		maskG := maskG bitShift:shG.
 12577                 shB := (maskB lowBit - 1) negated.
 12577 		shB := (maskB lowBit - 1) negated.
 12578                 bitsB := maskB highBit - maskB lowBit + 1.
 12578 		bitsB := maskB highBit - maskB lowBit + 1.
 12579                 maskB := maskB bitShift:shB.
 12579 		maskB := maskB bitShift:shB.
 12580             ].
 12580 	    ].
 12581             shR2 := (8 - bitsR).
 12581 	    shR2 := (8 - bitsR).
 12582             shG2 := (8 - bitsG).
 12582 	    shG2 := (8 - bitsG).
 12583             shB2 := (8 - bitsB).
 12583 	    shB2 := (8 - bitsB).
 12584 
 12584 
 12585             ((bitsPerPixelIn == 32) and:[bitsPerPixel == 24]) ifTrue:[
 12585 	    ((bitsPerPixelIn == 32) and:[bitsPerPixel == 24]) ifTrue:[
 12586                 "/ 'reformatting 32->24...' printNL.
 12586 		"/ 'reformatting 32->24...' printNL.
 12587                 1 to:h do:[:hi |
 12587 		1 to:h do:[:hi |
 12588                     srcIndex := srcRow.
 12588 		    srcIndex := srcRow.
 12589                     dstIndex := dstRow.
 12589 		    dstIndex := dstRow.
 12590 
 12590 
 12591                     1 to:w do:[:wi |
 12591 		    1 to:w do:[:wi |
 12592                         lword := tmpData doubleWordAt:srcIndex MSB:isMSB.
 12592 			lword := tmpData doubleWordAt:srcIndex MSB:isMSB.
 12593                         r := (lword bitShift:shR) bitAnd:maskR.
 12593 			r := (lword bitShift:shR) bitAnd:maskR.
 12594                         g := (lword bitShift:shG) bitAnd:maskG.
 12594 			g := (lword bitShift:shG) bitAnd:maskG.
 12595                         b := (lword bitShift:shB) bitAnd:maskB.
 12595 			b := (lword bitShift:shB) bitAnd:maskB.
 12596 
 12596 
 12597                         inData at:dstIndex   put:r.
 12597 			inData at:dstIndex   put:r.
 12598                         inData at:dstIndex+1 put:g.
 12598 			inData at:dstIndex+1 put:g.
 12599                         inData at:dstIndex+2 put:b.
 12599 			inData at:dstIndex+2 put:b.
 12600                         srcIndex := srcIndex + 4.
 12600 			srcIndex := srcIndex + 4.
 12601                         dstIndex := dstIndex + 3.
 12601 			dstIndex := dstIndex + 3.
 12602                     ].
 12602 		    ].
 12603                     dstRow := dstRow + bytesPerLine.
 12603 		    dstRow := dstRow + bytesPerLine.
 12604                     srcRow := srcRow + bytesPerLineIn
 12604 		    srcRow := srcRow + bytesPerLineIn
 12605                 ]
 12605 		]
 12606             ] ifFalse:[
 12606 	    ] ifFalse:[
 12607                 ((bitsPerPixelIn == 16) and:[bitsPerPixel == 24]) ifTrue:[
 12607 		((bitsPerPixelIn == 16) and:[bitsPerPixel == 24]) ifTrue:[
 12608                     "/ 'reformatting 16->24...' printNL.
 12608 		    "/ 'reformatting 16->24...' printNL.
 12609                     1 to:h do:[:hi |
 12609 		    1 to:h do:[:hi |
 12610                         srcIndex := srcRow.
 12610 			srcIndex := srcRow.
 12611                         dstIndex := dstRow.
 12611 			dstIndex := dstRow.
 12612 
 12612 
 12613                         1 to:w do:[:wi |
 12613 			1 to:w do:[:wi |
 12614                             word := tmpData wordAt:srcIndex MSB:isMSB.
 12614 			    word := tmpData wordAt:srcIndex MSB:isMSB.
 12615                             r := (word bitShift:shR) bitAnd:maskR.
 12615 			    r := (word bitShift:shR) bitAnd:maskR.
 12616                             g := (word bitShift:shG) bitAnd:maskG.
 12616 			    g := (word bitShift:shG) bitAnd:maskG.
 12617                             b := (word bitShift:shB) bitAnd:maskB.
 12617 			    b := (word bitShift:shB) bitAnd:maskB.
 12618 
 12618 
 12619                             inData at:dstIndex   put:(r bitShift:shR2).
 12619 			    inData at:dstIndex   put:(r bitShift:shR2).
 12620                             inData at:dstIndex+1 put:(g bitShift:shG2).
 12620 			    inData at:dstIndex+1 put:(g bitShift:shG2).
 12621                             inData at:dstIndex+2 put:(b bitShift:shB2).
 12621 			    inData at:dstIndex+2 put:(b bitShift:shB2).
 12622 
 12622 
 12623                             srcIndex := srcIndex + 2.
 12623 			    srcIndex := srcIndex + 2.
 12624                             dstIndex := dstIndex + 3.
 12624 			    dstIndex := dstIndex + 3.
 12625                         ].
 12625 			].
 12626                         dstRow := dstRow + bytesPerLine.
 12626 			dstRow := dstRow + bytesPerLine.
 12627                         srcRow := srcRow + bytesPerLineIn
 12627 			srcRow := srcRow + bytesPerLineIn
 12628                     ]
 12628 		    ]
 12629                 ] ifFalse:[
 12629 		] ifFalse:[
 12630                     ('Image [warning]: unsupported depth combination: ' , bitsPerPixelIn printString , ' -> ' ,
 12630 		    ('Image [warning]: unsupported depth combination: ' , bitsPerPixelIn printString , ' -> ' ,
 12631                                                         bitsPerPixel printString) errorPrintCR.
 12631 							bitsPerPixel printString) errorPrintCR.
 12632                     self shouldImplement.
 12632 		    self shouldImplement.
 12633                     ^ nil
 12633 		    ^ nil
 12634                 ]
 12634 		]
 12635             ].
 12635 	    ].
 12636         ] ifFalse:[
 12636 	] ifFalse:[
 12637             "/
 12637 	    "/
 12638             "/ repad in the buffer
 12638 	    "/ repad in the buffer
 12639             "/
 12639 	    "/
 12640             1 to:h do:[:hi |
 12640 	    1 to:h do:[:hi |
 12641                 inData replaceFrom:dstRow to:(dstRow + bytesPerLine - 1)
 12641 		inData replaceFrom:dstRow to:(dstRow + bytesPerLine - 1)
 12642                               with:tmpData startingAt:srcRow.
 12642 			      with:tmpData startingAt:srcRow.
 12643                 dstRow := dstRow + bytesPerLine.
 12643 		dstRow := dstRow + bytesPerLine.
 12644                 srcRow := srcRow + bytesPerLineIn
 12644 		srcRow := srcRow + bytesPerLineIn
 12645             ]
 12645 	    ]
 12646         ]
 12646 	]
 12647     ] ifFalse:[
 12647     ] ifFalse:[
 12648         (bytesPerLine * height) ~~ inData size ifTrue:[
 12648 	(bytesPerLine * height) ~~ inData size ifTrue:[
 12649             tmpData := inData.
 12649 	    tmpData := inData.
 12650             inData := ByteArray uninitializedNew:(bytesPerLine * height).
 12650 	    inData := ByteArray uninitializedNew:(bytesPerLine * height).
 12651             inData replaceFrom:1 to:bytesPerLine * height with:tmpData startingAt:1
 12651 	    inData replaceFrom:1 to:bytesPerLine * height with:tmpData startingAt:1
 12652         ]
 12652 	]
 12653     ].
 12653     ].
 12654     self bits:inData.
 12654     self bits:inData.
 12655 
 12655 
 12656     "/
 12656     "/
 12657     "/  if not #palette we are done, the pixel values are the rgb/grey values
 12657     "/  if not #palette we are done, the pixel values are the rgb/grey values
 12658     "/
 12658     "/
 12659     photometric == #palette ifTrue:[
 12659     photometric == #palette ifTrue:[
 12660         "/
 12660 	"/
 12661         "/ what we have now are the color numbers - still need the r/g/b values.
 12661 	"/ what we have now are the color numbers - still need the r/g/b values.
 12662         "/ find out, which colors are in the picture
 12662 	"/ find out, which colors are in the picture
 12663         "/
 12663 	"/
 12664         usedPixels := inData usedValues.
 12664 	usedPixels := inData usedValues.
 12665         mapSize := usedPixels max + 1.
 12665 	mapSize := usedPixels max + 1.
 12666 
 12666 
 12667         "get the palette"
 12667 	"get the palette"
 12668         map := Array new:mapSize.
 12668 	map := Array new:mapSize.
 12669         usedPixels do:[:colorIndex |
 12669 	usedPixels do:[:colorIndex |
 12670             |i|
 12670 	    |i|
 12671 
 12671 
 12672             i := colorIndex + 1.
 12672 	    i := colorIndex + 1.
 12673             device getRGBFrom:colorIndex into:[:r :g :b |
 12673 	    device getRGBFrom:colorIndex into:[:r :g :b |
 12674                 map at:i put:(Color red:r green:g blue:b)
 12674 		map at:i put:(Color red:r green:g blue:b)
 12675             ]
 12675 	    ]
 12676         ].
 12676 	].
 12677         self setColorMap:map.
 12677 	self setColorMap:map.
 12678     ].
 12678     ].
 12679 
 12679 
 12680     "Modified: / 9.1.1998 / 21:32:36 / stefan"
 12680     "Modified: / 9.1.1998 / 21:32:36 / stefan"
 12681     "Modified: / 7.2.1998 / 18:23:07 / cg"
 12681     "Modified: / 7.2.1998 / 18:23:07 / cg"
 12682 !
 12682 !
 12685     "read an image from the display screen.
 12685     "read an image from the display screen.
 12686      WARNING: this temporarily grabs the display
 12686      WARNING: this temporarily grabs the display
 12687 	      it may not work from within a buttonMotion
 12687 	      it may not work from within a buttonMotion
 12688 	      (use #fromScreen:on:grab: with a false grabArg then)."
 12688 	      (use #fromScreen:on:grab: with a false grabArg then)."
 12689 
 12689 
 12690     ^ self 
 12690     ^ self
 12691 	fromScreen:aRectangle 
 12691 	fromScreen:aRectangle
 12692 	on:Screen current
 12692 	on:Screen current
 12693 	grab:true
 12693 	grab:true
 12694 
 12694 
 12695     "Modified: 26.3.1997 / 10:43:34 / cg"
 12695     "Modified: 26.3.1997 / 10:43:34 / cg"
 12696 !
 12696 !
 12697 
 12697 
 12698 fromScreen:aRectangle on:aDevice
 12698 fromScreen:aRectangle on:aDevice
 12699     "read an image from aDevices display screen.
 12699     "read an image from aDevices display screen.
 12700      Since I have no other displays, only the MonoChrome, StaticGrey 
 12700      Since I have no other displays, only the MonoChrome, StaticGrey
 12701      and PseudoColor cases have been tested ... 
 12701      and PseudoColor cases have been tested ...
 12702      (especially True- and DirectColor may be wrong).
 12702      (especially True- and DirectColor may be wrong).
 12703      Late note: 24bit rgb now also works.
 12703      Late note: 24bit rgb now also works.
 12704      WARNING: this temporarily grabs the display
 12704      WARNING: this temporarily grabs the display
 12705 	      it may not work from within a buttonMotion
 12705 	      it may not work from within a buttonMotion
 12706 	      (use #fromScreen:on:grab: with a false grabArg then)."
 12706 	      (use #fromScreen:on:grab: with a false grabArg then)."
 12707 
 12707 
 12708     ^ self
 12708     ^ self
 12709 	fromScreen:aRectangle 
 12709 	fromScreen:aRectangle
 12710 	on:aDevice 
 12710 	on:aDevice
 12711 	grab:true
 12711 	grab:true
 12712 
 12712 
 12713     "
 12713     "
 12714      Image fromScreen:((0 @ 0) corner:(100 @ 100)) on:Display
 12714      Image fromScreen:((0 @ 0) corner:(100 @ 100)) on:Display
 12715      Image fromScreen:((0 @ 0) corner:(500 @ 500)) on:Display
 12715      Image fromScreen:((0 @ 0) corner:(500 @ 500)) on:Display
 12721 fromScreen:aRectangle on:aDevice grab:doGrab
 12721 fromScreen:aRectangle on:aDevice grab:doGrab
 12722     "read an image from aDevices display screen.
 12722     "read an image from aDevices display screen.
 12723      If the doGrab argument is true, the display
 12723      If the doGrab argument is true, the display
 12724      is grabbed (i.e. blocked for others) and a camera cursor is
 12724      is grabbed (i.e. blocked for others) and a camera cursor is
 12725      shown while the readout is done.
 12725      shown while the readout is done.
 12726      Since I have no other displays, only the MonoChrome, StaticGrey 
 12726      Since I have no other displays, only the MonoChrome, StaticGrey
 12727      and PseudoColor cases have been tested ... 
 12727      and PseudoColor cases have been tested ...
 12728      (especially True- and DirectColor may be wrong).
 12728      (especially True- and DirectColor may be wrong).
 12729      Late note: 24bit rgb now also works.
 12729      Late note: 24bit rgb now also works.
 12730      WARNING: with doGrab true, this temporarily grabs the display
 12730      WARNING: with doGrab true, this temporarily grabs the display
 12731               and it may not work from within a buttonMotion
 12731 	      and it may not work from within a buttonMotion
 12732               (use with a false grabArg then)."
 12732 	      (use with a false grabArg then)."
 12733 
 12733 
 12734     |curs rootView prevGrab|
 12734     |curs rootView prevGrab|
 12735 
 12735 
 12736 "/    doGrab ifTrue:[ |cid|
 12736 "/    doGrab ifTrue:[ |cid|
 12737 "/        curs := Cursor sourceForm:(Image fromFile:'bitmaps/Camera.xbm')
 12737 "/        curs := Cursor sourceForm:(Image fromFile:'bitmaps/Camera.xbm')
 12745     "
 12745     "
 12746      actually have to grabServer ... but thats not yet available
 12746      actually have to grabServer ... but thats not yet available
 12747     "
 12747     "
 12748     rootView := aDevice rootView.
 12748     rootView := aDevice rootView.
 12749     doGrab ifTrue:[
 12749     doGrab ifTrue:[
 12750         prevGrab := aDevice activePointerGrab.
 12750 	prevGrab := aDevice activePointerGrab.
 12751         aDevice grabPointerInView:rootView withCursor:curs. 
 12751 	aDevice grabPointerInView:rootView withCursor:curs.
 12752     ].
 12752     ].
 12753 
 12753 
 12754     "
 12754     "
 12755      get the pixels
 12755      get the pixels
 12756     "
 12756     "
 12757     [
 12757     [
 12758         self from:rootView in:aRectangle.
 12758 	self from:rootView in:aRectangle.
 12759     ] ensure:[
 12759     ] ensure:[
 12760         doGrab ifTrue:[
 12760 	doGrab ifTrue:[
 12761             aDevice ungrabPointer.
 12761 	    aDevice ungrabPointer.
 12762             prevGrab notNil ifTrue:[
 12762 	    prevGrab notNil ifTrue:[
 12763                  aDevice grabPointerInView:prevGrab.
 12763 		 aDevice grabPointerInView:prevGrab.
 12764             ]
 12764 	    ]
 12765         ]
 12765 	]
 12766     ]
 12766     ]
 12767 
 12767 
 12768     "
 12768     "
 12769      Image fromScreen:((100@100) corner:(200@200)) on:Display grab:false
 12769      Image fromScreen:((100@100) corner:(200@200)) on:Display grab:false
 12770      Image fromScreen:((100@100) corner:(200@200)) on:Display grab:true
 12770      Image fromScreen:((100@100) corner:(200@200)) on:Display grab:true
 12784     visType := aDevice visualType.
 12784     visType := aDevice visualType.
 12785     depth := aDevice depth.
 12785     depth := aDevice depth.
 12786 
 12786 
 12787     "/ kludge for 15bit XFree server
 12787     "/ kludge for 15bit XFree server
 12788     depth == 15 ifTrue:[
 12788     depth == 15 ifTrue:[
 12789         depth := 16
 12789 	depth := 16
 12790     ].
 12790     ].
 12791 
 12791 
 12792     (visType == #StaticGray) ifTrue:[
 12792     (visType == #StaticGray) ifTrue:[
 12793         (aDevice blackpixel == 0) ifTrue:[
 12793 	(aDevice blackpixel == 0) ifTrue:[
 12794             photometric := #blackIs0
 12794 	    photometric := #blackIs0
 12795         ] ifFalse:[
 12795 	] ifFalse:[
 12796             photometric := #whiteIs0
 12796 	    photometric := #whiteIs0
 12797         ].
 12797 	].
 12798         samplesPerPixel := 1.
 12798 	samplesPerPixel := 1.
 12799         bitsPerPixel := depth.
 12799 	bitsPerPixel := depth.
 12800         bitsPerSample := ByteArray with:bitsPerPixel.
 12800 	bitsPerSample := ByteArray with:bitsPerPixel.
 12801         "
 12801 	"
 12802          were done, the pixel values are the grey values
 12802 	 were done, the pixel values are the grey values
 12803         "
 12803 	"
 12804         ^ self
 12804 	^ self
 12805     ].
 12805     ].
 12806 
 12806 
 12807     ((visType == #TrueColor) or:[visType == #DirectColor]) ifTrue:[
 12807     ((visType == #TrueColor) or:[visType == #DirectColor]) ifTrue:[
 12808         photometric := #rgb.
 12808 	photometric := #rgb.
 12809         samplesPerPixel := 3.
 12809 	samplesPerPixel := 3.
 12810 
 12810 
 12811         "/ for now - only support 24bit TrueColor
 12811 	"/ for now - only support 24bit TrueColor
 12812         depth ~~ 24 ifTrue:[
 12812 	depth ~~ 24 ifTrue:[
 12813             'IMAGE: unsupported display depth' errorPrintCR.
 12813 	    'IMAGE: unsupported display depth' errorPrintCR.
 12814         ].
 12814 	].
 12815 "/                bitsPerPixel := depth.
 12815 "/                bitsPerPixel := depth.
 12816 "/                bitsPerSample := ByteArray with:aDevice bitsRed
 12816 "/                bitsPerSample := ByteArray with:aDevice bitsRed
 12817 "/                                       with:aDevice bitsGreen
 12817 "/                                       with:aDevice bitsGreen
 12818 "/                                       with:aDevice bitsBlue
 12818 "/                                       with:aDevice bitsBlue
 12819         bitsPerPixel := 24.
 12819 	bitsPerPixel := 24.
 12820         bitsPerSample := #[8 8 8].
 12820 	bitsPerSample := #[8 8 8].
 12821         "
 12821 	"
 12822          were done, the pixel values are the rgb values
 12822 	 were done, the pixel values are the rgb values
 12823         "
 12823 	"
 12824         ^ self
 12824 	^ self
 12825     ].
 12825     ].
 12826 
 12826 
 12827     ((visType ~~ #PseudoColor) 
 12827     ((visType ~~ #PseudoColor)
 12828     and:[(visType ~~ #StaticColor) 
 12828     and:[(visType ~~ #StaticColor)
 12829     and:[visType ~~ #GrayScale]]) ifTrue:[
 12829     and:[visType ~~ #GrayScale]]) ifTrue:[
 12830         self error:'screen visual not supported'.
 12830 	self error:'screen visual not supported'.
 12831         ^ nil
 12831 	^ nil
 12832     ].
 12832     ].
 12833 
 12833 
 12834     photometric := #palette.
 12834     photometric := #palette.
 12835     samplesPerPixel := 1.
 12835     samplesPerPixel := 1.
 12836     bitsPerPixel := depth.
 12836     bitsPerPixel := depth.
 12845 ! !
 12845 ! !
 12846 
 12846 
 12847 !Image class methodsFor:'documentation'!
 12847 !Image class methodsFor:'documentation'!
 12848 
 12848 
 12849 version
 12849 version
 12850     ^ '$Header: /cvs/stx/stx/libview/Image.st,v 1.386 2006-09-18 19:49:19 cg Exp $'
 12850     ^ '$Header: /cvs/stx/stx/libview/Image.st,v 1.387 2007-01-24 13:40:55 cg Exp $'
 12851 ! !
 12851 ! !
 12852 
 12852 
 12853 Image initialize!
 12853 Image initialize!