ImageRaster: add mipmap access & gamma correction
* Remove deprecated image raster methods from JmeSystem * Allow ImageRaster to read / write to arbitrary mipmaps * Allow ImageRaster to perform conversion to / from linear color space as required
This commit is contained in:
parent
09a104a7b1
commit
0a0fdca0b4
@ -172,15 +172,6 @@ public class JmeSystem {
|
||||
return systemDelegate.getPlatformAssetConfigURL();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Directly create an image raster via {@link DefaultImageRaster}.
|
||||
*/
|
||||
@Deprecated
|
||||
public static ImageRaster createImageRaster(Image image, int slice) {
|
||||
checkDelegate();
|
||||
return systemDelegate.createImageRaster(image, slice);
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays an error message to the user in whichever way the context
|
||||
* feels is appropriate. If this is a headless or an offscreen surface
|
||||
|
@ -132,11 +132,6 @@ public abstract class JmeSystemDelegate {
|
||||
return new DesktopAssetManager(null);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final ImageRaster createImageRaster(Image image, int slice) {
|
||||
return new DefaultImageRaster(image, slice);
|
||||
}
|
||||
|
||||
public abstract void writeImageFile(OutputStream outStream, String format, ByteBuffer imageData, int width, int height) throws IOException;
|
||||
|
||||
public abstract void showErrorDialog(String message);
|
||||
|
@ -44,7 +44,9 @@ public class DefaultImageRaster extends ImageRaster {
|
||||
private final ImageCodec codec;
|
||||
private final int width;
|
||||
private final int height;
|
||||
private final int offset;
|
||||
private final byte[] temp;
|
||||
private final boolean convertToLinear;
|
||||
private int slice;
|
||||
|
||||
private void rangeCheck(int x, int y) {
|
||||
@ -53,13 +55,40 @@ public class DefaultImageRaster extends ImageRaster {
|
||||
}
|
||||
}
|
||||
|
||||
public DefaultImageRaster(Image image, int slice) {
|
||||
public DefaultImageRaster(Image image, int slice, int mipMapLevel, boolean convertToLinear) {
|
||||
int[] mipMapSizes = image.getMipMapSizes();
|
||||
int availableMips = mipMapSizes != null ? mipMapSizes.length : 1;
|
||||
|
||||
if (mipMapLevel >= availableMips) {
|
||||
throw new IllegalStateException("Cannot create image raster for mipmap level #" + mipMapLevel + ". "
|
||||
+ "Image only has " + availableMips + " mipmap levels.");
|
||||
}
|
||||
|
||||
if (image.hasMipmaps()) {
|
||||
this.width = Math.max(1, image.getWidth() >> mipMapLevel);
|
||||
this.height = Math.max(1, image.getHeight() >> mipMapLevel);
|
||||
|
||||
int mipOffset = 0;
|
||||
for (int i = 0; i < mipMapLevel; i++) {
|
||||
mipOffset += mipMapSizes[i];
|
||||
}
|
||||
|
||||
this.offset = mipOffset;
|
||||
} else {
|
||||
this.width = image.getWidth();
|
||||
this.height = image.getHeight();
|
||||
this.offset = 0;
|
||||
}
|
||||
|
||||
this.image = image;
|
||||
this.slice = slice;
|
||||
|
||||
// Conversion to linear only needed if image's color space is sRGB.
|
||||
this.convertToLinear = convertToLinear && image.getColorSpace() == ColorSpace.sRGB;
|
||||
|
||||
this.buffer = image.getData(slice);
|
||||
this.codec = ImageCodec.lookup(image.getFormat());
|
||||
this.width = image.getWidth();
|
||||
this.height = image.getHeight();
|
||||
|
||||
if (codec instanceof ByteAlignedImageCodec || codec instanceof ByteOffsetImageCodec) {
|
||||
this.temp = new byte[codec.bpp];
|
||||
} else {
|
||||
@ -86,6 +115,12 @@ public class DefaultImageRaster extends ImageRaster {
|
||||
public void setPixel(int x, int y, ColorRGBA color) {
|
||||
rangeCheck(x, y);
|
||||
|
||||
if (convertToLinear) {
|
||||
// Input is linear, needs to be converted to sRGB before writing
|
||||
// into image.
|
||||
color = color.getAsSrgb();
|
||||
}
|
||||
|
||||
// Check flags for grayscale
|
||||
if (codec.isGray) {
|
||||
float gray = color.r * 0.27f + color.g * 0.67f + color.b * 0.06f;
|
||||
@ -113,7 +148,7 @@ public class DefaultImageRaster extends ImageRaster {
|
||||
components[3] = Math.min( (int) (color.b * codec.maxBlue + 0.5f), codec.maxBlue);
|
||||
break;
|
||||
}
|
||||
codec.writeComponents(getBuffer(), x, y, width, 0, components, temp);
|
||||
codec.writeComponents(getBuffer(), x, y, width, offset, components, temp);
|
||||
image.setUpdateNeeded();
|
||||
}
|
||||
|
||||
@ -128,7 +163,7 @@ public class DefaultImageRaster extends ImageRaster {
|
||||
public ColorRGBA getPixel(int x, int y, ColorRGBA store) {
|
||||
rangeCheck(x, y);
|
||||
|
||||
codec.readComponents(getBuffer(), x, y, width, 0, components, temp);
|
||||
codec.readComponents(getBuffer(), x, y, width, offset, components, temp);
|
||||
if (store == null) {
|
||||
store = new ColorRGBA();
|
||||
}
|
||||
@ -169,6 +204,12 @@ public class DefaultImageRaster extends ImageRaster {
|
||||
store.a = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (convertToLinear) {
|
||||
// Input image is sRGB, need to convert to linear.
|
||||
store.setAsSrgb(store.r, store.g, store.b, store.a);
|
||||
}
|
||||
|
||||
return store;
|
||||
}
|
||||
}
|
||||
|
@ -71,21 +71,42 @@ public abstract class ImageRaster {
|
||||
* @param image The image to read / write to.
|
||||
* @param slice Which slice to use. Only applies to 3D images, 2D image
|
||||
* arrays or cubemaps.
|
||||
* @param mipMapLevel The mipmap level to read / write to. To access levels
|
||||
* other than 0, the image must have
|
||||
* {@link Image#setMipMapSizes(int[]) mipmap sizes} set.
|
||||
* @param convertToLinear If true, the application expects read or written
|
||||
* colors to be in linear color space (<code>ImageRaster</code> will
|
||||
* automatically perform a conversion as needed). If false, the application expects
|
||||
* colors to be in the image's native {@link Image#getColorSpace() color space}.
|
||||
* @return An ImageRaster to read / write to the image.
|
||||
*/
|
||||
public static ImageRaster create(Image image, int slice, int mipMapLevel, boolean convertToLinear) {
|
||||
return new DefaultImageRaster(image, slice, mipMapLevel, convertToLinear);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new image reader / writer.
|
||||
*
|
||||
* @param image The image to read / write to.
|
||||
* @param slice Which slice to use. Only applies to 3D images, 2D image
|
||||
* arrays or cubemaps.
|
||||
* @return An ImageRaster to read / write to the image.
|
||||
*/
|
||||
public static ImageRaster create(Image image, int slice) {
|
||||
return JmeSystem.createImageRaster(image, slice);
|
||||
return create(image, slice, 0, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new image reader / writer for 2D images.
|
||||
*
|
||||
* @param image The image to read / write to.
|
||||
* @return An ImageRaster to read / write to the image.
|
||||
*/
|
||||
public static ImageRaster create(Image image) {
|
||||
if (image.getData().size() > 1) {
|
||||
throw new IllegalStateException("Use constructor that takes slices argument to read from multislice image");
|
||||
}
|
||||
return JmeSystem.createImageRaster(image, 0);
|
||||
return create(image, 0, 0, false);
|
||||
}
|
||||
|
||||
public ImageRaster() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user