[View]  [Edit]  [Lock]  [References]  [Attachments]  [History]  [Home]  [Changes]  [Search]  [Help] 

Converting IPLImages to DIB

This pieces of code are a simple explanation on how IPLImages are converted to DIBs (and viceversa) in Visual Smalltalk's implementation.
Only (24bits)RGB and grayScale images are supported.

Implementation methods follows:
!IPLImage class methods !
fromDIB: aDIB
    " Returns an instance of the receiver from aDIB. "

    | result depth bytes |
    (#( 8 24 ) includes: aDIB bitCount) ifFalse: [
        ^self error: 'Unsupported DIB image.'
    ].
    result := self
        extent: aDIB extent depth: 8
        channels: (aDIB bitCount = 8 ifTrue: [ 1 ] ifFalse: [ 3 ]).
    result copyBitsFrom: aDIB.
    ^result! !

!IPLImage methods !

asDIB
    " Returns the receiver as aDIB image. "

    | dib |
    dib := self createDIB.
    self fillDIB: dib.
    ^dib!

bitCount
    " Returns the bitCount of the receiver "

    ^8 * self nChannels!

colorTable
    " Returns the receiver's colorTable. "

    | size colorTable stream total index |
    size := WinBitmapInfo colorTableSize: self bitCount.
    size = 0 ifTrue: [ ^nil ].
    colorTable := ByteArray new: size.
    stream := WriteStream on: colorTable.
    total := size // 4.
    0 to: total - 1 do: [:i| "only grayScale bitmaps are supported."
        index := i * 256 // total.
        stream next: 3 put: index;nextPut: 0.
    ].
    ^colorTable!

copyBitsFrom: aDIB
    " Transfer the bits in aDIB to the receiver's imageData.
    Warning: No check is done to verify aDIB. "

    | bytes |
    bytes := aDIB bits copy.
    self flip: bytes by: (self scanLineSizeOf: aDIB bitmapInfo).
    self imageData
        replaceFrom: 1 to: bytes size
        with: bytes
        startingAt: 1.!

createDIB
    " Private - Returns aDIB capable to hold the receiver's pixels. "

    | bitmapInfo byteSize colorTable |
    (self isGray or: [ self isRGB ]) ifFalse: [ ^self notImplementedYet ].
    bitmapInfo := WinBitmapInfo
        width: self width height: self height
        planes: 1 bitCount: self bitCount.
    colorTable := self colorTable.
    colorTable notNil ifTrue: [
        bitmapInfo colorTable: self colorTable.
    ].
    byteSize := bitmapInfo sizeImage = 0
        ifTrue: [ self width * self bitCount + 31 // 32 * 4 * self height ]
        ifFalse: [ bitmapInfo sizeImage ].
    ^DIB new
        bitmapInfo: bitmapInfo;
        bits: (ByteArray new: byteSize);
        yourself!

extent
    " Returns the extent of the receiver "

    ^self width @ self height!

fillDIB: aDIB
    " Fill the bits of aDIB image with the receiver's bits.
    WARNING: aDIB must be of correct extent and resolution.
    Use #asDIB to ensure the dib is created as requiered. "

    ^self fillDIB: aDIB flip: true!

fillDIB: aDIB flip: aBoolean
    " Fill the bits of aDIB image with the receiver's bits.
    WARNING: aDIB must be of correct extent and resolution.
    Use #asDIB to ensure the dib is created as requiered. "

    | bytes |
    bytes := aDIB bits.
    bytes
        replaceFrom: 1 to: bytes size
        with: self imageData
        startingAt: 1.
    aBoolean ifTrue: [
        self flip: bytes by: (self scanLineSizeOf: aDIB bitmapInfo)
    ].!

flip: bits by: scanLineSize
    " Private - Flip the vertically the bits by scanLineSize."

    | buffer j |
    j := bits size.
    buffer := ByteArray new: scanLineSize.
    1 to: bits size - scanLineSize // 2 by: scanLineSize do: [:i|
        j := j - scanLineSize.
        buffer replaceFrom: 1 to: scanLineSize with: bits startingAt: i.
        bits
            replaceFrom: i to: i + scanLineSize - 1 with: bits startingAt: j + 1;
            replaceFrom: j + 1 to: j + scanLineSize with: buffer startingAt: 1
    ].
    ^bits!

isGray
    " Returns true if the receiver has 'G' color model. "

    ^self hasColorModel: 'G'!

isRGB
    " Returns true if the receiver has 'RGB' color model. "

    ^self hasColorModel: 'RGB'!

scanLineSizeOf: bitmapInfo
    "Private - Returns the scan line size of bitmapInfo."

    ^bitmapInfo sizeImage = 0
    ifTrue: [ ((bitmapInfo width * bitmapInfo bitCount) + 31) // 32 * 4 ]
    ifFalse: [ bitmapInfo sizeImage // bitmapInfo height ]! !


For any question please write to aleReimondo@smalltalking.net