def populate_from_image_file(self, path, f, composite_op = None): if not Image: raise RuntimeError, 'Cannot open non-native image types without Python Imaging Library: %s' % (path) src = Image.open(f) (w, h) = src.size # print ("conversion of image, sized " + str(w) + "," + str(h)) if len(self.frames) > 0 and (w != self.width or h != self.height): raise ValueError, "Image sizes must be uniform! Anim is %dx%d, image is %dx%d" % (w, h, self.width, self.height) (self.width, self.height) = (w, h) # I'm punting on animated gifs, because they're too slow. If you coalesce them # via image magic then they are fast again. if path.endswith('.gif'): import animgif self.frames += animgif.gif_frames(src, composite_op = composite_op) else: (w,h) = src.size if src.mode == "P": src.convert("RGB") src.mode = "RGB" surf = sdl2_DisplayManager.inst().make_texture_from_imagebits(bits=src.tobytes(), width=w, height=h, mode=src.mode, composite_op = composite_op) frame = Frame(w,h,surf) self.frames.append(frame)
def populate_from_mp4_file(self, file): if (cv2 is None): raise ValueError, "MP4 is unavailable as OpenCV is not installed" vc = cv2.VideoCapture(file) self.width = int(vc.get(cv.CV_CAP_PROP_FRAME_WIDTH)) self.height = int(vc.get(cv.CV_CAP_PROP_FRAME_HEIGHT)) frame_count = int(vc.get(cv.CV_CAP_PROP_FRAME_COUNT)) #vc.set(cv.CV_CAP_PROP_CONVERT_RGB, True) #print "width:" + str(self.width) + " Height: " + str(self.height) + "frame count: " + str(frame_count) for i in range(frame_count): rval, video_frame = vc.read() if rval is not None: video_frame = cv2.cvtColor(video_frame, cv2.cv.CV_BGR2RGB) the_frame = cv.fromarray(video_frame) # surface = pygame.image.frombuffer(the_frame.tostring(), (self.movie.width, self.movie.height), 'RGB') surf = sdl2_DisplayManager.inst().make_texture_from_imagebits( bits=the_frame.tostring(), width=self.width, height=self.height, mode='RGB', composite_op=None) new_frame = Frame(self.width, self.height, from_surface=surf) self.frames.append(new_frame) vc.release()
def drawHD(self, frame, text, x, y, line_color, line_width, interior_color, fill_color, font_size=None): """Uses this font's characters to draw the given string at the given position.""" #t = self.pygFont.render(text,False,(255,0,255),(0,0,0)) # print("drawHD(%s) - line color=%s | line width=%d" % (text,line_color, line_width )) if (line_color is None or line_width == 0): return self.draw(frame, text, x, y, interior_color, fill_color) # if(interior_color is None): # interior_color=(255,255,255) # surf = self.pygFont.render(text,False,color,(0,0,0)) # (w,h) = surf.get_size() if (text is None or text == ""): return x if (font_size is None): font_size = self.font_size surf = sdl2_DisplayManager.inst().font_render_bordered_text( text, font_alias=self.name, size=font_size, width=None, color=interior_color, bg_color=fill_color, border_color=line_color, border_width=line_width) (w, h) = surf.size tmp = Frame(w, h, from_surface=surf) # tmp.composite_op = "blacksrc" # w = min(w, frame.width) # h = min(h, frame.height) Frame.copy_rect(dst=frame, dst_x=x, dst_y=y, src=tmp, src_x=0, src_y=0, width=w, height=h, op=self.composite_op) #Frame.copy_rect(dst=frame, dst_x=x, dst_y=y, src=self.bitmap, src_x=char_x, src_y=char_y, width=width, height=self.char_size, op=self.composite_op) return x + w
def save(self, filename): """Save the font to the given path.""" out = Animation() out.width = self.__anim.width out.height = self.__anim.height out.frames = [self.bitmap, Frame(out.width, out.height)] for i in range(96): out.frames[1].set_font_dot(i%self.__anim.width, i/self.__anim.width, self.char_widths[i]) out.save_old(filename)
def load_single_frame(self, idx): ## ONLY USE THIS FROM STREAMING LOAD!! path = self.filenames[idx] print("loading %s" % path) tx = sdl2_DisplayManager.inst().load_texture(path, self.composite_op) (self.width,self.height) = tx._size frame = Frame(self.width,self.height,tx) return frame
def __init__(self, width, height, duration=None): super(ParticleLayer, self).__init__() self.buffer = Frame(width, height) self.start_time = None self.duration = duration # FIRE def emitter_dx(x): return random.randint(-10,10) def emitter_dy(x): return random.randint(-3,3) def dither_dx(x): return random.randint(-10,0) def dither_dy(x): return (x - 0.35) self.ps = ParticleSystem(width/2, height/2, max_life=20, max_particles=400, particles_per_update=20, emitter_dx_fn=emitter_dx, emitter_dy_fn=emitter_dy, dither_dx_fn=dither_dx, dither_dy_fn=dither_dy)
def load(self, filename, char_widths = None): """Loads the font from a ``.dmd`` file (see :meth:`Animation.load`). Fonts are stored in .dmd files with frame 0 containing the bitmap data and frame 1 containing the character widths. 96 characters (32..127, ASCII printables) are stored in a 10x10 grid, starting with space (``' '``) in the upper left at 0, 0. The character widths are stored in the second frame within the 'raw' bitmap data in bytes 0-95. """ (font_info_file, ext) = os.path.splitext(filename) (file_base_name, file_extension) = os.path.splitext(filename) #if ext == '.bmp': # self.load_png_font(filename) self.__anim.load(filename, composite_op = 'blacksrc') if self.__anim.width != self.__anim.height: raise ValueError, "Width != height!" if ext == '.dmd': if len(self.__anim.frames) == 1: # We allow 1 frame for handmade fonts. # This is so that they can be loaded as a basic bitmap, have their char widths modified, and then be saved. print "Font animation file %s has 1 frame; adding one" % (filename) self.__anim.frames += [Frame(self.__anim.width, self.__anim.height)] elif len(self.__anim.frames) != 2: raise ValueError, "Expected 2 frames: %d" % (len(self.__anim.frames)) self.char_size = self.__anim.width / 10 self.bitmap = self.__anim.frames[0] self.char_widths = [] if ext=='.dmd': if(char_widths==None): for i in range(96): #print 'getting widths for character number: ' + str(i) #print 'x ' + str(i%self.__anim.width) self.char_widths += [self.__anim.frames[1].get_font_dot(i%self.__anim.width, i/self.__anim.width)] #self.char_widths += [self.char_size] #JEK hack else: # print("font widths provided") self.char_widths = char_widths # for i in range(96): # self.__anim.frames[1].set_font_dot(i%self.__anim.width, i/self.__anim.width, self.char_widths[i]) elif ext =='.bmp' or ext == '.png' or ext =='.jpg': #now read in the widths (path,file) = os.path.split(filename) csv_file = font_info_file + ".csv" with open(csv_file, 'rb') as csvfile: reader = csv.reader(csvfile, delimiter=',', quotechar='|') for row in reader: for s in row: self.char_widths +=[int(s)] else: raise ValueError, "Font failed to load [%s] Expected font of type .dmd, .png, .bmp, or .jpg" % filename return self
def draw(self, frame, text, x, y, color=None, bg_color=None, font_size=None): """Uses this font's characters to draw the given string at the given position.""" #t = self.pygFont.render(text,False,(255,0,255),(0,0,0)) if (color is None): color = (255, 255, 255) # surf = self.pygFont.render(text,False,color,(0,0,0)) # (w,h) = surf.get_size() if (text is None or text == ""): return x if (font_size is None): font_size = self.font_size surf = sdl2_DisplayManager.inst().font_render_text( text, font_alias=self.name, size=font_size, width=None, color=color, bg_color=bg_color) (w, h) = surf.size tmp = Frame(w, h, from_surface=surf) tmp.composite_op = "blacksrc" # w = min(w, frame.width) # h = min(h, frame.height) Frame.copy_rect(dst=frame, dst_x=x, dst_y=y, src=tmp, src_x=0, src_y=0, width=w, height=h, op=self.composite_op) #Frame.copy_rect(dst=frame, dst_x=x, dst_y=y, src=self.bitmap, src_x=char_x, src_y=char_y, width=width, height=self.char_size, op=self.composite_op) return x + w
def gif_frames(src, composite_op=None): """Returns an array of frames to be added to the animation.""" frames = [] # We have to do some special stuff for animated GIFs: check for the background index, and if we get it use the last frame's value. transparent_idx = -1 background_idx = -1 if 'transparency' in src.info: transparent_idx = src.info['transparency'] if 'background' in src.info: background_idx = src.info['background'] last_frame = None (w, h) = src.size for src_im in ImageSequence(src): image = src_im.convert("RGB") (w, h) = image.size frame = procgame.dmd.Frame(w, h) surf = sdl2_DisplayManager.inst().make_texture_from_imagebits( bits=image.tostring(), width=w, height=h, mode=image.mode, composite_op=composite_op) # for x in range(w): # for y in range(h): # idx = src_im.getpixel((x, y)) # Get the palette index for this pixel # if idx == background_idx: # # background index means use the prior frame's dot data # if last_frame: # color = last_frame.pySurface.get_at((x,y)) # surface.set_at((x,y), (0,0,0)) # else: # # No prior frame to refer to. # surface.set_at((x,y), (0,0,0)) # elif idx == transparent_idx: # surface.set_at((x,y), (0,0,0)) frame = Frame(w, h, surf) frames.append(frame) # last_frame = frame return frames
def convertImageToOldDMD(src): pal_image = Image.new("P", (1, 1)) tuplePal = VgaDMD.get_palette() flatPal = [element for tupl in tuplePal for element in tupl] pal_image.putpalette(flatPal) src_rgb = src.convert("RGB").quantize(palette=pal_image) src_p = src_rgb.convert("P") (w, h) = src.size frame = Frame(w, h) for x in range(w): for y in range(h): color = src_p.getpixel((x, y)) frame.set_dot(x=x, y=y, value=color) return frame
def populate_from_dmd_file(self, f, composite_op=None): f.seek(0, os.SEEK_END) # Go to the end of the file to get its length file_length = f.tell() f.seek(0) # Skip back to the 4 byte DMD header. dmd_version = struct.unpack("I", f.read(4))[0] dmd_style = 0 # old if (dmd_version == 0x00646D64): # print("old dmd style") pass elif (dmd_version == 0x00DEFACE): # print("full color dmd style") dmd_style = 1 frame_count = struct.unpack("I", f.read(4))[0] self.width = struct.unpack("I", f.read(4))[0] self.height = struct.unpack("I", f.read(4))[0] if (dmd_style == 0): if file_length != 16 + self.width * self.height * frame_count: logging.getLogger('game.dmdcache').warning(f) logging.getLogger('game.dmdcache').warning( "expected size = {%d} got {%d}", (16 + self.width * self.height * frame_count), (file_length)) raise ValueError, "File size inconsistent with original DMD format header information. Old or incompatible file format?" elif (dmd_style == 1): if file_length != 16 + self.width * self.height * frame_count * 3: logging.getLogger('game.dmdcache').warning(f) raise ValueError, "File size inconsistent with true-color DMD format header information. Old or incompatible file format?" for frame_index in range(frame_count): new_frame = Frame(self.width, self.height) if (dmd_style == 0): str_frame = f.read(self.width * self.height) new_frame.build_surface_from_8bit_dmd_string( str_frame, composite_op) elif (dmd_style == 1): str_frame = f.read(self.width * self.height * 3) new_frame.pySurface = sdl2_DisplayManager.inst( ).make_texture_from_imagebits(bits=str_frame, width=self.width, height=self.height, composite_op=composite_op) if (frame_index == 1): new_frame.font_dots = str_frame[0:97] self.frames.append(new_frame)
def __init__(self, width, height, emitters, duration=None, num_hold_frames=1): super(ParticleLayer, self).__init__() self.buffer = Frame(width, height) self.start_time = None self.duration = duration self.width = width self.height = height self.num_hold_frames = num_hold_frames self.stalls = self.num_hold_frames # FIRE # def emitter_dx(x): return random.randint(-10,10) # def emitter_dy(x): return random.randint(-3,3) # def dither_dx(x): return random.randint(-10,0) # def dither_dy(x): return (x - 0.35) # self.ps = ParticleEmitter(width/2, height/2, max_life=20, max_particles=200, particles_per_update=100, total_creations=400, particle_class=Particle) self.ps = ParticleSystem(emitters=emitters, destination_texture=self.buffer.pySurface)
def populate_from_dmd_file(self, f, composite_op = None): f.seek(0, os.SEEK_END) # Go to the end of the file to get its length file_length = f.tell() ## MJO: Don't just skip the header! Check it. f.seek(0) # Skip over the 4 byte DMD header. dmd_version = struct.unpack("I", f.read(4))[0] dmd_style = 0 # old if(dmd_version == 0x00646D64): # print("old dmd style") pass elif(dmd_version == 0x00DEFACE): # print("full color dmd style") dmd_style = 1 frame_count = struct.unpack("I", f.read(4))[0] self.width = struct.unpack("I", f.read(4))[0] self.height = struct.unpack("I", f.read(4))[0] if(dmd_style==0): if file_length != 16 + self.width * self.height * frame_count: logging.getLogger('game.dmdcache').warning(f) logging.getLogger('game.dmdcache').warning("expected size = {%d} got {%d}", (16 + self.width * self.height * frame_count), (file_length)) raise ValueError, "File size inconsistent with original DMD format header information. Old or incompatible file format?" elif(dmd_style==1): if file_length != 16 + self.width * self.height * frame_count * 3: logging.getLogger('game.dmdcache').warning(f) raise ValueError, "File size inconsistent with true-color DMD format header information. Old or incompatible file format?" for frame_index in range(frame_count): new_frame = Frame(self.width, self.height) if(dmd_style==0): str_frame = f.read(self.width * self.height) new_frame.build_surface_from_8bit_dmd_string(str_frame, composite_op) elif(dmd_style==1): # print("LOADING FRAME...") str_frame = f.read(self.width * self.height * 3) # surface = pygame.image.fromstring(str_frame, (self.width, self.height), 'RGB') # new_frame.set_surface(surface) # https://wiki.libsdl.org/SDL_CreateRGBSurfaceFrom?? new_frame.pySurface = sdl2_DisplayManager.inst().make_texture_from_imagebits(bits=str_frame, width=self.width, height=self.height, composite_op=composite_op) # print("made texture for this frame -- contents: " + str(new_frame.pySurface)) if(frame_index==1): new_frame.font_dots = str_frame[0:97] self.frames.append(new_frame)
def convertImage(src): image = src.convert("RGBA") (w, h) = image.size frame = Frame(w, h) mode = image.mode size = image.size data = image.tostring() #assert mode in 'RGB', 'RGBA' # surface = pygame.image.fromstring(data, size, mode) #raise ValueError, "convertImage doesn't work..." frame.pySurface = HD_make_texture_from_bits(data, w, h) # print("ConvertImage made texture for this frame -- contents: " + str(new_frame.pySurface)) # frame.set_surface(surface) return frame
def old_populate_from_image_file(self, path, f): if not Image: raise RuntimeError, 'Cannot open non-native image types without Python Imaging Library: %s' % (path) src = Image.open(f) (w, h) = src.size if len(self.frames) > 0 and (w != self.width or h != self.height): raise ValueError, "Image sizes must be uniform! Anim is %dx%d, image is %dx%d" % (w, h, self.width, self.height) (self.width, self.height) = (w, h) if path.endswith('.gif'): from . import animgif self.frames += animgif.gif_frames(src) else: alpha = None try: alpha = Image.fromstring('L', src.size, src.tostring('raw', 'A')) except: pass # No alpha channel available? reduced = src.convert("L") frame = Frame(w, h) # Construct a lookup table from 0-255 to 0-15: eight_to_four_map = [0] * 256 for l in range(256): eight_to_four_map[l] = int(round((l/255.0) * 15.0)) for x in range(w): for y in range(h): color = eight_to_four_map[reduced.getpixel((x,y))] if alpha: color += eight_to_four_map[alpha.getpixel((x,y))] << 4 frame.set_dot(x=x, y=y, value=color) self.frames.append(frame)
def draw_in_rect(self, frame, text, rect=(0, 0, 128, 32), anchor=AnchorCenter, font_size=None): """Draw *text* on *frame* within the given *rect*, aligned in accordance with *anchor*. *rect* is a tuple of length 4: (origin_x, origin_y, height, width). 0,0 is in the upper left (NW) corner. *anchor* is one of: :attr:`~procgame.dmd.AnchorN`, :attr:`~procgame.dmd.AnchorE`, :attr:`~procgame.dmd.AnchorS`, :attr:`~procgame.dmd.AnchorW`, :attr:`~procgame.dmd.AnchorNE`, :attr:`~procgame.dmd.AnchorNW`, :attr:`~procgame.dmd.AnchorSE`, :attr:`~procgame.dmd.AnchorSW`, or :attr:`~procgame.dmd.AnchorCenter` (the default). """ origin_x, origin_y, width, height = rect if (font_size is None): font_size = self.font_size surf = sdl2_DisplayManager.inst().font_render_text( text, font_alias=self.name, size=font_size, width=None, color=None, bg_color=None) text_width, text_height = surf.size tmp = Frame(text_width, text_height, from_surface=surf) tmp.composite_op = "blacksrc" x = 0 y = 0 # print "Size: %d x %d" % (text_height) if anchor & AnchorN: y = origin_y elif anchor & AnchorS: y = origin_y + (height - text_height) else: y = origin_y + (height / 2.0 - text_height / 2.0) if anchor & AnchorW: x = origin_x elif anchor & AnchorE: x = origin_x + (width - text_width) else: x = origin_x + (width / 2.0 - text_width / 2.0) # w = min(width, frame.width) # h = min(height, frame.height) w = text_width #min(width, frame.width) h = text_height #min(height, frame.height) # self.draw(frame=frame, text=text, x=x, y=y) Frame.copy_rect(dst=frame, dst_x=x, dst_y=y, src=tmp, src_x=0, src_y=0, width=w, height=h, op=tmp.composite_op)
def main(): from os import sys if len(sys.argv) <= 1: show_commandline_help() import font from font import Font import layers from layers import HDTextLayer, TextLayer import time import sdl2 t0 = time.clock() import ctypes from ctypes import byref, cast, POINTER, c_int, c_float, sizeof, c_uint32, c_double, c_voidp, c_void_p from sdl2 import endian exp_font_name = sys.argv[1] font_size = 48 if len(sys.argv) > 2: font_size = int(sys.argv[2]) sdl2_DisplayManager.Init(10, 10, 1) sdl2_DisplayManager.inst().fonts_init("Courier", "HHSam") font_path = match_font(exp_font_name) #"coalition") sdl2_DisplayManager.inst().font_add( font_path=font_path, font_alias="export_font", size=font_size) #, color=None, bgcolor=None) char_size = 0 lChars = [chr(i + ord(' ')) for i in xrange(0, 95)] for char_offset, c in zip(xrange(0, 95), lChars): # surf = f.textHollow(c, line_color, interior_color, line_width, fill_color) (font_width, font_height) = sdl2_DisplayManager.inst().font_get_size( c, 'export_font', font_size) char_size = max(char_size, font_width, font_height) width = height = char_size * 10 font_sizes = '' # hack stuff to re-attach the correctly sized window sdl2_DisplayManager.inst().window = sdl2.ext.Window("Font Preview", size=(width, height)) sdl2_DisplayManager.inst().texture_renderer = sdl2.ext.Renderer( sdl2_DisplayManager.inst().window) sdl2_DisplayManager.inst().fill = sdl2_DisplayManager.inst( ).texture_renderer.fill sdl2_DisplayManager.inst().clear = sdl2_DisplayManager.inst( ).texture_renderer.clear sdl2_DisplayManager.inst().factory = sdl2.ext.SpriteFactory( renderer=sdl2_DisplayManager.inst().texture_renderer) sdl2_DisplayManager.inst().show_window() frame = Frame(width, height) #BGR? interior_color = (255, 255, 255) line_width = 0 #fill_color = (255,0,0) line_color = (1, 1, 1) for char_offset, c in zip(xrange(0, 95), lChars): # surf = f.textHollow(c, line_color, interior_color, line_width, fill_color) char_x = char_size * (char_offset % 10) char_y = char_size * (char_offset / 10) surf = sdl2_DisplayManager.inst().font_render_bordered_text_Faster( frame.pySurface, { 'x': char_x, 'y': char_y }, c, font_alias='export_font', size=font_size, border_width=line_width, border_color=line_color, color=interior_color) (font_width, font_height) = sdl2_DisplayManager.inst().font_get_size( c, 'export_font', font_size) #font_sizes += format(font_width,'x') font_sizes += str(font_width) font_sizes += "," sdl2_DisplayManager.inst().screen_blit( source_tx=frame.pySurface, expand_to_fill=True) #, area=(10,10,400,200)) texture_renderer = sdl2_DisplayManager.inst().texture_renderer bk = sdl2.SDL_GetRenderTarget(texture_renderer.renderer) t = sdl2.render.SDL_CreateTexture(texture_renderer.renderer, sdl2.pixels.SDL_PIXELFORMAT_RGBA8888, sdl2.render.SDL_TEXTUREACCESS_TARGET, width, height) #create a new texture and blit the frame to it, then grab bits from that texture_renderer.clear((0, 0, 0, 0)) sdl2.SDL_SetRenderTarget(texture_renderer.renderer, t) #sdl2_DisplayManager.inst().blit(source_tx=frame.pySurface, dest_tx = t, dest = (0,0,512,512)) texture_renderer.copy(frame.pySurface, (0, 0, width, height), (0, 0, width, height)) pitch = c_int() bytes = c_void_p() rect = sdl2.SDL_Rect(0, 0, width, height) sdl2.SDL_LockTexture(t, rect, ctypes.byref(bytes), ctypes.byref(pitch)) if endian.SDL_BYTEORDER == endian.SDL_LIL_ENDIAN: rmask = 0x000000FF gmask = 0x0000FF00 bmask = 0x00FF0000 amask = 0xFF000000 else: rmask = 0xFF000000 gmask = 0x00FF0000 bmask = 0x0000FF00 amask = 0x000000FF print rmask imgsurface = sdl2.surface.SDL_CreateRGBSurfaceFrom(bytes, width, height, 32, pitch, rmask, gmask, bmask, amask) if not imgsurface: raise sdl2.ext.SDLError() sdl2.SDL_RenderReadPixels(texture_renderer.renderer, rect, 0, bytes, pitch) sdl2.SDL_SaveBMP(imgsurface, 'image.png') #4) Restore renderer's texture target sdl2.SDL_SetRenderTarget(texture_renderer.renderer, bk) #ss = sdl2.ext.SoftwareSprite(surf, True) #ss = sdl2.ext.SoftwareSprite(imgsurface, True) #sdl2.SDL_SaveBMP(ss.contents, "file.bmp") # # print font_sizes sdl2_DisplayManager.inst().flip() sdl2.SDL_Delay(2)
def populate_from_image_file_sdl2(self, path, f, composite_op=None): # print("loading %s" % f) tx = sdl2_DisplayManager.inst().load_texture(path, composite_op) (self.width, self.height) = tx._size frame = Frame(self.width, self.height, tx) self.frames.append(frame)