diff --git a/src/main/scala/edu/stanford/graphics/shapenet/jme3/viewer/JmeSystemMod.java b/src/main/scala/edu/stanford/graphics/shapenet/jme3/viewer/JmeSystemMod.java new file mode 100644 index 0000000..48297c5 --- /dev/null +++ b/src/main/scala/edu/stanford/graphics/shapenet/jme3/viewer/JmeSystemMod.java @@ -0,0 +1,82 @@ +package edu.stanford.graphics.shapenet.jme3.viewer; + +import com.jme3.util.Screenshots; + +import javax.imageio.IIOImage; +import javax.imageio.ImageIO; +import javax.imageio.ImageWriteParam; +import javax.imageio.ImageWriter; +import javax.imageio.plugins.jpeg.JPEGImageWriteParam; +import javax.imageio.stream.ImageOutputStream; +import javax.imageio.stream.MemoryCacheImageOutputStream; +import java.awt.*; +import java.awt.geom.AffineTransform; +import java.awt.image.AffineTransformOp; +import java.awt.image.BufferedImage; +import java.awt.image.DataBufferInt; +import java.awt.image.WritableRaster; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.ByteBuffer; + +public final class JmeSystemMod { + + private static void fixAlphaAndSwapChannels(BufferedImage img) { + final WritableRaster wr = img.getRaster(); + final DataBufferInt db = (DataBufferInt)wr.getDataBuffer(); + final int[] cpuArray = db.getData(); + for (int i = 0; i < cpuArray.length; i++) { + int p = cpuArray[i]; + // Fix alpha channel (set to 0 for complete transparency) + if (p == -1) { + p &= 0x00ffffff; + } else { + // Convert ABGR to ARGB + final int b = p >> 16 & 0xff; + final int r = p & 0xff; + p = (p & 0xff00ff00) | r << 16 | b; + } + cpuArray[i] = p; + } + } + + private static BufferedImage verticalFlip(BufferedImage original) { + AffineTransform tx = AffineTransform.getScaleInstance(1, -1); + tx.translate(0, -original.getHeight()); + AffineTransformOp transformOp = new AffineTransformOp(tx, AffineTransformOp.TYPE_NEAREST_NEIGHBOR); + BufferedImage awtImage = new BufferedImage(original.getWidth(), original.getHeight(), BufferedImage.TYPE_INT_ARGB); + Graphics2D g2d = awtImage.createGraphics(); + g2d.setRenderingHint(RenderingHints.KEY_RENDERING, + RenderingHints.VALUE_RENDER_SPEED); + g2d.drawImage(original, transformOp, 0, 0); + g2d.dispose(); + return awtImage; + } + + public static void writeImageFile(OutputStream outStream, String format, ByteBuffer imageData, int width, int height) throws IOException { + BufferedImage awtImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + Screenshots.convertScreenShot2(imageData.asIntBuffer(), awtImage); + fixAlphaAndSwapChannels(awtImage); + + ImageWriter writer = ImageIO.getImageWritersByFormatName(format).next(); + ImageWriteParam writeParam = writer.getDefaultWriteParam(); + + if (format.equals("jpg")) { + JPEGImageWriteParam jpegParam = (JPEGImageWriteParam) writeParam; + jpegParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); + jpegParam.setCompressionQuality(0.95f); + } + + awtImage = verticalFlip(awtImage); + + ImageOutputStream imgOut = new MemoryCacheImageOutputStream(outStream); + writer.setOutput(imgOut); + IIOImage outputImage = new IIOImage(awtImage, null, null); + try { + writer.write(null, outputImage, writeParam); + } finally { + imgOut.close(); + writer.dispose(); + } + } +} diff --git a/src/main/scala/edu/stanford/graphics/shapenet/jme3/viewer/OffscreenView.scala b/src/main/scala/edu/stanford/graphics/shapenet/jme3/viewer/OffscreenView.scala index 684e8e9..d23939f 100644 --- a/src/main/scala/edu/stanford/graphics/shapenet/jme3/viewer/OffscreenView.scala +++ b/src/main/scala/edu/stanford/graphics/shapenet/jme3/viewer/OffscreenView.scala @@ -89,7 +89,7 @@ class OffscreenView(val renderManager: RenderManager, logger.info("Saving offscreen view to: {0}", file.getAbsolutePath()) try { outStream = IOUtils.fileOutputStream(filename) - JmeSystem.writeImageFile(outStream, imageFormat, outBuf, width, height) + JmeSystemMod.writeImageFile(outStream, imageFormat, outBuf, width, height) } catch { case ex: IOException => { logger.error("Error while saving offscreen view", ex) diff --git a/src/main/scala/edu/stanford/graphics/shapenet/jme3/viewer/ScreenshotAppState.java b/src/main/scala/edu/stanford/graphics/shapenet/jme3/viewer/ScreenshotAppState.java index ad8b05d..84a075f 100644 --- a/src/main/scala/edu/stanford/graphics/shapenet/jme3/viewer/ScreenshotAppState.java +++ b/src/main/scala/edu/stanford/graphics/shapenet/jme3/viewer/ScreenshotAppState.java @@ -201,7 +201,7 @@ public void postFrame(FrameBuffer out) { OutputStream outStream = null; try { outStream = new FileOutputStream(file); - JmeSystem.writeImageFile(outStream, imageFormat, outBuf, width, height); + JmeSystemMod.writeImageFile(outStream, imageFormat, outBuf, width, height); logger.log(Level.INFO, "Saved ScreenShot to: " + file.getAbsolutePath()); } catch (IOException ex) { logger.log(Level.SEVERE, "Error while saving screenshot", ex);