def _inject(self, fileobj, padding_func): """Write tag data into the Vorbis comment packet/page.""" # Find the old pages in the file; we'll need to remove them, # plus grab any stray setup packet data out of them. fileobj.seek(0) page = OggPage(fileobj) while not page.packets[0].startswith(b"\x03vorbis"): page = OggPage(fileobj) old_pages = [page] while not (old_pages[-1].complete or len(old_pages[-1].packets) > 1): page = OggPage(fileobj) if page.serial == old_pages[0].serial: old_pages.append(page) packets = OggPage.to_packets(old_pages, strict=False) content_size = get_size(fileobj) - len(packets[0]) # approx vcomment_data = b"\x03vorbis" + self.write() padding_left = len(packets[0]) - len(vcomment_data) info = PaddingInfo(padding_left, content_size) new_padding = info._get_padding(padding_func) # Set the new comment packet. packets[0] = vcomment_data + b"\x00" * new_padding new_pages = OggPage._from_packets_try_preserve(packets, old_pages) OggPage.replace(fileobj, old_pages, new_pages)
def __save_new(self, fileobj, atoms, ilst_data, padding_func): hdlr = Atom.render(b"hdlr", b"\x00" * 8 + b"mdirappl" + b"\x00" * 9) meta_data = b"\x00\x00\x00\x00" + hdlr + ilst_data try: path = atoms.path(b"moov", b"udta") except KeyError: path = atoms.path(b"moov") offset = path[-1]._dataoffset # ignoring some atom overhead... but we don't have padding left anyway # and padding_size is guaranteed to be less than zero content_size = get_size(fileobj) - offset padding_size = -len(meta_data) assert padding_size < 0 info = PaddingInfo(padding_size, content_size) new_padding = info._get_padding(padding_func) new_padding = min(0xFFFFFFFF, new_padding) free = Atom.render(b"free", b"\x00" * new_padding) meta = Atom.render(b"meta", meta_data + free) if path[-1].name != b"udta": # moov.udta not found -- create one data = Atom.render(b"udta", meta) else: data = meta insert_bytes(fileobj, len(data), offset) fileobj.seek(offset) fileobj.write(data) self.__update_parents(fileobj, path, len(data)) self.__update_offsets(fileobj, atoms, len(data), offset)
def _inject(self, fileobj, padding_func): """Write tag data into the Theora comment packet/page.""" fileobj.seek(0) page = OggPage(fileobj) while not page.packets[0].startswith(b"\x81theora"): page = OggPage(fileobj) old_pages = [page] while not (old_pages[-1].complete or len(old_pages[-1].packets) > 1): page = OggPage(fileobj) if page.serial == old_pages[0].serial: old_pages.append(page) packets = OggPage.to_packets(old_pages, strict=False) content_size = get_size(fileobj) - len(packets[0]) # approx vcomment_data = b"\x81theora" + self.write(framing=False) padding_left = len(packets[0]) - len(vcomment_data) info = PaddingInfo(padding_left, content_size) new_padding = info._get_padding(padding_func) packets[0] = vcomment_data + b"\x00" * new_padding new_pages = OggPage._from_packets_try_preserve(packets, old_pages) OggPage.replace(fileobj, old_pages, new_pages)
def render_full(self, asf, fileobj, available, padding_func): # Render everything except padding num_objects = 0 data = bytearray() for obj in self.objects: if obj.GUID == PaddingObject.GUID: continue data += obj.render(asf) num_objects += 1 # calculate how much space we need at least padding_obj = PaddingObject() header_size = len(HeaderObject.GUID) + 14 padding_overhead = len(padding_obj.render(asf)) needed_size = len(data) + header_size + padding_overhead # ask the user for padding adjustments file_size = get_size(fileobj) content_size = file_size - available if content_size < 0: raise ASFHeaderError("truncated content") info = PaddingInfo(available - needed_size, content_size) # add padding padding = info._get_padding(padding_func) padding_obj.parse(asf, b"\x00" * padding) data += padding_obj.render(asf) num_objects += 1 data = (HeaderObject.GUID + struct.pack("<QL", len(data) + 30, num_objects) + b"\x01\x02" + data) return data
def __save_existing(self, fileobj, atoms, path, ilst_data, padding_func): # Replace the old ilst atom. ilst = path[-1] offset = ilst.offset length = ilst.length # Use adjacent free atom if there is one free = _find_padding(path) if free is not None: offset = min(offset, free.offset) length += free.length # Always add a padding atom to make things easier padding_overhead = len(Atom.render(b"free", b"")) content_size = get_size(fileobj) - (offset + length) padding_size = length - (len(ilst_data) + padding_overhead) info = PaddingInfo(padding_size, content_size) new_padding = info._get_padding(padding_func) # Limit padding size so we can be sure the free atom overhead is as we # calculated above (see Atom.render) new_padding = min(0xFFFFFFFF, new_padding) ilst_data += Atom.render(b"free", b"\x00" * new_padding) resize_bytes(fileobj, length, len(ilst_data), offset) delta = len(ilst_data) - length fileobj.seek(offset) fileobj.write(ilst_data) self.__update_parents(fileobj, path[:-1], delta) self.__update_offsets(fileobj, atoms, delta, offset)
def _inject(self, fileobj, padding_func): """Write tag data into the Theora comment packet/page.""" fileobj.seek(0) page = OggPage(fileobj) while not page.packets or \ not page.packets[0].startswith(b"\x81theora"): page = OggPage(fileobj) old_pages = [page] while not (old_pages[-1].complete or len(old_pages[-1].packets) > 1): page = OggPage(fileobj) if page.serial == old_pages[0].serial: old_pages.append(page) packets = OggPage.to_packets(old_pages, strict=False) content_size = get_size(fileobj) - len(packets[0]) # approx vcomment_data = b"\x81theora" + self.write(framing=False) padding_left = len(packets[0]) - len(vcomment_data) info = PaddingInfo(padding_left, content_size) new_padding = info._get_padding(padding_func) packets[0] = vcomment_data + b"\x00" * new_padding new_pages = OggPage._from_packets_try_preserve(packets, old_pages) OggPage.replace(fileobj, old_pages, new_pages)
def render_full(self, asf, fileobj, available, padding_func): # Render everything except padding num_objects = 0 data = bytearray() for obj in self.objects: if obj.GUID == PaddingObject.GUID: continue data += obj.render(asf) num_objects += 1 # calculate how much space we need at least padding_obj = PaddingObject() header_size = len(HeaderObject.GUID) + 14 padding_overhead = len(padding_obj.render(asf)) needed_size = len(data) + header_size + padding_overhead # ask the user for padding adjustments file_size = get_size(fileobj) content_size = file_size - available assert content_size >= 0 info = PaddingInfo(available - needed_size, content_size) # add padding padding = info._get_padding(padding_func) padding_obj.parse(asf, b"\x00" * padding) data += padding_obj.render(asf) num_objects += 1 data = (HeaderObject.GUID + struct.pack("<QL", len(data) + 30, num_objects) + b"\x01\x02" + data) return data
def _save(self, filething, metadata_blocks, deleteid3, padding): f = StrictFileObject(filething.fileobj) header = self.__check_header(f, filething.name) audio_offset = self.__find_audio_offset(f) # "fLaC" and maybe ID3 available = audio_offset - header # Delete ID3v2 if deleteid3 and header > 4: available += header - 4 header = 4 content_size = get_size(f) - audio_offset assert content_size >= 0 data = MetadataBlock._writeblocks(metadata_blocks, available, content_size, padding) data_size = len(data) resize_bytes(filething.fileobj, available, data_size, header) f.seek(header - 4) f.write(b"fLaC") f.write(data) # Delete ID3v1 if deleteid3: try: f.seek(-128, 2) except IOError: pass else: if f.read(3) == b"TAG": f.seek(-128, 2) f.truncate()
def imag(company_name, image): # 获取图片大小 o_size = get_size(image) quality = 80 step = 10 # 处理图片名称 data_time = datetime.now().strftime("%Y%m%d%H%M%S") image_name = data_time + company_name + "." + image.name.split(".")[-1] # 图片路径 # path = "/root/Up_down_chain/up_down_chain/static/" + image_name path = "/root/Up_down_chain/up_down_chain/static/" + image_name if o_size <= 40000: im = Image.open(image) im.save(path, quality=quality) return image_name # path="" # 图片压缩 while o_size > 400000: im = Image.open(image) im.save(path, quality=quality) if quality - step < 0: break quality -= step o_size = os.path.getsize(path) return image_name
def __find_metadata(self, fileobj): # Try to find a header or footer. # Check for a simple footer. try: fileobj.seek(-32, 2) except IOError: fileobj.seek(0, 2) return if fileobj.read(8) == b"APETAGEX": fileobj.seek(-8, 1) self.footer = self.metadata = fileobj.tell() return # Check for an APEv2 tag followed by an ID3v1 tag at the end. try: if get_size(fileobj) < 128: raise IOError fileobj.seek(-128, 2) if fileobj.read(3) == b"TAG": fileobj.seek(-35, 1) # "TAG" + header length if fileobj.read(8) == b"APETAGEX": fileobj.seek(-8, 1) self.footer = fileobj.tell() return # ID3v1 tag at the end, maybe preceded by Lyrics3v2. # (http://www.id3.org/lyrics3200.html) # (header length - "APETAGEX") - "LYRICS200" fileobj.seek(15, 1) if fileobj.read(9) == b'LYRICS200': fileobj.seek(-15, 1) # "LYRICS200" + size tag try: offset = int(fileobj.read(6)) except ValueError: raise IOError fileobj.seek(-32 - offset - 6, 1) if fileobj.read(8) == b"APETAGEX": fileobj.seek(-8, 1) self.footer = fileobj.tell() return except IOError: pass # Check for a tag at the start. fileobj.seek(0, 0) if fileobj.read(8) == b"APETAGEX": self.is_at_start = True self.header = 0
def seek(self, offset, whence=0): self._check_fail() # make sure we don't go negative if whence == 0: final_position = offset elif whence == 1: final_position = self._fileobj.tell() + offset elif whence == 2: final_position = get_size(self._fileobj) + offset assert final_position >= 0, final_position return self._fileobj.seek(offset, whence)
def save(self, filething, deleteid3=False, padding=None): """Save metadata blocks to a file. Args: filething (filething) deleteid3 (bool): delete id3 tags while at it padding (PaddingFunction) If no filename is given, the one most recently loaded is used. """ f = StrictFileObject(filething.fileobj) header = self.__check_header(f, filething.name) audio_offset = self.__find_audio_offset(f) # "fLaC" and maybe ID3 available = audio_offset - header # Delete ID3v2 if deleteid3 and header > 4: available += header - 4 header = 4 content_size = get_size(f) - audio_offset assert content_size >= 0 data = MetadataBlock._writeblocks(self.metadata_blocks, available, content_size, padding) data_size = len(data) resize_bytes(filething.fileobj, available, data_size, header) f.seek(header - 4) f.write(b"fLaC") f.write(data) # Delete ID3v1 if deleteid3: try: f.seek(-128, 2) except IOError: pass else: if f.read(3) == b"TAG": f.seek(-128, 2) f.truncate()
def save(self, filething, deleteid3=False, padding=None): """Save metadata blocks to a file. Args: filething (filething) deleteid3 (bool): delete id3 tags while at it padding (PaddingFunction) If no filename is given, the one most recently loaded is used. """ f = StrictFileObject(filething.fileobj) header = self.__check_header(f, filething.name) audio_offset = self.__find_audio_offset(f) # "fLaC" and maybe ID3 available = audio_offset - header # Delete ID3v2 if deleteid3 and header > 4: available += header - 4 header = 4 content_size = get_size(f) - audio_offset assert content_size >= 0 data = MetadataBlock._writeblocks( self.metadata_blocks, available, content_size, padding) data_size = len(data) resize_bytes(filething.fileobj, available, data_size, header) f.seek(header - 4) f.write(b"fLaC") f.write(data) # Delete ID3v1 if deleteid3: try: f.seek(-128, 2) except IOError: pass else: if f.read(3) == b"TAG": f.seek(-128, 2) f.truncate()
def save(self, filename=None, deleteid3=False, padding=None): """Save metadata blocks to a file. If no filename is given, the one most recently loaded is used. """ if filename is None: filename = self.filename with open(filename, 'rb+') as f: header = self.__check_header(f) audio_offset = self.__find_audio_offset(f) # "fLaC" and maybe ID3 available = audio_offset - header # Delete ID3v2 if deleteid3 and header > 4: available += header - 4 header = 4 content_size = get_size(f) - audio_offset assert content_size >= 0 data = MetadataBlock._writeblocks(self.metadata_blocks, available, content_size, padding) data_size = len(data) resize_bytes(f, available, data_size, header) f.seek(header - 4) f.write(b"fLaC") f.write(data) # Delete ID3v1 if deleteid3: try: f.seek(-128, 2) except IOError: pass else: if f.read(3) == b"TAG": f.seek(-128, 2) f.truncate()
def save(self, filename=None, deleteid3=False, padding=None): """Save metadata blocks to a file. If no filename is given, the one most recently loaded is used. """ if filename is None: filename = self.filename with open(filename, 'rb+') as f: header = self.__check_header(f) audio_offset = self.__find_audio_offset(f) # "fLaC" and maybe ID3 available = audio_offset - header # Delete ID3v2 if deleteid3 and header > 4: available += header - 4 header = 4 content_size = get_size(f) - audio_offset assert content_size >= 0 data = MetadataBlock._writeblocks( self.metadata_blocks, available, content_size, padding) data_size = len(data) resize_bytes(f, available, data_size, header) f.seek(header - 4) f.write(b"fLaC") f.write(data) # Delete ID3v1 if deleteid3: try: f.seek(-128, 2) except IOError: pass else: if f.read(3) == b"TAG": f.seek(-128, 2) f.truncate()
def _inject(self, fileobj, padding_func): fileobj.seek(0) info = OggOpusInfo(fileobj) old_pages = self.__get_comment_pages(fileobj, info) packets = OggPage.to_packets(old_pages) vcomment_data = b"OpusTags" + self.write(framing=False) if self._pad_data: # if we have padding data to preserver we can't add more padding # as long as we don't know the structure of what follows packets[0] = vcomment_data + self._pad_data else: content_size = get_size(fileobj) - len(packets[0]) # approx padding_left = len(packets[0]) - len(vcomment_data) info = PaddingInfo(padding_left, content_size) new_padding = info._get_padding(padding_func) packets[0] = vcomment_data + b"\x00" * new_padding new_pages = OggPage._from_packets_try_preserve(packets, old_pages) OggPage.replace(fileobj, old_pages, new_pages)
def _inject(self, fileobj, padding_func): """Write tag data into the Speex comment packet/page.""" fileobj.seek(0) # Find the first header page, with the stream info. # Use it to get the serial number. page = OggPage(fileobj) while not page.packets[0].startswith(b"Speex "): page = OggPage(fileobj) # Look for the next page with that serial number, it'll start # the comment packet. serial = page.serial page = OggPage(fileobj) while page.serial != serial: page = OggPage(fileobj) # Then find all the pages with the comment packet. old_pages = [page] while not (old_pages[-1].complete or len(old_pages[-1].packets) > 1): page = OggPage(fileobj) if page.serial == old_pages[0].serial: old_pages.append(page) packets = OggPage.to_packets(old_pages, strict=False) content_size = get_size(fileobj) - len(packets[0]) # approx vcomment_data = self.write(framing=False) padding_left = len(packets[0]) - len(vcomment_data) info = PaddingInfo(padding_left, content_size) new_padding = info._get_padding(padding_func) # Set the new comment packet. packets[0] = vcomment_data + b"\x00" * new_padding new_pages = OggPage._from_packets_try_preserve(packets, old_pages) OggPage.replace(fileobj, old_pages, new_pages)
def test_get_size(self): f = BytesIO(b"foo") f.seek(1, 0) self.assertEqual(f.tell(), 1) self.assertEqual(get_size(f), 3) self.assertEqual(f.tell(), 1)
def test_get_size(self): f = cBytesIO(b"foo") f.seek(1, 0) self.assertEqual(f.tell(), 1) self.assertEqual(get_size(f), 3) self.assertEqual(f.tell(), 1)