def setupBackgroundImage(self): image_file = Filename(TestGameBase.__BACKGROUND_IMAGE_PATH__) # check if image can be loaded img_head = PNMImageHeader() if not img_head.readHeader(image_file ): raise IOError("PNMImageHeader could not read file %s. Try using absolute filepaths"%(image_file.c_str())) sys.exit() # Load the image with a PNMImage w = img_head.getXSize() h = img_head.getYSize() img = PNMImage(w,h) #img.alphaFill(0) img.read(image_file) texture = Texture() texture.setXSize(w) texture.setYSize(h) texture.setZSize(1) texture.load(img) texture.setWrapU(Texture.WM_border_color) # gets rid of odd black edges around image texture.setWrapV(Texture.WM_border_color) texture.setBorderColor(LColor(0,0,0,0)) # creating CardMaker to hold the texture cm = CardMaker('background') cm.setFrame(-0.5*w,0.5*w,-0.5*h,0.5*h) # This configuration places the image's topleft corner at the origin (left, right, bottom, top) background_np = NodePath(cm.generate()) background_np.setTexture(texture) background_np.reparentTo(self.render) background_np.setPos(TestGameBase.__BACKGROUND_POSITION__) background_np.setScale(TestGameBase.__BACKGROUND_SCALE__)
def read_texture(self, filename): """ Reads a texture from the Pandora resources repository. Returns a PNMImage object representing the image data. Throws a PalettizerException if file could not be found. :filename: Relative filename pointing to a texture file in the Pandora repository. """ full_filename = self.find_texture(filename) if self.debug: print(f'Reading {full_filename}...') # We've found the source file! Let's load it using Panda3D. img = PNMImage() img.read(Filename.from_os_specific(full_filename)) needs_alpha_fill = img.num_channels not in (2, 4) img.set_color_type(4) if needs_alpha_fill: # We need an alpha channel no matter what, so if the image does not have one, # it needs to be filled immediately with opaque pixels as it starts out with transparent pixels img.alpha_fill(1) return img
def __map_Topography(self, planet, model, pts=[]): height_map = PNMImage() height_map_path = "{}/maps/{}".format(planet.path, planet.height_map) height_map.read(Filename(height_map_path)) _hu_size = height_map.getXSize() - 1 _hv_size = height_map.getYSize() - 1 radius = planet.radius bottom = radius + planet.height_min elev_range = planet.height_max - planet.height_min _has_sea = "sea_level" in planet.__dict__ if _has_sea: sea_level = planet.sea_level + planet.radius if not pts: pts = model.read("vertex") for pt in pts: u, v = self.__get_Pt_Uv(pt, _hu_size, _hv_size) height_val = height_map.getGray( u, v) ## watch when extending w colours. height = bottom + elev_range * height_val ratio = height / radius pt *= ratio # If planet has sea then raise vert to sea level. if _has_sea: len_pt = pt.length() if len_pt <= sea_level: ratio = sea_level / len_pt pt *= ratio model.modify("vertex", pts)
def __map_Topography(self, planet, model, pts=[]): height_map = PNMImage() height_map_path = "{}/maps/{}".format(planet.path, planet.height_map) height_map.read(Filename(height_map_path)) _hu_size = height_map.getXSize()-1 _hv_size = height_map.getYSize()-1 radius = planet.radius bottom = radius + planet.height_min elev_range = planet.height_max - planet.height_min _has_sea = "sea_level" in planet.__dict__ if _has_sea: sea_level = planet.sea_level + planet.radius if not pts: pts = model.read("vertex") for pt in pts: u, v = self.__get_Pt_Uv(pt, _hu_size, _hv_size) height_val = height_map.getGray(u, v) ## watch when extending w colours. height = bottom + elev_range*height_val ratio = height / radius pt *= ratio # If planet has sea then raise vert to sea level. if _has_sea: len_pt = pt.length() if len_pt <= sea_level: ratio = sea_level/len_pt pt *= ratio model.modify("vertex", pts)
def __apply_Textures(self, recipe, tex_dict): for i, ter_dict in enumerate(recipe['terrains']): tex_img = PNMImage() tex_img.read(Filename("{}/tex/{}".format(recipe['planet_path'], ter_dict['texture']))) tex = Texture() tex.load(tex_img) tex.setMinfilter(Texture.FTLinear) ts = TextureStage(str(i)) ts.setSort(i) self.NP.setTexture(ts, tex, i*10)
def __apply_Textures(self, recipe, tex_dict): for i, ter_dict in enumerate(recipe['terrains']): tex_img = PNMImage() tex_img.read( Filename("{}/tex/{}".format(recipe['planet_path'], ter_dict['texture']))) tex = Texture() tex.load(tex_img) tex.setMinfilter(Texture.FTLinear) ts = TextureStage(str(i)) ts.setSort(i) self.NP.setTexture(ts, tex, i * 10)
def __build_Normal_Map(self, recipe): # Load ref image. ref_img = PNMImage() height_map_path = "{}/maps/{}".format(recipe['path'], recipe['height_map']) ref_img.read(Filename(height_map_path)) # Create normal map from height map with GPU. with GPU_Image(ref_img, print_times=True) as gpu: height_range = LVector2f(recipe['height_min'], recipe['height_max']) norm_img = gpu.generate_normal_map(height_range=height_range) norm_img.write(Filename("{}/maps/earth_norm.jpg".format(recipe['path']))) return recipe
def loadSpriteImages(self,file_path,cols,rows,flipx = False,flipy = False): """ Loads an image file containing individual animation frames and returns then in a list of PNMImages inputs: - file_path - cols - rows - flipx - flipy Output: - tuple ( bool , list[PNMImage] ) """ # Make a filepath image_file = Filename(file_path) if image_file .empty(): raise IOError("File not found") return (False, []) # Instead of loading it outright, check with the PNMImageHeader if we can open # the file. img_head = PNMImageHeader() if not img_head.readHeader(image_file ): raise IOError("PNMImageHeader could not read file %s. Try using absolute filepaths"%(file_path)) return (False, []) # Load the image with a PNMImage full_image = PNMImage(img_head.getXSize(),img_head.getYSize()) full_image.alphaFill(0) full_image.read(image_file) if flipx or flipy: full_image.flip(flipx,flipy,False) w = int(full_image.getXSize()/cols) h = int(full_image.getYSize()/rows) images = [] counter = 0 for i in range(0,cols): for j in range(0,rows): sub_img = PNMImage(w,h) sub_img.addAlpha() sub_img.alphaFill(0) sub_img.fill(1,1,1) sub_img.copySubImage(full_image ,0 ,0 ,i*w ,j*h ,w ,h) images.append(sub_img) return (True, images)
def takePictureRaw(self): img = PNMImage() tex = self.takePicture() tex.store(img) ss = StringStream() img.write(ss, 'jpg') if 1: # Test it img2 = PNMImage() img2.read(ss) img2.write(Filename("test_viewfinder.jpg")) return ss.getData()
def create_texture(image: Image) -> Texture: """Create a Panda3D Texture from a PIL Image.""" bytes_io = BytesIO() image.save(bytes_io, format='PNG') bytes_io.seek(0) stream = StringStream() stream.set_data(bytes_io.read()) bytes_io.close() pnm_image = PNMImage() pnm_image.read(stream) stream.clear_data() texture = Texture() texture.load(pnm_image) pnm_image.clear() return texture
def loadFlatQuad(self, fullFilename): cm = CardMaker('cm-%s' % fullFilename) cm.setColor(1.0, 1.0, 1.0, 1.0) aspect = base.camLens.getAspectRatio() htmlWidth = 2.0 * aspect * WEB_WIDTH_PIXELS / float(WIN_WIDTH) htmlHeight = 2.0 * float(WEB_HEIGHT_PIXELS) / float(WIN_HEIGHT) cm.setFrame(-htmlWidth / 2.0, htmlWidth / 2.0, -htmlHeight / 2.0, htmlHeight / 2.0) bottomRightX = WEB_WIDTH_PIXELS / float(WEB_WIDTH + 1) bottomRightY = WEB_HEIGHT_PIXELS / float(WEB_HEIGHT + 1) cm.setUvRange(Point2(0, 1 - bottomRightY), Point2(bottomRightX, 1)) card = cm.generate() quad = NodePath(card) jpgFile = PNMImage(WEB_WIDTH, WEB_HEIGHT) smallerJpgFile = PNMImage() readFile = smallerJpgFile.read(Filename(fullFilename)) if readFile: jpgFile.copySubImage(smallerJpgFile, 0, 0) guiTex = Texture('guiTex') guiTex.setupTexture(Texture.TT2dTexture, WEB_WIDTH, WEB_HEIGHT, 1, Texture.TUnsignedByte, Texture.FRgba) guiTex.setMinfilter(Texture.FTLinear) guiTex.load(jpgFile) guiTex.setWrapU(Texture.WMClamp) guiTex.setWrapV(Texture.WMClamp) ts = TextureStage('webTS') quad.setTexture(ts, guiTex) quad.setTransparency(0) quad.setTwoSided(True) quad.setColor(1.0, 1.0, 1.0, 1.0) result = quad else: result = None Texture.setTexturesPower2(1) return result
def __build_Normal_Map(self, recipe): # Load ref image. ref_img = PNMImage() height_map_path = "{}/maps/{}".format(recipe['path'], recipe['height_map']) ref_img.read(Filename(height_map_path)) # Create normal map from height map with GPU. with GPU_Image(ref_img, print_times=True) as gpu: height_range = LVector2f(recipe['height_min'], recipe['height_max']) norm_img = gpu.generate_normal_map(height_range=height_range) norm_img.write( Filename("{}/maps/earth_norm.jpg".format(recipe['path']))) return recipe
def load_image(self, category, grayscale=False): image = PNMImage() if image.read(self.get_terrain_file_name(category)): if grayscale: image.makeGrayscale() return image else: return None
def set_planet_textures(cls, planet): # Terrain map texture. map_img = PNMImage() map_img.read(Filename("{}/maps/{}".format(planet.path, planet.height_map))) map_tex = Texture() map_tex.load(map_img) planet.LOD_NP.setShaderInput("height_map", map_tex) # Colour map texture. col_img = PNMImage() col_img.read(Filename("{}/maps/{}".format(planet.path, planet.colour_map))) col_tex = Texture() col_tex.load(col_img) planet.LOD_NP.setShaderInput("col_map", col_tex) # Normal map texture. norm_img = PNMImage() norm_img.read(Filename("{}/maps/{}".format(planet.path, planet.normal_map))) norm_tex = Texture() norm_tex.load(norm_img) planet.LOD_NP.setShaderInput("normal_map", norm_tex) # Terrain map texture. ter_img = PNMImage() ter_img.read(Filename("{}/maps/{}".format(planet.path, planet.terrain_map))) ter_tex = Texture() ter_tex.load(ter_img) planet.LOD_NP.setShaderInput("terrain_map", ter_tex) # Terrain textures. tex_count = len(planet.terrains) near_tex_array = Texture() far_tex_array = Texture() near_tex_array.setup2dTextureArray(tex_count) far_tex_array.setup2dTextureArray(tex_count) for i, terrain in enumerate(planet.terrains): near_tex_img, far_tex_img = PNMImage(), PNMImage() near_tex_name, far_tex_name = terrain['textures'] near_tex_img.read(Filename("{}/textures/{}".format(planet.path, near_tex_name))) far_tex_img.read(Filename("{}/textures/{}".format(planet.path, far_tex_name))) near_tex_array.load(near_tex_img, i, 0) far_tex_array.load(far_tex_img, i, 0) planet.LOD_NP.setShaderInput("near_tex", near_tex_array) planet.LOD_NP.setShaderInput("far_tex", far_tex_array)
def __map_Colours(self, planet, model, rec, pts=[]): col_map_path = planet.colour_map.replace(".","_low.") col_map_fn = Filename("{}/maps/{}".format(planet.path, col_map_path)) col_map = PNMImage() col_map.read(col_map_fn) _cu_size = col_map.getXSize()-1 _cv_size = col_map.getYSize()-1 cols = [] if not pts: pts = model.read("vertex") for pt in pts: u, v = self.__get_Pt_Uv(pt, _cu_size, _cv_size) r = col_map.getRed(u, v) g = col_map.getGreen(u, v) b = col_map.getBlue(u, v) pt_col = (r, g, b, 1) cols.append(pt_col) model.modify("color", cols)
def __map_Colours(self, planet, model, rec, pts=[]): col_map_path = planet.colour_map.replace(".", "_low.") col_map_fn = Filename("{}/maps/{}".format(planet.path, col_map_path)) col_map = PNMImage() col_map.read(col_map_fn) _cu_size = col_map.getXSize() - 1 _cv_size = col_map.getYSize() - 1 cols = [] if not pts: pts = model.read("vertex") for pt in pts: u, v = self.__get_Pt_Uv(pt, _cu_size, _cv_size) r = col_map.getRed(u, v) g = col_map.getGreen(u, v) b = col_map.getBlue(u, v) pt_col = (r, g, b, 1) cols.append(pt_col) model.modify("color", cols)
def main(): sff_file ='' output_dir='' if len(sys.argv) >= 2: sff_file = sys.argv[1] else: logging.error('Usage: sff-test ssf_file [output_dir]') return if len(sys.argv) >= 3: output_dir = sys.argv[2] #checking output dir if (output_dir != '') and (not os.path.exists(output_dir)): os.makedirs(output_dir) else: logging.info("Output directory not set from command line, skipping image save") fh = open(sff_file, 'rb') header = sff1_file.parse(fh.read(512)) print(header) next_subfile = header.next_subfile count = 0 while next_subfile and count < header.image_total: fh.seek(next_subfile) subfile = sff1_subfile_header.parse(fh.read(32)) next_subfile = subfile.next_subfile try: buff = StringIO(fh.read(subfile.length)) image = Image.open(buff) buff = StringIO() image.save(buff,'PNG') output = PNMImage() if not output.read(StringStream(buff.getvalue()), "i.png"): logging.error("Failed to read image from buffer") raise ValueError("Invalid image!") print("Image Group: %i, no: %i, size: %i x %i ,offset: (%i , %i), palette %i"%(subfile.groupno,subfile.imageno, image.size[0],image.size[1],subfile.axisx,subfile.axisy,subfile.palette)) except IOError: print(("ioerror", subfile.groupno, subfile.imageno)) pass else: # image.save(output_dir + "/g{0}-i{1}.png".format(subfile.groupno, subfile.imageno)) if len(output_dir) > 0: output.write(output_dir + "/g{0}-i{1}.png".format(subfile.groupno, subfile.imageno)) count+=1
def load_terrain_map(self): image = PNMImage() if image.read(self.get_terrain_file_name()): for y in range(self.patch.r_height): for x in range(self.patch.r_width): self.patch.set_height(x, y, image.getGray(x, y)) return True else: return False
def loadImage(self,file_path,cols,rows,scale_x,scale_y,frame_rate): # Make a filepath image_file = Filename(file_path) if image_file .empty(): raise IOError, "File not found" return False # Instead of loading it outright, check with the PNMImageHeader if we can open # the file. img_head = PNMImageHeader() if not img_head.readHeader(image_file ): raise IOError, "PNMImageHeader could not read file %s. Try using absolute filepaths"%(file_path) return False # Load the image with a PNMImage full_image = PNMImage(img_head.getXSize(),img_head.getYSize()) full_image.alphaFill(0) full_image.read(image_file) right_image = PNMImage(img_head.getXSize(),img_head.getYSize()) left_image = PNMImage(img_head.getXSize(),img_head.getYSize()) right_image.copyFrom(full_image) left_image.copyFrom(full_image) left_image.flip(True,False,False) # storing individual sprite size self.size_ = (right_image.getReadXSize()/cols,right_image.getReadYSize()/rows) self.seq_right_ = self.attachNewNode(self.createSequenceNode(self.name_ + '_right_seq',right_image,cols,rows,scale_x,scale_y,frame_rate)) self.seq_left_ = self.attachNewNode(self.createSequenceNode(self.name_ + '_left_seq',left_image,cols,rows,scale_x,scale_y,frame_rate)) self.seq_right_.reparentTo(self) self.seq_left_.reparentTo(self) right_image.clear() left_image.clear() full_image.clear() self.faceRight(True) return True
def __loadSpritePair__(sprite_details): image_file = sprite_details.im_file img_head = PNMImageHeader() if not img_head.readHeader(image_file ): logging.error( "PNMImageHeader could not read file %s. Try using absolute filepaths"%(image_file)) return (None,None) # Load the right side image as a PNMImage right_img = PNMImage(img_head.getXSize(),img_head.getYSize()) right_img.alphaFill(0) right_img.read(image_file) # Flip to get the left side image left_img = PNMImage(right_img.getXSize(),right_img.getYSize()) left_img.copyFrom(right_img) left_img.flip(True ,False,False) images = [(right_img,False),(left_img,True)] sprites = [] for entry in images: img = entry[0] flip = entry[1] sprite = Sprite() sprite.setXSize(img.getXSize()) sprite.setYSize(img.getYSize()) sprite.setZSize(1) sprite.axisx = -sprite_details.axisx if (not flip ) else sprite_details.axisx sprite.axisy = sprite_details.axisy sprite.group = sprite_details.group_no sprite.no = sprite_details.image_no sprite.load(img) sprite.setWrapU(Texture.WM_border_color) # gets rid of odd black edges around image sprite.setWrapV(Texture.WM_border_color) sprite.setBorderColor(LColor(0,0,0,0)) sprites.append(sprite) return (sprites[0],sprites[1])
def read_texture(self, filename, alpha=False): """ Reads a texture from the model path. Throws a PalettizerException if file could not be found. :filename: Relative filename pointing to a texture file in the model path. :alpha: Do we need an alpha channel? """ img = PNMImage() img.read(Filename.from_os_specific(filename)) if alpha: needs_alpha_fill = img.num_channels not in (2, 4) img.set_color_type(4) if needs_alpha_fill: # We need an alpha channel no matter what, so if the image does not have one, # it needs to be filled immediately with opaque pixels as it starts out with transparent pixels img.alpha_fill(1) else: img.set_color_type(3) return img
def mapSelection(self, maps): """ Generate a window with list and thumbnails of region maps availiable. Provide two options, load map or, if there is no local version, save local version """ self.mapDialog = DirectWindow(title = "Select Map") mapList = [] m = [""] import base64 for mapName in maps: heightmap = maps[mapName] image = PNMImage() image.read(StringStream(heightmap)) thumbnail = PNMImage(64, 64) thumbnail.gaussianFilterFrom(1, image) heightTexture = Texture() heightTexture.load(image) label = DirectRadioButton(text=mapName, image=heightTexture, variable=m, value=[mapName]) mapList.append(label) for button in mapList: button.setOthers(mapList) self.mapDialog.addScrolledList(mapList) okButton = DirectButton(text = self.getText('TXT_UI_OK'), command = self.selectMap, extraArgs=m) self.mapDialog.addVertical([okButton])
def textureFromData(image_data, filename=""): tex = None if image_data: myTexture = Texture() myImage = PNMImage() success = myImage.read(StringStream(image_data), filename) if success == 1: #PNMImage can handle most texture formats myTexture.load(myImage) else: #Except for DDS, which PNMImage.read will return 0, so try to load as DDS success = myTexture.readDds(StringStream(image_data)) if success != 0: tex = myTexture tex.setMinfilter(Texture.FTLinearMipmapLinear) return tex
def addImage(self, image): """ Adds an image to the icon. Returns False on failure, True on success. Only one image per size can be loaded, and the image size must be square. """ if not isinstance(image, PNMImage): fn = image if not isinstance(fn, Filename): fn = Filename.fromOsSpecific(fn) image = PNMImage() if not image.read(fn): Icon.notify.warning("Image '%s' could not be read" % fn.getBasename()) return False if image.getXSize() != image.getYSize(): Icon.notify.warning("Ignoring image without square size") return False self.images[image.getXSize()] = image return True
def __build_Terrain_Map(self, recipe): # Height map. height_map = PNMImage() height_map_path = "{}/maps/{}".format(recipe['path'], recipe['height_map']) height_map.read(Filename(height_map_path)) # Colour map. col_map = PNMImage() col_map_path = "{}/maps/{}".format(recipe['path'], recipe['colour_map']) col_map.read(Filename(col_map_path)) # Normal map. norm_map = PNMImage() norm_map_path = "{}/maps/{}".format(recipe['path'], recipe['normal_map']) norm_map.read(Filename(norm_map_path)) # Dict of range qualifiers to pass directly to 'generate_terrain_map'. t_count = len(recipe['terrains']) ranges_dict = { 'lat_ranges': PTA_LVecBase2f([LVector2f(x * 0, 0) for x in range(t_count)]), 'lon_ranges': PTA_LVecBase2f([LVector2f(x * 0, 0) for x in range(t_count)]), 'alt_ranges': PTA_LVecBase2f([LVector2f(x * 0, 0) for x in range(t_count)]), 'red_ranges': PTA_LVecBase2f([LVector2f(x * 0, 0) for x in range(t_count)]), 'green_ranges': PTA_LVecBase2f([LVector2f(x * 0, 0) for x in range(t_count)]), 'blue_ranges': PTA_LVecBase2f([LVector2f(x * 0, 0) for x in range(t_count)]) } for i, terrain in enumerate(recipe['terrains']): for attr, val in list(terrain.items()): if attr.endswith("range"): ranges_dict[attr + "s"][i] = LVector2f(*val) # Create terrain map with GPU. height_range = LVector2f(recipe['height_min'], recipe['height_max']) with GPU_Image(height_map, print_times=True) as gpu: terrain_img = gpu.generate_terrain_map(height_range=height_range, col_map=col_map, **ranges_dict) file_path = "{}/maps/{}_ter.png".format(recipe['path'], recipe['name'].lower()) terrain_img.write(Filename(file_path))
def __build_Terrain_Map(self, recipe): # Height map. height_map = PNMImage() height_map_path = "{}/maps/{}".format(recipe['path'], recipe['height_map']) height_map.read(Filename(height_map_path)) # Colour map. col_map = PNMImage() col_map_path = "{}/maps/{}".format(recipe['path'], recipe['colour_map']) col_map.read(Filename(col_map_path)) # Normal map. norm_map = PNMImage() norm_map_path = "{}/maps/{}".format(recipe['path'], recipe['normal_map']) norm_map.read(Filename(norm_map_path)) # Dict of range qualifiers to pass directly to 'generate_terrain_map'. t_count = len(recipe['terrains']) ranges_dict = {'lat_ranges':PTA_LVecBase2f([LVector2f(x*0,0) for x in range(t_count)]), 'lon_ranges':PTA_LVecBase2f([LVector2f(x*0,0) for x in range(t_count)]), 'alt_ranges':PTA_LVecBase2f([LVector2f(x*0,0) for x in range(t_count)]), 'red_ranges':PTA_LVecBase2f([LVector2f(x*0,0) for x in range(t_count)]), 'green_ranges':PTA_LVecBase2f([LVector2f(x*0,0) for x in range(t_count)]), 'blue_ranges':PTA_LVecBase2f([LVector2f(x*0,0) for x in range(t_count)])} for i, terrain in enumerate(recipe['terrains']): for attr, val in list(terrain.items()): if attr.endswith("range"): ranges_dict[attr+"s"][i] = LVector2f(*val) # Create terrain map with GPU. height_range = LVector2f(recipe['height_min'],recipe['height_max']) with GPU_Image(height_map, print_times=True) as gpu: terrain_img = gpu.generate_terrain_map(height_range=height_range, col_map=col_map, **ranges_dict) file_path = "{}/maps/{}_ter.png".format(recipe['path'], recipe['name'].lower()) terrain_img.write(Filename(file_path))
#make it square if map.getReadYSize() != map_size: new_map = PNMImage(map_size, map_size) new_map.boxFilterFrom(0.0, map) map = new_map #generate data nods = [] for y in range(0, map_size): for x in range(0, map_size): nods += GetNeighbors((x, y), map, map_size) #write data with open(output, 'w') as output_file: #header output_file.write('Grid Size,' + str(map_size) + '\n') output_file.write( 'NULL,NodeType,GridX,GridY,Length,Width,Height,PosX,PosY,PosZ\n') #data... for nod in nods: output_file.write( '{NULL},{NodeType},{GridX},{GridY},{Length},{Width},{Height},{PosX},{PosY},{PosZ}\n' .format(**nod)) #test if __name__ == "__main__": map = PNMImage() map.read('nav1.png') GenerateNavmeshCSV(map, 'from_img.csv')
def getPmPerceptualError(mesh, pm_filebuf, mipmap_tarfilebuf): perceptualdiff = which('perceptualdiff') if perceptualdiff is None: raise Exception("perceptualdiff exectuable not found on path") pm_chunks = [] if pm_filebuf is not None: data = pm_filebuf.read(PM_CHUNK_SIZE) refinements_read = 0 num_refinements = None while len(data) > 0: (refinements_read, num_refinements, pm_refinements, data_left) = pdae_utils.readPDAEPartial(data, refinements_read, num_refinements) pm_chunks.append(pm_refinements) data = data_left + pm_filebuf.read(PM_CHUNK_SIZE) tar = tarfile.TarFile(fileobj=mipmap_tarfilebuf) texsizes = [] largest_tarinfo = (0, None) for tarinfo in tar: tarinfo.xsize = int(tarinfo.name.split('x')[0]) if tarinfo.xsize > largest_tarinfo[0]: largest_tarinfo = (tarinfo.xsize, tarinfo) if tarinfo.xsize >= 128: texsizes.append(tarinfo) if len(texsizes) == 0: texsizes.append(largest_tarinfo[1]) texsizes = sorted(texsizes, key=lambda t: t.xsize) texims = [] first_image_data = None for tarinfo in texsizes: f = tar.extractfile(tarinfo) texdata = f.read() if first_image_data is None: first_image_data = texdata texpnm = PNMImage() texpnm.read(StringStream(texdata), 'something.jpg') newtex = Texture() newtex.load(texpnm) texims.append(newtex) mesh.images[0].setData(first_image_data) scene_members = getSceneMembers(mesh) # turn off panda3d printing to stdout nout = MultiplexStream() Notify.ptr().setOstreamPtr(nout, 0) nout.addFile(Filename(os.devnull)) base = ShowBase() rotateNode = GeomNode("rotater") rotatePath = base.render.attachNewNode(rotateNode) matrix = numpy.identity(4) if mesh.assetInfo.upaxis == collada.asset.UP_AXIS.X_UP: r = collada.scene.RotateTransform(0, 1, 0, 90) matrix = r.matrix elif mesh.assetInfo.upaxis == collada.asset.UP_AXIS.Y_UP: r = collada.scene.RotateTransform(1, 0, 0, 90) matrix = r.matrix rotatePath.setMat(Mat4(*matrix.T.flatten().tolist())) geom, renderstate, mat4 = scene_members[0] node = GeomNode("primitive") node.addGeom(geom) if renderstate is not None: node.setGeomState(0, renderstate) geomPath = rotatePath.attachNewNode(node) geomPath.setMat(mat4) wrappedNode = ensureCameraAt(geomPath, base.camera) base.disableMouse() attachLights(base.render) base.render.setShaderAuto() base.render.setTransparency(TransparencyAttrib.MNone) base.render.setColorScaleOff(9999) controls.KeyboardMovement() controls.MouseDrag(wrappedNode) controls.MouseScaleZoom(wrappedNode) controls.ButtonUtils(wrappedNode) controls.MouseCamera() error_data = [] try: tempdir = tempfile.mkdtemp(prefix='meshtool-print-pm-perceptual-error') triangleCounts = [] hprs = [(0, 0, 0), (0, 90, 0), (0, 180, 0), (0, 270, 0), (90, 0, 0), (-90, 0, 0)] for texim in texims: np = base.render.find("**/rotater/collada") np.setTextureOff(1) np.setTexture(texim, 1) for angle, hpr in enumerate(hprs): wrappedNode.setHpr(*hpr) takeScreenshot(tempdir, base, geomPath, texim, angle) triangleCounts.append(getNumTriangles(geomPath)) for pm_chunk in pm_chunks: pdae_panda.add_refinements(geomPath, pm_chunk) for texim in texims: np = base.render.find("**/rotater/collada") np.setTextureOff(1) np.setTexture(texim, 1) for angle, hpr in enumerate(hprs): wrappedNode.setHpr(*hpr) takeScreenshot(tempdir, base, geomPath, texim, angle) triangleCounts.append(getNumTriangles(geomPath)) full_tris = triangleCounts[-1] full_tex = texims[-1] for numtris in triangleCounts: for texim in texims: pixel_diff = 0 for angle, hpr in enumerate(hprs): curFile = '%d_%d_%d_%d.png' % (numtris, texim.getXSize(), texim.getYSize(), angle) curFile = os.path.join(tempdir, curFile) fullFile = '%d_%d_%d_%d.png' % (full_tris, full_tex.getXSize(), full_tex.getYSize(), angle) fullFile = os.path.join(tempdir, fullFile) try: output = subprocess.check_output([ perceptualdiff, '-threshold', '1', fullFile, curFile ]) except subprocess.CalledProcessError as ex: output = ex.output output = output.strip() if len(output) > 0: pixel_diff = max(pixel_diff, int(output.split('\n')[1].split()[0])) error_data.append({ 'triangles': numtris, 'width': texim.getXSize(), 'height': texim.getYSize(), 'pixel_error': pixel_diff }) finally: shutil.rmtree(tempdir, ignore_errors=True) return error_data
class FloorBase: #(FSM): walkable_path = None music_path = None sound_names = [] walkable_y_offset = 0.0 free_hobot_z = None def __init__(self, parent): actor = Actor(self.model_path) actor.set_two_sided(True) actor.reparent_to(parent) #print(actor.get_anim_names()) #actor.list_joints() self.actor = actor self.actor.hide() if self.walkable_path: self.walk_map = PNMImage() self.load_walk_map(self.walkable_path) else: self.walk_map = None if self.music_path: self.music = base.loader.load_music(self.music_path) self.music.set_loop(True) self.music.set_volume(0.5) self.music.play() else: self.music = None self.sfx = {} for s in self.sound_names: self.sfx[s] = base.loader.load_sfx( Filename(self.sound_path, s + ".wav")) # Make subparts for hobot. actor.make_subpart('hobot', [ 'hobot root', 'chain_a', 'chain_b', 'hand', 'wheel', 'neck', 'head', 'tuit', 'eyes' ]) # Make a copy for inspection of the animations, specifically to be able # to obtain the starting position of hobot in each animation. self.shadow_actor = Actor(self.model_path) self.shadow_hobot_root = self.shadow_actor.expose_joint( None, 'modelRoot', 'hobot root') # Make sure hobot is in a defined state in the actor actor.pose('entrance', 0) self.hobot_root = actor.expose_joint(None, 'modelRoot', 'hobot root') self.hobot_hand = actor.expose_joint(None, 'modelRoot', 'hand') self.hobot = Hobot(self.hobot_root) shadow_texture = loader.load_texture('hobot/drop_shadow.png') shadow_texture.set_wrap_u(core.SamplerState.WM_clamp) shadow_texture.set_wrap_v(core.SamplerState.WM_clamp) cm = core.CardMaker('card') cm.set_frame(-0.35, 0.35, -0.45, -0.1) self.shadow = self.hobot_root.attach_new_node(cm.generate()) self.shadow.set_texture(shadow_texture) self.shadow.set_attrib( core.ColorBlendAttrib.make( core.ColorBlendAttrib.M_add, core.ColorBlendAttrib.O_zero, core.ColorBlendAttrib.O_one_minus_incoming_alpha)) self.shadow.set_p(-90) self.shadow.set_depth_write(False) self.shadow.set_x(0.2) self.shadow.set_billboard_point_eye() self.shadow.set_two_sided(True) self.shadow.set_bin('transparent', 0) self.shadow.set_alpha_scale(0) self.shadow_fade = None self.carrying_joint = None self.carrying_joint_name = None def destroy(self): self.actor.cleanup() self.hobot.destroy() if self.music: self.music.stop() self.actor.remove_node() for sound_name in self.sound_names: self.sfx[sound_name].stop() def start(self): pass def load_walk_map(self, path): path = Filename.expand_from('$MAIN_DIR/assets/' + path) if not self.walk_map.read(path): print("Failed to read {}".format(path)) def grab_joint(self, name): print("Grabbing {}".format(name)) self.carrying_joint_name = name self.hobot.model.set_pos(self.hobot.anim_root.get_pos()) transform = self.actor.get_joint_transform_state('modelRoot', name) parent = self.actor.attach_new_node('parent') self.carrying_joint = self.actor.control_joint( parent.attach_new_node('joint'), 'modelRoot', name) self.carrying_joint.set_transform(transform) self.carrying_joint_initial_transform = transform self.carrying_joint_initial_hobot_hand_pos = self.hobot.hand.get_pos( self.actor) def release_joint(self, name): print("Releasing {}".format(name)) self.actor.release_joint('modelRoot', name) self.carrying_joint = None self.carrying_joint_name = None def get_anim_starting_hobot_pos(self, anim): # Returns Hobot's starting position for a given animation. self.shadow_actor.pose(anim, 0) self.shadow_actor.update() return self.shadow_hobot_root.get_pos() def play(self, anim, parts=None, loop=False, extra_interval=None, from_frame=None, to_frame=None, callback=None, release_joint=None, sound=None): if parts is None: print("Playing {} on all parts".format(anim)) else: print("Playing {} on {}".format(anim, list(parts))) if parts is None or 'hobot' in parts: # Move hobot to the position first self.hobot.model.show() self.hobot.lock() hobot_pos = self.get_anim_starting_hobot_pos(anim) delta = hobot_pos.x - self.hobot.model.get_x() self.hobot.face(delta) time = abs(delta) * 4 anims = [] for part in parts or (None, ): anims.append( ActorInterval(self.actor, anim, startFrame=from_frame, endFrame=to_frame, partName=part)) if extra_interval: anims.append(extra_interval) if sound: anims.append(Func(sound.play)) if callback is None: callback = self.switch_to_free_hobot seq = Sequence( self.hobot.model.posInterval(time, hobot_pos, blendType='easeInOut'), Func(self.switch_to_scene_hobot), Parallel(*anims), Func(callback)) if loop: seq.loop() else: seq.start() elif loop: if sound: sound.play() if not parts: self.actor.loop(anim, fromFrame=from_frame, toFrame=to_frame) else: for part in parts: self.actor.loop(anim, fromFrame=from_frame, toFrame=to_frame, partName=part) else: if sound: sound.play() if callback: anims = [] for part in parts or (None, ): anims.append( ActorInterval(self.actor, anim, startFrame=from_frame, endFrame=to_frame, partName=part)) Sequence(Parallel(*anims), Func(callback)).start() else: if not parts: self.actor.play(anim) else: for part in parts: self.actor.play(anim, fromFrame=from_frame, toFrame=to_frame, partName=part) def switch_to_scene_hobot(self): self.hobot.lock() self.hobot.model.hide() self.hobot.lightbulb.hide() self.actor.release_joint('modelRoot', 'hobot root') if self.carrying_joint_name and self.carrying_joint: self.actor.release_joint('modelRoot', self.carrying_joint_name) self.carrying_joint = None if self.shadow_fade is not None: self.shadow_fade.pause() self.shadow.set_alpha_scale(self.hobot.shadow.get_color_scale()[3]) self.shadow_fade = self.shadow.colorScaleInterval( 5.0, (1, 1, 1, 0), blendType='easeInOut') self.shadow_fade.start() def switch_to_free_hobot(self): if self.hobot.model.is_empty(): return self.hobot.face(self.hobot_root.get_sz() * -1) self.hobot.model.show() bone = self.actor.control_joint(None, 'modelRoot', 'hobot root') bone.set_pos(-100, -100, -100) self.hobot.unlock() if self.hobot.shadow_fade is not None: self.hobot.shadow_fade.pause() self.hobot.shadow.set_alpha_scale(self.shadow.get_color_scale()[3]) self.hobot.shadow_fade = self.hobot.shadow.colorScaleInterval( 5.0, (1, 1, 1, 1), blendType='easeInOut') self.hobot.shadow_fade.start() if self.free_hobot_z is not None: self.hobot.model.set_z(self.free_hobot_z) if self.carrying_joint_name and not self.carrying_joint: self.grab_joint(self.carrying_joint_name) def hide_scene_hobot(self): print("Hiding hobot") self.actor.control_joint(None, 'modelRoot', 'hobot root').set_z(-10000) def adjust_move(self, pos, delta, slide=True): x = (pos[0] + 16 / 9 / 2) * (9 / 16.0) * self.walk_map.size.x y = -(pos[1] - self.walkable_y_offset) * 2 * self.walk_map.size.y new_pos = pos + delta new_x = (new_pos[0] + 16 / 9 / 2) * (9 / 16.0) * self.walk_map.size.x new_y = -(new_pos[1] - self.walkable_y_offset) * 2 * self.walk_map.size.y if new_x < 0 or round(new_x) >= self.walk_map.size.x: return pos elif new_y < 0 or round(new_y) >= self.walk_map.size.y: return pos x = int(round(x)) y = int(round(y)) new_x = int(round(new_x)) new_y = int(round(new_y)) if self.walk_map.get_gray(new_x, new_y) > 0.5: return new_pos if not slide: return pos if delta[0] != 0 and self.walk_map.get_gray(new_x, y) > 0.5: return (new_pos[0], pos[1]) elif delta[1] != 0 and self.walk_map.get_gray(x, new_y) > 0.5: return (pos[0], new_pos[1]) elif delta[0] != 0 and delta[1] == 0: # Try 45 degree angle down and up new_pos = self.adjust_move(pos, Vec2(delta[0] * 0.894, delta[0] * 0.447), slide=False) if new_pos == pos: new_pos = self.adjust_move(pos, Vec2(delta[0] * 0.894, delta[0] * -0.707), slide=False) if new_pos == pos: new_pos = self.adjust_move(pos, Vec2(delta[0] * 0.707, delta[0] * 0.707), slide=False) if new_pos == pos: new_pos = self.adjust_move(pos, Vec2(delta[0] * 0.707, delta[0] * -0.707), slide=False) if new_pos == pos: new_pos = self.adjust_move(pos, Vec2(delta[0] * 0.447, delta[0] * 0.894), slide=False) if new_pos == pos: new_pos = self.adjust_move(pos, Vec2(delta[0] * 0.447, delta[0] * -0.894), slide=False) return new_pos elif delta[0] == 0 and delta[1] != 0: # Try 45 degree angle left and right new_pos = self.adjust_move(pos, Vec2(delta[1] * 0.447, delta[1] * 0.894), slide=False) if new_pos == pos: new_pos = self.adjust_move(pos, Vec2(delta[1] * -0.447, delta[1] * 0.894), slide=False) if new_pos == pos: new_pos = self.adjust_move(pos, Vec2(delta[1] * 0.707, delta[1] * 0.707), slide=False) if new_pos == pos: new_pos = self.adjust_move(pos, Vec2(delta[1] * -0.707, delta[1] * 0.707), slide=False) if new_pos == pos: new_pos = self.adjust_move(pos, Vec2(delta[1] * 0.894, delta[1] * 0.447), slide=False) if new_pos == pos: new_pos = self.adjust_move(pos, Vec2(delta[1] * -0.894, delta[1] * 0.447), slide=False) return new_pos else: return pos def process_input(self, input, dt): if self.hobot.locked: return self.hobot.process_input(input, dt, self) if self.carrying_joint: pos = self.hobot.hand.get_pos( self.actor) - self.carrying_joint_initial_hobot_hand_pos self.carrying_joint.set_transform( TransformState.make_pos( (self.hobot.model.get_z(), pos[1], -pos[0])).compose(self.carrying_joint_initial_transform)) self.check_interactions() def check_interactions(self): pass
# =============== # swizzle_demo.py # =============== # Panda3d imports. from panda3d.core import PNMImage, Filename import direct.directbase.DirectStart # Local imports. from panda3d_gpu import GPU_Image, TimeIt, LVector3i # Load ref image. ref_img = PNMImage() ref_img.read(Filename("earth_col.jpg")) # Create 5 alternate versions of images with mixed up rgb vals. rgb = "rgb" mask_list = [(0,2,1),(1,0,2),(1,2,0),(2,0,1),(2,1,0)] write_time = 0 with GPU_Image(ref_img, print_times=True) as gpu: for swizzle_mask in mask_list: mod_img = gpu.swizzle_rgb(swizzle_mask=LVector3i(*swizzle_mask)) with TimeIt() as write_timer: a, b, c = swizzle_mask mod_img_name = "earth_col_{}{}{}.jpeg".format(rgb[a], rgb[b], rgb[c]) mod_img.write(Filename(mod_img_name)) write_time += write_timer.total_time print() print(" write: {}".format(round(write_time, 3)))
def getChannel(img, x, y, channel): if channel == CHANNEL_AO: return img.getRed(x, y) elif channel == CHANNEL_ROUGHNESS: return img.getGreen(x, y) elif channel == CHANNEL_METALLIC: return img.getBlue(x, y) elif channel == CHANNEL_EMISSIVE: return img.getAlpha(x, y) armeFile = raw_input("ARME file: ") armeFilename = Filename.fromOsSpecific(armeFile) img = PNMImage() img.read(armeFilename) for i in range(4): name = getChannelName(i).lower() print("Writing", name) chImg = PNMImage(img.getReadXSize(), img.getReadYSize()) chImg.setNumChannels(1) chImg.setColorType(PNMImageHeader.CTGrayscale) for x in range(img.getReadXSize()): for y in range(img.getReadYSize()): val = getChannel(img, x, y, i) chImg.setXel(x, y, val) chImg.write( Filename(armeFilename.getFullpathWoExtension() + "_" + name + ".png")) print("Done")
return nods def GenerateNavmeshCSV(map, output): #check the map size map_size=map.getReadXSize() #make it square if map.getReadYSize()!=map_size: new_map=PNMImage(map_size,map_size) new_map.boxFilterFrom(0.0,map) map=new_map #generate data nods=[] for y in range(0,map_size): for x in range(0,map_size): nods+=GetNeighbors((x,y), map, map_size) #write data with open(output, 'w') as output_file: #header output_file.write('Grid Size,'+str(map_size)+'\n') output_file.write('NULL,NodeType,GridX,GridY,Length,Width,Height,PosX,PosY,PosZ\n') #data... for nod in nods: output_file.write('{NULL},{NodeType},{GridX},{GridY},{Length},{Width},{Height},{PosX},{PosY},{PosZ}\n'.format(**nod)) #test if __name__ == "__main__": map=PNMImage() map.read('nav1.png') GenerateNavmeshCSV(map, 'from_img.csv')
def __init__(self, mesh_path, progressive_texture_path): resolutions = [] f = tarfile.open(progressive_texture_path) for resolution_name in f.getnames(): toset = { 'size': resolution_name[:-4], 'contents': f.extractfile(resolution_name).read() } texpnm = PNMImage() texpnm.read(StringStream(toset['contents']), 'something.jpg') newtex = Texture() newtex.load(texpnm) toset['texture'] = newtex resolutions.append(toset) self.resolutions = resolutions def aux_loader(fname): return resolutions[0]['contents'] mesh = collada.Collada(mesh_path, aux_file_loader=aux_loader) scene_members = getSceneMembers(mesh) base = ShowBase() rotateNode = GeomNode("rotater") rotatePath = render.attachNewNode(rotateNode) matrix = numpy.identity(4) if mesh.assetInfo.upaxis == collada.asset.UP_AXIS.X_UP: r = collada.scene.RotateTransform(0, 1, 0, 90) matrix = r.matrix elif mesh.assetInfo.upaxis == collada.asset.UP_AXIS.Y_UP: r = collada.scene.RotateTransform(1, 0, 0, 90) matrix = r.matrix rotatePath.setMat(Mat4(*matrix.T.flatten().tolist())) geom, renderstate, mat4 = scene_members[0] node = GeomNode("primitive") node.addGeom(geom) if renderstate is not None: node.setGeomState(0, renderstate) self.geomPath = rotatePath.attachNewNode(node) self.geomPath.setMat(mat4) wrappedNode = ensureCameraAt(self.geomPath, base.camera) base.disableMouse() attachLights(render) render.setShaderAuto() render.setTransparency(TransparencyAttrib.MDual, 1) base.render.analyze() KeyboardMovement() MouseDrag(wrappedNode) MouseScaleZoom(wrappedNode) MouseCamera() num_resolutions = len(resolutions) - 1 self.slider = DirectSlider(range=(0, num_resolutions), value=0, pageSize=1, command=self.sliderMoved, pos=(0, 0, -.9), scale=1) for key, val in uiArgs.iteritems(): self.slider.thumb[key] = val self.triText = OnscreenText(text="", pos=(-1, 0.85), scale=0.15, fg=(1, 0.5, 0.5, 1), align=TextNode.ALeft, mayChange=1) base.run()
def convert_texture(self, texture, model_path=None): if not self.model_path: self.print_exc('ERROR: No model path specified in ImageConverter.') return tex_path = texture[0] tex_basename = os.path.splitext(os.path.basename(tex_path))[0] if not os.path.isabs(tex_path): if '../' in tex_path and model_path: # This texture path is using relative paths. # We assume that the working directory is the model's directory tex_path = os.path.join(os.path.dirname(model_path), tex_path) else: tex_path = os.path.join(self.model_path, tex_path) tex_path = tex_path.replace('\\', os.sep).replace('/', os.sep) if not os.path.exists(tex_path): self.print_exc('ERROR: Could not convert {}: Missing RGB texture!'.format(tex_path)) return png_tex_path = os.path.join(os.path.dirname(tex_path), tex_basename + '.png') png_tex_path = png_tex_path.replace('\\', os.sep).replace('/', os.sep) print('Converting to PNG...', png_tex_path) if len(texture) == 1: # Only one texture, we can save this immediately if tex_path.lower().endswith('.rgb'): output_img = PNMImage() output_img.read(Filename.from_os_specific(tex_path)) if output_img.num_channels in (1, 2) and 'golf_ball' not in tex_path and 'roll-o-dex' not in tex_path: # HACK: Toontown output_img.set_color_type(4) for i in range(output_img.get_x_size()): for j in range(output_img.get_y_size()): output_img.set_alpha(i, j, output_img.get_gray(i, j)) else: output_img = self.read_texture(tex_path, alpha=False) elif len(texture) == 2: img = self.read_texture(tex_path, alpha=True) # Two textures: the second one should be a RGB file alpha_path = texture[1] if not os.path.isabs(alpha_path): if '../' in alpha_path and model_path: # This texture path is using relative paths. # We assume that the working directory is the model's directory alpha_path = os.path.join(os.path.dirname(model_path), alpha_path) else: alpha_path = os.path.join(self.model_path, alpha_path) alpha_path = alpha_path.replace('\\', os.sep).replace('/', os.sep) if not os.path.exists(alpha_path): self.print_exc('ERROR: Could not convert {} with alpha {}: Missing alpha texture!'.format(tex_path, alpha_path)) return alpha_img = PNMImage() alpha_img.read(Filename.from_os_specific(alpha_path)) alpha_img = self.resize_image(alpha_img, img.get_x_size(), img.get_y_size()) output_img = PNMImage(img.get_x_size(), img.get_y_size(), 4) output_img.alpha_fill(1) output_img.copy_sub_image(img, 0, 0, 0, 0, img.get_x_size(), img.get_y_size()) for i in range(img.get_x_size()): for j in range(img.get_y_size()): output_img.set_alpha(i, j, alpha_img.get_gray(i, j)) output_img.write(Filename.from_os_specific(png_tex_path))
def __init__(self, mesh_path, progressive_texture_path): resolutions = [] f = tarfile.open(progressive_texture_path) for resolution_name in f.getnames(): toset = {'size': resolution_name[:-4], 'contents': f.extractfile(resolution_name).read()} texpnm = PNMImage() texpnm.read(StringStream(toset['contents']), 'something.jpg') newtex = Texture() newtex.load(texpnm) toset['texture'] = newtex resolutions.append(toset) self.resolutions = resolutions def aux_loader(fname): return resolutions[0]['contents'] mesh = collada.Collada(mesh_path, aux_file_loader=aux_loader) scene_members = getSceneMembers(mesh) base = ShowBase() rotateNode = GeomNode("rotater") rotatePath = render.attachNewNode(rotateNode) matrix = numpy.identity(4) if mesh.assetInfo.upaxis == collada.asset.UP_AXIS.X_UP: r = collada.scene.RotateTransform(0,1,0,90) matrix = r.matrix elif mesh.assetInfo.upaxis == collada.asset.UP_AXIS.Y_UP: r = collada.scene.RotateTransform(1,0,0,90) matrix = r.matrix rotatePath.setMat(Mat4(*matrix.T.flatten().tolist())) geom, renderstate, mat4 = scene_members[0] node = GeomNode("primitive") node.addGeom(geom) if renderstate is not None: node.setGeomState(0, renderstate) self.geomPath = rotatePath.attachNewNode(node) self.geomPath.setMat(mat4) wrappedNode = ensureCameraAt(self.geomPath, base.camera) base.disableMouse() attachLights(render) render.setShaderAuto() render.setTransparency(TransparencyAttrib.MDual, 1) base.render.analyze() KeyboardMovement() MouseDrag(wrappedNode) MouseScaleZoom(wrappedNode) MouseCamera() num_resolutions = len(resolutions) - 1 self.slider = DirectSlider(range=(0, num_resolutions), value=0, pageSize=1, command=self.sliderMoved, pos=(0, 0, -.9), scale=1) for key, val in uiArgs.iteritems(): self.slider.thumb[key] = val self.triText = OnscreenText(text="", pos=(-1,0.85), scale = 0.15, fg=(1, 0.5, 0.5, 1), align=TextNode.ALeft, mayChange=1) base.run()
def __init__(self, image_path, name=None,\ rows=1, cols=1, scale=1.0,\ twoSided=True, alpha=TRANS_ALPHA,\ repeatX=1, repeatY=1,\ anchorX=ALIGN_LEFT, anchorY=ALIGN_BOTTOM): """ Create a card textured with an image. The card is sized so that the ratio between the card and image is the same. """ scale *= self.PIXEL_SCALE self.animations = {} self.scale = scale self.repeatX = repeatX self.repeatY = repeatY self.flip = {'x':False,'y':False} self.rows = rows self.cols = cols self.currentFrame = 0 self.currentAnim = None self.loopAnim = False self.frameInterrupt = True # Create the NodePath if name: self.node = NodePath("Sprite2d:%s" % name) else: self.node = NodePath("Sprite2d:%s" % image_path) # Set the attribute for transparency/twosided self.node.node().setAttrib(TransparencyAttrib.make(alpha)) if twoSided: self.node.setTwoSided(True) # Make a filepath self.imgFile = Filename(image_path) if self.imgFile.empty(): raise IOError("File not found") # Instead of loading it outright, check with the PNMImageHeader if we can open # the file. imgHead = PNMImageHeader() if not imgHead.readHeader(self.imgFile): raise IOError("PNMImageHeader could not read file. Try using absolute filepaths") # Load the image with a PNMImage image = PNMImage() image.read(self.imgFile) self.sizeX = image.getXSize() self.sizeY = image.getYSize() self.frames = [] for rowIdx in range(self.rows): for colIdx in range(self.cols): self.frames.append(Sprite2d.Cell(colIdx, rowIdx)) # We need to find the power of two size for the another PNMImage # so that the texture thats loaded on the geometry won't have artifacts textureSizeX = self.nextsize(self.sizeX) textureSizeY = self.nextsize(self.sizeY) # The actual size of the texture in memory self.realSizeX = textureSizeX self.realSizeY = textureSizeY self.paddedImg = PNMImage(textureSizeX, textureSizeY) if image.hasAlpha(): self.paddedImg.alphaFill(0) # Copy the source image to the image we're actually using self.paddedImg.blendSubImage(image, 0, 0) # We're done with source image, clear it image.clear() # The pixel sizes for each cell self.colSize = self.sizeX/self.cols self.rowSize = self.sizeY/self.rows # How much padding the texture has self.paddingX = textureSizeX - self.sizeX self.paddingY = textureSizeY - self.sizeY # Set UV padding self.uPad = float(self.paddingX)/textureSizeX self.vPad = float(self.paddingY)/textureSizeY # The UV dimensions for each cell self.uSize = (1.0 - self.uPad) / self.cols self.vSize = (1.0 - self.vPad) / self.rows card = CardMaker("Sprite2d-Geom") # The positions to create the card at if anchorX == self.ALIGN_LEFT: posLeft = 0 posRight = (self.colSize/scale)*repeatX elif anchorX == self.ALIGN_CENTER: posLeft = -(self.colSize/2.0/scale)*repeatX posRight = (self.colSize/2.0/scale)*repeatX elif anchorX == self.ALIGN_RIGHT: posLeft = -(self.colSize/scale)*repeatX posRight = 0 if anchorY == self.ALIGN_BOTTOM: posTop = 0 posBottom = (self.rowSize/scale)*repeatY elif anchorY == self.ALIGN_CENTER: posTop = -(self.rowSize/2.0/scale)*repeatY posBottom = (self.rowSize/2.0/scale)*repeatY elif anchorY == self.ALIGN_TOP: posTop = -(self.rowSize/scale)*repeatY posBottom = 0 card.setFrame(posLeft, posRight, posTop, posBottom) card.setHasUvs(True) self.card = self.node.attachNewNode(card.generate()) # Since the texture is padded, we need to set up offsets and scales to make # the texture fit the whole card self.offsetX = (float(self.colSize)/textureSizeX) self.offsetY = (float(self.rowSize)/textureSizeY) self.node.setTexScale(TextureStage.getDefault(), self.offsetX * repeatX, self.offsetY * repeatY) self.node.setTexOffset(TextureStage.getDefault(), 0, 1-self.offsetY) self.texture = Texture() self.texture.setXSize(textureSizeX) self.texture.setYSize(textureSizeY) self.texture.setZSize(1) # Load the padded PNMImage to the texture self.texture.load(self.paddedImg) self.texture.setMagfilter(Texture.FTNearest) self.texture.setMinfilter(Texture.FTNearest) #Set up texture clamps according to repeats if repeatX > 1: self.texture.setWrapU(Texture.WMRepeat) else: self.texture.setWrapU(Texture.WMClamp) if repeatY > 1: self.texture.setWrapV(Texture.WMRepeat) else: self.texture.setWrapV(Texture.WMClamp) self.node.setTexture(self.texture)
from panda3d.core import PNMImage, Filename inputFile = raw_input("Input linear image: ") inputFilename = Filename.fromOsSpecific(inputFile) outputFile = raw_input("Output sRGB image: ") outputFilename = Filename.fromOsSpecific(outputFile) img = PNMImage() img.read(inputFilename) img.applyExponent(1.0 / 2.2) img.write(outputFilename) print("Done")
def getPmPerceptualError(mesh, pm_filebuf, mipmap_tarfilebuf): perceptualdiff = which('perceptualdiff') if perceptualdiff is None: raise Exception("perceptualdiff exectuable not found on path") pm_chunks = [] if pm_filebuf is not None: data = pm_filebuf.read(PM_CHUNK_SIZE) refinements_read = 0 num_refinements = None while len(data) > 0: (refinements_read, num_refinements, pm_refinements, data_left) = pdae_utils.readPDAEPartial(data, refinements_read, num_refinements) pm_chunks.append(pm_refinements) data = data_left + pm_filebuf.read(PM_CHUNK_SIZE) tar = tarfile.TarFile(fileobj=mipmap_tarfilebuf) texsizes = [] largest_tarinfo = (0, None) for tarinfo in tar: tarinfo.xsize = int(tarinfo.name.split('x')[0]) if tarinfo.xsize > largest_tarinfo[0]: largest_tarinfo = (tarinfo.xsize, tarinfo) if tarinfo.xsize >= 128: texsizes.append(tarinfo) if len(texsizes) == 0: texsizes.append(largest_tarinfo[1]) texsizes = sorted(texsizes, key=lambda t: t.xsize) texims = [] first_image_data = None for tarinfo in texsizes: f = tar.extractfile(tarinfo) texdata = f.read() if first_image_data is None: first_image_data = texdata texpnm = PNMImage() texpnm.read(StringStream(texdata), 'something.jpg') newtex = Texture() newtex.load(texpnm) texims.append(newtex) mesh.images[0].setData(first_image_data) scene_members = getSceneMembers(mesh) # turn off panda3d printing to stdout nout = MultiplexStream() Notify.ptr().setOstreamPtr(nout, 0) nout.addFile(Filename(os.devnull)) base = ShowBase() rotateNode = GeomNode("rotater") rotatePath = base.render.attachNewNode(rotateNode) matrix = numpy.identity(4) if mesh.assetInfo.upaxis == collada.asset.UP_AXIS.X_UP: r = collada.scene.RotateTransform(0,1,0,90) matrix = r.matrix elif mesh.assetInfo.upaxis == collada.asset.UP_AXIS.Y_UP: r = collada.scene.RotateTransform(1,0,0,90) matrix = r.matrix rotatePath.setMat(Mat4(*matrix.T.flatten().tolist())) geom, renderstate, mat4 = scene_members[0] node = GeomNode("primitive") node.addGeom(geom) if renderstate is not None: node.setGeomState(0, renderstate) geomPath = rotatePath.attachNewNode(node) geomPath.setMat(mat4) wrappedNode = ensureCameraAt(geomPath, base.camera) base.disableMouse() attachLights(base.render) base.render.setShaderAuto() base.render.setTransparency(TransparencyAttrib.MNone) base.render.setColorScaleOff(9999) controls.KeyboardMovement() controls.MouseDrag(wrappedNode) controls.MouseScaleZoom(wrappedNode) controls.ButtonUtils(wrappedNode) controls.MouseCamera() error_data = [] try: tempdir = tempfile.mkdtemp(prefix='meshtool-print-pm-perceptual-error') triangleCounts = [] hprs = [(0, 0, 0), (0, 90, 0), (0, 180, 0), (0, 270, 0), (90, 0, 0), (-90, 0, 0)] for texim in texims: np = base.render.find("**/rotater/collada") np.setTextureOff(1) np.setTexture(texim, 1) for angle, hpr in enumerate(hprs): wrappedNode.setHpr(*hpr) takeScreenshot(tempdir, base, geomPath, texim, angle) triangleCounts.append(getNumTriangles(geomPath)) for pm_chunk in pm_chunks: pdae_panda.add_refinements(geomPath, pm_chunk) for texim in texims: np = base.render.find("**/rotater/collada") np.setTextureOff(1) np.setTexture(texim, 1) for angle, hpr in enumerate(hprs): wrappedNode.setHpr(*hpr) takeScreenshot(tempdir, base, geomPath, texim, angle) triangleCounts.append(getNumTriangles(geomPath)) full_tris = triangleCounts[-1] full_tex = texims[-1] for numtris in triangleCounts: for texim in texims: pixel_diff = 0 for angle, hpr in enumerate(hprs): curFile = '%d_%d_%d_%d.png' % (numtris, texim.getXSize(), texim.getYSize(), angle) curFile = os.path.join(tempdir, curFile) fullFile = '%d_%d_%d_%d.png' % (full_tris, full_tex.getXSize(), full_tex.getYSize(), angle) fullFile = os.path.join(tempdir, fullFile) try: output = subprocess.check_output([perceptualdiff, '-threshold', '1', fullFile, curFile]) except subprocess.CalledProcessError as ex: output = ex.output output = output.strip() if len(output) > 0: pixel_diff = max(pixel_diff, int(output.split('\n')[1].split()[0])) error_data.append({'triangles': numtris, 'width': texim.getXSize(), 'height': texim.getYSize(), 'pixel_error': pixel_diff}) finally: shutil.rmtree(tempdir, ignore_errors=True) return error_data
def getImageFromFile(filename="sample.png"): """ """ image = PNMImage() image.read(Filename(filename)) return image
from purses3d import Purses from ship import clamp # Load colors (256) #0 = White - debug (bonus points?) #1 = Yellow - endlevel #2 = LRed - death #3 = LGreen - turbo #4 = LBlue - hp/fuel #5 = Dgray - slide #6 = Dgreen - slow #7 = Magenta- parking #>7= Safe colors = [] palette = PNMImage() palette.read("assets/palette.png") for y in range(16): for x in range(16): c = palette.getXel(x, y) colors.append(tuple(c) + (1, )) # Set default parts, tiles and rows # a tile is a stack of parts # a row is 9 tiles wide P = None # None part N = [P] # None tile D = [(0, 0)] # Default H = [P, (1, 0)] # Test block T = D + [(5, 0)] # Test tunnel NR = [N, N, N, N, N, N, N, N, N] # Empty row/space EM = [[H, N, N, N, D, N, N, N, H]] # Empty start map
class LatexImage: # a LatexImage can in theory be incomplete. # it doesn't necessarily need an expression_str, if it's just loaded # by a hash (created from an expression_str) from disk def __init__(self, expression_str=None, sha_hash=None, tex_xcolor="white", p3d_PNMImage=None): self.sha_hash = sha_hash if self.sha_hash is None: # that is, if the image is already compiled # generate hash self.sha_hash = hashlib.sha256( str(expression_str).encode("utf-8")).hexdigest() # latex expression # You have to escape dollar signs if passed as arguments self.expression_str = expression_str # specify all file paths self.directory = os.getcwd() + "/" + LATEX_SUBFOLDER if not os.path.exists(self.directory): os.makedirs(self.directory) self.fullfilepath_without_extentsion = self.directory + "/" + self.sha_hash self.fullfilepath_tex_file = self.fullfilepath_without_extentsion + ".tex" self.fullfilepath_png_file = self.fullfilepath_without_extentsion + ".png" self.p3d_PNMImage = p3d_PNMImage # misc self.tex_xcolor = tex_xcolor # isn't actually used as of now def compileToPNG(self, load_p3d_PNMImage=True): latexcommands = (r''' \documentclass[convert={density=300,outext=.png},preview]{standalone} \usepackage{xcolor} \color{white} \begin{document} \color{white} ''' + self.expression_str + r''' \end{document} ''') print("compiling ", self.fullfilepath_without_extentsion) with open(self.fullfilepath_tex_file, 'w') as f: f.write(latexcommands) cmd = ['pdflatex', '-interaction', 'nonstopmode', '-shell-escape', "\"" + self.fullfilepath_tex_file + "\""] proc = subprocess.Popen(cmd, cwd=self.directory) proc.communicate() # deal with success/failure retcode = proc.returncode if not retcode == 0: os.unlink(self.sha_hash + '.pdf') raise ValueError('Error {} executing command: {}'.format( retcode, ' '.join(cmd))) # delete all auxiliary files os.unlink(self.fullfilepath_without_extentsion + '.tex') os.unlink(self.fullfilepath_without_extentsion + '.log') os.unlink(self.fullfilepath_without_extentsion + '.aux') # LatexImage can also be in a state where the image is not loaded # but for now, it always also loads the pnmImage from disk if load_p3d_PNMImage is True: self.p3d_PNMImage = texture_utils.getImageFromFile( filename=self.fullfilepath_without_extentsion + ".png") return self.p3d_PNMImage def getPNMImage(self): assert (self.p3d_PNMImage is not None) return self.p3d_PNMImage def assignImageFromCompiledFile(self): self.p3d_PNMImage = PNMImage() self.p3d_PNMImage.read(Filename(self.fullfilepath_png_file))
# =============== # swizzle_demo.py # =============== # Panda3d imports. from panda3d.core import PNMImage, Filename import direct.directbase.DirectStart # Local imports. from panda3d_gpu import GPU_Image, TimeIt, LVector3i # Load ref image. ref_img = PNMImage() ref_img.read(Filename("earth_col.jpg")) # Create 5 alternate versions of images with mixed up rgb vals. rgb = "rgb" mask_list = [(0, 2, 1), (1, 0, 2), (1, 2, 0), (2, 0, 1), (2, 1, 0)] write_time = 0 with GPU_Image(ref_img, print_times=True) as gpu: for swizzle_mask in mask_list: mod_img = gpu.swizzle_rgb(swizzle_mask=LVector3i(*swizzle_mask)) with TimeIt() as write_timer: a, b, c = swizzle_mask mod_img_name = "earth_col_{}{}{}.jpeg".format( rgb[a], rgb[b], rgb[c]) mod_img.write(Filename(mod_img_name)) write_time += write_timer.total_time print() print(" write: {}".format(round(write_time, 3)))
def __set_Planet_Constants(cls, planet, model_np, model_type): # Env constants. model_np.setShaderInput("radius", float(planet.radius)) model_np.setShaderInput("ambient_val", _env.AMBIENT) # Env vars. model_np.setShaderInput("light_vec", LVector3f(-1,0,0)) if "atmos_colour" in planet.__dict__: model_np.setShaderInput("atmos_colour", LVector4f(*planet.atmos_colour)) model_np.setShaderInput("atmos_ceiling", planet.atmos_ceiling) model_np.setShaderInput("atmos_radius", planet.radius+planet.atmos_ceiling) # Mid model. if model_type == "mid" and "colour_map" in planet.__dict__: col_path = "{}/maps/{}".format(planet.path, planet.colour_map.replace(".","_low.")) model_np.setShaderInput("colour_map", loader.loadTexture(Filename(col_path))) # High Model. elif model_type == "high": # Mapping textures. hm_path = "{}/maps/{}".format(planet.path, planet.height_map) nm_path = "{}/maps/{}".format(planet.path, planet.normal_map) col_path = "{}/maps/{}".format(planet.path, planet.colour_map) ter_path = "{}/maps/{}".format(planet.path, planet.terrain_map) model_np.setShaderInput("height_map", loader.loadTexture(Filename(hm_path))) model_np.setShaderInput("normal_map", loader.loadTexture(Filename(nm_path))) model_np.setShaderInput("colour_map", loader.loadTexture(Filename(col_path))) model_np.setShaderInput("terrain_map", loader.loadTexture(Filename(ter_path))) # Terrain textures. tex_count = len(planet.terrains) near_tex_array = Texture() far_tex_array = Texture() near_tex_array.setup2dTextureArray(tex_count) far_tex_array.setup2dTextureArray(tex_count) for i, terrain in enumerate(planet.terrains): near_tex_img, far_tex_img = PNMImage(), PNMImage() near_tex_name, far_tex_name = terrain['textures'] near_tex_img.read(Filename("{}/textures/{}".format(planet.path, near_tex_name))) far_tex_img.read(Filename("{}/textures/{}".format(planet.path, far_tex_name))) near_tex_array.load(near_tex_img, i, 0) far_tex_array.load(far_tex_img, i, 0) model_np.setShaderInput("near_tex", near_tex_array) model_np.setShaderInput("far_tex", far_tex_array) # Env vars. planet.MODEL_NP.setShaderInput("cull_dist", 999999999999999999) ## model_np.setAttrib(RenderModeAttrib.make(2)) # Wireframe. # Terrain specs. min_radius = planet.radius - planet.height_min elev_range = planet.height_max - planet.height_min terrain_count = len(planet.terrains) terrain_specs = LVector4f(min_radius, elev_range, terrain_count, 0) model_np.setShaderInput("terrain_specs", terrain_specs) # Geom tesselation specs. geom_lod_list = [LVector3i(x*0,0,0) for x in range(8)] ## lod ranges need to be un const. for i, (dist, inner, outer) in enumerate(planet.near_lod): if dist <= 4: dist *= planet.radius geom_lod_list[i].set(int(dist), inner, outer) geom_lod = PTA_LVecBase3i(geom_lod_list) model_np.setShaderInput("geom_lod", geom_lod) # Texture LOD. tex_lod_list = [LVector3f(x*0,0) for x in range(len(planet.tex_lod))] for i, (near, far, multi) in enumerate(planet.tex_lod): tex_lod_list[i].set(near, far, multi) tex_lod = PTA_LVecBase3f(tex_lod_list) model_np.setShaderInput("tex_lod", tex_lod) # Tesselation LOD. tess_lod_list = [LVector2f(x*0,0) for x in range(len(planet.tess_lod))] for i, (var_thresh, tess_max) in enumerate(planet.tess_lod): tess_lod_list[i].set(var_thresh, tess_max) tess_lod = PTA_LVecBase2f(tess_lod_list) model_np.setShaderInput("tess_lod", tess_lod)
emissive = Filename(raw_input("Emissive Image: ")) emissive_srgb = bool(int(raw_input("sRGB (Edited in image program)? [1/0]: "))) size = [1024, 1024] fImgs = [[ao, ao_srgb], [roughness, roughness_srgb], [metallic, metallic_srgb], [emissive, emissive_srgb]] imgs = {} foundSize = False for i in range(len(fImgs)): fImg, is_sRGB = fImgs[i] if fImg.exists(): img = PNMImage() img.read(fImg) img.makeRgb() if is_sRGB: # Convert to linear print("Converting", getChannelName(i), "to linear") img.applyExponent(2.2) if not foundSize: size = [img.getReadXSize(), img.getReadYSize()] foundSize = True imgs[i] = img else: # assume it is a constant value val = float(fImg.getFullpath()) if is_sRGB: print("Converting", getChannelName(i), "to linear") # Convert to linear
def checkForLoad(task): #print globalClock.getAverageFrameRate() global model_queue checkQueue() try: action = load_queue.get_nowait() except Queue.Empty: action = None if EXIT_AFTER and action is None and base.num_models_loaded >= NUM_MODELS and base.quit and base.screenshot_frame > base.quit_frame: sys.exit(0) elif action is None and base.num_models_loaded >= NUM_MODELS and base.quit and base.screenshot_frame > base.quit_frame: base.render.analyze() base.quit = False if action is None: return task.cont action_type = action[0] if action_type == ActionType.LOAD_MODEL: model = action[1] print 'Queueing model for load:', model.model_json['full_path'], 'queue size', len(model_queue) model_queue.append(model) checkQueue() elif action_type == ActionType.UPDATE_TEXTURE: model = action[1] offset = action[2] data = action[3] print model.model_json['base_path'], 'needs texture updating offset', offset texpnm = PNMImage() texpnm.read(StringStream(data), 'something.jpg') newtex = Texture() newtex.load(texpnm) path_search = '**/*' + model.model_json['full_path'].replace('/', '_') + '*' np = render.find(path_search) np.setTextureOff(1) np.setTexture(newtex, 1) elif action_type == ActionType.PROGRESSIVE_ADDITION: model = action[1] refinements = action[2] path_search = '**/*' + model.model_json['full_path'].replace('/', '_') + '*' np = render.find(path_search) np = np.find("**/primitive") pnode = np.node() start = time.time() update_nodepath(pnode, refinements) end = time.time() print '---JUST UPDATED ' + model.model_json['full_path'] + ' ----' elif action_type == ActionType.QUIT: print 'Got a quit message, triggering quit flag' base.quit = True return task.cont
# ================= # gen_normal_map.py # ================= # Panda3d imports. from panda3d.core import PNMImage, Filename import direct.directbase.DirectStart # Local imports. from panda3d_gpu import GPU_Image, TimeIt # Load ref image. ref_img = PNMImage() ref_img.read(Filename("earth_height.jpg")) # Create normal map from height map. with GPU_Image(ref_img, print_times=True) as gpu: norm_img = gpu.generate_normal_map(depth=72) with TimeIt(" write") as write_timer: norm_img.write(Filename("earth_norm.jpg"))
def checkForLoad(task): #print globalClock.getAverageFrameRate() global model_queue checkQueue() try: action = load_queue.get_nowait() except Queue.Empty: action = None if EXIT_AFTER and action is None and base.num_models_loaded >= NUM_MODELS and base.quit and base.screenshot_frame > base.quit_frame: sys.exit(0) elif action is None and base.num_models_loaded >= NUM_MODELS and base.quit and base.screenshot_frame > base.quit_frame: base.render.analyze() base.quit = False if action is None: return task.cont action_type = action[0] if action_type == ActionType.LOAD_MODEL: model = action[1] print 'Queueing model for load:', model.model_json[ 'full_path'], 'queue size', len(model_queue) model_queue.append(model) checkQueue() elif action_type == ActionType.UPDATE_TEXTURE: model = action[1] offset = action[2] data = action[3] print model.model_json[ 'base_path'], 'needs texture updating offset', offset texpnm = PNMImage() texpnm.read(StringStream(data), 'something.jpg') newtex = Texture() newtex.load(texpnm) path_search = '**/*' + model.model_json['full_path'].replace('/', '_') + '*' np = render.find(path_search) np.setTextureOff(1) np.setTexture(newtex, 1) elif action_type == ActionType.PROGRESSIVE_ADDITION: model = action[1] refinements = action[2] path_search = '**/*' + model.model_json['full_path'].replace('/', '_') + '*' np = render.find(path_search) np = np.find("**/primitive") pnode = np.node() start = time.time() update_nodepath(pnode, refinements) end = time.time() print '---JUST UPDATED ' + model.model_json['full_path'] + ' ----' elif action_type == ActionType.QUIT: print 'Got a quit message, triggering quit flag' base.quit = True return task.cont
def getStateFromMaterial(prim_material): state = RenderState.makeFullDefault() emission = None ambient = None diffuse = None specular = None shininess = None reflection = None reflectivity = None if prim_material: for prop in prim_material.supported: value = getattr(prim_material, prop) if value is None: continue if type(value) is tuple: val4 = value[3] if len(value) > 3 else 1.0 value = VBase4(value[0], value[1], value[2], val4) if isinstance(value, collada.material.Map): texture_file = value.sampler.surface.image.path if not texture_file is None: (root, leaf) = os.path.split(sys.argv[1]) tex_absolute = os.path.join(root, texture_file) myImage = PNMImage() myImage.read(Filename(tex_absolute)) myTexture = Texture(texture_file) myTexture.load(myImage) state = state.addAttrib(TextureAttrib.make(myTexture)) elif prop == 'emission': emission = value elif prop == 'ambient': ambient = value elif prop == 'diffuse': diffuse = value elif prop == 'specular': specular = value elif prop == 'shininess': shininess = value elif prop == 'reflective': reflective = value elif prop == 'reflectivity': reflectivity = value elif prop == 'transparent': pass elif prop == 'transparency': pass else: raise mat = Material() if not emission is None: mat.setEmission(emission) if not ambient is None: mat.setAmbient(ambient) if not diffuse is None: mat.setDiffuse(diffuse) if not specular is None: mat.setSpecular(specular) if not shininess is None: mat.setShininess(shininess) state = state.addAttrib(MaterialAttrib.make(mat)) return state
def __parseSff__(self,filename,load_all, groups = []): # Opening file if os.path.exists(filename): logging.error("SFF file %s was not found"%(filename)) return False if not filename.lower().endswith('.sff'): logging.error("File %s is not an .sff image") return False fh = open(filename, 'rb') header = sff1_file.parse(fh.read(512)) next_subfile = header.next_subfile count = 0 while next_subfile and count < header.image_total: fh.seek(next_subfile) subfile = sff1_subfile_header.parse(fh.read(32)) next_subfile = subfile.next_subfile try: buff = StringIO(fh.read(subfile.length)) image = Image.open(buff) buff = StringIO() image.save(buff,'PNG') pnm_img = PNMImage(image.size[0],image.size[1]) pnm_img.alphaFill(0) if not pnm_img.read(StringStream(buff.getvalue()), "i.png"): logging.error("Failed to read from buffer, invalid image found in sff file") return False logging.debug("Image Group: %i, no: %i, size: %i x %i ,offset: (%i , %i), palette %i"%(subfile.groupno,subfile.imageno, image.size[0],image.size[1],subfile.axisx,subfile.axisy,subfile.palette)) # Check if group is requested if not load_all: if groups.count(subfile.groupno) == 0: continue # skip this group # storing image if not self.hasGroup(subfile.groupno): # create left and right groupos self.groups_dict_[subfile.groupno] = (SpriteGroup(subfile.groupno),SpriteGroup(subfile.groupno)) group_pair = self.groups_dict_[subfile.groupno] group_right = group_pair[0] group_left = group_pair[1] group_right.addSprite(self.__makeSprite__(pnm_img,subfile,False)) group_left.addSprite(self.__makeSprite__(pnm_img,subfile,True)) except IOError: loggin.error("ioerror while reading image in group %i and no %i"%( subfile.groupno, subfile.imageno)) return False count+=1 return True