title: How to create & pass Python PNG images without saving them to a file
body: <p>Goal: Create images to be used in other parts of the program without creating disk files.</p>
  <p>I'm trying to add caption text to PNG plot images created with matplotlib.  There may be better ways to do this but my current approach is to create a PNG image of the text (with pillow) and merge that with the plot image.  So there are 3 distinct components to the task.  Two create the individual images and saves them as PNG files, and a third one merges them.  I'd like to eliminate the creation of the first two files by creating images that can be used by the merge code but haven't been able to determine the image type or image-open method to use.  Example code follows:</p>
  <pre><code>import matplotlib.pyplot as plt
  from PIL import Image, ImageDraw, ImageFont
  
  v = [106.0, 95.0, 125.0, 128.0, 100.0, 121.0, 97.0, 103.0, 104.0, 101.0]
  dt = range(len(v))
  cap_text = '     Number of tests: 10    Number of units: 8'
  size = 12
  color = 'white'
  fnt = ImageFont.truetype('arial.ttf', size)
      
  ############################################################################
  # Create the plot &amp; save as tmp1.png    
      
  plt.plot(dt, v, 'r-', label='Results')
  plt.ylabel('ms')
  plt.xlabel('Tests')
  plt.grid()
  plt.savefig('tmp1.png')
  plt.gcf().clear()
  
  ############################################################################
  # Create the caption text PNG image and save as tmp2.png
  
  image = Image.new(mode = &quot;RGB&quot;, size = (int(size/2)*len(cap_text),size+50), color = 'white')
  d = ImageDraw.Draw(image)
  d.text((12,12), cap_text, font=fnt, fill=(0,0,0))
  image.save('tmp2.png')
  
  ############################################################################
  # Merge the two PNG files, one above the other, to create the desired result
  
  imgs = [r'tmp1.png', r'tmp2.png']
  
  total_height = 0
  max_width = 0
  ix =[]
  for img in imgs:
      im = Image.open(img)
      size = im.size
      w = size[0]
      h = size[1]
      total_height += h 
      max_width = max(max_width, w)
      ix.append(im) 
  
  tmp3 = Image.new('RGB', (max_width, total_height), color='white')
  current_h = 0
  for img in ix:
      tmp3.paste(img, (0, current_h))
      current_h += img.size[1]
      
  tmp3.show()
  tmp3.save('tmp3.png', quality=100)
  </code></pre>
  <p>Which produces the following image (tmp3.png).</p>
  <p><a href="https://i.stack.imgur.com/D2Ftw.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/D2Ftw.png" alt="The plot chart with caption text below it." /></a></p>
  <p>I tried one more thing before submitting this and it appears to work.  Using BytesIO I created variables named buffer1 and buffer2 as shown in the 'save' calls for both the plot and PIL images; updated code follows (just the first half where the changes exist).  Look for the buffer variable names.</p>
  <pre><code>import matplotlib.pyplot as plt
  from PIL import Image, ImageDraw, ImageFont
  from io import BytesIO
  
  v = [106.0, 95.0, 125.0, 128.0, 100.0, 121.0, 97.0, 103.0, 104.0, 101.0]
  dt = range(len(v))
  cap_text = '     Number of tests: 10    Number of units: 8'
  size = 12
  color = 'white'
  fnt = ImageFont.truetype('arial.ttf', size)
      
  ############################################################################
  # Create the plot &amp; save as tmp1.png    
      
  plt.plot(dt, v, 'r-', label='Results')
  plt.ylabel('ms')
  plt.xlabel('Tests')
  plt.grid()
  buffer1 = BytesIO()
  plt.savefig(buffer1, format='png')
  plt.gcf().clear()
  
  ############################################################################
  # Create the caption text PNG image and save as tmp2.png
  
  image = Image.new(mode = &quot;RGB&quot;, size = (int(size/2)*len(cap_text),size+50), color = 'white')
  d = ImageDraw.Draw(image)
  d.text((12,12), cap_text, font=fnt, fill=(0,0,0))
  buffer2 = BytesIO()
  image.save(buffer2, format = 'png')
  
  ############################################################################
  # Merge the two PNG files, one above the other, to create the desired result
  
  imgs = [buffer1, buffer2]
  </code></pre>