我使用Selenium的TakesScreenshot方法在HTML报告中获取base64字符串。报告中生成的屏幕截图(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宽)的文件。让我检查一下我的解决方案,希望这能有所帮助:
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>
解决方案:首先使用降低图像质量,我定义了
- 最大图像大小为:例如:1048576
截图到一个文件(您选择的是base64由您决定)
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; } }
- Solution: Write as a thumbnail image (heigh x width)
- @author daviddoan * */
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;
/**
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
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;
}
}
}
希望有帮助:)