Faceți căutări pe acest blog

luni, 11 septembrie 2017

Creating bitmap BMP pictures without API calls (5)

Let's create the same flag, but with vertical lines.
Because BMP contains the matrix stored row by row of pixels, each row will have those three portions of pixels: from left to right, red, yellow, blue



****************************************************
* Creating a 30 x 100 bitmap with yellow background
* the leftmost 10 columns red, the middle 10 columns yellow, and the rightmost 10 columns blue
****************************************************
* The midmap look like this:
* RRRRRRRRRRYYYYYYYYYYBBBBBBBBBB
* RRRRRRRRRRYYYYYYYYYYBBBBBBBBBB
* RRRRRRRRRRYYYYYYYYYYBBBBBBBBBB
* RRRRRRRRRRYYYYYYYYYYBBBBBBBBBB
* RRRRRRRRRRYYYYYYYYYYBBBBBBBBBB
* etc (100 times)
****************************************************
LOCAL loBmp, lcTrailerZeros, lcRedPixel, lcRedRow
loBmp = CREATEOBJECT("bmpcreator")
loBmp.nWidth = 30
loBmp.nHeight = 100

* Each row of pixels must have as a length in bytes a multiple of 4. If necessary a few CHR(0) are added
lcTrailerZeros = IIF(MOD( m.loBmp.nWidth * 3,4) <> 0, REPLICATE(CHR(0),4 - MOD( m.loBmp.nWidth * 3,4)), "")
* One pixel has three bytes, corresponding to RGB (Red is the rightmost, blue is the leftmost)
lcRedPixel = CHR(0) + CHR(0) + CHR(255)
* One pixel has three bytes, corresponding to RGB (Red is the rightmost, blue is the leftmost)
lcYellowPixel = CHR(0) + CHR(255) + CHR(255)
* One pixel has three bytes, corresponding to RGB (Red is the rightmost, blue is the leftmost)
lcBluePixel = CHR(255) + CHR(0) + CHR(0)
* One row contain loBmp.nWidth npixels; DO NOT FORGET the trailing zeroes
* one row = 10 red pixels followed by 10 yellow pixels followed by 10 blue pixels
lcRow = REPLICATE(m.lcRedPixel, 10) + REPLICATE(m.lcYellowPixel, 10) + REPLICATE(m.lcBluePixel, 10) + m.lcTrailerZeros
* The BITMAP
loBmp.cBitmap = REPLICATE(m.lcRow, loBmp.nHeight)
     
loBmp.genbmp("05")


DEFINE CLASS bmpcreator as Custom
      * Generic properties
      nWidth = 1 && Bitmap width in pixels
      nHeight = 1 && bitmap height in pixels
      cBitmap = '' && the bitmap as a string of RGB triplets
      **************************************************************************************
      * generic procedure that writes the bitmap to a BMp file, stored in cBitmap property
      **************************************************************************************
      PROCEDURE genbmp
            *
            * Returns the name of the bmp file
            *
            * Parameters:
            * - tcFile (optional) file name. By default sys(2015)
            *
            LPARAMETERS tcFile
            LOCAL lni,lnByteLength,lcSa,lnNumber
            IF PCOUNT() < 1
                  tcFile = SYS(2015)
            ENDIF
            tcFile = FORCEEXT(m.tcFile, 'bmp')
            lnByteLength = LEN(This.cBitmap)
            * Header
            * Bitmap header field: BM (CHR(0x42)+CHR(0x4D))
            lcSa = CHR(0x42) + CHR(0x4D)
            * File length (file dimension in bytes  in hexadecimal)
            lnNumber = This.DecTohex(m.lnByteLength + 56)
            lcSa = m.lcSa + m.lnNumber
            FOR lni = 1 TO 8 - LEN(m.lnNumber)
                  lcSa = m.lcSa + CHR(0)
            NEXT
            *CHR(0x36)=3*16+6=56=header length in bytes
            *CHR(0x28)=2*16+8=40=number of bytes taken by the structure that follows the header
            lcSa = m.lcSa + CHR(0x36) + CHR(0) + CHR(0) + CHR(0) + CHR(0x28) + CHR(0) + CHR(0) + CHR(0)
            * bitmap width and height in pixels
            * bitmap width
            lnNumber = This.DecTohex(This.nWidth) &&(lnByteLength/lnSize-2)/3
            lcSa= m.lcSa + m.lnNumber
            FOR lni = 1 TO 4 - LEN(m.lnNumber)
                  lcSa = m.lcSa + CHR(0)
            NEXT
            * bitmap height
            lnNumber = This.DecTohex(This.nHeight)
            lcSa = m.lcSa + m.lnNumber && +CHR(0x0C)+CHR(0)+CHR(0)+CHR(0)
            FOR lni = 1 TO 4 - LEN(m.lnNumber)
                  lcSa = m.lcSa + CHR(0)
            NEXT
            * Number of layers, must be 1
            lcSa = m.lcSa + CHR(0x1) + CHR(0)
            * Color depth: 1, 4, 8 sau 24 (0x18) bits
            lcSa = m.lcSa + CHR(0x18) + CHR(0)
            * Information regarding compression
            lcSa = m.lcSa + CHR(0) + CHR(0) + CHR(0) + CHR(0)
            *  Image length in bytes (can be 0 if is not compressed)
            lnNumber = This.DecTohex(m.lnByteLength)
            lcSa = m.lcSa + m.lnNumber
            FOR lni = 1 TO 8 - LEN(m.lnNumber)
              lcSa = m.lcSa + CHR(0)
            NEXT
            * the device horizontal resolution in pixels
            lcSa = m.lcSa + CHR(0) + CHR(0) + CHR(0) + CHR(0)
            * the device vertical resolution in pixels
            lcSa = m.lcSa + CHR(0) + CHR(0) + CHR(0) + CHR(0)
            * 0 means the entire color set
            lcSa = m.lcSa + CHR(0) + CHR(0)
            * 0 means all the color counts in bitmap representation
            lcSa = m.lcSa + CHR(0) + CHR(0)

            STRTOFILE(m.lcSa + This.cBitmap, m.tcFile)
            RETURN m.tcFile
      ENDPROC
      * function used to represend numbers as char
      PROCEDURE DecTohex
            LPARAMETERS tnNo
            LOCAL lcS,lnC,lnI
            lnI = FLOOR(m.tnNo)
            lcS = ''
            DO WHILE m.lnI != 0
                  lnC = m.lnI % 256
                  lcS = m.lcS + CHR(m.lnC)
                  lnI = FLOOR(m.lnI / 256)
            ENDDO
            IF LEN(m.lcS)=0 && representation of 0
                  lcS = CHR(0)
            ENDIF
            RETURN m.lcS
      ENDPROC

Creating bitmap BMP pictures without API calls (4)

In the next step will create a flag with three horizontal colors.
From bottom to up: red, yellow, blue



****************************************************
* Creating a 100 x 30 bitmap with yellow background
* the lower 10 lines red, the middle 10 lines yellow, and the upper 10 lines blue
****************************************************
* The midmap look like this:
* BBBBBBBBBBBBBBBB... - 10 times
* YYYYYYYYYYYYYYYY... - 10 times
* RRRRRRRRRRRRRRRR... - 10 times
****************************************************
LOCAL loBmp, lcTrailerZeros, lcRedPixel, lcRedRow
loBmp = CREATEOBJECT("bmpcreator")
loBmp.nWidth = 100
loBmp.nHeight = 30

* Each row of pixels must have as a length in bytes a multiple of 4. If necessary a few CHR(0) are added
lcTrailerZeros = IIF(MOD( m.loBmp.nWidth * 3,4) <> 0, REPLICATE(CHR(0),4 - MOD( m.loBmp.nWidth * 3,4)), "")
* One pixel has three bytes, corresponding to RGB (Red is the rightmost, blue is the leftmost)
lcRedPixel = CHR(0) + CHR(0) + CHR(255)
* One pixel has three bytes, corresponding to RGB (Red is the rightmost, blue is the leftmost)
lcYellowPixel = CHR(0) + CHR(255) + CHR(255)
* One pixel has three bytes, corresponding to RGB (Red is the rightmost, blue is the leftmost)
lcBluePixel = CHR(255) + CHR(0) + CHR(0)
* One row contain loBmp.nWidth npixels; DO NOT FORGET the trailing zeroes
* The red row
lcRedRow = REPLICATE(m.lcRedPixel, m.loBmp.nWidth) + m.lcTrailerZeros
* The yellow row
lcYellowRow = REPLICATE(m.lcYellowPixel, m.loBmp.nWidth) + m.lcTrailerZeros
* The blue row
lcBlueRow = REPLICATE(m.lcBluePixel, m.loBmp.nWidth) + m.lcTrailerZeros
* The BITMAP
loBmp.cBitmap = REPLICATE(m.lcRedRow, 10) + ; && 10 yellow rows below
                        REPLICATE(m.lcYellowRow, 10) + ; && 10 yellow rows in the middle
                        REPLICATE(m.lcBlueRow, 10)  && 10 blue rows on top
     
loBmp.genbmp("04")


DEFINE CLASS bmpcreator as Custom
      * Generic properties
      nWidth = 1 && Bitmap width in pixels
      nHeight = 1 && bitmap height in pixels
      cBitmap = '' && the bitmap as a string of RGB triplets
      **************************************************************************************
      * generic procedure that writes the bitmap to a BMp file, stored in cBitmap property
      **************************************************************************************
      PROCEDURE genbmp
            *
            * Returns the name of the bmp file
            *
            * Parameters:
            * - tcFile (optional) file name. By default sys(2015)
            *
            LPARAMETERS tcFile
            LOCAL lni,lnByteLength,lcSa,lnNumber
            IF PCOUNT() < 1
                  tcFile = SYS(2015)
            ENDIF
            tcFile = FORCEEXT(m.tcFile, 'bmp')
            lnByteLength = LEN(This.cBitmap)
            * Header
            * Bitmap header field: BM (CHR(0x42)+CHR(0x4D))
            lcSa = CHR(0x42) + CHR(0x4D)
            * File length (file dimension in bytes  in hexadecimal)
            lnNumber = This.DecTohex(m.lnByteLength + 56)
            lcSa = m.lcSa + m.lnNumber
            FOR lni = 1 TO 8 - LEN(m.lnNumber)
                  lcSa = m.lcSa + CHR(0)
            NEXT
            *CHR(0x36)=3*16+6=56=header length in bytes
            *CHR(0x28)=2*16+8=40=number of bytes taken by the structure that follows the header
            lcSa = m.lcSa + CHR(0x36) + CHR(0) + CHR(0) + CHR(0) + CHR(0x28) + CHR(0) + CHR(0) + CHR(0)
            * bitmap width and height in pixels
            * bitmap width
            lnNumber = This.DecTohex(This.nWidth) &&(lnByteLength/lnSize-2)/3
            lcSa= m.lcSa + m.lnNumber
            FOR lni = 1 TO 4 - LEN(m.lnNumber)
                  lcSa = m.lcSa + CHR(0)
            NEXT
            * bitmap height
            lnNumber = This.DecTohex(This.nHeight)
            lcSa = m.lcSa + m.lnNumber && +CHR(0x0C)+CHR(0)+CHR(0)+CHR(0)
            FOR lni = 1 TO 4 - LEN(m.lnNumber)
                  lcSa = m.lcSa + CHR(0)
            NEXT
            * Number of layers, must be 1
            lcSa = m.lcSa + CHR(0x1) + CHR(0)
            * Color depth: 1, 4, 8 sau 24 (0x18) bits
            lcSa = m.lcSa + CHR(0x18) + CHR(0)
            * Information regarding compression
            lcSa = m.lcSa + CHR(0) + CHR(0) + CHR(0) + CHR(0)
            *  Image length in bytes (can be 0 if is not compressed)
            lnNumber = This.DecTohex(m.lnByteLength)
            lcSa = m.lcSa + m.lnNumber
            FOR lni = 1 TO 8 - LEN(m.lnNumber)
              lcSa = m.lcSa + CHR(0)
            NEXT
            * the device horizontal resolution in pixels
            lcSa = m.lcSa + CHR(0) + CHR(0) + CHR(0) + CHR(0)
            * the device vertical resolution in pixels
            lcSa = m.lcSa + CHR(0) + CHR(0) + CHR(0) + CHR(0)
            * 0 means the entire color set
            lcSa = m.lcSa + CHR(0) + CHR(0)
            * 0 means all the color counts in bitmap representation
            lcSa = m.lcSa + CHR(0) + CHR(0)

            STRTOFILE(m.lcSa + This.cBitmap, m.tcFile)
            RETURN m.tcFile
      ENDPROC
      * function used to represend numbers as char
      PROCEDURE DecTohex
            LPARAMETERS tnNo
            LOCAL lcS,lnC,lnI
            lnI = FLOOR(m.tnNo)
            lcS = ''
            DO WHILE m.lnI != 0
                  lnC = m.lnI % 256
                  lcS = m.lcS + CHR(m.lnC)
                  lnI = FLOOR(m.lnI / 256)
            ENDDO
            IF LEN(m.lcS)=0 && representation of 0
                  lcS = CHR(0)
            ENDIF
            RETURN m.lcS
      ENDPROC