Skip to content

Instantly share code, notes, and snippets.

@OneB1t
Last active September 30, 2023 21:59
Show Gist options
  • Save OneB1t/7b37e9ac769cec3589623a8cd11ec017 to your computer and use it in GitHub Desktop.
Save OneB1t/7b37e9ac769cec3589623a8cd11ec017 to your computer and use it in GitHub Desktop.
BMP generator in bash
#!/bin/bash
width=1280
height=640
imageSize=$((($width + 31) / 32 * 4 * $height)) # Image size (in bytes)
pixelDataOffset=54 # Offset to pixel data
# BMP header
printf "B" > monochromatic_with_text.bmp
printf "M" >> monochromatic_with_text.bmp
printf "\x00\x00\x00\x00" >> monochromatic_with_text.bmp # File size (dummy)
printf "\x00\x00\x00\x00" >> monochromatic_with_text.bmp # Reserved
printf "\x36\x00\x00\x00" >> monochromatic_with_text.bmp # Pixel data offset
printf "\x28\x00\x00\x00" >> monochromatic_with_text.bmp # Header size
printf "\x$(printf "%02x" $(($width & 0xFF)))\x$(printf "%02x" $(($width >> 8 & 0xFF)))\x00\x00" >> monochromatic_with_text.bmp # Image width
printf "\x$(printf "%02x" $(($height & 0xFF)))\x$(printf "%02x" $(($height >> 8 & 0xFF)))\x00\x00" >> monochromatic_with_text.bmp # Image height
printf "\x01\x00" >> monochromatic_with_text.bmp # Number of color planes
printf "\x01\x00" >> monochromatic_with_text.bmp # Bits per pixel
printf "\x00\x00\x00\x00" >> monochromatic_with_text.bmp # Compression method (none)
printf "\x00\x00\x00\x00" >> monochromatic_with_text.bmp # Image size (dummy)
printf "\x00\x00\x00\x00" >> monochromatic_with_text.bmp # Horizontal resolution (dummy)
printf "\x00\x00\x00\x00" >> monochromatic_with_text.bmp # Vertical resolution (dummy)
printf "\x00\x00\x00\x00" >> monochromatic_with_text.bmp # Number of colors in the palette
printf "\x00\x00\x00\x00" >> monochromatic_with_text.bmp # Important colors
# Palette (black and white)
printf "\x00\x00\x00\x00" >> monochromatic_with_text.bmp # Black
printf "\xff\xff\xff\x00" >> monochromatic_with_text.bmp # White
# Monochrome pixel data (all zeros for a black background)
batch_size=4096
batches=$((imageSize / batch_size))
for ((i=0; i<$batches; i++)); do
printf '\x00%.0s' {1..4096}
done >> monochromatic_with_text.bmp
# Write any remaining zeroes (if imageSize is not a multiple of 4096)
remaining=$((imageSize % batch_size))
if [ $remaining -gt 0 ]; then
printf '\x00%.0s' $(seq $remaining)
fi >> monochromatic_with_text.bmp
# Define the text "HELLO, WORLD!"
random=$(shuf -i 0-9 -n 1)
text="RANDOM VALUE $random"
# Calculate the starting X position to center the text horizontally
textWidth=$((${#text} * 8)) # Assuming each character is 8 pixels wide
textHeight=16 # Assuming each character is 16 pixels tall
x=$(($width / 2 - $textWidth / 2))
y=$(($height / 2 - $textHeight / 2))
# Define the font for characters and numbers
font=(
"\x00\x18\x18\x18\x18\x24\x24\x24\x3C\x24\x66\x42\x42\x81\x81\x00"
"\xFC\x82\x82\x82\xFC\x82\x82\x82\xFC\x82\x82\x82\xFC\x00\x00\x00"
"\x00\x3E\x40\x80\x80\x80\x80\x80\x80\x80\x80\x40\x3E\x00\x00\x00"
"\xF8\x84\x82\x82\x82\x82\x82\x82\x82\x82\x82\x84\xF8\x00\x00\x00"
"\xFE\x80\x80\x80\x80\x80\xF8\x80\x80\x80\x80\x80\xFE\x00\x00\x00"
"\xFE\x80\x80\x80\x80\x80\xF8\x80\x80\x80\x80\x80\x80\x00\x00\x00"
"\x00\x3E\x40\x80\x80\x80\x80\x87\x82\x82\x42\x3C\x00\x00\x00\x00"
"\x82\x82\x82\x82\x82\x82\xFE\x82\x82\x82\x82\x82\x82\x82\x00\x00"
"\x7C\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x7C\x00\x00\x00"
"\x3E\x04\x04\x04\x04\x04\x04\x04\x04\x04\x04\x08\x70\x00\x00\x00"
"\x82\x84\x88\x90\xA0\xC0\xC0\xA0\x90\x88\x84\x82\x82\x00\x00\x00"
"\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\xFE\x00\x00\x00"
"\x00\x82\xC6\xAA\xAA\xAA\xAA\xAA\x92\x82\x82\x82\x82\x00\x00\x00"
"\x81\xC1\xA1\xB1\x99\x8D\x87\x83\x81\x81\x00\x00\x00\x00\x00\x00"
"\x00\x3C\x42\x81\x81\x81\x81\x81\x81\x81\x81\x42\x3C\x00\x00\x00"
"\xFC\x82\x82\x82\x82\x82\xFC\x80\x80\x80\x80\x80\x80\x00\x00\x00"
"\x00\x3C\x42\x81\x81\x81\x81\x81\x81\x81\x81\xA1\x42\x3C\x0C\x02"
"\xFC\x82\x82\x82\x82\x82\xFC\x88\x90\x98\x8C\x86\x83\x00\x00\x00"
"\x00\x3C\x42\x81\x81\x80\x60\x18\x04\x02\x82\x42\x3C\x00\x00\x00"
"\xFE\x92\x92\x10\x10\x10\x10\x10\x10\x10\x10\x10\x38\x00\x00\x00"
"\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x42\x3C\x00\x00\x00"
"\x82\x82\x82\x82\x82\x45\x45\x45\x45\x28\x28\x10\x10\x00\x00\x00"
"\x82\x82\x82\x92\x92\x92\xAA\xAA\xAA\x44\x44\x44\x44\x00\x00\x00"
"\x82\x82\x44\x44\x28\x10\x28\x44\x82\x82\x82\x82\x82\x00\x00\x00"
"\x82\x82\x82\x44\x28\x10\x10\x10\x10\x10\x10\x38\x00\x00\x00\x00"
"\xFE\x04\x08\x08\x10\x10\x20\x20\x20\x40\x80\x80\xFE\x00\x00\x00"
"\x38\x44\x82\x81\x81\x81\x81\x99\x85\x82\x82\x44\x38\x00\x00\x00"
"\x18\x08\x08\x08\x18\x28\x48\x08\x08\x08\x08\x08\x1C\x00\x00\x00"
"\x1C\x22\x42\x42\x02\x02\x04\x08\x10\x20\x42\x7E\x00\x00\x00\x00"
"\x1C\x22\x42\x02\x02\x1C\x02\x02\x02\x42\x22\x1C\x00\x00\x00\x00"
"\x06\x0A\x12\x12\x22\x42\x82\xFE\x02\x02\x02\x02\x00\x00\x00\x00"
"\x3E\x20\x20\x20\x20\x3C\x02\x02\x02\x42\x22\x1C\x00\x00\x00\x00"
"\x1C\x22\x42\x40\x80\xBC\xC2\x82\x82\x42\x22\x1C\x00\x00\x00\x00"
"\x7E\x02\x04\x08\x08\x10\x10\x20\x20\x20\x20\x20\x00\x00\x00\x00"
"\x1C\x22\x42\x42\x22\x1C\x22\x42\x42\x42\x22\x1C\x00\x00\x00\x00"
"\x1C\x22\x42\x82\x82\x82\x7E\x02\x02\x02\x22\x1C\x00\x00\x00\x00"
# Add more characters here
)
# Function to write a character to the image
write_char() {
character=$1
fontIndex=$(($(printf "%d" "'$character") - 32)) # Assuming your font starts from ' '
if [[ $character =~ [0-9] ]]; then
fontIndex=$((fontIndex + 33))
fi
if ((fontIndex >= 0 && fontIndex < ${#font[@]})); then
for ((row=0; row<16; row++)); do
fontByte=$(printf "%d" "'${font[fontIndex]:row:1}")
for ((col=0; col<8; col++)); do
mask=$((1 << (7 - col)))
if ((fontByte & mask != 0)); then
# Calculate the pixel position
pixelX=$(($x + $i * 8 + $col))
pixelY=$(($y + $row))
# Calculate the byte and bit offset in the pixel data
byteOffset=$((pixelY * ($width / 8) + (pixelX / 8)))
bitOffset=$((7 - (pixelX % 8)))
# Read the current byte at the position
currentByte=$(dd if=monochromatic_with_text.bmp bs=1 count=1 skip=$((pixelDataOffset + byteOffset)) 2>/dev/null | xxd -ps)
currentByteDec=$((16#"$currentByte"))
# Set the bit at the calculated bit offset to 1
newByteDec=$((currentByteDec | (1 << bitOffset)))
# Convert the new byte back to hexadecimal
newByteHex=$(printf "%02x" $newByteDec)
# Write the new byte back to the image
printf "\x$newByteHex" | dd of=monochromatic_with_text.bmp bs=1 seek=$((pixelDataOffset + byteOffset)) count=1 conv=notrunc status=none
fi
done
done
fi
}
# Write the text to the pixel data
for ((i=0; i<${#text}; i++)); do
character=${text:i:1}
write_char "$character"
done
echo "Text written to monochromatic_with_text.bmp"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment