'From Squeak3.1alpha of 4 February 2001 [latest update: #3507] on 5 February 2001 at 3:42:52 pm'! "Change Set: BMPFixes-ar Date: 5 February 2001 Author: Andreas Raab Fixes issues when reading 16bit BMP files."! !Form class methodsFor: 'BMP file reading' stamp: 'ar 2/5/2001 00:02'! bmpColorsFrom: aBinaryStream count: colorCount depth: depth "Read colorCount BMP color map entries from the given binary stream. Answer an array of Colors." | maxLevel colors b g r | depth = 16 ifTrue:[^nil]. colorCount = 0 ifTrue: [ "this BMP file does not have a color map" "default monochrome color map" depth = 1 ifTrue: [^ Array with: Color white with: Color black]. "default gray-scale color map" maxLevel _ (2 raisedTo: depth) - 1. ^ (0 to: maxLevel) collect: [:level | Color gray: (level asFloat / maxLevel)]]. colors _ Array new: colorCount. 1 to: colorCount do: [:i | b _ aBinaryStream next. g _ aBinaryStream next. r _ aBinaryStream next. aBinaryStream skip: 1. colors at: i put: (Color r: r g: g b: b range: 255)]. ^ colors ! ! !Form class methodsFor: 'BMP file reading' stamp: 'ar 2/5/2001 00:15'! bmpPixelDataFrom: aBinaryStream width: w height: h depth: d colors: colors "Read uncompressed pixel data of depth d from the given BMP stream, where d is 1, 4, 8, or 16" | form bytesPerRow pixelData pixelLine startIndex cm word formBits | (colors == nil) ifTrue:[ form _ Form extent: w@h depth: d. ] ifFalse:[ form _ ColorForm extent: w@h depth: d. form colors: colors. ]. bytesPerRow _ (((d* w) + 31) // 32) * 4. pixelData _ ByteArray new: bytesPerRow * h. h to: 1 by: -1 do: [:y | pixelLine _ aBinaryStream next: bytesPerRow. startIndex _ ((y - 1) * bytesPerRow) + 1. pixelData replaceFrom: startIndex to: startIndex + bytesPerRow - 1 with: pixelLine startingAt: 1]. form bits copyFromByteArray: pixelData. d = 16 ifTrue:[ "swap red and blue components" cm _ Bitmap new: (1 << 15). word _ 0. 0 to: 31 do:[:r| 0 to: 31 do:[:g| 0 to: 31 do:[:b| cm at: (word _ word + 1) put: (b bitShift: 10) + (g bitShift: 5) + r]]]. cm at: 1 put: 1. formBits _ form bits. 1 to: formBits size do:[:i| word _ formBits at: i. word _ (cm at: (word bitAnd: 16r7FFF) + 1) + ((cm at: ((word bitShift: -16) bitAnd: 16r7FFF) +1) bitShift: 16). formBits at: i put: word. ]. ]. ^ form ! ! !Form class methodsFor: 'BMP file reading' stamp: 'ar 2/4/2001 21:54'! fromBMPFile: aBinaryStream "Read a BMP format image from the given binary stream." "Form fromBMPFile: (HTTPSocket httpGet: 'http://anHTTPServer/squeak/squeakers.bmp' accept: 'image/bmp')" | fType fSize reserved pixDataStart hdrSize w h planes d compressed colorCount colors colorForm | (aBinaryStream isMemberOf: String) ifTrue: [^ nil]. "a network error message" aBinaryStream binary. fType _ aBinaryStream nextLittleEndianNumber: 2. fSize _ aBinaryStream nextLittleEndianNumber: 4. reserved _ aBinaryStream nextLittleEndianNumber: 4. pixDataStart _ aBinaryStream nextLittleEndianNumber: 4. hdrSize _ aBinaryStream nextLittleEndianNumber: 4. w _ aBinaryStream nextLittleEndianNumber: 4. h _ aBinaryStream nextLittleEndianNumber: 4. planes _ aBinaryStream nextLittleEndianNumber: 2. d _ aBinaryStream nextLittleEndianNumber: 2. compressed _ aBinaryStream nextLittleEndianNumber: 4. aBinaryStream nextLittleEndianNumber: 4. "biSizeImage" aBinaryStream nextLittleEndianNumber: 4. "biXPelsPerMeter" aBinaryStream nextLittleEndianNumber: 4. "biYPelsPerMeter" colorCount _ aBinaryStream nextLittleEndianNumber: 4. aBinaryStream nextLittleEndianNumber: 4. "biClrImportant" ((fType = 19778) & (reserved = 0) & (planes = 1) & (hdrSize = 40) & (fSize <= aBinaryStream size)) ifFalse: [self error: 'Bad BMP file header']. compressed = 0 ifFalse: [self error: 'Can only read uncompressed BMP files']. d = 24 ifTrue: [ aBinaryStream position: pixDataStart. ^ self bmp24BitPixelDataFrom: aBinaryStream width: w height: h]. "read the color map" "Note: some programs (e.g. Photoshop 4.0) apparently do not set colorCount; assume that any data between the end of the header and the start of the pixel data is the color map" colorCount _ (pixDataStart - 54) // 4. colors _ self bmpColorsFrom: aBinaryStream count: colorCount depth: d. "read the pixel data" aBinaryStream position: pixDataStart. colorForm _ self bmpPixelDataFrom: aBinaryStream width: w height: h depth: d colors: colors. ^ colorForm ! ! Form class removeSelector: #bmpPixelDataFrom:width:height:depth:!