# converts image to Verilog HDL that infers a ROM using Xilinx Block RAM
# note: 12-bit color map word is r3, r2, r1, r0, g3, g2, g1, g0, b3, b2, b1, b0

from scipy import misc
import math
RAM_SIZE = 128 #32^2=1024

# returns string of 12-bit color at row x, column y of image
def get_color_bits(im, y, x):
    # convert color components to byte string and slice needed upper bits
    b  = format(im[y][x][0], 'x').zfill(2)
    #rx = b[0:int(4)]
    rx = b[0:int(2)]
    b  = format(im[y][x][1], 'x').zfill(2)
    #gx = b[0:int(4)]
    gx = b[0:int(2)]
    b  = format(im[y][x][2], 'x').zfill(2)
    #bx = b[0:int(4)]
    bx = b[0:int(2)]
    # return concatination of RGB bits
    return str(rx+gx+bx)

# write to file Verilog HDL
# takes name of file, image array,
# pixel coordinates of background color to mask as 0
#def rom_12_bit(name, im, mask=False, rem_x=-1, rem_y=-1):
def rom_24_bit(name, im, mask=False, rem_x=-1, rem_y=-1):

    # get colorbyte of background color
    # if coordinates left at default, map all data without masking
    if rem_x == -1 or rem_y == -1:
        a = "000000000000000000000000"
        
    # else set mask compare byte
    else:
        a = get_color_bits(im, rem_x, rem_y)

    # make output filename from input
    #file_name = name.split('.')[0] + "_12_bit_rom.v"
    #file_name = name.split('.')[0] + "_24_bit_rom.v"
    file_name = "init_bram.c"

    # open file
    f = open(file_name, 'w')

    # get image dimensions
    y_max, x_max, z = im.shape

    # get width of row and column case words
    col_width = int(math.ceil(math.log(y_max-1,2))) 
    row_width = int(math.ceil(math.log(x_max-1,2)))

    # write beginning part of module up to case statements
    #f.write("module " + name.split('.')[0] + "_rom\n\t(\n\t\t")
    #f.write("#include init_bram"+name.split('.')[0]+"h" + "\n\n")
    f.write("#include \"init_bram.h\"" + "\n\n")
    f.write("u32 ImgH="+str(y_max)+", ImgW="+str(x_max)+";\n\n")
    f.write("void init_bram(u32 *buf){\n" + "\n")

    # loops through y rows and x columns
    for y in range(RAM_SIZE):
        for x in range(RAM_SIZE):
          if (y<y_max)&(x<x_max):
            # write : color_data = 
            #case = format(y, 'x').zfill(int(row_width)) + format(x, 'x').zfill(int(col_width))
            case = format(y, 'x') + format(x, 'x')
            f.write("\t\t" + "buf["+str(y*RAM_SIZE+x)+"] = 0x" )

            # if mask is set to false, just write color data
            if(mask == False):
                f.write(get_color_bits(im, y, x))
                f.write(";\n")

            elif(get_color_bits(im, y, x) != a):
                # write color bits to file
                f.write(get_color_bits(im, y, x))
                f.write(";\n")
                
            else:
                f.write("000000;\n")
          else:
            f.write("\t\t" + "buf["+str(y*RAM_SIZE+x)+"] = 0x" )
            f.write("000000;\n")
                
        #f.write("\n")

    f.write("}\n")
    # close file
    f.close()    

# driver function
def generate(name, rem_x=-1, rem_y=-1):
    im = misc.imread(name, mode = 'RGB')
    print("width: " + str(im.shape[1]) + ", height: " + str(im.shape[0]))
    #rom_12_bit(name, im)
    rom_24_bit(name, im)

# generate rom from full bitmap image
#generate("yoshi.bmp")
generate("ev.png")
