使用 Selenium Webdriver TakesScreenshot 方法捕获 base64 图像。我可以减小图像尺寸吗?

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

我正在使用 Selenium 的 TakesScreenshot 方法将 base64 字符串添加到我的 HTML 报告中。报告 (extentreports) 中生成的屏幕截图有点太大,部分被推到屏幕外。缩小它也会减小报告的文件大小。

我可以截取更小的 base64 屏幕截图吗?将其缩小约 20% 将是完美的……或者我是否必须先将图像创建为 File,然后将其缩小,然后转换为 base64。

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

如果您想截取较小的屏幕截图文件。您应该降低图像质量或写入具有固定尺寸(高度 x 宽度)的文件。让我们检查一下我的解决方案,希望对您有所帮助:

图书馆:

<!-- 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. 解决方法:首先使用reduce image quality,我定义

    • 最大图像大小为:例如:1048576

    截屏到文件(你选择是不是base64由你决定)

    </p>
    
    <p>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;</p>
    
    <p>/**</p>
    
    <ul>
    <li><p>@author daviddoan
    *
    */
    public class ScreenShotUtils implements ImageObserver {</p>
    
    <p>private static final Color BKGROUND_COLOR = Color.WHITE;
    private boolean imageLoaded = false;</p>
    
    <p>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();
      }
    }</p>
    
    <p>return newGeneratedBufferedImage;
    }</p>
    
    <p>public static void reduceScreenShotQuality(File screenshotSource, String location, String fileName, String fileExtension) throws Exception {</p>
    
    <p>int sizeThreshold = 1048576;
    float quality = 1.0f;
    long fileSize = screenshotSource.length();</p>
    
    <p>if (fileSize <= sizeThreshold) {
      // Image file size is small, no need reduced any more.;
      writeImageToLocation(screenshotSource, location, fileName, "jpeg");
      return;
    }</p>
    
    <p>// Need to reduce 'cos over sizeThreshold</p>
    
    <p>ImageWriter writer = createImageWriter();</p>
    
    <p>ImageWriteParam iwp = writer.getDefaultWriteParam();</p>
    
    <p>iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);</p>
    
    <p>InputStream inputStream = new FileInputStream(screenshotSource);</p>
    
    <p>FileImageOutputStream output = getOutputStream(location, fileName, fileExtension);</p>
    
    <p>BufferedImage originalImage = ImageIO.read(inputStream);
    BufferedImage newBufferedImage;</p>
    
    <p>newBufferedImage = matrixTransparentPixels(originalImage, BKGROUND_COLOR);</p>
    
    <p>float percent = 0.1f; // 10% of 1</p>
    
    <p>while (fileSize > sizeThreshold) {
      if (percent >= quality) {
        percent = percent * 0.1f;
      }</p>
    
    <p>quality -= percent;</p>
    
    <p>iwp.setCompressionQuality(quality);</p>
    
    <p>writeImage(writer, newBufferedImage, output, iwp);</p>
    
    <p>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();
    }</p>
    
    <p>private static void writeImage(ImageWriter writer, BufferedImage bufferedImage, FileImageOutputStream output, ImageWriteParam iwp) {
    try {
      IIOImage image = new IIOImage(bufferedImage, null, null);
      writer.setOutput(output);</p>
    
    <p>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");
    }</p>
    
    <p>}</p>
    
    <p>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);</p>
    
    <p>return output;
    }</p>
    
    <p>private static ImageWriter createImageWriter() {
    Iterator iter = ImageIO.getImageWritersByFormatName("jpeg");
    ImageWriter writer = (ImageWriter) iter.next();
    return writer;
    }</p>
    
    <p>private static void writeImageToLocation(File filePng, String location, String fileName, String extension) throws IOException {
    ImageWriter writer = createImageWriter();</p>
    
    <p>ImageWriteParam iwp = writer.getDefaultWriteParam();</p>
    
    <p>SeekableStream seekableStream = new FileSeekableStream(filePng);
    PNGDecodeParam pngParams = new PNGDecodeParam();
    ImageDecoder dec = ImageCodec.createImageDecoder("png", seekableStream, pngParams);
    RenderedImage pngImage = dec.decodeAsRenderedImage();</p>
    
    <p>BufferedImage newImage = new BufferedImage(pngImage.getWidth(), pngImage.getHeight(), BufferedImage.TYPE_INT_RGB);</p>
    
    <p>newImage.createGraphics().drawImage(renderedImageToBufferedImage(pngImage), 0, 0, Color.BLACK, null);</p>
    
    <p>FileImageOutputStream output = getOutputStream(location, fileName, extension);
    writeImage(writer, newImage, output, iwp);</p>
    
    <p>newImage.flush();
    seekableStream.close();
    writer.dispose();
    }</p>
    
    <p>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;
        }
    }
    </pre>

    1. 解决方案:写成缩略图(高 x 宽)
  2. </p>
    
    <p>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;</p>
    
    <p>import javax.imageio.ImageIO;
    import javax.media.jai.JAI;
    import javax.media.jai.RenderedOp;</p>
    
    <p>import org.apache.log4j.Logger;</p>
    
    <p>import com.sun.media.jai.codec.SeekableStream;</p>
    
    <p>/**</p>
    
    <ul>
    <li><ul>
    <li>@author daviddoan
    *
    */</li>
    </ul></li>
    </ul>
    
    <p>public class ThumbnailUtils implements ImageObserver {</p>
    
    <pre><code>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
            thumbWidth = (int) (thumbHeight * photoRatio);
    
        // Checking if the photo's size is smaller than thumbnail's size: getting the original size
        if (photoWidth < thumbWidth) {
            thumbWidth = photoWidth;
        }
        if (photoHeight < thumbHeight) {
            thumbHeight = photoHeight;
        }
    
        final BufferedImage thumbnailBufferedImage = new BufferedImage(thumbWidth, thumbHeight, BufferedImage.TYPE_INT_RGB);
        final Graphics2D graphics2D = thumbnailBufferedImage.createGraphics();
    
        // Best Quality Render Hints!
        graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
        graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        graphics2D.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
        graphics2D.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        graphics2D.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
        graphics2D.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION,
                RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
    
        final AffineTransform t = new AffineTransform();
        t.scale((double) thumbWidth / photoWidth, (double) thumbHeight / photoHeight);
    
        graphics2D.setBackground(BKGROUND_COLOR);
        final boolean complete = graphics2D.drawImage(originalImage, t, this);
    
        if (!complete) {
            while (!imageLoaded) {
                try {
                    wait(100);
                } catch (InterruptedException ie) {
                }
            }
        }
    
        graphics2D.dispose();
    
        return thumbnailBufferedImage;
    }
    
    private synchronized ByteArrayOutputStream makeThumbnail(final InputStream originalImageStream, final int maxWidth,
            final int maxHeight) throws Exception {
    
        SeekableStream seekableStream = SeekableStream.wrapInputStream(originalImageStream, true);
        RenderedOp reop = JAI.create("stream", seekableStream);
        Image photo = reop.getAsBufferedImage();
    
        final BufferedImage thumbnail = (BufferedImage) makeThumbnail(photo, maxWidth, maxHeight);
    
        final ByteArrayOutputStream byteArrayStream = new ByteArrayOutputStream();
        ImageIO.write(thumbnail, GlobalResourceUtils.getFileExtension(), byteArrayStream);
    
        return byteArrayStream;
    }
    
    @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;
        }
    }
    

    }

希望对您有所帮助:)