Bitmaps under Linux
2 posts
• Page 1 of 1
Bitmaps under Linux
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:
where image is the file name of a ".bmp", ".jpg" or other image file.
But under Linux I get an error (as expected)
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?
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.
Please excuse any smelling pisstakes.
-
ray - Posts: 238
- Joined: Wed Feb 24, 2010 12:24 am
- Location: Blackwater, Camberley. UK
Re: Bitmaps under Linux
Here is my solution to reading a ".BMP" file created by a Raspberry Pi camera.
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
- 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.
Please excuse any smelling pisstakes.
-
ray - Posts: 238
- Joined: Wed Feb 24, 2010 12:24 am
- Location: Blackwater, Camberley. UK
2 posts
• Page 1 of 1
Who is online
Users browsing this forum: No registered users and 1 guest
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group