NativeImage.java
com.mojang.blaze3d.platform.NativeImage
信息
- 全限定名:com.mojang.blaze3d.platform.NativeImage
- 类型:public final class
- 包:com.mojang.blaze3d.platform
- 源码路径:src/main/java/com/mojang/blaze3d/platform/NativeImage.java
- 起始行号:L40
- 实现:AutoCloseable
- 职责:
TODO
字段/常量
-
LOGGER- 类型:
Logger - 修饰符:
private static final - 源码定位:
L41 - 说明:
TODO
- 类型:
-
MEMORY_POOL- 类型:
MemoryPool - 修饰符:
private static final - 源码定位:
L42 - 说明:
TODO
- 类型:
-
OPEN_OPTIONS- 类型:
Set<StandardOpenOption> - 修饰符:
private static final - 源码定位:
L43 - 说明:
TODO
- 类型:
-
format- 类型:
NativeImage.Format - 修饰符:
private final - 源码定位:
L46 - 说明:
TODO
- 类型:
-
width- 类型:
int - 修饰符:
private final - 源码定位:
L47 - 说明:
TODO
- 类型:
-
height- 类型:
int - 修饰符:
private final - 源码定位:
L48 - 说明:
TODO
- 类型:
-
useStbFree- 类型:
boolean - 修饰符:
private final - 源码定位:
L49 - 说明:
TODO
- 类型:
-
pixels- 类型:
long - 修饰符:
private - 源码定位:
L50 - 说明:
TODO
- 类型:
-
size- 类型:
long - 修饰符:
private final - 源码定位:
L51 - 说明:
TODO
- 类型:
内部类/嵌套类型
-
com.mojang.blaze3d.platform.NativeImage.Format- 类型:
enum - 修饰符:
public static - 源码定位:
L502 - 说明:
TODO
- 类型:
-
com.mojang.blaze3d.platform.NativeImage.WriteCallback- 类型:
class - 修饰符:
private static - 源码定位:
L645 - 说明:
TODO
- 类型:
构造器
public NativeImage(int width, int height, boolean zero) @ L53
- 构造器名:NativeImage
- 源码定位:L53
- 修饰符:public
参数:
- width: int
- height: int
- zero: boolean
说明:
TODO
public NativeImage(NativeImage.Format format, int width, int height, boolean zero) @ L57
- 构造器名:NativeImage
- 源码定位:L57
- 修饰符:public
参数:
- format: NativeImage.Format
- width: int
- height: int
- zero: boolean
说明:
TODO
public NativeImage(NativeImage.Format format, int width, int height, boolean useStbFree, long pixels) @ L79
- 构造器名:NativeImage
- 源码定位:L79
- 修饰符:public
参数:
- format: NativeImage.Format
- width: int
- height: int
- useStbFree: boolean
- pixels: long
说明:
TODO
方法
下面的方法块按源码顺序生成。
public String toString() @ L92
- 方法名:toString
- 源码定位:L92
- 返回类型:String
- 修饰符:public
参数:
- 无
说明:
TODO
private boolean isOutsideBounds(int x, int y) @ L97
- 方法名:isOutsideBounds
- 源码定位:L97
- 返回类型:boolean
- 修饰符:private
参数:
- x: int
- y: int
说明:
TODO
public static NativeImage read(InputStream inputStream) @ L101
- 方法名:read
- 源码定位:L101
- 返回类型:NativeImage
- 修饰符:public static
参数:
- inputStream: InputStream
说明:
TODO
public static NativeImage read(NativeImage.Format format, InputStream inputStream) @ L105
- 方法名:read
- 源码定位:L105
- 返回类型:NativeImage
- 修饰符:public static
参数:
- format: NativeImage.Format
- inputStream: InputStream
说明:
TODO
public static NativeImage read(ByteBuffer bytes) @ L120
- 方法名:read
- 源码定位:L120
- 返回类型:NativeImage
- 修饰符:public static
参数:
- bytes: ByteBuffer
说明:
TODO
public static NativeImage read(byte[] bytes) @ L124
- 方法名:read
- 源码定位:L124
- 返回类型:NativeImage
- 修饰符:public static
参数:
- bytes: byte[]
说明:
TODO
private static NativeImage putAndRead(ByteBuffer nativeBuffer, byte[] bytes) @ L149
- 方法名:putAndRead
- 源码定位:L149
- 返回类型:NativeImage
- 修饰符:private static
参数:
- nativeBuffer: ByteBuffer
- bytes: byte[]
说明:
TODO
public static NativeImage read(NativeImage.Format format, ByteBuffer bytes) @ L155
- 方法名:read
- 源码定位:L155
- 返回类型:NativeImage
- 修饰符:public static
参数:
- format: NativeImage.Format
- bytes: ByteBuffer
说明:
TODO
private void checkAllocated() @ L182
- 方法名:checkAllocated
- 源码定位:L182
- 返回类型:void
- 修饰符:private
参数:
- 无
说明:
TODO
public void close() @ L188
- 方法名:close
- 源码定位:L188
- 返回类型:void
- 修饰符:public
参数:
- 无
说明:
TODO
public boolean isClosed() @ L203
- 方法名:isClosed
- 源码定位:L203
- 返回类型:boolean
- 修饰符:public
参数:
- 无
说明:
TODO
public int getWidth() @ L207
- 方法名:getWidth
- 源码定位:L207
- 返回类型:int
- 修饰符:public
参数:
- 无
说明:
TODO
public int getHeight() @ L211
- 方法名:getHeight
- 源码定位:L211
- 返回类型:int
- 修饰符:public
参数:
- 无
说明:
TODO
public NativeImage.Format format() @ L215
- 方法名:format
- 源码定位:L215
- 返回类型:NativeImage.Format
- 修饰符:public
参数:
- 无
说明:
TODO
private int getPixelABGR(int x, int y) @ L219
- 方法名:getPixelABGR
- 源码定位:L219
- 返回类型:int
- 修饰符:private
参数:
- x: int
- y: int
说明:
TODO
public int getPixel(int x, int y) @ L231
- 方法名:getPixel
- 源码定位:L231
- 返回类型:int
- 修饰符:public
参数:
- x: int
- y: int
说明:
TODO
public void setPixelABGR(int x, int y, int pixel) @ L235
- 方法名:setPixelABGR
- 源码定位:L235
- 返回类型:void
- 修饰符:public
参数:
- x: int
- y: int
- pixel: int
说明:
TODO
public void setPixel(int x, int y, int pixel) @ L247
- 方法名:setPixel
- 源码定位:L247
- 返回类型:void
- 修饰符:public
参数:
- x: int
- y: int
- pixel: int
说明:
TODO
public NativeImage mappedCopy(IntUnaryOperator function) @ L251
- 方法名:mappedCopy
- 源码定位:L251
- 返回类型:NativeImage
- 修饰符:public
参数:
- function: IntUnaryOperator
说明:
TODO
public int[] getPixelsABGR() @ L271
- 方法名:getPixelsABGR
- 源码定位:L271
- 返回类型:int[]
- 修饰符:public
参数:
- 无
说明:
TODO
public int[] getPixels() @ L282
- 方法名:getPixels
- 源码定位:L282
- 返回类型:int[]
- 修饰符:public
参数:
- 无
说明:
TODO
public byte getLuminanceOrAlpha(int x, int y) @ L292
- 方法名:getLuminanceOrAlpha
- 源码定位:L292
- 返回类型:byte
- 修饰符:public
参数:
- x: int
- y: int
说明:
TODO
public int[] makePixelArray() @ L303
- 方法名:makePixelArray
- 源码定位:L303
- 返回类型:int[]
- 修饰符:public
参数:
- 无
说明:
TODO
public void writeToFile(File file) @ L321
- 方法名:writeToFile
- 源码定位:L321
- 返回类型:void
- 修饰符:public
参数:
- file: File
说明:
TODO
public boolean copyFromFont(FT_Face face, int index) @ L325
- 方法名:copyFromFont
- 源码定位:L325
- 返回类型:boolean
- 修饰符:public
参数:
- face: FT_Face
- index: int
说明:
TODO
public void writeToFile(Path file) @ L355
- 方法名:writeToFile
- 源码定位:L355
- 返回类型:void
- 修饰符:public
参数:
- file: Path
说明:
TODO
private boolean writeToChannel(WritableByteChannel output) @ L369
- 方法名:writeToChannel
- 源码定位:L369
- 返回类型:boolean
- 修饰符:private
参数:
- output: WritableByteChannel
说明:
TODO
public void copyFrom(NativeImage from) @ L392
- 方法名:copyFrom
- 源码定位:L392
- 返回类型:void
- 修饰符:public
参数:
- from: NativeImage
说明:
TODO
public void fillRect(int xs, int ys, int width, int height, int pixel) @ L414
- 方法名:fillRect
- 源码定位:L414
- 返回类型:void
- 修饰符:public
参数:
- xs: int
- ys: int
- width: int
- height: int
- pixel: int
说明:
TODO
public void copyRect(int startX, int startY, int offsetX, int offsetY, int sizeX, int sizeY, boolean swapX, boolean swapY) @ L422
- 方法名:copyRect
- 源码定位:L422
- 返回类型:void
- 修饰符:public
参数:
- startX: int
- startY: int
- offsetX: int
- offsetY: int
- sizeX: int
- sizeY: int
- swapX: boolean
- swapY: boolean
说明:
TODO
public void copyRect(NativeImage target, int sourceX, int sourceY, int targetX, int targetY, int sizeX, int sizeY, boolean swapX, boolean swapY) @ L426
- 方法名:copyRect
- 源码定位:L426
- 返回类型:void
- 修饰符:public
参数:
- target: NativeImage
- sourceX: int
- sourceY: int
- targetX: int
- targetY: int
- sizeX: int
- sizeY: int
- swapX: boolean
- swapY: boolean
说明:
TODO
public void resizeSubRectTo(int sourceX, int sourceY, int sizeX, int sizeY, NativeImage to) @ L437
- 方法名:resizeSubRectTo
- 源码定位:L437
- 返回类型:void
- 修饰符:public
参数:
- sourceX: int
- sourceY: int
- sizeX: int
- sizeY: int
- to: NativeImage
说明:
TODO
public void untrack() @ L457
- 方法名:untrack
- 源码定位:L457
- 返回类型:void
- 修饰符:public
参数:
- 无
说明:
TODO
public long getPointer() @ L461
- 方法名:getPointer
- 源码定位:L461
- 返回类型:long
- 修饰符:public
参数:
- 无
说明:
TODO
public Transparency computeTransparency(int x0, int y0, int x1, int y1) @ L465
- 方法名:computeTransparency
- 源码定位:L465
- 返回类型:Transparency
- 修饰符:public
参数:
- x0: int
- y0: int
- x1: int
- y1: int
说明:
TODO
public Transparency computeTransparency() @ L497
- 方法名:computeTransparency
- 源码定位:L497
- 返回类型:Transparency
- 修饰符:public
参数:
- 无
说明:
TODO
代码
@OnlyIn(Dist.CLIENT)
public final class NativeImage implements AutoCloseable {
private static final Logger LOGGER = LogUtils.getLogger();
private static final MemoryPool MEMORY_POOL = TracyClient.createMemoryPool("NativeImage");
private static final Set<StandardOpenOption> OPEN_OPTIONS = EnumSet.of(
StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING
);
private final NativeImage.Format format;
private final int width;
private final int height;
private final boolean useStbFree;
private long pixels;
private final long size;
public NativeImage(int width, int height, boolean zero) {
this(NativeImage.Format.RGBA, width, height, zero);
}
public NativeImage(NativeImage.Format format, int width, int height, boolean zero) {
if (width > 0 && height > 0) {
this.format = format;
this.width = width;
this.height = height;
this.size = (long)width * height * format.components();
this.useStbFree = false;
if (zero) {
this.pixels = MemoryUtil.nmemCalloc(1L, this.size);
} else {
this.pixels = MemoryUtil.nmemAlloc(this.size);
}
MEMORY_POOL.malloc(this.pixels, (int)this.size);
if (this.pixels == 0L) {
throw new IllegalStateException("Unable to allocate texture of size " + width + "x" + height + " (" + format.components() + " channels)");
}
} else {
throw new IllegalArgumentException("Invalid texture size: " + width + "x" + height);
}
}
public NativeImage(NativeImage.Format format, int width, int height, boolean useStbFree, long pixels) {
if (width > 0 && height > 0) {
this.format = format;
this.width = width;
this.height = height;
this.useStbFree = useStbFree;
this.pixels = pixels;
this.size = (long)width * height * format.components();
} else {
throw new IllegalArgumentException("Invalid texture size: " + width + "x" + height);
}
}
@Override
public String toString() {
return "NativeImage[" + this.format + " " + this.width + "x" + this.height + "@" + this.pixels + (this.useStbFree ? "S" : "N") + "]";
}
private boolean isOutsideBounds(int x, int y) {
return x < 0 || x >= this.width || y < 0 || y >= this.height;
}
public static NativeImage read(InputStream inputStream) throws IOException {
return read(NativeImage.Format.RGBA, inputStream);
}
public static NativeImage read(NativeImage.@Nullable Format format, InputStream inputStream) throws IOException {
ByteBuffer file = null;
NativeImage var3;
try {
file = TextureUtil.readResource(inputStream);
var3 = read(format, file);
} finally {
MemoryUtil.memFree(file);
IOUtils.closeQuietly(inputStream);
}
return var3;
}
public static NativeImage read(ByteBuffer bytes) throws IOException {
return read(NativeImage.Format.RGBA, bytes);
}
public static NativeImage read(byte[] bytes) throws IOException {
MemoryStack memoryStack = MemoryStack.stackGet();
int bytesAvailable = memoryStack.getPointer();
if (bytesAvailable < bytes.length) {
ByteBuffer buffer = MemoryUtil.memAlloc(bytes.length);
NativeImage var13;
try {
var13 = putAndRead(buffer, bytes);
} finally {
MemoryUtil.memFree(buffer);
}
return var13;
} else {
NativeImage var5;
try (MemoryStack stack = MemoryStack.stackPush()) {
ByteBuffer buffer = stack.malloc(bytes.length);
var5 = putAndRead(buffer, bytes);
}
return var5;
}
}
private static NativeImage putAndRead(ByteBuffer nativeBuffer, byte[] bytes) throws IOException {
nativeBuffer.put(bytes);
nativeBuffer.rewind();
return read(nativeBuffer);
}
public static NativeImage read(NativeImage.@Nullable Format format, ByteBuffer bytes) throws IOException {
if (format != null && !format.supportedByStb()) {
throw new UnsupportedOperationException("Don't know how to read format " + format);
} else if (MemoryUtil.memAddress(bytes) == 0L) {
throw new IllegalArgumentException("Invalid buffer");
} else {
PngInfo.validateHeader(bytes);
NativeImage var9;
try (MemoryStack stack = MemoryStack.stackPush()) {
IntBuffer w = stack.mallocInt(1);
IntBuffer h = stack.mallocInt(1);
IntBuffer comp = stack.mallocInt(1);
ByteBuffer pixels = STBImage.stbi_load_from_memory(bytes, w, h, comp, format == null ? 0 : format.components);
if (pixels == null) {
throw new IOException("Could not load image: " + STBImage.stbi_failure_reason());
}
long address = MemoryUtil.memAddress(pixels);
MEMORY_POOL.malloc(address, pixels.limit());
var9 = new NativeImage(format == null ? NativeImage.Format.getStbFormat(comp.get(0)) : format, w.get(0), h.get(0), true, address);
}
return var9;
}
}
private void checkAllocated() {
if (this.pixels == 0L) {
throw new IllegalStateException("Image is not allocated.");
}
}
@Override
public void close() {
if (this.pixels != 0L) {
if (this.useStbFree) {
STBImage.nstbi_image_free(this.pixels);
} else {
MemoryUtil.nmemFree(this.pixels);
}
MEMORY_POOL.free(this.pixels);
}
this.pixels = 0L;
}
public boolean isClosed() {
return this.pixels == 0L;
}
public int getWidth() {
return this.width;
}
public int getHeight() {
return this.height;
}
public NativeImage.Format format() {
return this.format;
}
private int getPixelABGR(int x, int y) {
if (this.format != NativeImage.Format.RGBA) {
throw new IllegalArgumentException(String.format(Locale.ROOT, "getPixelRGBA only works on RGBA images; have %s", this.format));
} else if (this.isOutsideBounds(x, y)) {
throw new IllegalArgumentException(String.format(Locale.ROOT, "(%s, %s) outside of image bounds (%s, %s)", x, y, this.width, this.height));
} else {
this.checkAllocated();
long offset = (x + (long)y * this.width) * 4L;
return MemoryUtil.memGetInt(this.pixels + offset);
}
}
public int getPixel(int x, int y) {
return ARGB.fromABGR(this.getPixelABGR(x, y));
}
public void setPixelABGR(int x, int y, int pixel) {
if (this.format != NativeImage.Format.RGBA) {
throw new IllegalArgumentException(String.format(Locale.ROOT, "setPixelRGBA only works on RGBA images; have %s", this.format));
} else if (this.isOutsideBounds(x, y)) {
throw new IllegalArgumentException(String.format(Locale.ROOT, "(%s, %s) outside of image bounds (%s, %s)", x, y, this.width, this.height));
} else {
this.checkAllocated();
long offset = (x + (long)y * this.width) * 4L;
MemoryUtil.memPutInt(this.pixels + offset, pixel);
}
}
public void setPixel(int x, int y, int pixel) {
this.setPixelABGR(x, y, ARGB.toABGR(pixel));
}
public NativeImage mappedCopy(IntUnaryOperator function) {
if (this.format != NativeImage.Format.RGBA) {
throw new IllegalArgumentException(String.format(Locale.ROOT, "function application only works on RGBA images; have %s", this.format));
} else {
this.checkAllocated();
NativeImage result = new NativeImage(this.width, this.height, false);
int pixelCount = this.width * this.height;
IntBuffer sourceBuffer = MemoryUtil.memIntBuffer(this.pixels, pixelCount);
IntBuffer targetBuffer = MemoryUtil.memIntBuffer(result.pixels, pixelCount);
for (int i = 0; i < pixelCount; i++) {
int pixel = ARGB.fromABGR(sourceBuffer.get(i));
int modified = function.applyAsInt(pixel);
targetBuffer.put(i, ARGB.toABGR(modified));
}
return result;
}
}
public int[] getPixelsABGR() {
if (this.format != NativeImage.Format.RGBA) {
throw new IllegalArgumentException(String.format(Locale.ROOT, "getPixels only works on RGBA images; have %s", this.format));
} else {
this.checkAllocated();
int[] result = new int[this.width * this.height];
MemoryUtil.memIntBuffer(this.pixels, this.width * this.height).get(result);
return result;
}
}
public int[] getPixels() {
int[] result = this.getPixelsABGR();
for (int i = 0; i < result.length; i++) {
result[i] = ARGB.fromABGR(result[i]);
}
return result;
}
public byte getLuminanceOrAlpha(int x, int y) {
if (!this.format.hasLuminanceOrAlpha()) {
throw new IllegalArgumentException(String.format(Locale.ROOT, "no luminance or alpha in %s", this.format));
} else if (this.isOutsideBounds(x, y)) {
throw new IllegalArgumentException(String.format(Locale.ROOT, "(%s, %s) outside of image bounds (%s, %s)", x, y, this.width, this.height));
} else {
int offset = (x + y * this.width) * this.format.components() + this.format.luminanceOrAlphaOffset() / 8;
return MemoryUtil.memGetByte(this.pixels + offset);
}
}
@Deprecated
public int[] makePixelArray() {
if (this.format != NativeImage.Format.RGBA) {
throw new UnsupportedOperationException("can only call makePixelArray for RGBA images.");
} else {
this.checkAllocated();
int[] pixels = new int[this.getWidth() * this.getHeight()];
for (int y = 0; y < this.getHeight(); y++) {
for (int x = 0; x < this.getWidth(); x++) {
pixels[x + y * this.getWidth()] = this.getPixel(x, y);
}
}
return pixels;
}
}
public void writeToFile(File file) throws IOException {
this.writeToFile(file.toPath());
}
public boolean copyFromFont(FT_Face face, int index) {
if (this.format.components() != 1) {
throw new IllegalArgumentException("Can only write fonts into 1-component images.");
} else if (FreeTypeUtil.checkError(FreeType.FT_Load_Glyph(face, index, 4), "Loading glyph")) {
return false;
} else {
FT_GlyphSlot glyph = Objects.requireNonNull(face.glyph(), "Glyph not initialized");
FT_Bitmap bitmap = glyph.bitmap();
if (bitmap.pixel_mode() != 2) {
throw new IllegalStateException("Rendered glyph was not 8-bit grayscale");
} else if (bitmap.width() == this.getWidth() && bitmap.rows() == this.getHeight()) {
int bufferSize = bitmap.width() * bitmap.rows();
ByteBuffer buffer = Objects.requireNonNull(bitmap.buffer(bufferSize), "Glyph has no bitmap");
MemoryUtil.memCopy(MemoryUtil.memAddress(buffer), this.pixels, bufferSize);
return true;
} else {
throw new IllegalArgumentException(
String.format(
Locale.ROOT,
"Glyph bitmap of size %sx%s does not match image of size: %sx%s",
bitmap.width(),
bitmap.rows(),
this.getWidth(),
this.getHeight()
)
);
}
}
}
public void writeToFile(Path file) throws IOException {
if (!this.format.supportedByStb()) {
throw new UnsupportedOperationException("Don't know how to write format " + this.format);
} else {
this.checkAllocated();
try (WritableByteChannel out = Files.newByteChannel(file, OPEN_OPTIONS)) {
if (!this.writeToChannel(out)) {
throw new IOException("Could not write image to the PNG file \"" + file.toAbsolutePath() + "\": " + STBImage.stbi_failure_reason());
}
}
}
}
private boolean writeToChannel(WritableByteChannel output) throws IOException {
NativeImage.WriteCallback writer = new NativeImage.WriteCallback(output);
boolean var4;
try {
int height = Math.min(this.getHeight(), Integer.MAX_VALUE / this.getWidth() / this.format.components());
if (height < this.getHeight()) {
LOGGER.warn("Dropping image height from {} to {} to fit the size into 32-bit signed int", this.getHeight(), height);
}
if (STBImageWrite.nstbi_write_png_to_func(writer.address(), 0L, this.getWidth(), height, this.format.components(), this.pixels, 0) != 0) {
writer.throwIfException();
return true;
}
var4 = false;
} finally {
writer.free();
}
return var4;
}
public void copyFrom(NativeImage from) {
if (from.format() != this.format) {
throw new UnsupportedOperationException("Image formats don't match.");
} else {
int components = this.format.components();
this.checkAllocated();
from.checkAllocated();
if (this.width == from.width) {
MemoryUtil.memCopy(from.pixels, this.pixels, Math.min(this.size, from.size));
} else {
int minWidth = Math.min(this.getWidth(), from.getWidth());
int minHeight = Math.min(this.getHeight(), from.getHeight());
for (int y = 0; y < minHeight; y++) {
int fromOffset = y * from.getWidth() * components;
int toOffset = y * this.getWidth() * components;
MemoryUtil.memCopy(from.pixels + fromOffset, this.pixels + toOffset, minWidth);
}
}
}
}
public void fillRect(int xs, int ys, int width, int height, int pixel) {
for (int y = ys; y < ys + height; y++) {
for (int x = xs; x < xs + width; x++) {
this.setPixel(x, y, pixel);
}
}
}
public void copyRect(int startX, int startY, int offsetX, int offsetY, int sizeX, int sizeY, boolean swapX, boolean swapY) {
this.copyRect(this, startX, startY, startX + offsetX, startY + offsetY, sizeX, sizeY, swapX, swapY);
}
public void copyRect(NativeImage target, int sourceX, int sourceY, int targetX, int targetY, int sizeX, int sizeY, boolean swapX, boolean swapY) {
for (int y = 0; y < sizeY; y++) {
for (int x = 0; x < sizeX; x++) {
int dx = swapX ? sizeX - 1 - x : x;
int dy = swapY ? sizeY - 1 - y : y;
int source = this.getPixelABGR(sourceX + x, sourceY + y);
target.setPixelABGR(targetX + dx, targetY + dy, source);
}
}
}
public void resizeSubRectTo(int sourceX, int sourceY, int sizeX, int sizeY, NativeImage to) {
this.checkAllocated();
if (to.format() != this.format) {
throw new UnsupportedOperationException("resizeSubRectTo only works for images of the same format.");
} else {
int components = this.format.components();
STBImageResize.nstbir_resize_uint8_linear(
this.pixels + (sourceX + sourceY * this.getWidth()) * components,
sizeX,
sizeY,
this.getWidth() * components,
to.pixels,
to.getWidth(),
to.getHeight(),
0,
components
);
}
}
public void untrack() {
DebugMemoryUntracker.untrack(this.pixels);
}
public long getPointer() {
return this.pixels;
}
public Transparency computeTransparency(int x0, int y0, int x1, int y1) {
this.checkAllocated();
if (this.format != NativeImage.Format.RGBA) {
return Transparency.NONE;
} else if (x0 >= 0 && y0 >= 0 && x1 <= this.width && y1 <= this.height) {
if ((long)this.width * this.height * 4L > 2147483647L) {
throw new IllegalArgumentException("Image of size " + this.width + "x" + this.height + " is too large to compute translucency");
} else {
boolean hasTransparentPixel = false;
boolean hasTranslucentPixel = false;
IntBuffer buffer = MemoryUtil.memIntBuffer(this.pixels, this.width * this.height);
for (int y = y0; y < y1; y++) {
for (int x = x0; x < x1; x++) {
int alpha = ARGB.alpha(buffer.get(x + y * this.width));
if (alpha == 0) {
hasTransparentPixel = true;
} else if (alpha != 255) {
hasTranslucentPixel = true;
}
}
}
return Transparency.of(hasTransparentPixel, hasTranslucentPixel);
}
} else {
throw new IllegalArgumentException(
"Cannot compute translucency out of bounds: [" + x0 + ", " + y0 + ", " + x1 + ", " + y1 + "] in " + this.width + "x" + this.height + " image"
);
}
}
public Transparency computeTransparency() {
return this.computeTransparency(0, 0, this.width, this.height);
}
@OnlyIn(Dist.CLIENT)
public static enum Format {
RGBA(4, true, true, true, false, true, 0, 8, 16, 255, 24, true),
RGB(3, true, true, true, false, false, 0, 8, 16, 255, 255, true),
LUMINANCE_ALPHA(2, false, false, false, true, true, 255, 255, 255, 0, 8, true),
LUMINANCE(1, false, false, false, true, false, 0, 0, 0, 0, 255, true);
private final int components;
private final boolean hasRed;
private final boolean hasGreen;
private final boolean hasBlue;
private final boolean hasLuminance;
private final boolean hasAlpha;
private final int redOffset;
private final int greenOffset;
private final int blueOffset;
private final int luminanceOffset;
private final int alphaOffset;
private final boolean supportedByStb;
private Format(
int components,
boolean hasRed,
boolean hasGreen,
boolean hasBlue,
boolean hasLuminance,
boolean hasAlpha,
int redOffset,
int greenOffset,
int blueOffset,
int luminanceOffset,
int alphaOffset,
boolean supportedByStb
) {
this.components = components;
this.hasRed = hasRed;
this.hasGreen = hasGreen;
this.hasBlue = hasBlue;
this.hasLuminance = hasLuminance;
this.hasAlpha = hasAlpha;
this.redOffset = redOffset;
this.greenOffset = greenOffset;
this.blueOffset = blueOffset;
this.luminanceOffset = luminanceOffset;
this.alphaOffset = alphaOffset;
this.supportedByStb = supportedByStb;
}
public int components() {
return this.components;
}
public boolean hasRed() {
return this.hasRed;
}
public boolean hasGreen() {
return this.hasGreen;
}
public boolean hasBlue() {
return this.hasBlue;
}
public boolean hasLuminance() {
return this.hasLuminance;
}
public boolean hasAlpha() {
return this.hasAlpha;
}
public int redOffset() {
return this.redOffset;
}
public int greenOffset() {
return this.greenOffset;
}
public int blueOffset() {
return this.blueOffset;
}
public int luminanceOffset() {
return this.luminanceOffset;
}
public int alphaOffset() {
return this.alphaOffset;
}
public boolean hasLuminanceOrRed() {
return this.hasLuminance || this.hasRed;
}
public boolean hasLuminanceOrGreen() {
return this.hasLuminance || this.hasGreen;
}
public boolean hasLuminanceOrBlue() {
return this.hasLuminance || this.hasBlue;
}
public boolean hasLuminanceOrAlpha() {
return this.hasLuminance || this.hasAlpha;
}
public int luminanceOrRedOffset() {
return this.hasLuminance ? this.luminanceOffset : this.redOffset;
}
public int luminanceOrGreenOffset() {
return this.hasLuminance ? this.luminanceOffset : this.greenOffset;
}
public int luminanceOrBlueOffset() {
return this.hasLuminance ? this.luminanceOffset : this.blueOffset;
}
public int luminanceOrAlphaOffset() {
return this.hasLuminance ? this.luminanceOffset : this.alphaOffset;
}
public boolean supportedByStb() {
return this.supportedByStb;
}
private static NativeImage.Format getStbFormat(int i) {
switch (i) {
case 1:
return LUMINANCE;
case 2:
return LUMINANCE_ALPHA;
case 3:
return RGB;
case 4:
default:
return RGBA;
}
}
}
@OnlyIn(Dist.CLIENT)
private static class WriteCallback extends STBIWriteCallback {
private final WritableByteChannel output;
private @Nullable IOException exception;
private WriteCallback(WritableByteChannel output) {
this.output = output;
}
@Override
public void invoke(long context, long data, int size) {
ByteBuffer dataBuf = getData(data, size);
try {
this.output.write(dataBuf);
} catch (IOException var8) {
this.exception = var8;
}
}
public void throwIfException() throws IOException {
if (this.exception != null) {
throw this.exception;
}
}
}
}引用的其他类
-
- 引用位置:
方法调用 - 关联成员:
DebugMemoryUntracker.untrack()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
TextureUtil.readResource()
- 引用位置:
-
- 引用位置:
方法调用/返回值 - 关联成员:
Transparency.of()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
FreeTypeUtil.checkError()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
ARGB.alpha(), ARGB.fromABGR(), ARGB.toABGR()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
PngInfo.validateHeader()
- 引用位置:
-
- 引用位置:
参数
- 引用位置: