Add multiple quality levels for JPG encoding - adjust default to 0.85

This commit is contained in:
Mike Primm 2011-08-16 12:26:28 +08:00 committed by mikeprimm
parent 4616f6a5be
commit 477a7d13de
8 changed files with 69 additions and 41 deletions

View File

@ -6,7 +6,6 @@ import java.util.List;
import org.bukkit.World;
import org.bukkit.Location;
import org.dynmap.debug.Debug;
import org.dynmap.kzedmap.KzedMap;
import org.dynmap.utils.DynmapBufferedImage;
import org.dynmap.utils.FileLockManager;
import org.dynmap.utils.MapChunkCache;
@ -447,7 +446,7 @@ public class DynmapWorld {
try {
if(!zf.getParentFile().exists())
zf.getParentFile().mkdirs();
FileLockManager.imageIOWrite(zIm, pd.fmt.getFileExt(), zf);
FileLockManager.imageIOWrite(zIm, pd.fmt, zf);
Debug.debug("Saved zoom-out tile at " + zf.getPath());
} catch (IOException e) {
Debug.error("Failed to save zoom-out tile: " + zf.getName(), e);

View File

@ -7,14 +7,26 @@ import org.json.simple.JSONObject;
public abstract class MapType {
public enum ImageFormat {
FORMAT_PNG("png"),
FORMAT_JPG("jpg");
FORMAT_PNG("png", "png", 0.0f),
FORMAT_JPG75("jpg-q75", "jpg", 0.75f),
FORMAT_JPG80("jpg-q80", "jpg", 0.80f),
FORMAT_JPG85("jpg-q85", "jpg", 0.85f),
FORMAT_JPG("jpg", "jpg", 0.85f),
FORMAT_JPG90("jpg-q90", "jpg", 0.90f),
FORMAT_JPG95("jpg-q95", "jpg", 0.95f),
FORMAT_JPG100("jpg-q100", "jpg", 1.00f);
String id;
String ext;
ImageFormat(String ext) {
float qual;
ImageFormat(String id, String ext, float quality) {
this.id = id;
this.ext = ext;
this.qual = quality;
}
public String getID() { return id; }
public String getFileExt() { return ext; }
public float getQuality() { return qual; }
};
public abstract MapTile[] getTiles(Location l);

View File

@ -9,8 +9,6 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.imageio.ImageIO;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.World.Environment;
@ -23,9 +21,7 @@ import org.dynmap.MapManager;
import org.dynmap.TileHashManager;
import org.dynmap.MapTile;
import org.dynmap.MapType;
import org.dynmap.MapType.MapStep;
import org.dynmap.debug.Debug;
import org.dynmap.kzedmap.KzedMap;
import org.dynmap.utils.DynmapBufferedImage;
import org.dynmap.utils.FileLockManager;
import org.dynmap.utils.MapChunkCache;
@ -312,7 +308,7 @@ public class FlatMap extends MapType {
if(!outputFile.getParentFile().exists())
outputFile.getParentFile().mkdirs();
try {
FileLockManager.imageIOWrite(im.buf_img, "png", outputFile);
FileLockManager.imageIOWrite(im.buf_img, ImageFormat.FORMAT_PNG, outputFile);
} catch (IOException e) {
Debug.error("Failed to save image: " + outputFile.getPath(), e);
} catch (java.lang.NullPointerException e) {
@ -343,7 +339,7 @@ public class FlatMap extends MapType {
if(!dayfile.getParentFile().exists())
dayfile.getParentFile().mkdirs();
try {
FileLockManager.imageIOWrite(im_day.buf_img, "png", dayfile);
FileLockManager.imageIOWrite(im_day.buf_img, ImageFormat.FORMAT_PNG, dayfile);
} catch (IOException e) {
Debug.error("Failed to save image: " + dayfile.getPath(), e);
} catch (java.lang.NullPointerException e) {
@ -447,7 +443,7 @@ public class FlatMap extends MapType {
public String getPrefix() {
return prefix;
}
/* Get maps rendered concurrently with this map in this world */
public List<MapType> getMapsSharingRender(DynmapWorld w) {
return Collections.singletonList((MapType)this);
@ -585,6 +581,7 @@ public class FlatMap extends MapType {
s(o, "mapzoomin", c.getInteger("mapzoomin", 3));
s(o, "mapzoomout", world.getExtraZoomOutLevels());
s(o, "compassview", "S"); /* Always from south */
s(o, "image-format", ImageFormat.FORMAT_PNG.getFileExt());
a(worldObject, "maps", o);
}
}

View File

@ -91,11 +91,17 @@ public class HDMap extends MapType {
}
String fmt = configuration.getString("image-format", "png");
/* Only allow png or jpg */
if(fmt.equals(IMGFORMAT_PNG))
for(ImageFormat f : ImageFormat.values()) {
if(fmt.equals(f.getID())) {
imgformat = f;
break;
}
}
if(imgformat == null) {
Log.severe("HDMap '"+name+"' set invalid image-format: " + fmt);
imgformat = ImageFormat.FORMAT_PNG;
else
imgformat = ImageFormat.FORMAT_JPG;
}
}
}
public HDShader getShader() { return shader; }
public HDPerspective getPerspective() { return perspective; }

View File

@ -1041,7 +1041,7 @@ public class IsoHDPerspective implements HDPerspective {
if(!f.getParentFile().exists())
f.getParentFile().mkdirs();
try {
FileLockManager.imageIOWrite(im[i].buf_img, fmt.getFileExt(), f);
FileLockManager.imageIOWrite(im[i].buf_img, fmt, f);
} catch (IOException e) {
Debug.error("Failed to save image: " + f.getPath(), e);
} catch (java.lang.NullPointerException e) {
@ -1074,7 +1074,7 @@ public class IsoHDPerspective implements HDPerspective {
if(!f.getParentFile().exists())
f.getParentFile().mkdirs();
try {
FileLockManager.imageIOWrite(dayim[i].buf_img, fmt.getFileExt(), f);
FileLockManager.imageIOWrite(dayim[i].buf_img, fmt, f);
} catch (IOException e) {
Debug.error("Failed to save image: " + f.getPath(), e);
} catch (java.lang.NullPointerException e) {

View File

@ -18,6 +18,7 @@ import org.dynmap.ColorScheme;
import org.dynmap.ConfigurationNode;
import org.dynmap.DynmapWorld;
import org.dynmap.MapManager;
import org.dynmap.MapType.ImageFormat;
import org.dynmap.TileHashManager;
import org.dynmap.debug.Debug;
import org.dynmap.utils.DynmapBufferedImage;
@ -276,7 +277,7 @@ public class DefaultTileRenderer implements MapTileRenderer {
if(!fname.getParentFile().exists())
fname.getParentFile().mkdirs();
try {
FileLockManager.imageIOWrite(img.buf_img, "png", fname);
FileLockManager.imageIOWrite(img.buf_img, ImageFormat.FORMAT_PNG, fname);
} catch (IOException e) {
Debug.error("Failed to save image: " + fname.getPath(), e);
} catch (java.lang.NullPointerException e) {
@ -306,7 +307,7 @@ public class DefaultTileRenderer implements MapTileRenderer {
if(!dfname.getParentFile().exists())
dfname.getParentFile().mkdirs();
try {
FileLockManager.imageIOWrite(img_day.buf_img, "png", dfname);
FileLockManager.imageIOWrite(img_day.buf_img, ImageFormat.FORMAT_PNG, dfname);
} catch (IOException e) {
Debug.error("Failed to save image: " + dfname.getPath(), e);
} catch (java.lang.NullPointerException e) {
@ -390,7 +391,7 @@ public class DefaultTileRenderer implements MapTileRenderer {
zoomFile.getParentFile().mkdirs();
try {
FileLockManager.imageIOWrite(zIm, "png", zoomFile);
FileLockManager.imageIOWrite(zIm, ImageFormat.FORMAT_PNG, zoomFile);
Debug.debug("Saved zoom-out tile at " + zoomFile.getName());
} catch (IOException e) {
Debug.error("Failed to save zoom-out tile: " + zoomFile.getName(), e);
@ -589,6 +590,7 @@ public class DefaultTileRenderer implements MapTileRenderer {
s(o, "mapzoomin", c.getInteger("mapzoomin", 2));
s(o, "mapzoomout", world.getExtraZoomOutLevels()+1);
s(o, "compassview", "SE"); /* Always from southeast */
s(o, "image-format", ImageFormat.FORMAT_PNG.getFileExt());
a(worldObject, "maps", o);
}
}

View File

@ -1,14 +1,9 @@
package org.dynmap.kzedmap;
import org.dynmap.DynmapWorld;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Logger;
@ -19,16 +14,8 @@ import org.dynmap.Log;
import org.dynmap.MapManager;
import org.dynmap.MapTile;
import org.dynmap.MapType;
import org.dynmap.MapType.MapStep;
import org.dynmap.utils.DynmapBufferedImage;
import org.dynmap.utils.MapChunkCache;
import org.dynmap.utils.Vector3D;
import org.json.simple.JSONObject;
import java.awt.image.DataBufferInt;
import java.awt.image.DataBuffer;
import java.awt.image.WritableRaster;
import java.awt.image.ColorModel;
import java.awt.image.Raster;
public class KzedMap extends MapType {
protected static final Logger log = Logger.getLogger("Minecraft");

View File

@ -1,17 +1,22 @@
package org.dynmap.utils;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.RandomAccessFile;
import java.util.HashMap;
import java.util.Iterator;
import java.awt.image.BufferedImage;
import java.awt.image.DirectColorModel;
import java.awt.image.WritableRaster;
import java.io.IOException;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageOutputStream;
import org.dynmap.Log;
import org.dynmap.MapType.ImageFormat;
import org.dynmap.debug.Debug;
/**
* Implements soft-locks for prevent concurrency issues with file updates
@ -141,13 +146,13 @@ public class FileLockManager {
/**
* Wrapper for IOImage.write - implements retries for busy files
*/
public static void imageIOWrite(BufferedImage img, String type, File fname) throws IOException {
public static void imageIOWrite(BufferedImage img, ImageFormat fmt, File fname) throws IOException {
int retrycnt = 0;
boolean done = false;
byte[] rslt;
synchronized(baos_lock) {
baos.reset();
if(type.equals("jpg")) {
if(fmt.getFileExt().equals("jpg")) {
WritableRaster raster = img.getRaster();
WritableRaster newRaster = raster.createWritableChild(0, 0, img.getWidth(),
img.getHeight(), 0, 0, new int[] {0, 1, 2});
@ -156,11 +161,31 @@ public class FileLockManager {
cm.getRedMask(), cm.getGreenMask(), cm.getBlueMask());
// now create the new buffer that is used ot write the image:
BufferedImage rgbBuffer = new BufferedImage(newCM, newRaster, false, null);
ImageIO.write(rgbBuffer, type, baos); /* Write to byte array stream - prevent bogus I/O errors */
// Find a jpeg writer
ImageWriter writer = null;
Iterator iter = ImageIO.getImageWritersByFormatName("jpg");
if (iter.hasNext()) {
writer = (ImageWriter)iter.next();
}
if(writer == null) {
Log.severe("No JPEG ENCODER - Java VM does not support JPEG encoding");
return;
}
ImageWriteParam iwp = writer.getDefaultWriteParam();
iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
iwp.setCompressionQuality(fmt.getQuality());
ImageOutputStream ios = ImageIO.createImageOutputStream(baos);
writer.setOutput(ios);
writer.write(null, new IIOImage(rgbBuffer, null, null), iwp);
writer.dispose();
rgbBuffer.flush();
}
else {
ImageIO.write(img, type, baos); /* Write to byte array stream - prevent bogus I/O errors */
ImageIO.write(img, fmt.getFileExt(), baos); /* Write to byte array stream - prevent bogus I/O errors */
}
rslt = baos.toByteArray();
}