Bitmaps under Linux

Using Dyalog under 'nixes

Bitmaps under Linux

Postby ray on Tue Mar 21, 2017 1:03 pm

I wish to examine, in APL, the contents of a bitmap on a Linux (Raspberry Pi) machine.

Under Windows, with the bitmap held on file, I would use:
Code: Select all
 'item'⎕WC'Bitmap'('File'image)
 bits←item.CBits

where image is the file name of a ".bmp", ".jpg" or other image file.

But under Linux I get an error (as expected)
Process '/home/pi/image2.bmp'
DOMAIN ERROR: There was an error processing the property at position 0 of the ri
ght argument
Process[7] 'item'⎕WC'Bitmap'('File'image)



Other than the code in my 1993 Vector artical "Windows.BMP files and APL" (Vol.10 No.1) which does it via ⎕NREAD under STSC's Pocket APL, is there any code around for reading in bitmaps that I can use?
Ray Cannon
Please excuse any smelling pisstakes.
User avatar
ray
 
Posts: 100
Joined: Wed Feb 24, 2010 12:24 am
Location: Blackwater, Camberley. UK

Re: Bitmaps under Linux

Postby ray on Wed Mar 22, 2017 4:16 pm

Here is my solution to reading a ".BMP" file created by a Raspberry Pi camera.

Code: Select all
 (rc err rgb)←Read_BI_RGB fname;tie;bits;len;type;size;unused;start;headersize;width;height;planes;bpp;comp;isize;hres;vres;ncols;ignore;bytes;padded_len;unpadded_len;padding;vec;item;rgb;shape;mat
⍝ Reads pixel data from a Device-independent bitmap file in BI_RGB form.
⍝ rc  ←→ Return code 0=OK 1=Error
⍝ err ←→'OK' or error text
⍝ rgb ←→ 3D array of pixel colours or ⍬ if error

⍝ Return pixel data from a Device-independent bitmaps(DIB) with ".BMP" bitmap file (of Windows "BITMAPINFOHEADER" type BI_RGB)
⍝ BI_RGB: The bitmap is in uncompressed red green blue (RGB) format that is not compressed and does not use color masks.
⍝ See https://en.wikipedia.org/wiki/BMP_file_format

⍝ For compatibility reasons, most applications use the older DIB headers for saving files.
⍝ With OS/2 no longer supported after Windows 2000, the most common format i use now has the BITMAPINFOHEADER header.
⍝ NOTE This is also the format used in Raspberry Pi Camera images when ".BMP" file is requested.

⍝ NOTE All values are to be stored as unsigned integers except where noted (such as width and height)

⍝ The pixels are returned as a 3 dimensional matrix
⍝ with the 3 colour planes (Red Green Blue) in the 1st dimension
⍝ and the other two dimensions being the rows and columns of the origional image
⍝ This allows easy processing by colour  EG rgb[1;;] ⍝ Just the RED image

 rc←1                                 ⍝ default for error
 rgb←⍬                                ⍝ default for error

⍝ Get the bits from the file as a boolean vector
 tie←fname ⎕NTIE 0
 bits←⎕NREAD tie 11 ¯1 0              ⍝ Read the whole file  as a bit string
 ⎕NUNTIE tie

⍝ Process the bitmap header to check it is in the expected format
⍝ Bitmap type as 2 character: BM. BA, CI, CP, IC, or PT
 len←16                               ⍝ 2 bytes/characters
 type←80 ⎕DR len↑bits                 ⍝ Convert first 16 bits into 2 characters
 bits←len↓bits                        ⍝ drop the data already used
 :If 'BM'≢type                        ⍝ Check if the expected type
     err←'Not a Windows ".BMP" type bitmap'
     :Return
 :End
⍝ Size of the BMP file including header, pallet, bitmap data etc
 len←32                               ⍝ 4 bytes
 size←323 ⎕DR len↑bits                ⍝ size data NOT USED HERE
 bits←len↓bits
⍝ 4 (Application specific) unused bytes
 len←32                               ⍝ 4 bytes
 unused←323 ⎕DR len↑bits              ⍝ this data NOT USED HERE
 bits←len↓bits
⍝ Staring point of bitmap pixels in the data
 len←32                               ⍝ 4 bytes
 start←323 ⎕DR len↑bits               ⍝ 54 expected (14 for bitmap header, 40 for DID header)
 bits←len↓bits
⍝ DIB header (bitmap information header)
 len←32                               ⍝ 4 bytes
 headersize←323 ⎕DR len↑bits          ⍝ Size of the DIB header
 bits←len↓bits
 :If headersize≠40                    ⍝ DIB header is expected to take up 40 bytes
     err←'Not a "BITMAPINFOHEADER"'
     :Return
 :End
⍝ We appear to have read a windows "BITMAPINFOHEADER" BI_RGB file
⍝ Next item in the header is the bitmap width (columns) in pixels (signed integer)
 len←32                               ⍝ 4 bytes
 width←323 ⎕DR len↑bits
 bits←len↓bits
⍝ the bitmap height (rows) in pixels (signed integer)
 len←32                               ⍝ 4 bytes
 height←323 ⎕DR len↑bits              ⍝ NOTE a negative value implies an inverted image (top to bottom)
 bits←len↓bits
⍝ the number of color planes (must be 1)
 len←16                               ⍝ 2 bytes
 planes←163 ⎕DR len↑bits              ⍝ NOT USED HERE
 bits←len↓bits
⍝ the number of bits per pixel, (24) which is the color depth of the image. Typical values are 1, 4, 8, 16, 24 and 32.
 len←16                               ⍝ 2 bytes
 bpp←163 ⎕DR len↑bits
 bits←len↓bits
 :If bpp≠24
     err←'Unexpected colour depth'
     :Return
 :End
⍝ the compression method being used. 0=BI_RGB (Most Common) means NO COMPRESSION
 len←32                               ⍝ 4 bytes
 comp←323 ⎕DR len↑bits
 bits←len↓bits
 :If comp≠0                           ⍝ Expected to be 0
     err←'Compressed bitmat'
     :Return
 :End

⍝ The next block of the header can be ignored.
⍝ the image size. This is the size of the raw bitmap data; a dummy 0 can be given for BI_RGB bitmaps.
 len←32                               ⍝ 4 bytes
 isize←323 ⎕DR len↑bits               ⍝ NOT USED HERE
 bits←len↓bits
⍝ the horizontal resolution of the image. (pixel per meter, signed integer)
 len←32                               ⍝ 4 bytes
 hres←323 ⎕DR len↑bits                ⍝ NOT USED HERE
 bits←len↓bits
⍝ the vertical resolution of the image. (pixel per meter, signed integer)
 len←32                               ⍝ 4 bytes
 vres←323 ⎕DR len↑bits                ⍝ NOT USED HERE
 bits←len↓bits
⍝ the number of colors in the color palette, or 0 to default to 2n
 len←32                               ⍝ 4 bytes
 ncols←323 ⎕DR len↑bits               ⍝ NOT USED HERE
 bits←len↓bits
⍝ the number of important colors used, or 0 when every color is important; generally ignored
 len←32                               ⍝ 4 bytes
 ignore←323 ⎕DR len↑bits              ⍝ NOT USED HERE
 bits←len↓bits

⍝ Pixels
⍝ The 24-bit pixel (24 bpp) format supports 16,777,216 distinct colors
⍝ and stores 1 pixel value per 3 bytes.
⍝ Each pixel value defines the red, green and blue samples of the pixel.
⍝ Specifically, in the order: Blue, Green and Red (8 bits per each sample).

⍝ Convert bit vector into 8 bit unsigned integer vector. 83 ⎕DR would produced 8 bit signed values.
 bytes←⎕UCS 80 ⎕DR bits               ⍝ blue green red unsigned 8 bit values 0-255

⍝ Check for padded rows (All rows must be a multiple of 4 bytes)
 padded_len←(⍴bytes)÷height           ⍝ bytes in each row as supplied with any padding
 unpadded_len←width×3                 ⍝ bytes in each row without trailing padding
 padding←padded_len-unpadded_len      ⍝ number of padding bytes at end of each row
 :If padding≠0                        ⍝ Need to remove padding bytes
     bytes←,(height,unpadded_len)↑(height,padded_len)⍴bytes
 :End

⍝ convert byte vector into a 2D array with 3 columns
 mat←⌽(((⍴bytes)÷3),3)⍴bytes          ⍝ one row per pixel each with a columns for each colour in RGB order

⍝ convert into a 3D array with the most useful orientation for colour manipulation
 rgb←3 2 1⍉(height,width,3)⍴mat       ⍝ colours by rows by columns
 rc←0
 err←'OK'

⍝⍝⍝ commented out code to cross-check against CBits property read via ⎕WC
⍝⍝ vec←256⊥⍉mat                       ⍝ vector of RGB 24bit pixels
⍝⍝ CBits←⊖(height,width)⍴vec          ⍝ matches dyalog CBits property of a Bitmap
⍝⍝ 'item'⎕WC'Bitmap'('File'fname)
⍝⍝ :If CBits≢item.CBits
⍝⍝     rc←1
⍝⍝     err←'Problem CBits cross-check failed'
⍝⍝     rgb←⍬
⍝⍝ :End


I used the commented out code at the end to confirm that the function could return the same data as available in the CBits property when tested under Windows.

However, I have returned the pixel array as a "number of colours" by "number of rows", by "number of columns" byte array, which (I expect) will make further processing easier
Ray Cannon
Please excuse any smelling pisstakes.
User avatar
ray
 
Posts: 100
Joined: Wed Feb 24, 2010 12:24 am
Location: Blackwater, Camberley. UK


Return to UNIX and Linux

Who is online

Users browsing this forum: No registered users and 1 guest