Esempio n. 1
0
def test_pil_kwargs_png():
    Image = pytest.importorskip("PIL.Image")
    from PIL.PngImagePlugin import PngInfo
    buf = io.BytesIO()
    pnginfo = PngInfo()
    pnginfo.add_text("Software", "test")
    plt.figure().savefig(buf, format="png", pil_kwargs={"pnginfo": pnginfo})
    im = Image.open(buf)
    assert im.info["Software"] == "test"
Esempio n. 2
0
    def to_file(self, filename, *, palette=False):
        # assemble comment
        comment = self._assemble_comment()

        # assemble spritesheet
        W, H = self.width, self.height
        num_frames = sum(len(state.frames) for state in self.states)
        sqrt = math.ceil(math.sqrt(num_frames))
        output = Image.new('RGBA', (sqrt * W, math.ceil(num_frames / sqrt) * H))

        i = 0
        for state in self.states:
            for frame in state.frames:
                output.paste(frame, ((i % sqrt) * W, (i // sqrt) * H))
                i += 1

        # save
        pnginfo = PngInfo()
        pnginfo.add_text('Description', comment, zip=True)
        if palette:
            output = output.convert('P')
        output.save(filename, 'png', optimize=True, pnginfo=pnginfo)
Esempio n. 3
0
    def print_png(self, filename_or_obj, *args,
                  metadata=None, pil_kwargs=None,
                  **kwargs):
        """
        Write the figure to a PNG file.

        Parameters
        ----------
        filename_or_obj : str or PathLike or file-like object
            The file to write to.

        metadata : dict, optional
            Metadata in the PNG file as key-value pairs of bytes or latin-1
            encodable strings.
            According to the PNG specification, keys must be shorter than 79
            chars.

            The `PNG specification`_ defines some common keywords that may be
            used as appropriate:

            - Title: Short (one line) title or caption for image.
            - Author: Name of image's creator.
            - Description: Description of image (possibly long).
            - Copyright: Copyright notice.
            - Creation Time: Time of original image creation
              (usually RFC 1123 format).
            - Software: Software used to create the image.
            - Disclaimer: Legal disclaimer.
            - Warning: Warning of nature of content.
            - Source: Device used to create the image.
            - Comment: Miscellaneous comment;
              conversion from other image format.

            Other keywords may be invented for other purposes.

            If 'Software' is not given, an autogenerated value for matplotlib
            will be used.

            For more details see the `PNG specification`_.

            .. _PNG specification: \
                https://www.w3.org/TR/2003/REC-PNG-20031110/#11keywords

        pil_kwargs : dict, optional
            If set to a non-None value, use Pillow to save the figure instead
            of Matplotlib's builtin PNG support, and pass these keyword
            arguments to `PIL.Image.save`.

            If the 'pnginfo' key is present, it completely overrides
            *metadata*, including the default 'Software' key.
        """
        from matplotlib import _png

        if metadata is None:
            metadata = {}
        metadata = {
            "Software":
                f"matplotlib version{__version__}, http://matplotlib.org/",
            **metadata,
        }

        if pil_kwargs is not None:
            from PIL import Image
            from PIL.PngImagePlugin import PngInfo
            buf, size = self.print_to_buffer()
            # Only use the metadata kwarg if pnginfo is not set, because the
            # semantics of duplicate keys in pnginfo is unclear.
            if "pnginfo" not in pil_kwargs:
                pnginfo = PngInfo()
                for k, v in metadata.items():
                    pnginfo.add_text(k, v)
                pil_kwargs["pnginfo"] = pnginfo
            pil_kwargs.setdefault("dpi", (self.figure.dpi, self.figure.dpi))
            (Image.frombuffer("RGBA", size, buf, "raw", "RGBA", 0, 1)
             .save(filename_or_obj, format="png", **pil_kwargs))

        else:
            FigureCanvasAgg.draw(self)
            renderer = self.get_renderer()
            with cbook._setattr_cm(renderer, dpi=self.figure.dpi), \
                    cbook.open_file_cm(filename_or_obj, "wb") as fh:
                _png.write_png(renderer._renderer, fh,
                               self.figure.dpi, metadata=metadata)
	def generateComics( self, instance ):
		image = Image.new( mode="1", size=(0, 0) )
		for self.generatedComicNumber in range( self.numberOfComics ):
			try:
				if self.commandLineComicID is None:
					wordBubbleFileName = random.choice( os.listdir( self.wordBubblesDir ) )
				else:
					wordBubbleFileName = os.path.join( self.wordBubblesDir, self.commandLineComicID + ".tsv" )
			except IndexError as error:
				six.print_( error, file=sys.stderr )
				exit( EX_NOINPUT )
			
			if not self.silence:
				six.print_( "wordBubbleFileName:", wordBubbleFileName )
			
			if self.commandLineComicID is None:
				comicID = os.path.splitext( wordBubbleFileName )[ 0 ]
			else:
				comicID = self.commandLineComicID
			wordBubbleFileName = os.path.join( self.wordBubblesDir, wordBubbleFileName )
			if not self.silence:
				six.print_( "Loading word bubbles from", wordBubbleFileName )

			try:
				wordBubbleFile = open( wordBubbleFileName, mode="rt" )
			except OSError as error:
				six.print_( error, file=sys.stderr )
				exit( EX_NOINPUT )
			
			if not idChecker.checkFile( wordBubbleFile, wordBubbleFileName, self.commentMark ):
				six.print_( "Error: Word bubble file", wordBubbleFileName, "is not in the correct format." )
				exit( EX_DATAERR )
			
			lookForSpeakers = True
			speakers = []
			while lookForSpeakers:
				line = wordBubbleFile.readline()
				if len( line ) > 0:
					line = line.partition( self.commentMark )[0].strip()
					if len( line ) > 0:
						speakers = line.upper().split( "\t" )
						if len( speakers ) > 0:
							lookForSpeakers = False
				else:
					lookForSpeakers = False; #End of file reached, no speakers found
			
			if len( speakers ) == 0:
				six.print_( "Error: Word bubble file", wordBubbleFileName, "contains no speakers." )
				exit( EX_DATAERR )
			
			if not self.silence:
				six.print_( "These characters speak:", speakers )
			
			for speaker in speakers:
				if speaker not in self.generators:
					if not self.silence:
						six.print_( "Now building a Markov graph for character", speaker, "..." )
					newGenerator = Generator( charLabel = speaker, cm = self.commentMark, randomizeCapitals = self.randomizeCapitals )
					newGenerator.buildGraph( self.inDir )
					
					if not self.silence:
						newGenerator.showStats()
					
					self.generators[ speaker ] = newGenerator
			
			if not self.silence:
				six.print_( comicID )
			
			inImageFileName = os.path.join( self.imageDir, comicID + ".png" )
			
			try:
				image = Image.open( inImageFileName ).convert() #Text rendering looks better if we ensure the image's mode is not palette-based. Calling convert() with no mode argument does this.
			except IOError as error:
				six.print_( error, file=sys.stderr )
				exit( EX_NOINPUT )
			
			transcript = str( comicID ) + "\n"
			
			previousBox = ( int( -1 ), int( -1 ), int( -1 ), int( -1 ) ) #For detecting when two characters share a speech bubble; don't generate text twice.
			
			for line in wordBubbleFile:
				line = line.partition( self.commentMark )[ 0 ].strip()
				
				if len( line ) > 0:
					line = line.split( "\t" )
					character = line[ 0 ].rstrip( ":" ).strip().upper()
					
					try:
						generator = self.generators[ character ]
					except:
						six.print_( "Error: Word bubble file", wordBubbleFileName, "does not list", character, "in its list of speakers.", file=sys.stderr )
						exit( EX_DATAERR )
					
					topLeftX = int( line[ 1 ] )
					topLeftY = int( line[ 2 ] )
					bottomRightX = int( line[ 3 ] )
					bottomRightY = int( line[ 4 ] )
					
					box = ( topLeftX, topLeftY, bottomRightX, bottomRightY )
					
					if box != previousBox:
						previousBox = box
						
						text = ""
						nodeList = generator.generateSentences( 1 )[ 0 ]
						for node in nodeList:
							text += node.word + " "
						text.rstrip()
						
						oneCharacterTranscript = character + ": "
						oneCharacterTranscript += self.stringFromNodes( nodeList )
						if not self.silence:
							six.print_( oneCharacterTranscript )
						oneCharacterTranscript += "\n"
						transcript += oneCharacterTranscript
						
						wordBubble = image.crop( box )
						draw = ImageDraw.Draw( wordBubble )
						
						width = bottomRightX - topLeftX
						if width <= 0: #Width must be positive
							width = 1
						height = bottomRightY - topLeftY
						if height <= 0:
							height = 1
						
						size = int( height * 1.2 ) #Contrary to the claim by PIL's documentation, font sizes are apparently in pixels, not points. The size being requested is the height of a generic character; the actual height of any particular character will be approximately (not exactly) the requested size. We will try smaller and smaller sizes in the while loop below. The 1.2, used to account for the fact that real character sizes aren't exactly the same as the requested size, I just guessed an appropriate value.
						
						normalFont = ImageFont.truetype( self.normalFontFile, size = size )
						boldFont = ImageFont.truetype( self.boldFontFile, size = size )
						
						listoflists = self.rewrap_nodelistlist( nodeList, normalFont, boldFont, width, fontSize = size )
						
						margin = 0
						offset = originalOffset = 0
						goodSizeFound = False
						
						while not goodSizeFound:
							goodSizeFound = True
							totalHeight = 0
							for line in listoflists:
								
								lineWidth = 0
								lineHeight = 0
								for node in line:
									wordSize = normalFont.getsize( node.word + " " )
									lineWidth += wordSize[ 0 ]
									lineHeight = max( lineHeight, wordSize[ 1 ] )
								lineWidth -= normalFont.getsize( " " )[ 0 ]
								totalHeight += lineHeight
								if lineWidth > width:
									goodSizeFound = False
							
							if totalHeight > height:
								goodSizeFound = False
							
							if not goodSizeFound:
								size -= 1
								try:
									normalFont = ImageFont.truetype( self.normalFontFile, size = size )
									boldFont = ImageFont.truetype( self.boldFontFile, size = size )
								except IOError as error:
									six.print_( error, "\nUsing default font instead.", file=sys.stderr )
									normalFont = ImageFont.load_default()
									boldFont = ImageFont.load_default()
								listoflists = self.rewrap_nodelistlist( nodeList, normalFont, boldFont, width, fontSize = size )
						
						midX = int( wordBubble.size[ 0 ] / 2 )
						midY = int( wordBubble.size[ 1 ] / 2 )
						
						try: #Choose a text color that will be visible against the background
							backgroundColor = ImageStat.Stat( wordBubble ).mean #wordBubble.getpixel( ( midX, midY ) )
							textColorList = []
							
							useIntegers = False
							useFloats = False
							if wordBubble.mode.startswith( "1" ):
								bandMax = 1
								useIntegers = True
							elif wordBubble.mode.startswith( "L" ) or wordBubble.mode.startswith( "P" ) or wordBubble.mode.startswith( "RGB" ) or wordBubble.mode.startswith( "CMYK" ) or wordBubble.mode.startswith( "YCbCr" ) or wordBubble.mode.startswith( "LAB" ) or wordBubble.mode.startswith( "HSV" ):
								bandMax = 255
								useIntegers = True
							elif wordBubble.mode.startswith( "I" ):
								bandMax = 2147483647 #max for a 32-bit signed integer
								useIntegers = True
							elif wordBubble.mode.startswith( "F" ):
								bandMax = float( "infinity" )
								useFloats = True
							else: #I've added all modes currently supported according to Pillow documentation; this is for future compatibility
								bandMax = max( ImageStat.Stat( image ).extrema )
							
							for c in backgroundColor:
								d = bandMax - ( c * 1.5 )
								
								if d < 0:
									d = 0
								
								if useIntegers:
									d = int( d )
								elif useFloats:
									d = float( d )
								
								textColorList.append( d )
							
							if wordBubble.mode.endswith( "A" ): #Pillow supports two modes with alpha channels
								textColorList[ -1 ] = bandMax
							
							textColor = tuple( textColorList )
							
						except ValueError:
							textColor = "black"
						
						offset = originalOffset
						for line in listoflists:
							xOffset = 0
							yOffsetAdditional = 0
							for node in line:
								usedFont = node.font
								draw.text( ( margin + xOffset, offset ), node.word + " ", font = usedFont, fill = textColor )
								tempSize = usedFont.getsize( node.word + " " )
								xOffset += tempSize[ 0 ]
								yOffsetAdditional = max( yOffsetAdditional, tempSize[ 1 ] )
								node.unselectStyle()
							offset += yOffsetAdditional
						
						image.paste( wordBubble, box )
						
			wordBubbleFile.close()
			
			if self.numberOfComics > 1:
				oldOutTextFileName = self.outTextFileName
				temp = os.path.splitext(self.outTextFileName )
				self.outTextFileName = temp[ 0 ] + str( self.generatedComicNumber ) + temp[ 1 ]
			
			#---------------------------Split into separate function
			try:
				#os.makedirs( os.path.dirname( outTextFileName ), exist_ok = True )
				outFile = open( self.outTextFileName, mode="wt" )
			except OSError as error:
				six.print_( error, "\nUsing standard output instead", file=sys.stderr )
				outFile = sys.stdout
			
			if self.numberOfComics > 1:
				self.outTextFileName = oldOutTextFileName
			
			six.print_( transcript, file=outFile )
			
			outFile.close()
			
			if self.numberOfComics > 1:
				oldOutImageFileName = self.outImageFileName
				temp = os.path.splitext( self.outImageFileName )
				outImageFileName = temp[ 0 ] + str( self.generatedComicNumber ) + temp[ 1 ]
			
			if self.topImageFileName != None:
				try:
					topImage = Image.open( self.topImageFileName ).convert( mode=image.mode )
				except IOError as error:
					six.print_( error, file=sys.stderr )
					exit( EX_NOINPUT )
				oldSize = topImage.size
				size = ( max( topImage.size[ 0 ], image.size[ 0 ] ), topImage.size[ 1 ] + image.size[ 1 ] )
				
				newImage = Image.new( mode=image.mode, size=size )
				newImage.paste( im=topImage, box=( 0, 0 ) )
				newImage.paste( im=image, box=( 0, oldSize[ 1 ] ) )
				image = newImage
			
			
			
			originalURL = None
			URLFile = open( os.path.join( self.inDir, "sources.tsv" ), "rt" )
			for line in URLFile:
				line = line.partition( self.commentMark )[ 0 ].strip()
				
				if len( line ) > 0:
					line = line.split( "\t" )
					
					if comicID == line[ 0 ]:
						originalURL = line[ 1 ]
						break;
			URLFile.close()
			
			transcriptWithURL = transcript + "\n" + originalURL #The transcript that gets embedded into the image file should include the URL. The transcript that gets uploaded to blogs doesn't need it, as the URL gets sent anyway.
			
			infoToSave = PngInfo()
			
			encodingErrors = "backslashreplace" #If we encounter errors during text encoding, I feel it best to replace unencodable text with escape sequences; that way it may be possible for reader programs to recover the original unencodable text.
			
			#According to the Pillow documentation, key names should be "latin-1 encodable". I take this to mean that we ourselves don't need to encode it in latin-1.
			key = "transcript"
			keyUTF8 = key.encode( "utf-8", errors=encodingErrors )
			
			#uncomment the following if using Python 3
			#transcriptISO = transcriptWithURL.encode( "iso-8859-1", errors=encodingErrors )
			#transcriptUTF8 = transcriptWithURL.encode( "utf-8", errors=encodingErrors )
			
			#python 2:
			tempencode = transcriptWithURL.decode( 'ascii', errors='replace' ) # I really don't like using this ascii-encoded intermediary called tempencode, but i couldn't get the program to work when encoding directly to latin-1
			transcriptISO = tempencode.encode( "iso-8859-1", errors='replace' )
			transcriptUTF8 = tempencode.encode( "utf-8", errors='replace' )
			
			
			infoToSave.add_itxt( key=key, value=transcriptUTF8, tkey=keyUTF8 )
			infoToSave.add_text( key=key, value=transcriptISO )
			
			#GIMP only recognizes comments
			key = "Comment"
			keyUTF8 = key.encode( "utf-8", errors=encodingErrors )
			
			infoToSave.add_text( key=key, value=transcriptISO )
			infoToSave.add_itxt( key=key, value=transcriptUTF8, tkey=keyUTF8 )
			
			try:
				#os.makedirs( os.path.dirname( outImageFileName ), exist_ok = True )
				if self.saveForWeb:
					image = image.convert( mode = "P", palette="ADAPTIVE", dither=False ) #Try turning dithering on or off.
					image.save( self.outImageFileName, format="PNG", optimize=True, pnginfo=infoToSave )
				else:
					image.save( self.outImageFileName, format="PNG", pnginfo=infoToSave )
			except IOError as error:
				six.print_( error, file = sys.stderr )
				exit( EX_CANTCREAT )
			except OSError as error:
				six.print_( error, file = sys.stderr )
				exit( EX_CANTCREAT )
			
			if not self.silence:
				six.print_( "Original comic URL:", originalURL )
			
			for blog in self.blogUploaders:
				blog.upload( postStatus = "publish", inputFileName = outImageFileName, shortComicTitle = self.shortName, longComicTitle = self.longName, transcript = transcript, originalURL = originalURL, silence = self.silence )
			
			if self.numberOfComics > 1:
				outImageFileName = oldOutImageFileName
		#end of loop: for generatedComicNumber in range( numberOfComics ):
		
		#---------------------------It's display time!
		if image.mode != "RGB":
			image = image.convert( mode = "RGB" )
		self.gui.comicArea.texture = Texture.create( size = image.size, colorfmt = 'rgb' )
		self.gui.comicArea.texture.blit_buffer( pbuffer = image.transpose( Image.FLIP_TOP_BOTTOM ).tobytes(), colorfmt = 'rgb' )
Esempio n. 5
0
import sys
from PIL import Image
from PIL.PngImagePlugin import PngInfo

png = Image.open('original.png')
pixels = png.load()

new_pixels = []
with open(sys.argv[1], "r") as kg:
    new_pixels = kg.read()

print "setting %d new pixels" % len(new_pixels)

k = 0

for i in range(png.size[0]):    # for every pixel:
    if k >= len(new_pixels):
        break
    for j in range(png.size[1]):
        r, g, b = list(pixels[i, j])
        b = new_pixels[k]  # change the blue pixel ;)
        pixels[i, j] = r, g, ord(b)
        k += 1
        if k >= len(new_pixels):
            break

info = PngInfo()
info.add_text("flag", "not here ...but john loves that song ;)")
png.save('Ub7XL8T.png', 'PNG', compress_level=9, pnginfo=info)
Esempio n. 6
0
def add_to_pnginfo(image_filename="", data_name="", data_dict={}):
    targetImage = PngImageFile(image_filename)
    metadata = PngInfo()
    metadata.add_text(data_name, json.dumps(data_dict))
    targetImage.save(image_filename, pnginfo=metadata)
Esempio n. 7
0
def insert_instrument_settings(filename="", instrument_dict=[]):
    isimage = False
    if (filename.endswith('PNG') or filename.endswith('png')):
        targetImage = PngImageFile(filename)
        metadata = PngInfo()
        isimage = True
    else:
        outfile = open(filename, 'w')
        settings_dict = {}

    rm = pyvisa.ResourceManager()

    for key in instrument_dict:
        if (key.startswith("HAMEG,HMP4040")):
            hmp4040 = hmp4040_power_supply(
                pyvisa_instr=rm.open_resource(instrument_dict[key]))
            hmp4040_unique_scpi = hmp4040.get_unique_scpi_list()
            if (isimage):
                metadata.add_text("hmp4040_unique_scpi",
                                  json.dumps(hmp4040_unique_scpi))
            else:
                settings_dict['hmp4040_unique_scpi'] = hmp4040_unique_scpi
        if (key.startswith("KEITHLEY INSTRUMENTS INC.,MODEL 2308")):
            k2308 = keithley_2308(
                pyvisa_instr=rm.open_resource(instrument_dict[key]))
            k2308_unique_scpi = k2308.get_unique_scpi_list()
            if (isimage):
                metadata.add_text("k2308_unique_scpi",
                                  json.dumps(k2803_unique_scpi))
            else:
                settings_dict['k2308_unique_scpi'] = k2308_unique_scpi
        if (key.startswith("KEITHLEY INSTRUMENTS INC.,MODEL 2460")):
            k2460 = keithley_2460(
                pyvisa_instr=rm.open_resource(instrument_dict[key]))
            k2460_unique_scpi = k2460.get_unique_scpi_list()
            if (isimage):
                metadata.add_text("k2460_unique_scpi",
                                  json.dumps(k2460_unique_scpi))
            else:
                settings_dict['k2460_unique_scpi'] = k2460_unique_scpi
        if (key.startswith("TEKTRONIX,AFG3102")):
            tek_afg3000 = tektronics_afg3000(
                pyvisa_instr=rm.open_resource(instrument_dict[key]))
            tek_afg3000_unique_scpi = tek_afg3000.get_unique_scpi_list()
            if (isimage):
                metadata.add_text("tek_afg3000_unique_scpi",
                                  json.dumps(tek_afg3000_unique_scpi))
            else:
                settings_dict[
                    'tek_afg3000_unique_scpi'] = tek_afg3000_unique_scpi
        if (key.startswith("KIKUSUI,PLZ164WA,")):
            plz4w = kikusui_plz4w(
                pyvisa_instr=rm.open_resource(instrument_dict[key]))
            plz4w_unique_scpi = plz4w.get_unique_scpi_list()
            if (isimage):
                metadata.add_text("plzw4_unique_scpi",
                                  json.dumps(plz4w_unique_scpi))
            else:
                settings_dict['plz4w_unique_scpi'] = plz4w_unique_scpi
        if (key.startswith("Agilent Technologies,33250A")):
            key_33250a = keysight_33250a(
                pyvisa_instr=rm.open_resource(instrument_dict[key]))
            key_33250a_unique_scpi = key_33250a.get_unique_scpi_list()
            if (isimage):
                metadata.add_text("key_33250a_unique_scpi",
                                  json.dumps(key_33250a_unique_scpi))
            else:
                settings_dict[
                    'key_33250a_unique_scpi'] = key_33250a_unique_scpi
        targetImage.save(filename, pnginfo=metadata)
    if (not isimage):
        json.dump(settings_dict, outfile)
Esempio n. 8
0
    def print_png(self,
                  filename_or_obj,
                  *args,
                  metadata=None,
                  pil_kwargs=None,
                  **kwargs):
        """
        Write the figure to a PNG file.

        Parameters
        ----------
        filename_or_obj : str or PathLike or file-like object
            The file to write to.

        metadata : dict, optional
            Metadata in the PNG file as key-value pairs of bytes or latin-1
            encodable strings.
            According to the PNG specification, keys must be shorter than 79
            chars.

            The `PNG specification`_ defines some common keywords that may be
            used as appropriate:

            - Title: Short (one line) title or caption for image.
            - Author: Name of image's creator.
            - Description: Description of image (possibly long).
            - Copyright: Copyright notice.
            - Creation Time: Time of original image creation
              (usually RFC 1123 format).
            - Software: Software used to create the image.
            - Disclaimer: Legal disclaimer.
            - Warning: Warning of nature of content.
            - Source: Device used to create the image.
            - Comment: Miscellaneous comment;
              conversion from other image format.

            Other keywords may be invented for other purposes.

            If 'Software' is not given, an autogenerated value for matplotlib
            will be used.

            For more details see the `PNG specification`_.

            .. _PNG specification: \
                https://www.w3.org/TR/2003/REC-PNG-20031110/#11keywords

        pil_kwargs : dict, optional
            Keyword arguments passed to `PIL.Image.Image.save`.

            If the 'pnginfo' key is present, it completely overrides
            *metadata*, including the default 'Software' key.
        """

        if metadata is None:
            metadata = {}
        if pil_kwargs is None:
            pil_kwargs = {}
        metadata = {
            "Software":
            f"matplotlib version{mpl.__version__}, http://matplotlib.org/",
            **metadata,
        }
        FigureCanvasAgg.draw(self)
        # Only use the metadata kwarg if pnginfo is not set, because the
        # semantics of duplicate keys in pnginfo is unclear.
        if "pnginfo" not in pil_kwargs:
            pnginfo = PngInfo()
            for k, v in metadata.items():
                pnginfo.add_text(k, v)
            pil_kwargs["pnginfo"] = pnginfo
        pil_kwargs.setdefault("dpi", (self.figure.dpi, self.figure.dpi))
        (Image.fromarray(np.asarray(self.buffer_rgba())).save(filename_or_obj,
                                                              format="png",
                                                              **pil_kwargs))
Esempio n. 9
0
    def main(self):
        message_broker_host = local.env.get("MESSAGE_BROKER_HOST")
        message_broker_exchange_name = local.env.get(
            "MESSAGE_BROKER_EXCHANGE_NAME", "observed_cam_events")
        rtsp_endpoint = local.env.get("RTSP_ENDPOINT")
        yolo_host = local.env.get("YOLO_HOST")
        yolo_port = local.env.get("YOLO_PORT", 8080)

        # If specified, will save a png of the capture for any detection,
        # with the detections included, json encoded as png metadata.
        image_save_path = local.env.get("IMAGE_SAVE_PATH")
        if image_save_path:
            image_save_path = local.path(image_save_path)
            image_save_path.mkdir()
        threshold = local.env.get("THRESHOLD", "0.25")

        # Include image specifies whether to include a cropped image in the message for a detection
        include_image = local.env.get("INCLUDE_IMAGE")
        if include_image in FALSEY_VALUES:
            include_image = False

        yolo_endpoint = f"http://{yolo_host}:{yolo_port}/detect"

        with broker.MessageBrokerConnection(message_broker_host) as con:
            con.channel.exchange_declare(exchange=message_broker_exchange_name,
                                         exchange_type="fanout")

            cam = Camera(rtsp_endpoint)
            try:
                logging.info("Capturing frames")
                while True:
                    frame = cam.getFrame()
                    dt = datetime.datetime.now(datetime.timezone.utc)
                    if frame is None:
                        # No new frame, sleeping
                        time.sleep(0.1)
                        continue

                    with cam.lock:
                        enc_success, encoded = cv2.imencode(".png", frame)

                    if not enc_success:
                        logging.error("Failed to encode frame")
                        continue

                    response = requests.post(
                        yolo_endpoint,
                        files={"image_file": encoded},
                        data={"threshold": threshold},
                    )

                    try:
                        decoded_response = json.loads(response.text)
                    except Exception as e:
                        logging.exception(
                            f"Failed to parse response response {response.text}"
                        )
                        continue

                    formatted_detections_no_image = []
                    for detection in decoded_response:
                        logging.info(f"got detection: {detection}")
                        body = {
                            "stream": rtsp_endpoint,
                            "time": dt.isoformat(),
                            "detection": detection,
                        }

                        formatted_detections_no_image.append(body.copy())

                        if include_image:
                            xcenter, ycenter, width, height = detection[2]
                            w2 = width / 2
                            h2 = height / 2
                            subframe = frame[max(int(ycenter -
                                                     h2), 0):int(ycenter + h2),
                                             max(int(xcenter -
                                                     w2), 0):int(xcenter +
                                                                 w2), ]

                            enc_success, subframe_encoded = cv2.imencode(
                                ".png", subframe)

                            body["image"] = base64.b64encode(
                                subframe_encoded).decode("ascii")

                        con.channel.basic_publish(
                            exchange=message_broker_exchange_name,
                            routing_key="",
                            body=json.dumps(body),
                        )

                    # Save image to disk with detection metadata if asked for and we had detections
                    if image_save_path and formatted_detections_no_image:
                        pif = PngImageFile(io.BytesIO(encoded))

                        metadata = PngInfo()
                        metadata.add_text(
                            "detections",
                            json.dumps(formatted_detections_no_image))

                        target_folder_name = make_safe_for_filename(
                            rtsp_endpoint)
                        folder = (image_save_path / target_folder_name /
                                  str(dt.year) / str(dt.month) / str(dt.day))
                        folder.mkdir()

                        pif.save(
                            folder /
                            f"{dt.hour}-{dt.minute}-{dt.second}-{dt.microsecond}.png",
                            pnginfo=metadata,
                        )

                    time.sleep(0.5)
            finally:
                cam.close()
Esempio n. 10
0
    def print_png(self,
                  filename_or_obj,
                  *args,
                  metadata=None,
                  pil_kwargs=None,
                  **kwargs):
        """
        Write the figure to a PNG file.

        Parameters
        ----------
        filename_or_obj : str or PathLike or file-like object
            The file to write to.

        metadata : dict, optional
            Metadata in the PNG file as key-value pairs of bytes or latin-1
            encodable strings.
            According to the PNG specification, keys must be shorter than 79
            chars.

            The `PNG specification`_ defines some common keywords that may be
            used as appropriate:

            - Title: Short (one line) title or caption for image.
            - Author: Name of image's creator.
            - Description: Description of image (possibly long).
            - Copyright: Copyright notice.
            - Creation Time: Time of original image creation
              (usually RFC 1123 format).
            - Software: Software used to create the image.
            - Disclaimer: Legal disclaimer.
            - Warning: Warning of nature of content.
            - Source: Device used to create the image.
            - Comment: Miscellaneous comment;
              conversion from other image format.

            Other keywords may be invented for other purposes.

            If 'Software' is not given, an autogenerated value for matplotlib
            will be used.

            For more details see the `PNG specification`_.

            .. _PNG specification: \
                https://www.w3.org/TR/2003/REC-PNG-20031110/#11keywords

        pil_kwargs : dict, optional
            If set to a non-None value, use Pillow to save the figure instead
            of Matplotlib's builtin PNG support, and pass these keyword
            arguments to `PIL.Image.save`.

            If the 'pnginfo' key is present, it completely overrides
            *metadata*, including the default 'Software' key.
        """

        if metadata is None:
            metadata = {}
        metadata = {
            "Software":
            f"matplotlib version{__version__}, http://matplotlib.org/",
            **metadata,
        }

        if pil_kwargs is not None:
            from PIL import Image
            from PIL.PngImagePlugin import PngInfo
            buf, size = self.print_to_buffer()
            # Only use the metadata kwarg if pnginfo is not set, because the
            # semantics of duplicate keys in pnginfo is unclear.
            if "pnginfo" not in pil_kwargs:
                pnginfo = PngInfo()
                for k, v in metadata.items():
                    pnginfo.add_text(k, v)
                pil_kwargs["pnginfo"] = pnginfo
            pil_kwargs.setdefault("dpi", (self.figure.dpi, self.figure.dpi))
            (Image.frombuffer("RGBA", size, buf, "raw", "RGBA", 0,
                              1).save(filename_or_obj,
                                      format="png",
                                      **pil_kwargs))

        else:
            FigureCanvasAgg.draw(self)
            renderer = self.get_renderer()
            with cbook._setattr_cm(renderer, dpi=self.figure.dpi), \
                    cbook.open_file_cm(filename_or_obj, "wb") as fh:
                _png.write_png(renderer._renderer,
                               fh,
                               self.figure.dpi,
                               metadata=metadata)
Esempio n. 11
0
# buffered = io.BytesIO()
# targetImage = PngImageFile("embed-test.png")

# metadata = PngInfo()
# metadata.add_text("MyNewString", "A string")
# metadata.add_text("MyNewInt", str(1234))

# targetImage.save(, pnginfo=metadata)
# imgdata = pybase64.b64decode(buffered.getvalue())
# hostImage = PngImageFile(imgdata)

# # targetImage = PngImageFile("NewPath.png")

# print(hostImage.text)
from PIL.PngImagePlugin import PngImageFile, PngInfo
import json

targetImage = PngImageFile("embed-test.png")

metadata = PngInfo()
metadata.add_text("MyNewString", "A string")
metadata.add_text("MyNewInt", str(1234))

targetImage.save("NewPath.png", pnginfo=metadata)
targetImage = PngImageFile("NewPath.png")
targetImageSize = targetImage.size
print('targetImage', targetImage, 'targetImageSize', targetImageSize)
a = {'name': 'wang', 'age': 29}
print('nameExist', 'name' in a)
b = json.dumps(a)
print('b', b)
Esempio n. 12
0
def load_skin(uuid, conf):
    file = os.path.join(conf["output_dir"], "static", "markers", uuid + ".png")
    if not os.path.isfile(file) or time.time() - os.path.getmtime(file) >= 86400:
        r = requests.get('https://sessionserver.mojang.com/session/minecraft/profile/' + uuid)
        if r.status_code == requests.codes.ok:
            data = r.json()
            data = data["properties"][0]["value"]
            data = json5.loads(base64.b64decode(data))
            if "SKIN" in data["textures"]:
                # do not download and create the icon again if the skin stayed the same
                if os.path.isfile(file):
                    old_img = Image.open(file)
                    if old_img.info.get("SKIN", "") == data["textures"]["SKIN"]["url"]:
                        return None
                ri = requests.get(data["textures"]["SKIN"]["url"])
                if ri.status_code == requests.codes.ok:
                    img = Image.open(BytesIO(ri.content))
                    width, height = img.size
                    skin = Image.new('RGBA', (16, 32), (0, 0, 0, 0))
                    big = 0 if "metadata" in data["textures"]["SKIN"] else 1
                    # inverted to paste the arm with spacing
                    small = 1 if "metadata" in data["textures"]["SKIN"] else 0
                    # New Texture Format
                    if height == 64:
                        head = img.crop((8, 8, 16, 16))
                        head_o = img.crop((40, 8, 48, 16))
                        legr = img.crop((4, 20, 8, 32))
                        legr_o = img.crop((4, 36, 8, 48))
                        body = img.crop((20, 20, 28, 32))
                        body_o = img.crop((20, 36, 28, 48))
                        armr = img.crop((44, 20, 47+big, 32))
                        armr_o = img.crop((44, 36, 47+big, 48))
                        legl = img.crop((20, 52, 24, 64))
                        legl_o = img.crop((4, 52, 8, 64))
                        arml = img.crop((36, 52, 39+big, 64))
                        arml_o = img.crop((52, 52, 55+big, 64))

                        skin.paste(head, (4, 0, 12, 8))
                        skin.paste(head_o, (4, 0, 12, 8), head_o)

                        skin.paste(legr, (4, 20, 8, 32))
                        skin.paste(legr_o, (4, 20, 8, 32), legr_o)

                        skin.paste(body, (4, 8, 12, 20))
                        skin.paste(body_o, (4, 8, 12, 20), body_o)

                        skin.paste(armr, (0+small, 8, 4, 20))
                        skin.paste(armr_o, (0+small, 8, 4, 20), armr_o)

                        skin.paste(legl, (8, 20, 12, 32))
                        skin.paste(legl_o, (8, 20, 12, 32), legl_o)

                        skin.paste(arml, (12, 8, 15+big, 20))
                        skin.paste(arml_o, (12, 8, 15+big, 20), arml_o)

                    elif height == 32:
                        head = img.crop((8, 8, 16, 16))
                        head_o = img.crop((40, 8, 48, 16))
                        body = img.crop((20, 20, 28, 32))
                        legr = img.crop((4, 20, 8, 32))
                        armr = img.crop((44, 20, 48, 32))
                        legl = ImageOps.mirror(legr)
                        arml = ImageOps.mirror(armr)

                        skin.paste(head, (4, 0, 12, 8))
                        skin.paste(head_o, (4, 0, 12, 8), head_o)

                        skin.paste(legr, (4, 20, 8, 32))
                        skin.paste(body, (4, 8, 12, 20))
                        skin.paste(armr, (0, 8, 4, 20))
                        skin.paste(legl, (8, 20, 12, 32))
                        skin.paste(arml, (12, 8, 16, 20))
                    metadata = PngInfo()
                    metadata.add_text("SKIN", data["textures"]["SKIN"]["url"])
                    skin.save(file, pnginfo=metadata)
                    return None
        if os.path.isfile(file):
            return None
        if is_alex(uuid):
            copyfile(os.path.join(sys.path[0], "alex.png"), file)
        else:
            copyfile(os.path.join(sys.path[0], "steve.png"), file)
        return None
    return None