Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
394 views
in Technique[技术] by (71.8m points)

java - Using Selenium Webdriver TakesScreenshot method to capture a base64 image. Can I reduce the image size?

I am using Selenium's TakesScreenshot method getting a base64 string into my HTML report. The screenshot produced in the report (extentreports) is a little too big, and is partially pushed offscreen. Shrinking it would also reduce the report's file size.

Can I take a smaller base64 screenshot? Shrinking it by about 20% would be perfect... Or would I have to create the image as a File first, then shrink it, then convert to base64.

 public static String CaptureScreen(WebDriver driver) {
    TakesScreenshot newScreen = (TakesScreenshot) driver;
    String scnShot = newScreen.getScreenshotAs(OutputType.BASE64);
    return "data:image/jpg;base64, " + scnShot ;
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

If you want to take a smaller screenshot file. You should be reduced image quality or write file with a fixed dimension (height x width). Let check my solution hope this help:

LIB:

<!-- SELENIUM LIBs and Image Process LIBs -->
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-firefox-driver</artifactId>
        <version>2.41.0</version>
    </dependency>
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-java</artifactId>
        <version>2.41.0</version>
    </dependency>
    <dependency>
        <groupId>xml-apis</groupId>
        <artifactId>xml-apis</artifactId>
        <version>1.4.01</version>
    </dependency>
    <dependency>
        <groupId>com.sun.media</groupId>
        <artifactId>jai_codec</artifactId>
        <version>1.1.3</version>
    </dependency>
    <dependency>
        <groupId>javax.media</groupId>
        <artifactId>jai_core</artifactId>
        <version>1.1.3</version>
    </dependency>
  1. Solution: First using reduce image quality, I defined

    • maximum image size is: ex: 1048576

    Take a screenshot to a file (you choose is a base64 is up to you)

    
    
    import java.awt.Color;
    import java.awt.Graphics2D;
    import java.awt.RenderingHints;
    import java.awt.image.BufferedImage;
    import java.awt.image.ColorModel;
    import java.awt.image.ImageObserver;
    import java.awt.image.RenderedImage;
    import java.awt.image.WritableRaster;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.Hashtable;
    import java.util.Iterator;
    import javax.imageio.IIOImage;
    import javax.imageio.ImageIO;
    import javax.imageio.ImageWriteParam;
    import javax.imageio.ImageWriter;
    import javax.imageio.stream.FileImageOutputStream;
    
    /**
    
    
    @author daviddoan
    *
    */
    public class ScreenShotUtils implements ImageObserver {
    
    private static final Color BKGROUND_COLOR = Color.WHITE;
    private boolean imageLoaded = false;
    
    private static BufferedImage matrixTransparentPixels(BufferedImage originalBufferedImage, Color fillColor) {
    int w = originalBufferedImage.getWidth();
    int h = originalBufferedImage.getHeight();
    BufferedImage newGeneratedBufferedImage;
    if (originalBufferedImage.getType() == BufferedImage.TYPE_4BYTE_ABGR) {
      newGeneratedBufferedImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
    } else {
      newGeneratedBufferedImage = new BufferedImage(w, h, originalBufferedImage.getType());
    }
    // clone the original image
    Graphics2D graphics2D = null;
    try {
      graphics2D = newGeneratedBufferedImage.createGraphics();
      graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
      graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
      graphics2D.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
      final boolean isDrawingSuccess = graphics2D.drawImage(originalBufferedImage, 0, 0, w, h, fillColor, null);
      if (!isDrawingSuccess) {
      while (!imageLoaded) {
        System.err.println("DRAWING IMAGE, PLEASE WAITING...");
        Thread.sleep(10000);
      }
      }
    } finally {
      if (graphics2D != null) {
        graphics2D.dispose();
      }
    }
    
    return newGeneratedBufferedImage;
    }
    
    public static void reduceScreenShotQuality(File screenshotSource, String location, String fileName, String fileExtension) throws Exception {
    
    int sizeThreshold = 1048576;
    float quality = 1.0f;
    long fileSize = screenshotSource.length();
    
    if (fileSize <= sizeThreshold) {
      // Image file size is small, no need reduced any more.;
      writeImageToLocation(screenshotSource, location, fileName, "jpeg");
      return;
    }
    
    // Need to reduce 'cos over sizeThreshold
    
    ImageWriter writer = createImageWriter();
    
    ImageWriteParam iwp = writer.getDefaultWriteParam();
    
    iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
    
    InputStream inputStream = new FileInputStream(screenshotSource);
    
    FileImageOutputStream output = getOutputStream(location, fileName, fileExtension);
    
    BufferedImage originalImage = ImageIO.read(inputStream);
    BufferedImage newBufferedImage;
    
    newBufferedImage = matrixTransparentPixels(originalImage, BKGROUND_COLOR);
    
    float percent = 0.1f; // 10% of 1
    
    while (fileSize > sizeThreshold) {
      if (percent >= quality) {
        percent = percent * 0.1f;
      }
    
    quality -= percent;
    
    iwp.setCompressionQuality(quality);
    
    writeImage(writer, newBufferedImage, output, iwp);
    
    File fileOut2 = new File(location + fileName + "." + fileExtension);
      long newFileSize = fileOut2.length();
      if (newFileSize == fileSize) {
        // cannot reduce more
        break;
      } else {
        fileSize = newFileSize;
      }
    }
    // Flush all stream
    inputStream.close();
    originalImage.flush();
    newBufferedImage.flush();
    writer.dispose();
    }
    
    private static void writeImage(ImageWriter writer, BufferedImage bufferedImage, FileImageOutputStream output, ImageWriteParam iwp) {
    try {
      IIOImage image = new IIOImage(bufferedImage, null, null);
      writer.setOutput(output);
    
    if (iwp != null) {
        writer.write(null, image, iwp);
      } else {
        writer.write(image);
      }
      output.close();
    } catch (IOException e) {
      System.err.println("writeImage: IOException- " + e.getMessage());
    } finally {
      System.err.println("End writeImage");
    }
    
    }
    
    private static FileImageOutputStream getOutputStream(String location, String fileName, String fileExtension) throws FileNotFoundException, IOException {
    File fileOut = new File(location + fileName + "." + fileExtension);
    if (fileOut.exists()) {
      fileOut.delete();
    }
    FileImageOutputStream output = new FileImageOutputStream(fileOut);
    
    return output;
    }
    
    private static ImageWriter createImageWriter() {
    Iterator iter = ImageIO.getImageWritersByFormatName("jpeg");
    ImageWriter writer = (ImageWriter) iter.next();
    return writer;
    }
    
    private static void writeImageToLocation(File filePng, String location, String fileName, String extension) throws IOException {
    ImageWriter writer = createImageWriter();
    
    ImageWriteParam iwp = writer.getDefaultWriteParam();
    
    SeekableStream seekableStream = new FileSeekableStream(filePng);
    PNGDecodeParam pngParams = new PNGDecodeParam();
    ImageDecoder dec = ImageCodec.createImageDecoder("png", seekableStream, pngParams);
    RenderedImage pngImage = dec.decodeAsRenderedImage();
    
    BufferedImage newImage = new BufferedImage(pngImage.getWidth(), pngImage.getHeight(), BufferedImage.TYPE_INT_RGB);
    
    newImage.createGraphics().drawImage(renderedImageToBufferedImage(pngImage), 0, 0, Color.BLACK, null);
    
    FileImageOutputStream output = getOutputStream(location, fileName, extension);
    writeImage(writer, newImage, output, iwp);
    
    newImage.flush();
    seekableStream.close();
    writer.dispose();
    }
    
    private static BufferedImage renderedImageToBufferedImage(RenderedImage img) {
    if (img instanceof BufferedImage) {
      return (BufferedImage) img;
    }
    ColorModel cm = img.getColorModel();
    int width = img.getWidth();
    int height = img.getHeight();
    WritableRaster raster = cm.createCompatibleWritableRaster(width, height);
    boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
    Hashtable properties = new Hashtable();
    String[] keys = img.getPropertyNames();
    if (keys != null) {
      for (String key : keys) {
        properties.put(key, img.getProperty(key));
      }
    }
    BufferedImage result = new BufferedImage(cm, raster, isAlphaPremultiplied, properties);
    img.copyData(raster);
    return result;
    }
    }
    @Override
    public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) {
        if (infoflags != ALLBITS) {
            // Image has not finished loading!
            // Return true to tell the image loading thread to keep drawing until image fully loads.
            return true;
        } else {
            imageLoaded = true;
            return false;
        }
    }
    
    1. Solution: Write as a thumbnail image (heigh x width)
  2. import java.awt.Color; import java.awt.Graphics2D; import java.awt.Image; import java.awt.RenderingHints; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import java.awt.image.ImageObserver; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import javax.imageio.ImageIO; import javax.media.jai.JAI; import javax.media.jai.RenderedOp; import org.apache.log4j.Logger; import com.sun.media.jai.codec.SeekableStream; /**
    • @author daviddoan * */
  3. public class ThumbnailUtils implements ImageObserver { private static final String CLASS_NAME = ThumbnailUtils.class.getSimpleName(); private final Color BKGROUND_COLOR = Color.WHITE; private boolean imageLoaded = false; public void writeThumbnail(String originalImagePath, int thumbWidth, int thumbHeight, String thumbImagePath) throws Exception { InputStream originalImageStream = new FileInputStream(originalImagePath); File fileOut = new File(thumbImagePath); if (fileOut.exists()) { fileOut.delete(); } OutputStream thumbImageOutStream = new FileOutputStream(fileOut); writeThumbnail(originalImageStream, thumbWidth, thumbHeight, thumbImageOutStream); thumbImageOutStream.close(); originalImageStream.close(); } public void writeThumbnail(File file, int thumbWidth, int thumbHeight, String thumbImagePath) throws Exception { InputStream originalImageStream = new FileInputStream(file); File fileOut = new File(thumbImagePath); if (fileOut.exists()) { fileOut.delete(); } OutputStream thumbImageOutStream = new FileOutputStream(fileOut); writeThumbnail(originalImageStream, thumbWidth, thumbHeight, thumbImageOutStream); thumbImageOutStream.close(); originalImageStream.close(); } private void writeThumbnail(InputStream originalImageStream, int thumbWidth, int thumbHeight, OutputStream thumbImageOutStream) throws Exception { ByteArrayOutputStream byteArrOutputStream = null; try { byteArrOutputStream = makeThumbnail(originalImageStream, thumbWidth, thumbHeight); byteArrOutputStream.writeTo(thumbImageOutStream); byteArrOutputStream.flush(); } finally { if (byteArrOutputStream != null) { byteArrOutputStream.close(); } } } private Image makeThumbnail(final Image originalImage, final int maxWidth, final int maxHeight) throws Exception { // ImageOveserve is ingnored for BufferedImages final int photoWidth = originalImage.getWidth(null); final int photoHeight = originalImage.getHeight(null); int thumbWidth = maxWidth; int thumbHeight = maxHeight; final double thumbRatio = (double) thumbWidth / (double) thumbHeight; final double photoRatio = (double) photoWidth / (double) photoHeight; if (thumbRatio < photoRatio) thumbHeight = (int) (thumbWidth / photoRatio); else thu

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...