java - 使用 Selenium Webdriver TakesScreenshot 方法捕获 Base64 图像。我可以缩小图像尺寸吗?

标签 java image selenium base64 screenshot

我正在使用 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. 解决方案:首先使用降低图像质量,我定义

    • 最大图片尺寸为:例如:1048576

    截图到文件(你选择的是base64由你决定)

    <p></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;
        }
    }
    </p></li></ul>

  2. 解决方案:写为缩略图(高 x 宽)

<p></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;
    }
}
</code></pre>

<p>}
</p>

希望这有帮助:)

关于java - 使用 Selenium Webdriver TakesScreenshot 方法捕获 Base64 图像。我可以缩小图像尺寸吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42140967/

相关文章:

java - java中如何读取Xml?

java - Android(Eclipse)找不到google-play-services_lib.apk尝试了多种解决方案

java - 从 Fragment 类外部更新 View 的 arrayAdapter

docker - 容器自行退出并且无法执行

javascript - 使用 jasmine 测试 javascript UI 的最佳方法

java - 如何交换两个按钮的背景颜色?

javascript - 为什么我有这么大的延迟?

javascript - 新应用程序的随机图片脚本

html - 如何在 Messenger Chat 中添加图片?

python selenium - 如何使 webdriver 使用 XPATH 2.0 版