def test_getdata(self): # test getheader/getdata against legacy values # Create a 'P' image with holes in the palette im = Image._wedge().resize((16, 16)) im.putpalette(ImagePalette.ImagePalette('RGB')) im.info = {'background': 0} passed_palette = bytes(bytearray([255 - i // 3 for i in range(768)])) GifImagePlugin._FORCE_OPTIMIZE = True try: h = GifImagePlugin.getheader(im, passed_palette) d = GifImagePlugin.getdata(im) import pickle # Enable to get target values on pre-refactor version # with open('Tests/images/gif_header_data.pkl', 'wb') as f: # pickle.dump((h, d), f, 1) with open('Tests/images/gif_header_data.pkl', 'rb') as f: (h_target, d_target) = pickle.load(f) self.assertEqual(h, h_target) self.assertEqual(d, d_target) finally: GifImagePlugin._FORCE_OPTIMIZE = False
def test_getdata(self): # test getheader/getdata against legacy values # Create a 'P' image with holes in the palette im = Image._wedge().resize((16, 16)) im.putpalette(ImagePalette.ImagePalette('RGB')) im.info = {'background': 0} passed_palette = bytes(bytearray([255-i//3 for i in range(768)])) GifImagePlugin._FORCE_OPTIMIZE = True try: h = GifImagePlugin.getheader(im, passed_palette) d = GifImagePlugin.getdata(im) import pickle # Enable to get target values on pre-refactor version # with open('Tests/images/gif_header_data.pkl', 'wb') as f: # pickle.dump((h, d), f, 1) with open('Tests/images/gif_header_data.pkl', 'rb') as f: (h_target, d_target) = pickle.load(f) self.assertEqual(h, h_target) self.assertEqual(d, d_target) finally: GifImagePlugin._FORCE_OPTIMIZE = False
def test_getdata(): # Test getheader/getdata against legacy values. # Create a 'P' image with holes in the palette. im = Image._wedge().resize((16, 16), Image.NEAREST) im.putpalette(ImagePalette.ImagePalette("RGB")) im.info = {"background": 0} passed_palette = bytes([255 - i // 3 for i in range(768)]) GifImagePlugin._FORCE_OPTIMIZE = True try: h = GifImagePlugin.getheader(im, passed_palette) d = GifImagePlugin.getdata(im) import pickle # Enable to get target values on pre-refactor version # with open('Tests/images/gif_header_data.pkl', 'wb') as f: # pickle.dump((h, d), f, 1) with open("Tests/images/gif_header_data.pkl", "rb") as f: (h_target, d_target) = pickle.load(f) assert h == h_target assert d == d_target finally: GifImagePlugin._FORCE_OPTIMIZE = False
def test_save_netpbm_bmp_mode(self): with Image.open(TEST_GIF) as img: img = img.convert("RGB") tempfile = self.tempfile("temp.gif") GifImagePlugin._save_netpbm(img, 0, tempfile) with Image.open(tempfile) as reloaded: self.assert_image_similar(img, reloaded.convert("RGB"), 0)
def test_save_netpbm_l_mode(tmp_path): with Image.open(TEST_GIF) as img: img = img.convert("L") tempfile = str(tmp_path / "temp.gif") GifImagePlugin._save_netpbm(img, 0, tempfile) with Image.open(tempfile) as reloaded: assert_image_similar(img, reloaded.convert("L"), 0)
def test_number_of_loops(self): number_of_loops = 2 out = self.tempfile('temp.gif') with open(out, "wb") as fp: im = Image.new('L', (100, 100), '#000') for s in GifImagePlugin.getheader(im)[0] + GifImagePlugin.getdata(im, loop=number_of_loops): fp.write(s) fp.write(b";") reread = Image.open(out) self.assertEqual(reread.info['loop'], number_of_loops)
def test_duration(self): duration = 1000 out = self.tempfile('temp.gif') with open(out, "wb") as fp: im = Image.new('L', (100, 100), '#000') for s in GifImagePlugin.getheader(im)[0] + GifImagePlugin.getdata(im, duration=duration): fp.write(s) fp.write(b";") reread = Image.open(out) self.assertEqual(reread.info['duration'], duration)
def test_number_of_loops(self): number_of_loops = 2 out = self.tempfile("temp.gif") fp = open(out, "wb") im = Image.new("L", (100, 100), "#000") for s in GifImagePlugin.getheader(im)[0] + GifImagePlugin.getdata(im, loop=number_of_loops): fp.write(s) fp.write(b";") fp.close() reread = Image.open(out) self.assertEqual(reread.info["loop"], number_of_loops)
def test_duration(self): duration = 1000 out = self.tempfile("temp.gif") fp = open(out, "wb") im = Image.new("L", (100, 100), "#000") for s in GifImagePlugin.getheader(im)[0] + GifImagePlugin.getdata(im, duration=duration): fp.write(s) fp.write(b";") fp.close() reread = Image.open(out) self.assertEqual(reread.info["duration"], duration)
def __init__(self, filename): self.source = Image.open(filename) self.palette = GifImagePlugin._get_palette_bytes(self.source) self.source.info[ "disposal"] = 2 # This should get set automatically, but it doesn't so whatever, if your GIF looks f****d then its probably this self.source.encoderinfo = self.source.info
def get_tags(driver, path, filter=False): tags = set() frames = [] video = path.suffix in ('.gif', '.webm', '.mp4') if video: tags.add('animated') if path.suffix in ('.webm', '.mp4'): try: for stream in FFProbe(str(path)).streams: if stream.codec_type == 'audio': tags.add('audio') break except: pass vidcap = VideoCapture(str(path)) frame_count = int(vidcap.get(CAP_PROP_FRAME_COUNT)) vidcap.release() elif path.suffix in ('.gif'): gifcap = GifImagePlugin.GifImageFile(str(path)) frame_count = gifcap.n_frames gifcap.close() step = 90 * log((frame_count * .002) + 1) + 1 frames = video_generator(path, round(step)) else: frames.append(path) for frame in frames: driver.get('http://dev.kanotype.net:8003/deepdanbooru/') driver.find('//*[@id="exampleFormControlFile1"]', str(frame)) driver.find('//button[@type="submit"]', click=True) for _ in range(4): html = bs4.BeautifulSoup(driver.page_source(), 'lxml') try: tags.update([ tag.text for tag in html.find('tbody').findAll(href=True) ]) break except AttributeError: if driver.current_url().endswith('deepdanbooru/'): driver.find('//*[@id="exampleFormControlFile1"]', str(frame)) driver.find('//button[@type="submit"]', click=True) driver.refresh() if filter: tags.difference_update(REMOVE) return ' '.join(tags)
def __iadd__(self, other): if self.previous is None: # Globaler Header header = ''.join(GifImagePlugin.getheader(other)) header = header.replace('GIF87a', 'GIF89a') self.fo.write(header) # Graphic Control Extension-Block header = [ '\x21', # Signatur für Beginn eines # Extension-Blocks '\xf9', # Graphic Control Extension-Signatur '\x04\x00', # Größe des Blocks (4 Bytes) '\x0a\x00', # Irgendwas + reservierter Block '\xff\x00', # Pause zwischen Frames (1/100 s) ] self.fo.write(''.join(header)) # Application Extension Block header = [ '\x21', # Signatur für Beginn eines # Extension-Blocks '\xff', # Application Extension-Signatur '\x0b', # Größe des Blocks (11 Bytes) 'NETSCAPE2.0', '\x03', # Größe des Sub-Datenblocks (3 Bytes) '\x01', '\x00\x00', # Anzahl der Schleifen (0 = unendlich) '\x00' # Ende des Blocks ] #self.fo.write(''.join(header)) # Erstes Frame for string in GifImagePlugin.getdata(other): self.fo.write(string) else: # Delta-Frame delta = ImageChops.subtract_modulo(other, self.previous) bbox = delta.getbbox() if bbox: for string in GifImagePlugin.getdata(other.crop(bbox), offset=bbox[:2]): self.fo.write(string) else: # XXX Was macht man in dem Fall? pass self.previous = other.copy() return self
def __iadd__(self, other): if self.previous is None: # Globaler Header header = "".join(GifImagePlugin.getheader(other)) header = header.replace("GIF87a", "GIF89a") self.fo.write(header) # Graphic Control Extension-Block header = [ "\x21", # Signatur für Beginn eines # Extension-Blocks "\xf9", # Graphic Control Extension-Signatur "\x04\x00", # Größe des Blocks (4 Bytes) "\x0a\x00", # Irgendwas + reservierter Block "\xff\x00", # Pause zwischen Frames (1/100 s) ] self.fo.write("".join(header)) # Application Extension Block header = [ "\x21", # Signatur für Beginn eines # Extension-Blocks "\xff", # Application Extension-Signatur "\x0b", # Größe des Blocks (11 Bytes) "NETSCAPE2.0", "\x03", # Größe des Sub-Datenblocks (3 Bytes) "\x01", "\x00\x00", # Anzahl der Schleifen (0 = unendlich) "\x00", # Ende des Blocks ] # self.fo.write(''.join(header)) # Erstes Frame for string in GifImagePlugin.getdata(other): self.fo.write(string) else: # Delta-Frame delta = ImageChops.subtract_modulo(other, self.previous) bbox = delta.getbbox() if bbox: for string in GifImagePlugin.getdata(other.crop(bbox), offset=bbox[:2]): self.fo.write(string) else: # XXX Was macht man in dem Fall? pass self.previous = other.copy() return self
def build_animated_gif(stream, images, delay=0.1): """Writes an animated GIF into a stream given an iterator of PIL.Images. See http://en.wikipedia.org/wiki/Graphics_Interchange_Format#Animated_GIF. """ # Process the images lazily to avoid unnecessary memory load. The first # image is used to build the GIF headers. images = (image.convert('P') for image in images) image = images.next() # Header stream.write("GIF89a") # Logical Screen Descriptor stream.write(struct.pack('<H', image.size[0])) stream.write(struct.pack('<H', image.size[1])) stream.write("\x87\x00\x00") # Palette stream.write(GifImagePlugin.getheader(image)[1]) # Application Extension stream.write("\x21\xFF\x0B") stream.write("NETSCAPE2.0") stream.write("\x03\x01") stream.write(struct.pack('<H', 2**16 - 1)) stream.write('\x00') for im in itertools.chain([image], images): # Graphic Control Extension stream.write('\x21\xF9\x04') stream.write('\x08') stream.write(struct.pack('<H', int(round(delay * 100)))) stream.write('\x00\x00') data = GifImagePlugin.getdata(im) for d in data: stream.write(d) # GIF file terminator stream.write(";")
def build_animated_gif(stream, images, delay=0.1): """Writes an animated GIF into a stream given an iterator of PIL.Images. See http://en.wikipedia.org/wiki/Graphics_Interchange_Format#Animated_GIF. """ # Process the images lazily to avoid unnecessary memory load. The first # image is used to build the GIF headers. images = (image.convert('P') for image in images) image = images.next() # Header stream.write("GIF89a") # Logical Screen Descriptor stream.write(struct.pack('<H', image.size[0])) stream.write(struct.pack('<H', image.size[1])) stream.write("\x87\x00\x00") # Palette stream.write(GifImagePlugin.getheader(image)[1]) # Application Extension stream.write("\x21\xFF\x0B") stream.write("NETSCAPE2.0") stream.write("\x03\x01") stream.write(struct.pack('<H', 2**16-1)) stream.write('\x00') for im in itertools.chain([image], images): # Graphic Control Extension stream.write('\x21\xF9\x04') stream.write('\x08') stream.write(struct.pack('<H', int(round(delay*100)))) stream.write('\x00\x00') data = GifImagePlugin.getdata(im) for d in data: stream.write(d) # GIF file terminator stream.write(";")
def writeImage(out, frames, filename="blurple.gif"): # Instead of saving a series of complete images, this saves the deltas for s in GifImagePlugin._get_global_header(frames[0], frames[0].info): out.write(s) for frame in frames: dispose_extent = frame.dispose_extent disposal_method = frame.disposal_method include_color_table = frame.palette.palette != frame.global_palette.palette frame = frame.crop(dispose_extent) GifImagePlugin._write_frame_data( out, frame, dispose_extent[:2], { 'disposal': disposal_method, 'duration': frame.info["duration"], 'include_color_table': include_color_table, 'transparency': 255, 'loop': frame.info["loop"], }, )
def write_gif(self, fp, im_frames): frame_count = 0 if len(im_frames) > 1: for frame_data in im_frames: im_frame = frame_data['im'] if frame_count == 0: # global header for s in GifImagePlugin._get_global_header( im_frame, frame_data['encoderinfo']): fp.write(s) else: frame_data['encoderinfo']['include_color_table'] = True offset = (0, 0) GifImagePlugin._write_frame_data(fp, im_frame, offset, frame_data['encoderinfo']) frame_count += 1 fp.write(b";") print(f'Wrote {frame_count} frames')
def _open(self): # Screen s = self.fp.read(13) if s[:6] not in ["GIF87a", "GIF89a"]: raise SyntaxError, "not a GIF file" self.info["version"] = s[:6] self.size = GifImagePlugin.i16(s[6:]), GifImagePlugin.i16(s[8:]) self.tile = [] flags = ord(s[10]) bits = (flags & 7) + 1 if flags & 128: # get global palette self.info["background"] = ord(s[11]) # check if palette contains colour indices p = self.fp.read(3 << bits) for i in range(0, len(p), 3): if not (chr(i / 3) == p[i] == p[i + 1] == p[i + 2]): p = ImagePalette.raw("RGB", p) self.global_palette = self.palette = p break self.__fp = self.fp self.__rewind = self.fp.tell() self.seek(0) # get ready to read first frame
def _open(self): # Screen s = self.fp.read(13) if s[:6] not in ["GIF87a", "GIF89a"]: raise SyntaxError, "not a GIF file" self.info["version"] = s[:6] self.size = GifImagePlugin.i16(s[6:]), GifImagePlugin.i16(s[8:]) self.tile = [] flags = ord(s[10]) bits = (flags & 7) + 1 if flags & 128: # get global palette self.info["background"] = ord(s[11]) # check if palette contains colour indices p = self.fp.read(3<<bits) for i in range(0, len(p), 3): if not (chr(i/3) == p[i] == p[i+1] == p[i+2]): p = ImagePalette.raw("RGB", p) self.global_palette = self.palette = p break self.__fp = self.fp self.__rewind = self.fp.tell() self.seek(0) # get ready to read first frame
def make_animated_gif(stream, images, delays): ''' Adapted from https://github.com/GoogleCloudPlatform/appengine-mandelbrot-python/blob/master/mandelbrot_animation.py ''' image = images[0] # Header stream.write("GIF89a") # Logical Screen Descriptor stream.write(struct.pack('<H', image.size[0])) stream.write(struct.pack('<H', image.size[1])) stream.write("\x87\x00\x00") # Palette stream.write(GifImagePlugin.getheader(image)[1]) # Application Extension stream.write("\x21\xFF\x0B") stream.write("NETSCAPE2.0") stream.write("\x03\x01") stream.write(struct.pack('<H', 2 ** 16 - 1)) stream.write('\x00') for i in xrange(1, len(images)): # Graphic Control Extension stream.write('\x21\xF9\x04') stream.write('\x08') stream.write(struct.pack('<H', delays[i])) stream.write('\x00\x00') data = GifImagePlugin.getdata(images[i]) for d in data: stream.write(d) # GIF file terminator stream.write(";")
def prepare_glitch(self, offset=100): # MODIFIED FROM # https://github.com/python-pillow/Pillow/blob/48a05e6cf3fc98b6385034372143f06fe6719e4e/src/PIL/GifImagePlugin.py#L416 duration = self.source.encoderinfo.get( "duration", self.source.info.get("duration")) disposal = self.source.encoderinfo.get( "disposal", self.source.info.get("disposal")) im_frames = [] frame_count = 0 for imSequence in itertools.chain([self.source], self.source.encoderinfo.get( "append_images", [])): for im_frame in ImageSequence.Iterator(imSequence): # a copy is required here since seek can still mutate the image im_frame = GifImagePlugin._normalize_mode(im_frame.copy()) if frame_count == 0: for k, v in im_frame.info.items(): self.source.encoderinfo.setdefault(k, v) im_frame = GifImagePlugin._normalize_palette( im_frame, self.palette, self.source.encoderinfo) encoderinfo = self.source.encoderinfo.copy() if isinstance(duration, (list, tuple)): encoderinfo['duration'] = duration[frame_count] if isinstance(disposal, (list, tuple)): encoderinfo["disposal"] = disposal[frame_count] frame_count += 1 # Crop the image to add <glitch_offset> px to the bottom im_frame = im_frame.crop( (0, 0, self.source.size[0], self.source.size[1] + offset)) im_frames.append({'im': im_frame, 'encoderinfo': encoderinfo}) return im_frames
def write_image(out, frames, filename="blurple.gif"): """Instead of saving a series of complete images, this saves the deltas. Useful for making GIFs not take as much space. Raw function: don't use this unless you know what you're doing. """ for s in GifImagePlugin._get_global_header(frames[0], frames[0].info): out.write(s) for frame in frames: dispose_extent = frame.dispose_extent disposal_method = frame.disposal_method include_color_table = frame.palette.palette != frame.global_palette.palette frame = frame.crop(dispose_extent) GifImagePlugin._write_frame_data( out, frame, dispose_extent[:2], { "disposal": disposal_method, "duration": frame.info["duration"], "include_color_table": include_color_table, "transparency": 255, "loop": frame.info["loop"], }, )
def level_22(): f=GifImagePlugin.GifImageFile(r'white.gif') my=Image.new('RGB',(640,480)) # 用于画字符的图片 draw=ImageDraw.Draw(my) curpoint=[0,0] pointlist=[tuple(curpoint)] frameno=1 while True: print ('frame=%d'%(frameno,)) try: for y in range(98,103):#f.size[1]): for x in range(98,103):#f.size[0]): if f.getpixel((x,y))!=0: print ('%d: %d,%d=%d'%(frameno,x,y,f.getpixel((x,y)))) # 可知每帧里面都有个调色板索引为8的点,坐标范围在(98,98)-(102,102)之间且坐标为偶数,相当于在3×3的九宫格中 k='%d-%d'%(x,y) # 到此为止没有思路了。参考攻略,原来是网页上那个游戏摇杆的图片是暗示你九宫格的点是用矢量方法记录的,可以据此划出线条来,太有想象力了! #(98,98) (100,98) (102,98) (-1,-1) (0,-1) (1,-1) #(98,100)(100,100)(102,100) == (-1,0) (0,0) (1,0) #(98,102)(100,102)(102,102) (-1,1) (0,1) (1,1) d={ '98-98':(-5,-5),'100-98':(0,-5),'102-98':(5,-5), '98-100':(-5,0),'100-100':(0,0),'102-100':(5,0), '98-102':(-5,5),'100-102':(0,5),'102-102':(5,5)} if d[k]==(0,0): print ('回到原点,开始画新字符') if len(pointlist)>1: draw.line(pointlist) # 画出字符 del pointlist[:] # 清空列表 curpoint[0]+=50 # 设定开始画字符的坐标,以免把上一个字符覆盖 curpoint[1]+=50 pointlist.append(tuple(curpoint)) continue curpoint[0]+=d[k][0] curpoint[1]+=d[k][1] pointlist.append(tuple(curpoint)) f.seek(f.tell()+1) # 跳到下一帧 frameno+=1 except EOFError as e: # 最后一帧后会触发此异常 print ('end of frame.%d'%(frameno,)) # 可知此GIF有133帧 draw.line(pointlist) # 画出最后一个字符 my.save(r'23_white.png','png') # 能看出画的字符为 bonus ==> http://www.pythonchallenge.com/pc/hex/bonus.html break
def level_16(): ## # 尝试把不是粉短线的颜色都去掉 ## f=GifImagePlugin.GifImageFile(ur'd:\mozart.gif') ## mf=PIL.Image.new('P',f.size) ## for y in range(f.size[1]): ## for x in range(f.size[0]): ## if f.getpixel((x,y))==195: ## mf.putpixel((x,y),195) ## mf.save(ur'd:\16.gif','gif') # 啥都看不出来 查看攻略 原来所谓get this straight是说把这些粉短线都按行对齐 f=GifImagePlugin.GifImageFile(r'mozart.gif') mf=Image.new('P',f.size) mf.putpalette(f.getpalette()) # 用原图的调色板 for y in range(f.size[1]): for x in range(f.size[0]): if f.getpixel((x,y))==195: # 找到头一个粉色像素 以此为对准线 for mx in range(f.size[0]): mf.putpixel((mx,y),f.getpixel(((mx+x)%f.size[0],y))) #往前走mx<--mx+x之前替换 # 将从这个粉色像素开始的一行复制到新图片中 break mf.save(r'mozart16.gif','gif')
def gif_image(): return GifImagePlugin.GifImageFile(create_test_image('gif'))
def test_save_netpbm_l_mode(self): img = Image.open(TEST_GIF).convert("L") tempfile = self.tempfile("temp.gif") GifImagePlugin._save_netpbm(img, 0, tempfile) self.assert_image_similar(img, Image.open(tempfile).convert("L"), 0)
def export_animation(app, art, out_filename, bg_color=None, loop=True): # get list of rendered frame images frames = [] # use arbitrary color for transparency i_transp = art.palette.get_random_non_palette_color() # if bg color is specified, this isn't art mode; play along if bg_color is not None: f_transp = bg_color art.palette.colors[0] = (round(bg_color[0] * 255), round(bg_color[1] * 255), round(bg_color[2] * 255), 255) else: # GL wants floats f_transp = (i_transp[0] / 255, i_transp[1] / 255, i_transp[2] / 255, 1.) for frame in range(art.frames): frame_img = get_frame_image(app, art, frame, allow_crt=False, scale=1, bg_color=f_transp) if bg_color is not None: # if bg color is specified, assume no transparency frame_img = art.palette.get_palettized_image( frame_img, force_no_transparency=True) else: frame_img = art.palette.get_palettized_image( frame_img, i_transp[:3]) frames.append(frame_img) # compile frames into animated GIF with proper frame delays # technique thanks to: # https://github.com/python-pillow/Pillow/blob/master/Scripts/gifmaker.py output_img = open(out_filename, 'wb') for i, img in enumerate(frames): delay = art.frame_delays[i] * 1000 if i == 0: data = GifImagePlugin.getheader(img)[0] # PIL only wants to write GIF87a for some reason... # welcome to 1989 B] data[0] = data[0].replace(b'7', b'9') # TODO: loop doesn't work? if bg_color is not None: # if bg color is specified, assume no transparency if loop: data += GifImagePlugin.getdata(img, duration=delay, loop=0) else: data += GifImagePlugin.getdata(img, duration=delay) else: data += GifImagePlugin.getdata(img, duration=delay, transparency=0, loop=0) for b in data: output_img.write(b) continue delta = ImageChops.subtract_modulo(img, frames[i - 1]) # Image.getbbox() rather unhelpfully returns None if no delta dw, dh = delta.size bbox = delta.getbbox() or (0, 0, dw, dh) for b in GifImagePlugin.getdata(img.crop(bbox), offset=bbox[:2], duration=delay, transparency=0, loop=0): output_img.write(b) output_img.write(b';') output_img.close() output_format = 'Animated GIF'
def seek(self, frame): if frame == 0: # rewind self.__offset = 0 self.dispose = None self.__frame = -1 self.__fp.seek(self.__rewind) if frame != self.__frame + 1: raise ValueError, "cannot seek to frame %d" % frame self.__frame = frame self.tile = [] self.fp = self.__fp if self.__offset: # backup to last frame self.fp.seek(self.__offset) while self.data(): pass self.__offset = 0 if self.dispose: self.im = self.dispose self.dispose = None self.palette = self.global_palette while 1: s = self.fp.read(1) if not s or s == ";": break elif s == "!": # # extensions # s = self.fp.read(1) block = self.data() if ord(s) == 249: # # graphic control extension # flags = ord(block[0]) if flags & 1: self.info["transparency"] = ord(block[3]) self.info["duration"] = GifImagePlugin.i16(block[1:3]) * 10 try: # disposal methods if flags & 8: # replace with background colour self.dispose = Image.core.fill("P", self.size, self.info["background"]) elif flags & 16: # replace with previous contents self.dispose = self.im.copy() except (AttributeError, KeyError): pass elif ord(s) == 255: # # application extension # self.info["extension"] = block, self.fp.tell() if block[:11] == "NETSCAPE2.0": block = self.data() if len(block) >= 3 and ord(block[0]) == 1: self.info["loop"] = GifImagePlugin.i16(block[1:3]) while self.data(): pass elif s == ",": # # local image # s = self.fp.read(9) # extent x0, y0 = GifImagePlugin.i16(s[0:]), GifImagePlugin.i16(s[2:]) x, y = GifImagePlugin.i16(s[4:]), GifImagePlugin.i16(s[6:]) x1, y1 = x0 + x, y0 + y self.info['frame_box'] = (x0,y0,x1,y1) flags = ord(s[8]) interlace = (flags & 64) != 0 if flags & 128: bits = (flags & 7) + 1 self.palette =\ ImagePalette.raw("RGB", self.fp.read(3<<bits)) # image data bits = ord(self.fp.read(1)) self.__offset = self.fp.tell() self.tile = [("gif", (x0, y0, x1, y1), self.__offset, (bits, interlace))] break else: pass # raise IOError, "illegal GIF tag `%x`" % ord(s) if not self.tile: # self.__fp = None raise EOFError, "no more images in GIF file" self.mode = "L" if self.palette: self.mode = "P"
def seek(self, frame): if frame == 0: # rewind self.__offset = 0 self.dispose = None self.__frame = -1 self.__fp.seek(self.__rewind) if frame != self.__frame + 1: raise ValueError, "cannot seek to frame %d" % frame self.__frame = frame self.tile = [] self.fp = self.__fp if self.__offset: # backup to last frame self.fp.seek(self.__offset) while self.data(): pass self.__offset = 0 if self.dispose: self.im = self.dispose self.dispose = None self.palette = self.global_palette while 1: s = self.fp.read(1) if not s or s == ";": break elif s == "!": # # extensions # s = self.fp.read(1) block = self.data() if ord(s) == 249: # # graphic control extension # flags = ord(block[0]) if flags & 1: self.info["transparency"] = ord(block[3]) self.info["duration"] = GifImagePlugin.i16(block[1:3]) * 10 try: # disposal methods if flags & 8: # replace with background colour self.dispose = Image.core.fill( "P", self.size, self.info["background"]) elif flags & 16: # replace with previous contents self.dispose = self.im.copy() except (AttributeError, KeyError): pass elif ord(s) == 255: # # application extension # self.info["extension"] = block, self.fp.tell() if block[:11] == "NETSCAPE2.0": block = self.data() if len(block) >= 3 and ord(block[0]) == 1: self.info["loop"] = GifImagePlugin.i16(block[1:3]) while self.data(): pass elif s == ",": # # local image # s = self.fp.read(9) # extent x0, y0 = GifImagePlugin.i16(s[0:]), GifImagePlugin.i16(s[2:]) x, y = GifImagePlugin.i16(s[4:]), GifImagePlugin.i16(s[6:]) x1, y1 = x0 + x, y0 + y self.info['frame_box'] = (x0, y0, x1, y1) flags = ord(s[8]) interlace = (flags & 64) != 0 if flags & 128: bits = (flags & 7) + 1 self.palette =\ ImagePalette.raw("RGB", self.fp.read(3<<bits)) # image data bits = ord(self.fp.read(1)) self.__offset = self.fp.tell() self.tile = [("gif", (x0, y0, x1, y1), self.__offset, (bits, interlace))] break else: pass # raise IOError, "illegal GIF tag `%x`" % ord(s) if not self.tile: # self.__fp = None raise EOFError, "no more images in GIF file" self.mode = "L" if self.palette: self.mode = "P"
def test_invalid_file(self): invalid_file = "Tests/images/flower.jpg" self.assertRaises(SyntaxError, lambda: GifImagePlugin.GifImageFile(invalid_file))
def level_27(): zig=GifImagePlugin.GifImageFile(r'zigzag.gif') zigdata=zig.tostring() import array data=[] for i in zigdata[:10]: data.append(i) data = array.array("B", data).tostring() print("zigdata,10:",data[:10]) print (''.join(['%X'%(i,) for i in zigdata[:20]])) # 查看前面几个字节,没有头绪) #print (len(zig.getcolors())) palette=zig.palette.getdata()[1][::3] # 获取其调色板 data1=[] for i in palette[:10]: data1.append(i) data1 = array.array("B", data1).tostring() print("palette,10:",palette[:10]) #print(data1,type(data1)) print (''.join(['%X'%(i,) for i in palette[:20]])) #t=string.maketrans(''.join([chr(i) for i in range(256)]),palette) ch1=b''.join([bytes([i]) for i in range(256)]) t=bytes.maketrans(ch1,palette) zigtrans=zigdata.translate(t) # 用调色板值转换像素值 print("zigtrans,10",zigtrans[:10]) print (''.join(['%X'%(i,) for i in zigtrans[:20]])) #实现hex(zigtrans[:20],python3下,前面为python2版 # 还是看不出来什么,不过似乎转换后的数据除了第一个字节外都与原数据很相似) print (zigdata[1:]==zigtrans[:-1]) # 尝试将两组数据中所有不相同的字节放在一起 deltas=filter(lambda p:p[0]!=p[1],zip(zigdata[1:],zigtrans[:-1])) diffs=[b''.join([bytes([p[i]]) for p in deltas]) for i in range(2)] print (diffs[0][:20]) # 看起来是个bz文件) print (diffs[1][:20]) #这一句结果与别人的不同也. bz=bz2.BZ2Decompressor().decompress(diffs[0]) #bz=bz2.decompress(diffs[0])#在python3下要用上面这一句,真是奇怪 #也许比较的是字节吧 print (len(bz)) print (bz[:100]) # 输出是python的关键字和地址 ../ring/bell.html keywords=bz.split(b' ') keys={} for k in keywords: keys[k]=1 print (keys.keys()) print (len(keywords)) print (len(keys.keys())) # 很多关键字 print (len(keywords)/len(keys.keys())) # 将不一样的像素按位置显示出来 im=Image.new('1',zig.size,0) im.putdata([ p[0]==p[1] for p in zip(zigdata[1:],zigtrans[:-1])]) #im.show() # 有个钥匙图样,左边是not,右边是word,下面是busy? # 暗示 not key word # 那么找找上面看到的那些关键字里面哪些不是key word im.save("27_notkeyword.png","png") for k in keys.keys(): k=str(k)[2:-1] if not keyword.iskeyword(k): print (k) # 打印出来 switch 和 repeat 不是关键字,../ring/bell.html不算。 # 用switch 和 repeat 分别做用户名和密码,还有print,exec,当然这是python3下的 k1,k2='switch','repeat' t=((k1+":"+k2),(k2+":"+k1)) n1 = urllib.request.FancyURLopener() for i in t: try: url='http://'+i+'@www.pythonchallenge.com/pc/ring/bell.html' r=n1.open(url) if r: print ('got, %s '%(i)) # 正确的用户名是repeat 密码是 switch ==> http://www.pythonchallenge.com/pc/ring/bell.html break except urllib.request.HTTPError: pass
def test_invalid_file(): invalid_file = "Tests/images/flower.jpg" with pytest.raises(SyntaxError): GifImagePlugin.GifImageFile(invalid_file)