[casetta] Of course, I forgot to attach the new img_to_basic

[ Thread Index | Date Index | More lists.tuxfamily.org/casetta Archives ]


Hello,

Hre is the new img_to_basic function...I'm so absent-minded
--
Fabien ANDRE aka Xion345
Linux User #418689 -- fabien.andre.g@xxxxxxxxxx -- xion345@xxxxxxxxxxxxx
World domination. Fast. ( Linus Torvalds, Not dated )
# -*- coding: utf-8 -*-
#
############################################################################
#
# (c) 2006-2007 Florian Birée aka Thesa <florian.biree@xxxxxxxxxxx>
# (c) 2006 Achraf Cherti aka Asher256 <achrafcherti@xxxxxxxxx>
# function img_to_basic is (c) 2007 Xion345 aka Fabien ANDRE 
#                              <fabien.andre.g@xxxxxxxxxx>
#
# Website: <URL:http://casetta.tuxfamily.org>
#
# Version 0.3.0dev
#
# changelog:
#
# # 0.3.0 version:
#
#   o First release
#
############################################################################
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
# MA 02110-1301, USA.
#
# http://www.gnu.org/copyleft/gpl.html
#
############################################################################
"""Pictures manager for casetta"""

__author__ = "Florian Birée, Achraf Cherti, Fabien ANDRE"
__version__ = "0.3.0dev"
__copyright__ = "Copyright (c) 2006-2007, Florian Birée, Achraf Cherti, " + \
                "Fabien ANDRE"
__license__ = "GPL"
__revision__ = "$Revision: $"
# $Source: $
__date__ = "$Date: $"

import Image

# Constants:
ORANGE = (255, 128, 0)
GREEN = (0, 128, 0)
BLUE = (0, 0, 128)
WHITE = (255, 255, 255)
CASIO_SIZE = (128, 64)
COLORS = (ORANGE, GREEN, BLUE, WHITE)
_COLOR_DIC = {'o' : ORANGE,
              'g' : GREEN,
              'b' : BLUE,
              'w' : WHITE}
DEFAULT_PALLET = ['b', 'g', 'w', 'o']
WHITE_LIMIT = 210
# If all color of a pixel are superior of WHITE_LIMITE, they will be white.

# Conversion functions
def normalize(image, colors=COLORS):
    """Convert an image object in a casio-like format.
    
    This will:
    resize image to 128x64
    convert color to 4-color mode
    return a data list.
    pal is a 4-color tuple.
    """
    if image.size != CASIO_SIZE:
        image = image.resize(CASIO_SIZE, Image.ANTIALIAS)
    data = list(image.getdata())
    out = []
    # color conversion
    for pixel in data:
        red, green, blue = pixel[0], pixel[1], pixel[2]
        if red > WHITE_LIMIT and green > WHITE_LIMIT and blue > WHITE_LIMIT:
            pixel = colors[3] # white
        elif red > green and red > blue:
            pixel = colors[0] # orange
        elif green > red and green > blue:
            pixel = colors[1] # green
        elif blue > green and blue > red:
            pixel = colors[2] # blue
        elif red == green and red > blue:
            pixel = colors[1] # green
        elif green == blue and green > red:
            pixel = colors[2] # blue
        elif red == blue and red > green:
            pixel = colors[2] # blue
        elif (red, green, blue) == (0, 0, 0):
            pixel = colors[2] # blue
        out.append(pixel)
    return out

def data_to_sheets(data, wanted_pallet=DEFAULT_PALLET):
    """Make raw picture sheets from *normalized* data
    
    wanted_pallet is a list of color id as 'b', 'g', 'w' or 'o'
    Return a list of data sheets, sorted as wanted_pallet, with the
    color byte at 0."""
    sheets = []
    for color_id in wanted_pallet :
        color = _COLOR_DIC[color_id]
        rev_sheet = '0' * (128 * 64)
        for index in range(len(data)):
            if data[index] == color:
                line = index / 128
                col = (index % 128) / 8
                car = (index % 128) % 8
                pos = car + line * 8 + col * (8 * 64)
                rev_sheet = rev_sheet[:pos] + '1' + rev_sheet[pos + 1:]
        # reverse and compact the rev_sheet
        sheet = ''
        for index in range(0, len(data), 8):
            car = chr(int(rev_sheet[index : index + 8], 2))
            sheet = car + sheet
        sheets.append(chr(wanted_pallet.index(color_id) + 1) + sheet)
    return sheets

def sheets_to_raw(sheets, headers = None):
    """Join sheets to make raw data
    
    The function can add a sheet header form the headers list (one string by 
    sheet).
    """
    raw_img = ''
    for index in range(len(sheets)):
        if headers != None:
            raw_img += headers[index]
        raw_img += sheets[index]
    return raw_img

def data_to_raw(data, wanted_pallet=DEFAULT_PALLET, headers = None):
    """Work as sheets_to_raw(data_to_sheets(data)), with same arguments"""
    return sheets_to_raw(data_to_sheets(data, wanted_pallet), headers)

def raw_to_data(raw_picture, color_byte=0, pal=DEFAULT_PALLET, \
                colors=COLORS, background=WHITE):
    """Make image data from a raw picture
    
    colors is a 4-color tuple,
    color_byte is the index of the color_byte (last byte of a sheet header)
    pal is the ordoned list of the color corresponding to each sheet
    background is the default color of a pixel."""
    #make color dic:
    color_dic = { 'o' : colors[0],
                  'g' : colors[1],
                  'b' : colors[2],
                  'w' : colors[3]}
    #extract raw sheets from raw_picture
    raw_sheets = []
    sh_len = 0x400 + color_byte + 1
    for index in range(len(pal)):
        offset = index * sh_len
        raw_sheets.append(raw_picture[offset: offset + sh_len])
    #convert raw sheets to list data
    data = [background] * (CASIO_SIZE[0] * CASIO_SIZE[1])
    for raw_sheet in raw_sheets:
        color = ord(raw_sheet[color_byte]) - 1
        raw_sheet = raw_sheet[color_byte + 1:]
        for index in range(len(raw_sheet)):
            byte = bin(ord(raw_sheet[index]))
            col, line = (15 - ((index) / 64)) * 8, 63 - ((index) % 64)
            data_pos = line * 128 + (col )
            for bit_index in range(len(byte)):
                if byte[bit_index] == '1':
                    bit_pos = data_pos + bit_index 
                    data[bit_pos] = color_dic[pal[color]]
    return data

def raw_to_sheets(raw_picture, color_byte = 0, sheet_number = 4):
    """Split raw data into sheets"""
    raw_sheets = []
    sh_len = 0x400 + color_byte + 1
    for index in range(sheet_number):
        offset = index * sh_len
        raw_sheets.append(raw_picture[offset + color_byte: offset + sh_len])
    return raw_sheets

def change_sheets_pallet(sheets, old_pallet, new_pallet):
    """Resort sheets from old_pallet to new_pallet
    
    If a collor in new_pallet is not in old_pallet, a empty sheet
    will be made for this color.
    """
    sheet_dic = {}
    for index in range(len(old_pallet)):
        sheet_dic[old_pallet[index]] = sheets[index][1:]
    new_sheets = []
    for index in range(len(new_pallet)):
        new_sheets.append(chr(index + 1) + sheet_dic.get(new_pallet[index], \
                                                         '\x00' * (16 * 64)))
    return new_sheets

# Misc functions
def bin(number, total_length = 8):
    """Convert a number in binary, filled with 0 to reach total_length."""
    out = ''
    while number != 0: 
        number, out = number >> 1, `number & 1` + out
    out = '0' * (total_length - len(out)) + out
    return out



# This function is a contribution of Xion345 aka Fabien ANDRE.
# Xion345, thank you! 
def img_to_basic(imagen, colors=COLORS):
    """Convert a *normalized* image into a Casio Basic program
    This function only returns Horinzontal F-line. It may not be really
    optimised for size"""
    program_header = "\Cls\n\ViewWindow 0,127,1,0,63,1\n"
    orange, green, _, white = colors # colors dictionnary
    # Splits the BIG list given by normalize into a list of list
    # in order to have a table of 128 columns per 64 lines
    picture_table = []
    basic_pictureh = '' # A picture under the form of a basic program / Returned
                        # by the function - Horizontal lines
    basic_picturev='' # A picture under the form of a basic program / Returned
                      # by the function - Vertical lines
    line = 0
    plot_table=[]
    while line <= 63:
        picture_table.append(imagen[line*128:((line+1)*128)])
        line += 1
    line = 0
##### This Big blocks transforms the picture into a program using :    
##### HORIZONTAL F-lines only (except for orphan plots, it tries to detect
##### vertical F-lines)   
    while line <= 63:
        col = 0
        current_color = 0 # This var contains the previously saved color
        orig_x = 0
        orig_y = 0
        end_x = 0
       
        while col <= 127:
            if picture_table[line][col] != current_color and \
            picture_table[line][col-1] == current_color \
            and current_color in colors[:3] or col==127 and current_color != \
            white and picture_table[line][col] == current_color:
            # If you get a pixel which color is different from current_color 
            # and if before you have a colored pixel, 
            #that's because you encountered the end of the F-line
           
                # The second condition after the or is an UGLY correction of a
                # BUG ^W Feature
                # If an F-line goes at the lats pixel of a picture_table line,
                # the line is not drawn because the first confition (end line
                # see above ), waits for the pixel just after the end of the
                # line. This blocks checks if were are at the last pixel of the
                # line and if a F-line is being drawn (current_color != white) 
                
                if col != 127:
                    end_x -= 1
                
                # The origin of the reference mark is different 
                #on the casio graph and on the picture
                # On casio origin is bottom left-hand corner 
                # On the picture and my table, it's top left-hand corner
                # That's why it must do casio_line = 63-line
                casio_orig_y = 63-orig_y 
                
                if end_x-orig_x>1:
                    if current_color == orange:
                        basic_pictureh += "\\Orange "
                    if current_color == green:
                        basic_pictureh += "\\Green "
                    if end_x-orig_x!=127:
                        basic_pictureh += "\\F-Line " \
                        + str(orig_x) + "," + str(casio_orig_y) + "," \
                        + str(end_x) + "," + str(casio_orig_y) + "\n"
                    else:
                        basic_pictureh += "\\Horizontal "+str(casio_orig_y)+"\n"
                #
                elif end_x==orig_x:
                    # basic_pictureh += "\\PlotOn " \
                    # + str(orig_x) + ","+str(casio_orig_y) + "\n"
                    #
                    # Rather than drawing directly orphan Plot-on, 
                    # they are stored in
                    # a table in order to detec if they could be drawn as a 
                    # **VERTICAL** F-line
                    plot_table.append((current_color, orig_x, casio_orig_y))
                elif end_x-orig_x==1:
                    # Rather than writing a 2-pixel long F-line, 
                    # we store two plots 
                    # in plot_table, expecting that it is part of a longer
                    # F-line
                    plot_table.append((current_color, orig_x, casio_orig_y))
                    plot_table.append((current_color, end_x, casio_orig_y))
                current_color = 0 # This var contains the previously saved color
                orig_x = 0
                orig_y = 0
                end_x = 0
            if picture_table[line][col] != white and \
            picture_table[line][col] != current_color:
                # New F-line to add detected
                current_color = picture_table[line][col]
                end_x = col
                orig_x = col
                orig_y = line
            if picture_table[line][col] !=  white and \
            picture_table[line][col] == current_color:
                # Continues the F-line
                end_x += 1
            col += 1
        line += 1
    ### This bloc tries to draw VERTICAL F-lines from stored orphan plots
    ### in plot-table
    while len(plot_table) > 0:
        #print plot_table
        current_color=plot_table[0][0]
        orig_x=plot_table[0][1]
        casio_orig_y=casio_end_y=plot_table[0][2]
        plot_table.pop(0)
        i=0
        while i < len(plot_table):
            #print '*'+str(plot_table.index(i))
            #print plot_table
            if plot_table[i][0]==current_color and \
            plot_table[i][1]==orig_x and plot_table[i][2]==casio_end_y-1:
                casio_end_y=plot_table[i][2]
                plot_table.pop(i)
                i -= 1
            i += 1 
        # End of VERTICAL F-line, all plots were checked
        if current_color == orange:
            basic_pictureh += "\\Orange "
        if current_color == green:
            basic_pictureh += "\\Green "
        if casio_orig_y != casio_end_y:
            basic_pictureh += "\\F-Line " \
                    + str(orig_x) + "," + str(casio_orig_y) + "," \
                    + str(orig_x) + "," + str(casio_end_y) + "\n"
        else:
            basic_pictureh += "\\PlotOn " \
            + str(orig_x) + ","+str(casio_orig_y) + "\n"
            
##### This Big blocks transforms the picture into a program using :    
##### VERTICAL F-lines only (except for orphan plots, it tries to detect
##### horizontal F-lines)   
    col=0
    while col <= 127:
        line = 0
        current_color = 0 # This var contains the previously saved color
        orig_x = 0
        orig_y = 0
        end_y = 0
       
        while line <= 63:
            
            if picture_table[line][col] != current_color and \
            picture_table[line-1][col] == current_color \
            and current_color in colors[:3] or line==63 and current_color != \
            white and picture_table[line][col] == current_color:
            # If you get a pixel which color is different from current_color 
            # and if before you have a colored pixel, 
            #that's because you encountered the end of the F-line
           
                # The second condition after the or is an UGLY correction of a
                # BUG ^W Feature
                # If an F-line goes at the lats pixel of a picture_table line,
                # the line is not drawn because the first confition (end line
                # see above ), waits for the pixel just after the end of the
                # line. This blocks checks if were are at the last pixel of the
                # line and if a F-line is being drawn (current_color != white) 
                if line != 63:
                    end_y -= 1
                
                # The origin of the reference mark is different 
                # on the casio graph and on the picture
                # On casio origin is bottom left-hand corner 
                # On the picture and my table, it's top left-hand corner
                # That's why it must do casio_line = 63-line
                casio_orig_y = 63-orig_y 
                casio_end_y = 63-end_y
                print str(casio_orig_y)+'-'+str(casio_end_y)
                if abs(casio_end_y-casio_orig_y)>1:
                    if current_color == orange:
                        basic_picturev += "\\Orange "
                    if current_color == green:
                        basic_picturev += "\\Green "
                    if abs(casio_end_y-casio_orig_y) != 63:
                        basic_picturev += "\\F-Line " \
                        + str(orig_x) + "," + str(casio_orig_y) + "," \
                        + str(orig_x) + "," + str(casio_end_y) + "\n"
                    else:
                        basic_picturev += "\\Vertical "+str(orig_x)+"\n"
                elif casio_end_y==casio_orig_y:
                    # Rather than drawing directly orphan Plot-on, 
                    # they are stored in
                    # a table in order to detec if they could be drawn as a 
                    # **VERTICAL** F-line
                    # 
                    plot_table.append((current_color, orig_x, casio_orig_y))
                elif abs(casio_end_y-casio_orig_y)==1:
                    # Rather than writing a 2-pixel F-line, we store two plots 
                    # in plot_table, expecting that it is part of a longer
                    # F-line
                    # 
                    plot_table.append((current_color, orig_x, casio_orig_y))
                    plot_table.append((current_color, end_x, casio_end_y))
                current_color = 0 # This var contains the previously saved color
                orig_x = 0
                orig_y = 0
                end_y = 0
            
            if picture_table[line][col] != white and \
            picture_table[line][col] != current_color:
                # New F-line to add detected
                current_color = picture_table[line][col]
                end_y = line
                orig_x = col
                orig_y = line
            if picture_table[line][col] !=  white and \
            picture_table[line][col] == current_color:
                # Continues the F-line
                end_y += 1
            line += 1
        col += 1
    ### This bloc tries to draw HORIZONTAL F-lines from stored orphan plots
    print plot_table
    while len(plot_table) > 0:
        current_color=plot_table[0][0]
        end_x=orig_x=plot_table[0][1]
        casio_orig_y=plot_table[0][2]
        plot_table.pop(0)
        i=0
        while i < len(plot_table):
            if plot_table[i][0]==current_color and \
            plot_table[i][2]==casio_orig_y and plot_table[i][1]==end_x+1:
                end_x=plot_table[i][1]
                plot_table.pop(i)
                i -= 1
            i += 1 
        # End of HORIZONTAL F-line, all plots were checked
        if current_color == orange:
            basic_picturev += "\\Orange "
        if current_color == green:
            basic_picturev += "\\Green "
        if orig_x != end_x:
            basic_picturev += "\\F-Line " \
                    + str(orig_x) + "," + str(casio_orig_y) + "," \
                    + str(end_x) + "," + str(casio_orig_y) + "\n"
        else:
            basic_picturev += "\\PlotOn " \
            + str(orig_x) + ","+str(casio_orig_y) + "\n"

### Then the function returns the lightest picture : using horizontal F-lines 
### or using vertical F-lines

    if len(basic_pictureh) <= len(basic_picturev):
        return program_header + basic_pictureh
    else:
        return program_header + basic_picturev


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/