/**
   * Creates a scaled version of the image provided by the specified input stream. This method tries
   * to use thumbnails in the original image: If none fits, the full image is read and scaled.
   */
  public static BufferedImage createScaledImage(
      InputStream aInputStream, int aMaxSize, boolean aWithAlpha, Object aInterpolationQuality)
      throws IOException {
    ImageInputStream theImageInputStream = ImageIO.createImageInputStream(aInputStream);
    Iterator<ImageReader> theImageReaders = ImageIO.getImageReaders(theImageInputStream);

    ImageReader theReader;
    if (theImageReaders.hasNext()) theReader = theImageReaders.next();
    else return null;

    theReader.setInput(theImageInputStream);

    BufferedImage theOriginalImage = null;
    if (theReader.readerSupportsThumbnails()) {
      // Find the most suitable thumbnail, ie. the smallest that is bigger than requested size.
      int theThumbnailsCount = theReader.getNumThumbnails(0);
      int theFittest = -1; // Which is the fittest thumbnail?
      int theFittestScore = Integer.MAX_VALUE; // Score of the current fittest. Lower is better.

      for (int i = 0; i < theThumbnailsCount; i++) {
        int theW = theReader.getThumbnailWidth(0, i);
        int theH = theReader.getThumbnailHeight(0, i);

        int theScore;
        if (theW < aMaxSize & theH < aMaxSize) theScore = Integer.MAX_VALUE;
        else theScore = Math.max(theW, theH) - aMaxSize;

        if (theScore < theFittestScore) {
          theFittest = i;
          theFittestScore = theScore;
          if (theScore == 0) break; // Can't improve, so don't iterate any more.
        }
      }

      // Get the thumbnail
      if (theFittest >= 0) theOriginalImage = theReader.readThumbnail(0, theFittest);
    }

    // Fallback if no thumbnail is found
    if (theOriginalImage == null) theOriginalImage = theReader.read(0);

    return createScaledImage(theOriginalImage, aMaxSize, aWithAlpha, aInterpolationQuality);
  }