XBMReader.st
author claus
Wed, 03 May 1995 02:26:52 +0200
changeset 66 6ee963fd8e27
parent 53 4f5e734bc59f
child 80 e029e7deed8b
permissions -rw-r--r--
.

"
 COPYRIGHT (c) 1992 by Claus Gittinger
	      All Rights Reserved

 This software is furnished under a license and may be used
 only in accordance with the terms of that license and with the
 inclusion of the above copyright notice.   This software may not
 be provided or otherwise made available to, or used by, any
 other person.  No title to or ownership of the software is
 hereby transferred.
"

'From Smalltalk/X, Version:2.10.4 on 18-feb-1995 at 2:23:58 am'!

ImageReader subclass:#XBMReader
	 instanceVariableNames:''
	 classVariableNames:''
	 poolDictionaries:''
	 category:'Graphics-Images support'
!

XBMReader comment:'
COPYRIGHT (c) 1992 by Claus Gittinger
	      All Rights Reserved

$Header: /cvs/stx/stx/libview2/XBMReader.st,v 1.13 1995-05-03 00:26:52 claus Exp $
'!

!XBMReader class methodsFor:'documentation'!

copyright
"
 COPYRIGHT (c) 1992 by Claus Gittinger
	      All Rights Reserved

 This software is furnished under a license and may be used
 only in accordance with the terms of that license and with the
 inclusion of the above copyright notice.   This software may not
 be provided or otherwise made available to, or used by, any
 other person.  No title to or ownership of the software is
 hereby transferred.
"
!

version
"
$Header: /cvs/stx/stx/libview2/XBMReader.st,v 1.13 1995-05-03 00:26:52 claus Exp $
"
!

documentation
"
    this class provides methods for loading and saving x-bitmap-file images.
    These images can (for example) be created using the bitmap editor supplied
    with X. 
    Only monochrome images can be represented in this format.
    See also: XPMRreader, SunReader, WinIconReader, GIFReader and TIFFReader
"
! !

!XBMReader class methodsFor:'initialization'!

initialize
    Image fileFormats at:'.xbm'  put:self.
! !

!XBMReader class methodsFor:'testing'!

isValidImageFile:aFileName
    "return true, if aFileName contains an x-bitmap-file image"

    |line inStream index1 index2 keyword|

    inStream := self streamReadingFile:aFileName.
    inStream isNil ifTrue:[^ false].

    line := inStream nextLine.
    line isNil ifTrue:[
	inStream close.
	^ false
    ].
    [line startsWith:'#'] whileFalse:[
	line := inStream nextLine.
	line isNil ifTrue:[
	    inStream close.
	    ^ false
	]
    ].
    index1 := line indexOf:(Character space).
    index2 := line indexOf:(Character space) startingAt:(index1 + 1).
    (index2 == 0) ifTrue:[
	inStream close.
	^ false
    ].
    keyword := line copyFrom:index1 to:(index2 - 1).
    (keyword endsWith:'_width') ifFalse:[
	inStream close.
	^ false
    ].
    inStream close.
    ^ true
!

canRepresent:anImage
    "return true, if anImage can be represented in my file format"

    |photometric|

    (anImage depth ~~ 1) ifTrue:[^ false.].
    (((photometric := anImage photometric) ~~ #blackIs0) and:[photometric ~~ #whiteIs0]) ifTrue:[^ false.].
    ^ true
! !

!XBMReader methodsFor:'reading from file'!

fromStream:aStream
    |line 
     index    "{ Class: SmallInteger }"
     dstIndex "{ Class: SmallInteger }"
     bytesPerRow
     lo       "{ Class: SmallInteger }"
     hi       "{ Class: SmallInteger }"
     val      "{ Class: SmallInteger }"
     reverseBits|

    inStream := aStream.

    line := aStream nextLine.
    line isNil ifTrue:[
	'XBMReader: short file' errorPrintNL.
	^ nil
    ].

    [line startsWith:'#'] whileFalse:[
	line := aStream nextLine
    ].

    (line startsWith:'#define') ifFalse:[
	'XBMReader: format error (expected #define)' errorPrintNL.
	^ nil
    ].

    index := line indexOf:(Character space).
    index := line indexOf:(Character space) startingAt:(index + 1).
    (index == 0) ifTrue:[
	'XBMReader: format error' errorPrintNL.
	^ nil
    ].
    ((line copyTo:index - 1) endsWith:'width') ifFalse:[
	'XBMReader: format error (expected width)' errorPrintNL.
	^ nil
    ].
    line := line copyFrom:(index + 1).
    width := Number readFromString:line.

    line := aStream nextLine.
    index := line indexOf:(Character space).
    index := line indexOf:(Character space) startingAt:(index + 1).
    (index == 0) ifTrue:[
	'XBMReader: format error' errorPrintNL.
	^ nil
    ].
    ((line copyTo:index - 1) endsWith:'height') ifFalse:[
	'XBMReader: format error (expected height)' errorPrintNL.
	^ nil
    ].
    line := line copyFrom:(index + 1).
    height := Number readFromString:line.

    bytesPerRow := width // 8.
    ((width \\ 8) ~~ 0) ifTrue:[
	bytesPerRow := bytesPerRow + 1
    ].

    reverseBits := self class reverseBits.

    data := ByteArray new:(bytesPerRow * height).
    dstIndex := 1.

    line := aStream nextLine.
    [line startsWith:'#'] whileTrue:[
	line := aStream nextLine.
    ].

    [line notNil and:[(line startsWith:'static') not]] whileTrue:[
	line := aStream nextLine.
    ].
    line := aStream nextLine.

    [line notNil] whileTrue:[
	index := 1.
	[index ~~ 0] whileTrue:[
	    index := line indexOf:$x startingAt:index.
	    (index ~~ 0) ifTrue:[
		index := index + 1.
		hi := (line at:index) digitValue.
		index := index + 1.
		lo := (line at:index) digitValue.
		val := (hi bitShift:4) bitOr:lo.
		data at:dstIndex put:(reverseBits at:(val + 1)).
		dstIndex := dstIndex + 1
	    ]
	].
	line := aStream nextLine
    ].
    photometric := #whiteIs0.
    samplesPerPixel := 1.
    bitsPerSample := #(1).

    "
     XBMReader fromFile:'bitmaps/globe1.xbm'
    " 
! !

!XBMReader methodsFor:'writing to file'!

save:image onFile:aFileName
    "save image as XBM file on aFileName"

    |reverseBits bits byte
     h        "{ Class: SmallInteger }"
     srcIndex "{ Class: SmallInteger }"
     rowBytes "{ Class: SmallInteger }" |

    (self class canRepresent:image) ifFalse:[
	self error:'can only save depth 1 B&W images'.
	^ nil.
    ].

    outStream := FileStream newFileNamed:aFileName.
    outStream isNil ifTrue:[
	'create error' errorPrintNL. 
	^ nil
    ].

    width := image width.
    height := image height.
    photometric := image photometric.
    samplesPerPixel := image samplesPerPixel.
    bitsPerSample := image bitsPerSample.
    colorMap := image colorMap.

    outStream nextPutAll: '#define xbm_width '.
    outStream nextPutAll:(width printString).
    outStream cr.
    outStream nextPutAll: '#define xbm_height '.
    outStream nextPutAll:(height printString).
    outStream cr.
    outStream nextPutAll: 'static char xbm_bits[] = {'; cr.

    reverseBits := self class reverseBits.

    rowBytes := width + 7 // 8.
    data := image bits.
    srcIndex := 1.

    h := height.
    h timesRepeat:[
	rowBytes timesRepeat:[
	    outStream nextPutAll: '0x'.
	    bits := data at:srcIndex. srcIndex := srcIndex + 1.
	    photometric == #blackIs0 ifTrue:[
		bits := bits bitInvert bitAnd:16rFF
	    ].
	    byte := (reverseBits at:(bits + 1)).
	    byte < 16 ifTrue:[
		outStream nextPut:$0
	    ].
	    byte printOn:outStream radix:16.
	    outStream nextPutAll: ', '.
	].
	outStream cr
    ].
    outStream nextPutAll: '};'; cr.
    outStream close

    "
     XBMReader save:(Image fromFile:'bitmaps/SBrowser.xbm') onFile:'test.xbm'
    "
    "
     convert sun icon to XBM format:

     XBMReader save:(Image fromFile:'bitmaps/hello_world.icon') onFile:'test.xbm'
    "
! !

XBMReader initialize!