35 " |
35 " |
36 ! |
36 ! |
37 |
37 |
38 documentation |
38 documentation |
39 " |
39 " |
40 this class provides methods for loading x-pixmap-file (xpm) images. |
40 This class provides methods for loading x-pixmap-file (xpm) images. |
41 |
41 |
42 These images are used (in X) for palette images (see ctwm or hp-vue for a lot |
42 These images are used (in X) for palette images |
43 of them). |
43 (see ctwm or hp-vue for a lot of them). |
|
44 The format is actually a piece of C-code, which can be compiled by the C-compiler |
|
45 into a constant image data structure. |
|
46 |
44 The code here is a hack - it may not work for all images |
47 The code here is a hack - it may not work for all images |
45 (it works for the testfiles I got here). |
48 (it works for the testfiles I got here). |
46 |
49 |
47 Limitations: |
50 Limitations: |
48 only reads the full-color specification, ignoring monochrome |
51 only reads the full-color specification, ignoring monochrome |
51 Can only handle single-character index. |
54 Can only handle single-character index. |
52 |
55 |
53 Only understands single-word color names (i.e. names with spaces |
56 Only understands single-word color names (i.e. names with spaces |
54 are not supported) |
57 are not supported) |
55 |
58 |
56 Image writing is only supported for images with less than about 50 |
59 Image writing is only supported for images with less than about 200 |
57 colors (single byte encoding). If present, the mask must be a |
60 colors (single byte encoding). |
58 single bit mask (i.e. no alpha channel). |
61 If present, the mask must be a single bit mask (i.e. no alpha channel). |
59 Due to the algorithm, writing may be slow for big images |
62 Due to the algorithm, writing may be slow for big images |
60 |
63 |
61 Suggestions: adapt & use the XPM library here. |
64 Suggestions: adapt & use the XPM library here. |
62 |
65 |
63 |
66 |
64 [See also:] |
67 [See also:] |
65 Image Form Icon |
68 Image Form Icon |
66 BlitImageReader FaceReader GIFReader JPEGReader PBMReader PCXReader |
69 BlitImageReader FaceReader GIFReader JPEGReader PBMReader PCXReader |
67 ST80FormReader SunRasterReader TargaReader TIFFReader WindowsIconReader |
70 ST80FormReader SunRasterReader TargaReader TIFFReader WindowsIconReader |
68 XBMReader XWDReader |
71 XBMReader XWDReader |
|
72 " |
|
73 ! |
|
74 |
|
75 examples |
|
76 " |
|
77 Reading from a file: |
|
78 [exBegin] |
|
79 |image| |
|
80 |
|
81 image := Image fromFile:('../../goodies/bitmaps/xpmBitmaps/INFO.xpm'). |
|
82 image inspect |
|
83 [exEnd] |
|
84 |
|
85 |
|
86 Saving to a file: |
|
87 [exBegin] |
|
88 |image| |
|
89 |
|
90 image := Image fromScreen:(0@0 corner:30@30). |
|
91 image usedColors size > 256 ifTrue:[ |
|
92 image := image asDitheredImageUsing:(Color standardDitherColorsForDepth8) depth:8. |
|
93 ]. |
|
94 XPMReader save:image onFile:'/tmp/test.xpm'. |
|
95 '/tmp/test.xpm' asFilename contents asString inspect |
|
96 [exEnd] |
|
97 |
|
98 |
|
99 Or directly into a stream: |
|
100 [exBegin] |
|
101 |image stream| |
|
102 |
|
103 image := Image fromScreen:(0@0 corner:30@30). |
|
104 image usedColors size > 256 ifTrue:[ |
|
105 image := image asDitheredImageUsing:(Color standardDitherColorsForDepth8) depth:8. |
|
106 ]. |
|
107 stream := WriteStream on:(String new). |
|
108 XPMReader save:image onStream:stream. |
|
109 stream contents inspect |
|
110 [exEnd] |
69 " |
111 " |
70 ! ! |
112 ! ! |
71 |
113 |
72 !XPMReader class methodsFor:'initialization'! |
114 !XPMReader class methodsFor:'initialization'! |
73 |
115 |
460 save:image onFile:aFileName |
502 save:image onFile:aFileName |
461 "save image as XPM file on aFileName. |
503 "save image as XPM file on aFileName. |
462 Caveat: currently, only a maximum of roughly 50 colors is handled |
504 Caveat: currently, only a maximum of roughly 50 colors is handled |
463 (i.e. very simple images)" |
505 (i.e. very simple images)" |
464 |
506 |
465 |usedColors nColorsUsed nColors nChars baseName map maskColorIndex |
507 |nColorsUsed nColors imageName imageMask stream| |
|
508 |
|
509 "sigh - check this before creating the file" |
|
510 nColors := nColorsUsed := image usedColors size. |
|
511 (imageMask := image mask) notNil ifTrue:[ |
|
512 nColors := nColors + 1. |
|
513 ]. |
|
514 nColors > 256 ifTrue:[ |
|
515 ^ Image cannotRepresentImageSignal |
|
516 raiseWith:image |
|
517 errorString:('XPMReader cannot represent this image (too many colors)'). |
|
518 ]. |
|
519 |
|
520 [ |
|
521 stream := aFileName asFilename newReadWriteStream. |
|
522 ] on:FileStream openErrorSignal do:[:ex| |
|
523 ^ Image fileCreationErrorSignal |
|
524 raiseWith:image |
|
525 errorString:('file creation error: ' , aFileName asString). |
|
526 ]. |
|
527 |
|
528 imageName := aFileName asFilename baseName asFilename withoutSuffix asString. |
|
529 imageName replaceAll:$. with:$_. |
|
530 |
|
531 self save:image onStream:stream named:imageName. |
|
532 |
|
533 stream close. |
|
534 ! |
|
535 |
|
536 save:image onStream:aStream |
|
537 "save image as XPM file on aStream. |
|
538 Caveat: currently, only a maximum of roughly 50 colors is handled |
|
539 (i.e. very simple images)" |
|
540 |
|
541 ^ self |
|
542 save:image |
|
543 onStream:aStream |
|
544 named:'unnamed' |
|
545 ! ! |
|
546 |
|
547 !XPMReader methodsFor:'writing-private'! |
|
548 |
|
549 colorNameOf:aColor |
|
550 "generate a name for a color. If its a standard color, |
|
551 return its name; otherwise return the hex representation." |
|
552 |
|
553 #(white black red green blue |
|
554 yellow magenta cyan orange) do:[:aStandardColorName | |
|
555 aColor = (Color name:aStandardColorName) ifTrue:[ |
|
556 ^ aStandardColorName. |
|
557 ] |
|
558 ]. |
|
559 ^ '#' |
|
560 , (aColor redByte hexPrintString:2) |
|
561 , (aColor greenByte hexPrintString:2) |
|
562 , (aColor blueByte hexPrintString:2) |
|
563 |
|
564 "Created: / 27.2.1997 / 11:48:40 / cg" |
|
565 "Modified: / 6.6.1998 / 20:58:49 / cg" |
|
566 ! |
|
567 |
|
568 save:image onStream:aStream named:imageName |
|
569 "save image as XPM file on aStream. |
|
570 Caveat: currently, only a maximum of 256 colors is handled |
|
571 (i.e. very simple images)" |
|
572 |
|
573 |usedColors nColorsUsed nColors nChars map maskColorIndex |
466 isMasked imageMask| |
574 isMasked imageMask| |
467 |
575 |
468 usedColors := image usedColors asArray. |
576 usedColors := image usedColors asArray. |
469 nColors := nColorsUsed := usedColors size. |
577 nColors := nColorsUsed := usedColors size. |
470 (imageMask := image mask) notNil ifTrue:[ |
578 (imageMask := image mask) notNil ifTrue:[ |
482 map addAll:($0 to: $9) asOrderedCollection. |
590 map addAll:($0 to: $9) asOrderedCollection. |
483 map addAll:#($. $, $` $^ $* $: $; $< $> $? $% $# $& $( $) $- $+ $=) asOrderedCollection. |
591 map addAll:#($. $, $` $^ $* $: $; $< $> $? $% $# $& $( $) $- $+ $=) asOrderedCollection. |
484 nChars := 1. |
592 nChars := 1. |
485 |
593 |
486 nColors > map size ifTrue:[ |
594 nColors > map size ifTrue:[ |
487 "/ ^ Image cannotRepresentImageSignal |
|
488 "/ raiseWith:image |
|
489 "/ errorString:('XPMReader cannot represent this image (too many colors)'). |
|
490 map := OrderedCollection new. |
595 map := OrderedCollection new. |
491 $a to: $j do:[:c1 | |
596 $a to: $j do:[:c1 | |
492 map addAll:(($a to: $z) collect:[:c2 | c1 asString , c2 asString]). |
597 map addAll:(($a to: $z) collect:[:c2 | c1 asString , c2 asString]). |
493 ]. |
598 ]. |
494 nChars := 2. |
599 nChars := 2. |
495 ]. |
600 ]. |
496 |
601 |
497 [ |
602 outStream := aStream. |
498 outStream := aFileName asFilename newReadWriteStream. |
|
499 ] on:FileStream openErrorSignal do:[:ex| |
|
500 ^ Image fileCreationErrorSignal |
|
501 raiseWith:image |
|
502 errorString:('file creation error: ' , aFileName asString). |
|
503 ]. |
|
504 |
|
505 baseName := aFileName asFilename baseName asFilename withoutSuffix asString. |
|
506 baseName replaceAll:$. with:$_. |
|
507 |
603 |
508 outStream nextPutLine:'/* XPM */'. |
604 outStream nextPutLine:'/* XPM */'. |
509 outStream nextPutLine:'static char *' , baseName , '_xpm[] = {'. |
605 outStream nextPutLine:'static char *' , imageName , '_xpm[] = {'. |
510 outStream nextPutLine:'/* width height ncolors chars_per_pixel */'. |
606 outStream nextPutLine:'/* width height ncolors chars_per_pixel */'. |
511 outStream nextPutLine:'"' , image width printString , ' ' |
607 outStream nextPutLine:'"' , image width printString , ' ' |
512 , image height printString , ' ' |
608 , image height printString , ' ' |
513 , nColors printString , ' ' |
609 , nColors printString , ' ' |
514 , nChars printString , '",'. |
610 , nChars printString , '",'. |
551 ] |
647 ] |
552 ]. |
648 ]. |
553 outStream nextPutLine:'",'. |
649 outStream nextPutLine:'",'. |
554 ]. |
650 ]. |
555 outStream nextPutLine:'};'. |
651 outStream nextPutLine:'};'. |
556 outStream close. |
|
557 |
652 |
558 "Modified: / 28.7.1998 / 21:52:13 / cg" |
653 "Modified: / 28.7.1998 / 21:52:13 / cg" |
559 ! ! |
654 ! ! |
560 |
655 |
561 !XPMReader methodsFor:'writing-private'! |
|
562 |
|
563 colorNameOf:aColor |
|
564 "generate a name for a color. If its a standard color, |
|
565 return its name; otherwise return the hex representation." |
|
566 |
|
567 #(white black red green blue |
|
568 yellow magenta cyan orange) do:[:aStandardColorName | |
|
569 aColor = (Color name:aStandardColorName) ifTrue:[ |
|
570 ^ aStandardColorName. |
|
571 ] |
|
572 ]. |
|
573 ^ '#' |
|
574 , (aColor redByte hexPrintString:2) |
|
575 , (aColor greenByte hexPrintString:2) |
|
576 , (aColor blueByte hexPrintString:2) |
|
577 |
|
578 "Created: / 27.2.1997 / 11:48:40 / cg" |
|
579 "Modified: / 6.6.1998 / 20:58:49 / cg" |
|
580 ! ! |
|
581 |
|
582 !XPMReader class methodsFor:'documentation'! |
656 !XPMReader class methodsFor:'documentation'! |
583 |
657 |
584 version |
658 version |
585 ^ '$Header: /cvs/stx/stx/libview2/XPMReader.st,v 1.54 2003-09-01 14:47:55 cg Exp $' |
659 ^ '$Header: /cvs/stx/stx/libview2/XPMReader.st,v 1.55 2003-09-12 10:38:04 cg Exp $' |
586 ! ! |
660 ! ! |
587 |
661 |
588 XPMReader initialize! |
662 XPMReader initialize! |