def _load_bitmap_decoder(self, file, filename): data = file.read() # Create a HGLOBAL with image data hglob = kernel32.GlobalAlloc(GMEM_MOVEABLE, len(data)) ptr = kernel32.GlobalLock(hglob) memmove(ptr, data, len(data)) kernel32.GlobalUnlock(hglob) # Create IStream for the HGLOBAL stream = com.IUnknown() ole32.CreateStreamOnHGlobal(hglob, True, byref(stream)) # Load image from stream decoder = IWICBitmapDecoder() status = self._factory.CreateDecoderFromStream(stream, None, WICDecodeMetadataCacheOnDemand, byref(decoder)) if status != 0: stream.Release() raise ImageDecodeException('WIC cannot load %r' % (filename or file)) return decoder, stream
def _load_bitmap(self, filename, file): data = file.read() # Create a HGLOBAL with image data hglob = kernel32.GlobalAlloc(GMEM_MOVEABLE, len(data)) ptr = kernel32.GlobalLock(hglob) memmove(ptr, data, len(data)) kernel32.GlobalUnlock(hglob) # Create IStream for the HGLOBAL self.stream = pIUnknown() ole32.CreateStreamOnHGlobal(hglob, True, byref(self.stream)) # Load image from stream bitmap = c_void_p() status = gdiplus.GdipCreateBitmapFromStream(self.stream, byref(bitmap)) if status != 0: self.stream.Release() raise ImageDecodeException('GDI+ cannot load %r' % (filename or file)) return bitmap
def __init__(self, filename, file=None): assert any([self.decode_audio, self.decode_video ]), "Source must decode audio, video, or both, not none." self._current_audio_sample = None self._current_audio_buffer = None self._current_video_sample = None self._current_video_buffer = None self._timestamp = 0 self._attributes = None self._stream_obj = None self._wfx = None self._stride = None self.set_config_attributes() # Create SourceReader self._source_reader = IMFSourceReader() # If it's a file, we need to load it as a stream. if file is not None: data = file.read() # Stole code from GDIPlus for older IStream support. hglob = kernel32.GlobalAlloc(GMEM_MOVEABLE, len(data)) ptr = kernel32.GlobalLock(hglob) ctypes.memmove(ptr, data, len(data)) kernel32.GlobalUnlock(hglob) # Create IStream self._stream_obj = com.IUnknown() ole32.CreateStreamOnHGlobal(hglob, True, ctypes.byref(self._stream_obj)) imf_bytestream = IMFByteStream() # MFCreateMFByteStreamOnStreamEx for future async operations exists, however Windows 8+ only. Requires new interface # (Also unsure how/if new Windows async functions and callbacks work with ctypes.) MFCreateMFByteStreamOnStream( self._stream_obj, ctypes.byref(imf_bytestream)) # Allows 7 support still try: MFCreateSourceReaderFromByteStream( imf_bytestream, self._attributes, ctypes.byref(self._source_reader)) except OSError as err: raise MediaDecodeException(err) from None else: # We can just load from filename if no file object specified.. try: MFCreateSourceReaderFromURL(filename, self._attributes, ctypes.byref(self._source_reader)) except OSError as err: raise MediaDecodeException(err) from None if self.decode_audio: self._load_audio() if self.decode_video: self._load_video() assert self.audio_format or self.video_format, "Source was decoded, but no video or audio streams were found."
def __init__(self, filename, file=None): assert any([self.decode_audio, self.decode_video ]), "Source must decode audio, video, or both, not none." self._current_audio_sample = None self._current_audio_buffer = None self._current_video_sample = None self._current_video_buffer = None self._timestamp = 0 self._attributes = None self._stream_obj = None self._imf_bytestream = None self._wfx = None self._stride = None self.set_config_attributes() # Create SourceReader self._source_reader = IMFSourceReader() # If it's a file, we need to load it as a stream. if file is not None: data = file.read() self._imf_bytestream = IMFByteStream() data_len = len(data) if WINDOWS_7_OR_GREATER: # Stole code from GDIPlus for older IStream support. hglob = kernel32.GlobalAlloc(GMEM_MOVEABLE, data_len) ptr = kernel32.GlobalLock(hglob) ctypes.memmove(ptr, data, data_len) kernel32.GlobalUnlock(hglob) # Create IStream self._stream_obj = com.IUnknown() ole32.CreateStreamOnHGlobal(hglob, True, ctypes.byref(self._stream_obj)) # MFCreateMFByteStreamOnStreamEx for future async operations exists, however Windows 8+ only. Requires new interface # (Also unsure how/if new Windows async functions and callbacks work with ctypes.) MFCreateMFByteStreamOnStream( self._stream_obj, ctypes.byref(self._imf_bytestream)) else: # Vista does not support MFCreateMFByteStreamOnStream. # HACK: Create file in Windows temp folder to write our byte data to. # (Will be automatically deleted when IMFByteStream is Released.) MFCreateTempFile(MF_ACCESSMODE_READWRITE, MF_OPENMODE_DELETE_IF_EXIST, MF_FILEFLAGS_NONE, ctypes.byref(self._imf_bytestream)) wrote_length = ULONG() data_ptr = cast(data, POINTER(BYTE)) self._imf_bytestream.Write(data_ptr, data_len, ctypes.byref(wrote_length)) self._imf_bytestream.SetCurrentPosition(0) if wrote_length.value != data_len: raise MediaDecodeException( "Could not write all of the data to the bytestream file." ) try: MFCreateSourceReaderFromByteStream( self._imf_bytestream, self._attributes, ctypes.byref(self._source_reader)) except OSError as err: raise MediaDecodeException(err) from None else: # We can just load from filename if no file object specified.. try: MFCreateSourceReaderFromURL(filename, self._attributes, ctypes.byref(self._source_reader)) except OSError as err: raise MediaDecodeException(err) from None if self.decode_audio: self._load_audio() if self.decode_video: self._load_video() assert self.audio_format or self.video_format, "Source was decoded, but no video or audio streams were found." # Get duration of the media file after everything has been ok to decode. try: prop = PROPVARIANT() self._source_reader.GetPresentationAttribute( MF_SOURCE_READER_MEDIASOURCE, ctypes.byref(MF_PD_DURATION), ctypes.byref(prop)) self._duration = timestamp_from_wmf(prop.llVal) ole32.PropVariantClear(ctypes.byref(prop)) except OSError: warnings.warn( "Could not determine duration of media file: '{}'.".format( filename))
def encode(self, image, filename, file): image = image.get_image_data() wicstream = IWICStream() encoder = IWICBitmapEncoder() frame = IWICBitmapFrameEncode() property_bag = IPropertyBag2() ext = (filename and os.path.splitext(filename)[1]) or '.png' # Choose container based on extension. Default to PNG. container = extension_to_container.get(ext, GUID_ContainerFormatPng) _factory.CreateStream(byref(wicstream)) # https://docs.microsoft.com/en-us/windows/win32/wic/-wic-codec-native-pixel-formats#native-image-formats if container == GUID_ContainerFormatJpeg: # Expects BGR, no transparency available. Hard coded. fmt = 'BGR' default_format = GUID_WICPixelFormat24bppBGR else: # Windows encodes in BGRA. if len(image.format) == 3: fmt = 'BGR' default_format = GUID_WICPixelFormat24bppBGR else: fmt = 'BGRA' default_format = GUID_WICPixelFormat32bppBGRA pitch = image.width * len(fmt) image_data = image.get_data(fmt, -pitch) size = pitch * image.height if file: istream = IStream() ole32.CreateStreamOnHGlobal(None, True, byref(istream)) wicstream.InitializeFromIStream(istream) else: wicstream.InitializeFromFilename(filename, GENERIC_WRITE) _factory.CreateEncoder(container, None, byref(encoder)) encoder.Initialize(wicstream, WICBitmapEncoderNoCache) encoder.CreateNewFrame(byref(frame), byref(property_bag)) frame.Initialize(property_bag) frame.SetSize(image.width, image.height) frame.SetPixelFormat(byref(default_format)) data = (c_byte * size).from_buffer(bytearray(image_data)) frame.WritePixels(image.height, abs(image.pitch), size, data) frame.Commit() encoder.Commit() if file: sts = STATSTG() istream.Stat(byref(sts), 0) stream_size = sts.cbSize istream.Seek(0, STREAM_SEEK_SET, None) buf = (BYTE * stream_size)() written = ULONG() istream.Read(byref(buf), stream_size, byref(written)) if written.value == stream_size: file.write(buf) else: print( f"Failed to read all of the data from stream attempting to save {file}" ) istream.Release() encoder.Release() frame.Release() property_bag.Release() wicstream.Release()