' .ApplicationSource XBM-Reader(1.0)'! 'From VisualWorks(R) Release 2.0 of 4 August 1994 on 31 March 1995 at 6:00:39 am'! '- sources of XBM-Reader(1.0) -'! ImageReader subclass: #XBMReader instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Graphics-Images'! !XBMReader methodsFor: 'attributes'! format "Answer a string naming the format used to store the image." ^'X11 Bitmap (XBM)'! ! !XBMReader methodsFor: 'private'! mirror: byte "reverse bit order in a byte. Should be moved to SmallInteger" | etyb maskIn maskOut | etyb := 0. maskIn := 1. maskOut := 128. 8 timesRepeat: [(byte bitAnd: maskIn) isZero ifFalse: [etyb := etyb bitOr: maskOut]. maskIn := maskIn bitShift: 1. maskOut := maskOut bitShift: -1]. ^etyb! readImageData | packedRow | ioStream throughAll: 'static'. ioStream skipUpTo: ${; next. packedRow := ByteArray new: bytesPerRow. (0 to: height - 1) do: [:row | (1 to: rowEndOffset + 1) do: [:i | | byte | ioStream skipSeparators. ioStream next; next. byte := Integer readFrom: ioStream radix: 16. byte := self mirror: byte. ioStream next. packedRow at: i put: byte]. image packedRowAt: row putAll: packedRow]! readParameter: aString ioStream skipSeparators. ioStream throughAll: aString. ioStream skipSeparators. ^Integer readFrom: ioStream! ! !XBMReader methodsFor: 'initialize-release'! readImage "Read the image stored the input stream." "import X bitmap file as Depth1Image" | depth w h | (ioStream respondsTo: #text) ifTrue: ["set mode to character" ioStream text]. ioStream lineEndLF. Stream endOfStreamSignal handle: [:ex | ex restartDo: [self formatError: 'Image data ended prematurely.']] do: [palette := MappedPalette monochromeDefault. depth := 1. w := self readParameter: 'width'. h := self readParameter: 'height'. self width: w height: h bitsPerPixel: depth. self initializeImage. self readImageData]! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! !XBMReader class methodsFor: 'private'! canRead: aFilenameOrString "Answer whether the receiver can read the named file." ('*.xbm' match: aFilenameOrString asString) ifTrue: [^true]. ^Object errorSignal handle: [:ex | ex returnWith: false] do: [| inputStream token | token := '#define'. inputStream := aFilenameOrString asFilename readStream. [token = (inputStream nextAvailable: token size)] valueNowOrOnUnwindDo: [inputStream close]]! ! !XBMReader class methodsFor: 'documentation'! xbmFiles "The following is an extract of the UNIX manual entry for 'bitmap': FILE FORMAT The Write Output command stores bitmaps as simple C program fragments that can be compiled into programs, referred to by X Toolkit pixmap resources, manipulated by other programs (see xsetroot), or read in using utility routines in the various programming libraries. The width and height of the bitmap as well as the hotspot, if specified, are written as preprocessor symbols at the start of the file. The bitmap image is then written out as an array of characters: #define name_width 11 #define name_height 5 #define name_x_hot 5 #define name_y_hot 2 static char name_bits[] = { 0x91, 0x04, 0xca, 0x06, 0x84, 0x04, 0x8a, 0x04, 0x91, 0x04 }; The name prefix to the preprocessor symbols and to the bits array is constructed from the filename argument given on the command line. Any directories are stripped off the front of the name and any suffix beginning with a period is stripped off the end. Any remaining non-alphabetic characters are replaced with underscores. The name_x_hot and name_y_hot symbols will only be present if a hotspot has been desig- nated using the Set Hot Spot command. Each character in the the array contains 8 bits from one row of the image (rows are padded out at the end to a multiple of 8 to make this is possible). Rows are written out from left to right and top to bottom. The first character of the array holds the leftmost 8 bits of top line, and the last characters holds the right most 8 bits (including padding) of the bottom line. Within each character, the leftmost bit in the bitmap is the least significant bit in the character. This process can be demonstrated visually by splitting a row into words containing 8 bits each, reversing the bits each word (since Arabic numbers have the significant digit on the right and images have the least significant bit on the left), and translating each word from binary to hexadecimal. In the following example, the array of 1's and 0's on the left represents a bitmap containing 5 rows and 11 columns that spells X11. To its right is is the same array split into 8 bit words with each row padded with 0's so that it is a multiple of 8 in length (16): 10001001001 10001001 00100000 01010011011 01010011 01100000 00100001001 00100001 00100000 01010001001 01010001 00100000 10001001001 10001001 00100000 Reversing the bits in each word of the padded, split version of the bitmap yields the left hand figure below. Interpret- ing each word as hexadecimal number yields the array of numbers on the right: 10010001 00000100 0x91 0x04 11001010 00000110 0xca 0x06 10000100 00000100 0x84 0x04 10001010 00000100 0x8a 0x04 10010001 00000100 0x91 0x04 The character array can then be generated by reading each row from left to right, top to bottom: static char name_bits[] = { 0x91, 0x04, 0xca, 0x06, 0x84, 0x04, 0x8a, 0x04, 0x91, 0x04 }; "! !