Module: SimpleBMP

Defined in:
lib/simple_bmp.rb

Constant Summary collapse

@@align4 =
->_{ (_ + 3) / 4 * 4 }

Class Method Summary collapse

Class Method Details

.enlarge(array, **args) ⇒ Object

Truncated box modal resizing



74
75
76
# File 'lib/simple_bmp.rb', line 74

def self.enlarge array, **args
    array = array.flat_map{ |row| [ row.flat_map{ |cell| [cell] * args[:times] } ] * args[:times] }
end

.export(pixels, filename = "temp.bmp") ⇒ Object

pixels is either two or three dimensional array:

[height x width x 3] of 0..255 for RGB
[height x width] of 0..255 for grayscale

Two-dimensional will be processed as it’s three, where R, G anb B are equal.

Examples of exporting a single pixel image which is almost gray:

export [[100]], "temp.bmp"
export [[[90,100,110]]], "temp.bmp"


19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/simple_bmp.rb', line 19

def self.export pixels, filename = "temp.bmp"
    #fail "pixel array shouldn't be empty" if pixels.empty?
    fail "all pixel array rows should be of the same length" if pixels.map(&:size).uniq.size != 1
    bitmap_width = pixels.first.size
    bitmap_height = pixels.size
    pixel_array = pixels.reverse.flat_map do |row|
        # row_bytes = row.map(&hsv2bgr).flatten
        row_bytes = row.flat_map{ |pixel| pixel.is_a?(Array) ? pixel.reverse : [pixel]*3 }
        row_bytes.fill 0, row_bytes.size .. @@align4[row_bytes.size] - 1
    end

    # 12=>BITMAPCOREHEADER, 40=>BITMAPINFOHEADER
    dib_header_size = 12
    file_size = 14 + dib_header_size + pixel_array.size

    open(filename, "wb") do |file|
        # Bitmap file header
        file.write ["BM", file_size, 14 + dib_header_size].pack "A2qi" # "A2QL"
        # DIB header
        # file.write [dib_header_size, bitmap_width, bitmap_height, 1, 24].pack "LllSS"
        # file.write [0, 0, 1, 1, 0, 0].pack "LLllLL" # BITMAPINFOHEADER
        file.write [dib_header_size, bitmap_width, bitmap_height, 1, 24].pack "LSSSS"
        file.write pixel_array.pack "C*"
    end
end

.import(filename = "temp.bmp") ⇒ Object

This imports BITMAPCOREHEADER and 24bpp BITMAPINFOHEADER headed RGB bmp images returning a 3-dimentional array.



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/simple_bmp.rb', line 47

def self.import filename = "temp.bmp"
    File.open(filename, "rb") do |file|
        _, _, shift = file.read(14).unpack("A2qi")
        dib_header_size, = file.read(4).unpack("L")
        case dib_header_size
            when 12 ; bitmap_width, bitmap_height = file.read(4).unpack("SS")
            when 40 ; bitmap_width, bitmap_height = file.read(8).unpack("ii")
            else ; fail "can import only BITMAPCOREHEADER (12 bytes) and 24bpp BITMAPINFOHEADER (40 bytes)"
        end
        file.pos = shift
        (file.read(bitmap_height * @@align4[bitmap_width * 3]).unpack("C*")).
                each_slice(@@align4[bitmap_width * 3]).map do |row|
            row.each_slice(3).take(bitmap_width).map(&:reverse)
        end.reverse
    end
end

.reduce(array, **args) ⇒ Object

Truncated box modal resizing



65
66
67
68
69
70
71
# File 'lib/simple_bmp.rb', line 65

def self.reduce array, **args
    array = array.each_slice(args[:times]).take(array.size/args[:times]).map{ |rows|
        rows.transpose.each_slice(args[:times]).take(array.first.size/args[:times]).map{ |cells|
            cells.flatten(1).group_by{ |i| i }.sort_by{ |i,g| g.size }.last.first
        }
    }
end