All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.humbleui.skija.Bitmap Maven / Gradle / Ivy

There is a newer version: 0.116.3
Show newest version
package io.github.humbleui.skija;

import java.lang.ref.*;
import java.nio.*;
import lombok.*;
import org.jetbrains.annotations.*;
import io.github.humbleui.skija.impl.*;
import io.github.humbleui.types.*;

public class Bitmap extends Managed implements IHasImageInfo {
    static { Library.staticLoad(); }

    @ApiStatus.Internal
    public ImageInfo _imageInfo = null;
    
    @ApiStatus.Internal
    public Bitmap(long ptr) {
        super(ptr, _FinalizerHolder.PTR);
    }

    /**
     * Creates an empty Bitmap without pixels, with {@link ColorType#UNKNOWN},
     * {@link ColorAlphaType#UNKNOWN}, and with a width and height of zero. 
     * PixelRef origin is set to (0, 0). Bitmap is not volatile.
     *
     * Use {@link #setImageInfo(ImageInfo, long)} to associate ColorType, ColorAlphaType, width, and height after Bitmap has been created.
     * 
     * @see https://fiddle.skia.org/c/@Bitmap_empty_constructor
     */
    public Bitmap() {
        this(_nMake());
        Stats.onNativeCall();
    }

    /**
     * Copies settings from src to returned Bitmap. Shares pixels if src has pixels
     * allocated, so both bitmaps reference the same pixels.
     *
     * @return  copy of src
     *
     * @see https://fiddle.skia.org/c/@Bitmap_copy_const_SkBitmap
     */
    @NotNull @Contract("-> new")
    public Bitmap makeClone() {
        try {
            Stats.onNativeCall();
            return new Bitmap(_nMakeClone(_ptr));
        } finally {
            Reference.reachabilityFence(this);
        }
    }

    @NotNull @Contract("-> new")
    public static Bitmap makeFromImage(@NotNull Image image) {
        assert image != null : "Can’t makeFromImage with image == null";
        Bitmap bitmap = new Bitmap();
        bitmap.allocPixels(image.getImageInfo());
        if (image.readPixels(bitmap))
            return bitmap;
        else {
            bitmap.close();
            throw new RuntimeException("Failed to readPixels from " + image);
        }
    }

    /**
     * Swaps the fields of the two bitmaps.
     *
     * @param other  Bitmap exchanged with original
     *
     * @see https://fiddle.skia.org/c/@Bitmap_swap
     */
    public void swap(@NotNull Bitmap other) {
        Stats.onNativeCall();
        _nSwap(_ptr, Native.getPtr(other));
        _imageInfo = null;
        Reference.reachabilityFence(this);
        Reference.reachabilityFence(other);
    }

    @Override @NotNull
    public ImageInfo getImageInfo() {
        try {
            if (_imageInfo == null) {
                Stats.onNativeCall();
                _imageInfo = _nGetImageInfo(_ptr);
            }
            return _imageInfo;
        } finally {
            Reference.reachabilityFence(this);
        }        
    }


    /**
     * Returns number of pixels that fit on row. Should be greater than or equal to
     * getWidth().
     *
     * @return  maximum pixels per row
     */
    public int getRowBytesAsPixels() {
        try {
            Stats.onNativeCall();
            return _nGetRowBytesAsPixels(_ptr);
        } finally {
            Reference.reachabilityFence(this);
        }
    }

    /**
     * Returns true if PixelRef is null.
     *
     * Does not check if width or height are zero; call {@link #drawsNothing()}
     * to check width, height, and PixelRef.
     * 
     * @return  true if no PixelRef is associated
     */
    public boolean isNull() {
        try {
            Stats.onNativeCall();
            return _nIsNull(_ptr);
        } finally {
            Reference.reachabilityFence(this);
        }
    }

    /**
     * Returns true if width or height are zero, or if PixelRef is null.
     * If true, Bitmap has no effect when drawn or drawn into.
     *
     * @return  true if drawing has no effect
     */
    public boolean drawsNothing() {
        return isEmpty() || isNull();
    }

    /**
     * Returns row bytes, the interval from one pixel row to the next. Row bytes
     * is at least as large as: getWidth() * getBytesPerPixel().
     *
     * Returns zero if getColorType() is {@link ColorType#UNKNOWN}, or if row bytes
     * supplied to {@link #setImageInfo(ImageInfo)} is not large enough to hold a row of pixels.
     *
     * @return  byte length of pixel row
     */
    public long getRowBytes() {
        try {
            Stats.onNativeCall();
            return _nGetRowBytes(_ptr);
        } finally {
            Reference.reachabilityFence(this);
        }
    }

    /**
     * 

Sets alpha type, if argument is compatible with current color type. * Returns true unless argument is {@link ColorAlphaType#UNKNOWN} and current * value is {@link ColorAlphaType#UNKNOWN}.

* *

Returns true if current color type is {@link ColorType#UNKNOWN}. * Argument is ignored, and alpha type remains {@link ColorAlphaType#UNKNOWN}.

* *

Returns true if current color type is {@link ColorType#RGB_565} or * {@link ColorType#GRAY_8}. Argument is ignored, and alpha type remains * {@link ColorAlphaType#OPAQUE}.

* *

If current color type is {@link ColorType#ARGB_4444}, {@link ColorType#RGBA_8888}, * {@link ColorType#BGRA_8888}, or {@link ColorType#RGBA_F16}: returns true unless * argument is {@link ColorAlphaType#UNKNOWN} and current alpha type is not * {@link ColorAlphaType#UNKNOWN}. If current alpha type is * {@link ColorAlphaType#UNKNOWN}, argument is ignored.

* *

If current color type is {@link ColorType#ALPHA_8}, returns true unless * argument is {@link ColorAlphaType#UNKNOWN} and current alpha type is not * {@link ColorAlphaType#UNKNOWN}. If current alpha type is * {@link ColorAlphaType#UNKNOWN}, argument is ignored. If argument is * {@link ColorAlphaType#UNPREMUL}, it is treated as {@link ColorAlphaType#PREMUL}.

* *

This changes alpha type in PixelRef; all bitmaps sharing PixelRef * are affected.

* * @return true if alpha type is set * * @see https://fiddle.skia.org/c/@Bitmap_setAlphaType */ public boolean setAlphaType(ColorAlphaType alphaType) { try { Stats.onNativeCall(); _imageInfo = null; return _nSetAlphaType(_ptr, alphaType.ordinal()); } finally { Reference.reachabilityFence(this); } } /** * Returns minimum memory required for pixel storage. * Does not include unused memory on last row when getRowBytesAsPixels() exceeds getWidth(). * Returns zero if height() or width() is 0. * Returns getHeight() times getRowBytes() if getColorType() is {@link ColorType#UNKNOWN}. * * @return size in bytes of image buffer */ public long computeByteSize() { try { Stats.onNativeCall(); return _nComputeByteSize(_ptr); } finally { Reference.reachabilityFence(this); } } /** *

Returns true if pixels can not change.

* *

Most immutable Bitmap checks trigger an assert only on debug builds.

* * @return true if pixels are immutable * * @see https://fiddle.skia.org/c/@Bitmap_isImmutable */ public boolean isImmutable() { try { Stats.onNativeCall(); return _nIsImmutable(_ptr); } finally { Reference.reachabilityFence(this); } } /** *

Sets internal flag to mark Bitmap as immutable. Once set, pixels can not change. * Any other bitmap sharing the same PixelRef are also marked as immutable. * Once PixelRef is marked immutable, the setting cannot be cleared.

* *

Writing to immutable Bitmap pixels triggers an assert on debug builds.

* * @see https://fiddle.skia.org/c/@Bitmap_setImmutable */ @NotNull @Contract("-> this") public Bitmap setImmutable() { Stats.onNativeCall(); _nSetImmutable(_ptr); return this; } /** *

Resets to its initial state; all fields are set to zero, as if Bitmap had * been initialized by Bitmap().

* *

Sets width, height, row bytes to zero; pixel address to nullptr; ColorType to * {@link ColorType#UNKNOWN}; and ColorAlphaType to {@link ColorAlphaType#UNKNOWN}.

* *

If PixelRef is allocated, its reference count is decreased by one, releasing * its memory if Bitmap is the sole owner.

* * @see https://fiddle.skia.org/c/@Bitmap_reset */ @NotNull @Contract("-> this") public Bitmap reset() { Stats.onNativeCall(); _imageInfo = null; _nReset(_ptr); return this; } /** *

Returns true if all pixels are opaque. ColorType determines how pixels * are encoded, and whether pixel describes alpha. Returns true for ColorType * without alpha in each pixel; for other ColorType, returns true if all * pixels have alpha values equivalent to 1.0 or greater.

* *

For {@link ColorType#RGB_565} or {@link ColorType#GRAY_8}: always * returns true. For {@link ColorType#ALPHA_8}, {@link ColorType#BGRA_8888}, * {@link ColorType#RGBA_8888}: returns true if all pixel alpha values are 255. * For {@link ColorType#ARGB_4444}: returns true if all pixel alpha values are 15. * For {@link ColorType#RGBA_F16}: returns true if all pixel alpha values are 1.0 or * greater.

* *

Returns false for {@link ColorType#UNKNOWN}. * * @return true if all pixels have opaque values or ColorType is opaque */ public boolean computeIsOpaque() { try { Stats.onNativeCall(); return _nComputeIsOpaque(_ptr); } finally { Reference.reachabilityFence(this); } } /** * Returns IRect { 0, 0, width(), height() }. * * @see https://fiddle.skia.org/c/@Bitmap_getBounds_2 */ @NotNull public IRect getBounds() { return IRect.makeXYWH(0, 0, getWidth(), getHeight()); } /** * Returns the bounds of this bitmap, offset by its PixelRef origin. */ @NotNull public IRect getSubset() { IPoint origin = getPixelRefOrigin(); return IRect.makeXYWH(origin.getX(), origin.getY(), getWidth(), getHeight()); } /** *

Sets width, height, ColorAlphaType, ColorType, ColorSpace. * Frees pixels, and returns true if successful.

* *

imageInfo.getAlphaType() may be altered to a value permitted by imageInfo.getColorSpace(). * If imageInfo.getColorType() is {@link ColorType#UNKNOWN}, imageInfo.getAlphaType() is * set to {@link ColorAlphaType#UNKNOWN}. * If imageInfo.colorType() is {@link ColorType#ALPHA_8} and imageInfo.getAlphaType() is * {@link ColorAlphaType#UNPREMUL}, imageInfo.getAlphaType() is replaced by {@link ColorAlphaType#PREMUL}. * If imageInfo.colorType() is {@link ColorType#RGB_565} or {@link ColorType#GRAY_8}, * imageInfo.getAlphaType() is set to {@link ColorAlphaType#OPAQUE}. * If imageInfo.colorType() is {@link ColorType#ARGB_4444}, {@link ColorType#RGBA_8888}, * {@link ColorType#BGRA_8888}, or {@link ColorType#RGBA_F16}: imageInfo.getAlphaType() remains * unchanged.

* *

Calls reset() and returns false if: * - rowBytes exceeds 31 bits * - imageInfo.getWidth() is negative * - imageInfo.getHeight() is negative * - rowBytes is positive and less than imageInfo.getWidth() times imageInfo.getBytesPerPixel()

* * @param imageInfo contains width, height, AlphaType, ColorType, ColorSpace * @return true if ImageInfo set successfully * * @see https://fiddle.skia.org/c/@Bitmap_setInfo */ public boolean setImageInfo(@NotNull ImageInfo imageInfo) { _imageInfo = null; return setImageInfo(imageInfo, 0); } /** *

Sets width, height, ColorAlphaType, ColorType, ColorSpace, and optional * rowBytes. Frees pixels, and returns true if successful.

* *

imageInfo.getAlphaType() may be altered to a value permitted by imageInfo.getColorSpace(). * If imageInfo.getColorType() is {@link ColorType#UNKNOWN}, imageInfo.getAlphaType() is * set to {@link ColorAlphaType#UNKNOWN}. * If imageInfo.colorType() is {@link ColorType#ALPHA_8} and imageInfo.getAlphaType() is * {@link ColorAlphaType#UNPREMUL}, imageInfo.getAlphaType() is replaced by {@link ColorAlphaType#PREMUL}. * If imageInfo.colorType() is {@link ColorType#RGB_565} or {@link ColorType#GRAY_8}, * imageInfo.getAlphaType() is set to {@link ColorAlphaType#OPAQUE}. * If imageInfo.colorType() is {@link ColorType#ARGB_4444}, {@link ColorType#RGBA_8888}, * {@link ColorType#BGRA_8888}, or {@link ColorType#RGBA_F16}: imageInfo.getAlphaType() remains * unchanged.

* *

rowBytes must equal or exceed imageInfo.getMinRowBytes(). If imageInfo.getColorSpace() is * {@link ColorType#UNKNOWN}, rowBytes is ignored and treated as zero; for all other * ColorSpace values, rowBytes of zero is treated as imageInfo.getMinRowBytes().

* *

Calls reset() and returns false if: * - rowBytes exceeds 31 bits * - imageInfo.getWidth() is negative * - imageInfo.getHeight() is negative * - rowBytes is positive and less than imageInfo.getWidth() times imageInfo.getBytesPerPixel()

* * @param imageInfo contains width, height, AlphaType, ColorType, ColorSpace * @param rowBytes imageInfo.getMinRowBytes() or larger; or zero * @return true if ImageInfo set successfully * * @see https://fiddle.skia.org/c/@Bitmap_setInfo */ public boolean setImageInfo(@NotNull ImageInfo imageInfo, long rowBytes) { try { _imageInfo = null; Stats.onNativeCall(); return _nSetImageInfo(_ptr, imageInfo._width, imageInfo._height, imageInfo._colorInfo._colorType.ordinal(), imageInfo._colorInfo._alphaType.ordinal(), Native.getPtr(imageInfo._colorInfo._colorSpace), rowBytes); } finally { Reference.reachabilityFence(this); Reference.reachabilityFence(imageInfo._colorInfo._colorSpace); } } /** *

Sets ImageInfo to info following the rules in setImageInfo() and allocates pixel * memory. Memory is zeroed.

* *

Returns false and calls reset() if ImageInfo could not be set, or memory could * not be allocated, or memory could not optionally be zeroed.

* *

On most platforms, allocating pixel memory may succeed even though there is * not sufficient memory to hold pixels; allocation does not take place * until the pixels are written to. The actual behavior depends on the platform * implementation of calloc().

* * @param imageInfo contains width, height, ColorAlphaType, ColorType, ColorSpace * @param zeroPixels whether pixels should be zeroed * @return true if pixels allocation is successful */ public boolean allocPixelsFlags(@NotNull ImageInfo imageInfo, boolean zeroPixels) { try { _imageInfo = null; Stats.onNativeCall(); return _nAllocPixelsFlags(_ptr, imageInfo._width, imageInfo._height, imageInfo._colorInfo._colorType.ordinal(), imageInfo._colorInfo._alphaType.ordinal(), Native.getPtr(imageInfo._colorInfo._colorSpace), zeroPixels ? 1 : 0); } finally { Reference.reachabilityFence(this); Reference.reachabilityFence(imageInfo._colorInfo._colorSpace); } } /** *

Sets ImageInfo to info following the rules in setImageInfo() and allocates pixel * memory. rowBytes must equal or exceed info.width() times info.bytesPerPixel(), * or equal zero.

* *

Returns false and calls reset() if ImageInfo could not be set, or memory could * not be allocated.

* *

On most platforms, allocating pixel memory may succeed even though there is * not sufficient memory to hold pixels; allocation does not take place * until the pixels are written to. The actual behavior depends on the platform * implementation of malloc().

* * @param info contains width, height, ColorAlphaType, ColorType, ColorSpace * @param rowBytes size of pixel row or larger; may be zero * @return true if pixel storage is allocated */ public boolean allocPixels(@NotNull ImageInfo info, long rowBytes) { try { _imageInfo = null; Stats.onNativeCall(); return _nAllocPixelsRowBytes(_ptr, info._width, info._height, info._colorInfo._colorType.ordinal(), info._colorInfo._alphaType.ordinal(), Native.getPtr(info._colorInfo._colorSpace), rowBytes); } finally { Reference.reachabilityFence(this); Reference.reachabilityFence(info._colorInfo._colorSpace); } } /** *

Sets ImageInfo to info following the rules in {@link #setImageInfo(ImageInfo, long)} and allocates pixel * memory.

* *

Returns false and calls reset() if ImageInfo could not be set, or memory could * not be allocated.

* *

On most platforms, allocating pixel memory may succeed even though there is * not sufficient memory to hold pixels; allocation does not take place * until the pixels are written to. The actual behavior depends on the platform * implementation of malloc().

* * @param imageInfo contains width, height, ColorAlphaType, ColorType, ColorSpace * @return true if pixel storage is allocated * @see https://fiddle.skia.org/c/@Bitmap_allocPixels_2 */ public boolean allocPixels(@NotNull ImageInfo imageInfo) { return allocPixels(imageInfo, imageInfo.getMinRowBytes()); } /** * Sets ImageInfo to width, height, and native color type; and allocates * pixel memory. Sets ImageInfo to {@link ColorAlphaType#PREMUL}. * * Calls reset() and returns false if width exceeds 29 bits or is negative, * or height is negative. * * Returns false if allocation fails. * * Use to create Bitmap that matches the native pixel arrangement on * the platform. Bitmap drawn to output device skips converting its pixel format. * * @param width pixel column count; must be zero or greater * @param height pixel row count; must be zero or greater * @return true if pixel storage is allocated */ public boolean allocN32Pixels(int width, int height) { return allocN32Pixels(width, height, false); } /** * Sets ImageInfo to width, height, and native color type; and allocates * pixel memory. If opaque is true, sets ImageInfo to {@link ColorAlphaType#OPAQUE}; * otherwise, sets to {@link ColorAlphaType#PREMUL}. * * Calls reset() and returns false if width exceeds 29 bits or is negative, * or height is negative. * * Returns false if allocation fails. * * Use to create Bitmap that matches the native pixel arrangement on * the platform. Bitmap drawn to output device skips converting its pixel format. * * @param width pixel column count; must be zero or greater * @param height pixel row count; must be zero or greater * @param opaque true if pixels do not have transparency * @return true if pixel storage is allocated */ public boolean allocN32Pixels(int width, int height, boolean opaque) { return allocPixels(ImageInfo.makeN32(width, height, opaque ? ColorAlphaType.OPAQUE : ColorAlphaType.PREMUL)); } public boolean installPixels(byte[] pixels) { return installPixels(getImageInfo(), pixels, getRowBytes()); } /** *

Sets ImageInfo to info following the rules in setImageInfo(), and creates PixelRef * containing pixels and rowBytes.

* *

If ImageInfo could not be set, or rowBytes is less than info.getMinRowBytes(): * calls reset(), and returns false.

* * @param info contains width, height, SkAlphaType, SkColorType, SkColorSpace * @param pixels pixel storage * @param rowBytes size of pixel row or larger * @return true if ImageInfo is set to info */ public boolean installPixels(@NotNull ImageInfo info, @Nullable byte[] pixels, long rowBytes) { try { _imageInfo = null; Stats.onNativeCall(); return _nInstallPixels(_ptr, info._width, info._height, info._colorInfo._colorType.ordinal(), info._colorInfo._alphaType.ordinal(), Native.getPtr(info._colorInfo._colorSpace), pixels, rowBytes); } finally { Reference.reachabilityFence(this); Reference.reachabilityFence(info._colorInfo._colorSpace); } } /** *

Allocates pixel memory with HeapAllocator, and replaces existing PixelRef. * The allocation size is determined by ImageInfo width, height, and ColorType.

* *

Returns false if info().colorType() is {@link ColorType#UNKNOWN}, or allocation fails.

* * @return true if the allocation succeeds */ public boolean allocPixels() { try { _imageInfo = null; Stats.onNativeCall(); return _nAllocPixels(_ptr); } finally { Reference.reachabilityFence(this); } } /** * Returns PixelRef, which contains: pixel base address; its dimensions; and * rowBytes(), the interval from one row to the next. * PixelRef may be shared by multiple bitmaps. * If PixelRef has not been set, returns null. * * @return SkPixelRef, or null */ @Nullable public PixelRef getPixelRef() { try { Stats.onNativeCall(); long res = _nGetPixelRef(_ptr); return res == 0 ? null : new PixelRef(res); } finally { Reference.reachabilityFence(this); } } /** *

Returns origin of pixels within PixelRef. Bitmap bounds is always contained * by PixelRef bounds, which may be the same size or larger. Multiple Bitmap * can share the same PixelRef, where each Bitmap has different bounds.

* *

The returned origin added to Bitmap dimensions equals or is smaller than the * PixelRef dimensions.

* *

Returns (0, 0) if PixelRef is nullptr.

* * @return pixel origin within PixelRef * * @see https://fiddle.skia.org/c/@Bitmap_pixelRefOrigin */ @NotNull public IPoint getPixelRefOrigin() { try { Stats.onNativeCall(); long res = _nGetPixelRefOrigin(_ptr); return new IPoint((int) (res & 0xFFFFFFFF), (int) (res >>> 32)); } finally { Reference.reachabilityFence(this); } } /** *

Replaces pixelRef and origin in Bitmap. dx and dy specify the offset * within the PixelRef pixels for the top-left corner of the bitmap.

* *

Asserts in debug builds if dx or dy are out of range. Pins dx and dy * to legal range in release builds.

* *

The caller is responsible for ensuring that the pixels match the * ColorType and ColorAlphaType in ImageInfo.

* * @param pixelRef PixelRef describing pixel address and rowBytes() * @param dx column offset in PixelRef for bitmap origin * @param dy row offset in PixelRef for bitmap origin * * @see https://fiddle.skia.org/c/@Bitmap_setPixelRef */ @NotNull @Contract("_, _, _ -> this") public Bitmap setPixelRef(@Nullable PixelRef pixelRef, int dx, int dy) { try { _imageInfo = null; Stats.onNativeCall(); _nSetPixelRef(_ptr, Native.getPtr(pixelRef), dx, dy); return this; } finally { Reference.reachabilityFence(pixelRef); } } /** * Returns true if Bitmap can be drawn. * * @return true if getPixels() is not null */ public boolean isReadyToDraw() { try { Stats.onNativeCall(); return _nIsReadyToDraw(_ptr); } finally { Reference.reachabilityFence(this); } } /** *

Returns a unique value corresponding to the pixels in PixelRef. * Returns a different value after notifyPixelsChanged() has been called. * Returns zero if PixelRef is null.

* *

Determines if pixels have changed since last examined.

* * @return unique value for pixels in PixelRef * * @see https://fiddle.skia.org/c/@Bitmap_getGenerationID */ public int getGenerationId() { try { Stats.onNativeCall(); return _nGetGenerationId(_ptr); } finally { Reference.reachabilityFence(this); } } /** *

Marks that pixels in PixelRef have changed. Subsequent calls to * getGenerationId() return a different value.

* * @see https://fiddle.skia.org/c/@Bitmap_notifyPixelsChanged */ @NotNull @Contract("-> this") public Bitmap notifyPixelsChanged() { try { Stats.onNativeCall(); _nNotifyPixelsChanged(_ptr); return this; } finally { Reference.reachabilityFence(this); } } /** * Replaces pixel values with color, interpreted as being in the colorSpace. * All pixels contained by getBounds() are affected. If the getColorType() is * {@link ColorType#GRAY_8} or {@link ColorType#RGB_565}, then alpha is ignored; RGB is * treated as opaque. If getColorType() is {@link ColorType#ALPHA_8}, then RGB is ignored. * * @param color unpremultiplied color * @param colorSpace SkColorSpace describing the encoding of color * @return this * * @see https://fiddle.skia.org/c/@Bitmap_eraseColor */ @NotNull @Contract("_, _ -> this") public Bitmap erase(@NotNull Color4f color, @Nullable ColorSpace colorSpace) { try { assert color != null : "Bitmap::erase expected color != null"; Stats.onNativeCall(); _nErase4f(_ptr, color._r, color._g, color._b, color._a, Native.getPtr(colorSpace)); return this; } finally { Reference.reachabilityFence(this); } } /** * Replaces pixel values with color. * All pixels contained by getBounds() are affected. If the getColorType() is * {@link ColorType#GRAY_8} or {@link ColorType#RGB_565}, then alpha is ignored; RGB is * treated as opaque. If getColorType() is {@link ColorType#ALPHA_8}, then RGB is ignored. * * @param color unpremultiplied color * @return this * * @see https://fiddle.skia.org/c/@Bitmap_eraseColor */ @NotNull @Contract("_ -> this") public Bitmap erase(@NotNull Color4f color) { return erase(color, (ColorSpace) null); } /** * Replaces pixel values with color, interpreted as being in the colorSpace. * All pixels contained by getBounds() are affected. If the getColorType() is * {@link ColorType#GRAY_8} or {@link ColorType#RGB_565}, then alpha is ignored; RGB is * treated as opaque. If getColorType() is {@link ColorType#ALPHA_8}, then RGB is ignored. * * @param color unpremultiplied color * @param colorSpace SkColorSpace describing the encoding of color * @param area rectangle to fill * @return this * * @see https://fiddle.skia.org/c/@Bitmap_erase */ @NotNull @Contract("_, _, _ -> this") public Bitmap erase(@NotNull Color4f color, @Nullable ColorSpace colorSpace, @NotNull IRect area) { try { assert color != null : "Bitmap::erase expected color != null"; assert area != null : "Bitmap::erase expected area != null"; Stats.onNativeCall(); _nEraseRect4f(_ptr, color._r, color._g, color._b, color._a, Native.getPtr(colorSpace), area._left, area._top, area._right, area._bottom); return this; } finally { Reference.reachabilityFence(this); } } /** * Replaces pixel values with color. * All pixels contained by getBounds() are affected. If the getColorType() is * {@link ColorType#GRAY_8} or {@link ColorType#RGB_565}, then alpha is ignored; RGB is * treated as opaque. If getColorType() is {@link ColorType#ALPHA_8}, then RGB is ignored. * * @param color unpremultiplied color * @param area rectangle to fill * @return this * * @see https://fiddle.skia.org/c/@Bitmap_eraseColor */ @NotNull @Contract("_, _ -> this") public Bitmap erase(@NotNull Color4f color, @NotNull IRect area) { return erase(color, null, area); } /** * Replaces pixel values with color, interpreted as being in the sRGB ColorSpace. * All pixels contained by getBounds() are affected. If the getColorType() is * {@link ColorType#GRAY_8} or {@link ColorType#RGB_565}, then alpha is ignored; RGB is * treated as opaque. If getColorType() is {@link ColorType#ALPHA_8}, then RGB is ignored. * * @param color unpremultiplied color * @return this * * @see https://fiddle.skia.org/c/@Bitmap_eraseColor */ @NotNull @Contract("_ -> this") public Bitmap erase(int color) { try { Stats.onNativeCall(); _nErase(_ptr, color); return this; } finally { Reference.reachabilityFence(this); } } /** * Replaces pixel values inside area with color, interpreted as being in the sRGB * ColorSpace. If area does not intersect getBounds(), call has no effect. * * If the getColorType() is {@link ColorType#GRAY_8} or {@link ColorType#RGB_565}, * then alpha is ignored; RGB is treated as opaque. If getColorType() is * {@link ColorType#ALPHA_8}, then RGB is ignored. * * @param color unpremultiplied color * @param area rectangle to fill * @return this * * @see https://fiddle.skia.org/c/@Bitmap_erase */ @NotNull @Contract("_, _ -> this") public Bitmap erase(int color, @NotNull IRect area) { try { Stats.onNativeCall(); _nEraseRect(_ptr, color, area._left, area._top, area._right, area._bottom); return this; } finally { Reference.reachabilityFence(this); } } /** *

Returns pixel at (x, y) as unpremultiplied color. * Returns black with alpha if ColorType is {@link ColorType#ALPHA_8}.

* *

Input is not validated: out of bounds values of x or y returns undefined values * or may crash if. Fails if ColorType is {@link ColorType#UNKNOWN} or * pixel address is nullptr.

* *

ColorSpace in ImageInfo is ignored. Some color precision may be lost in the * conversion to unpremultiplied color; original pixel data may have additional * precision.

* * @param x column index, zero or greater, and less than getWidth() * @param y row index, zero or greater, and less than getHeight() * @return pixel converted to unpremultiplied color */ public int getColor(int x, int y) { try { Stats.onNativeCall(); return _nGetColor(_ptr, x, y); } finally { Reference.reachabilityFence(this); } } /** *

Returns pixel at (x, y) as unpremultiplied color. * Returns black with alpha if ColorType is {@link ColorType#ALPHA_8}.

* *

Input is not validated: out of bounds values of x or y returns undefined values * or may crash if. Fails if ColorType is {@link ColorType#UNKNOWN} or * pixel address is nullptr.

* *

ColorSpace in ImageInfo is ignored. Some color precision may be lost in the * conversion to unpremultiplied color; original pixel data may have additional * precision.

* * @param x column index, zero or greater, and less than getWidth() * @param y row index, zero or greater, and less than getHeight() * @return pixel converted to unpremultiplied color */ public Color4f getColor4f(int x, int y) { try { Stats.onNativeCall(); return _nGetColor4f(_ptr, x, y); } finally { Reference.reachabilityFence(this); } } /** *

Look up the pixel at (x,y) and return its alpha component, normalized to [0..1]. * This is roughly equivalent to GetColorA(getColor()), but can be more efficent * (and more precise if the pixels store more than 8 bits per component).

* * @param x column index, zero or greater, and less than getWidth() * @param y row index, zero or greater, and less than getHeight() * @return alpha converted to normalized float */ public float getAlphaf(int x, int y) { try { Stats.onNativeCall(); return _nGetAlphaf(_ptr, x, y); } finally { Reference.reachabilityFence(this); } } /** *

Shares PixelRef with dst. Pixels are not copied; this and dst point * to the same pixels; dst.getBounds() are set to the intersection of subset * and the original getBounds().

* *

subset may be larger than getBounds(). Any area outside of getBounds() is ignored.

* *

Any contents of dst are discarded. isVolatile() setting is copied to dst. * dst is set to getColorType(), getAlphaType(), and getColorSpace().

* *

Return false if: *

    *
  • dst is null
  • *
  • PixelRef is null
  • *
  • subset does not intersect getBounds()
  • *
* * @param dst Bitmap set to subset * @param subset rectangle of pixels to reference * @return true if dst is replaced by subset * * @see https://fiddle.skia.org/c/@Bitmap_extractSubset */ public boolean extractSubset(@NotNull Bitmap dst, @NotNull IRect subset) { try { Stats.onNativeCall(); return _nExtractSubset(_ptr, Native.getPtr(dst), subset._left, subset._top, subset._right, subset._bottom); } finally { Reference.reachabilityFence(this); Reference.reachabilityFence(dst); } } @Nullable public byte[] readPixels() { return readPixels(getImageInfo(), getRowBytes(), 0, 0); } /** *

Copies a rect of pixels from Bitmap. Copy starts at (srcX, srcY), * and does not exceed Bitmap (getWidth(), getHeight()).

* *

dstInfo specifies width, height, ColorType, AlphaType, and ColorSpace of * destination. dstRowBytes specifics the gap from one destination row to the next. * Returns true if pixels are copied. Returns false if: * *

    *
  • dstRowBytes is less than dstInfo.getMinRowBytes()
  • *
  • PixelRef is null
  • *
* *

Pixels are copied only if pixel conversion is possible. If Bitmap getColorType() is * {@link ColorType#GRAY_8}, or {@link ColorType#ALPHA_8}; dstInfo.colorType() must match. * If Bitmap getClorType() is {@link ColorType#GRAY_8}, dstInfo.getColorSpace() must match. * If Bitmap getAlphaType() is {@link ColorAlphaType#OPAQUE}, dstInfo.getAlphaType() must * match. If Bitmap getColorSpace() is null, dstInfo.getColorSpace() must match. Returns * false if pixel conversion is not possible.

* *

srcX and srcY may be negative to copy only top or left of source. Returns * false if getWidth() or getHeight() is zero or negative. * Returns false if abs(srcX) >= getWidth(), or if abs(srcY) >= getHeight().

* * @param dstInfo destination width, height, ColorType, AlphaType, ColorSpace * @param dstRowBytes destination row length * @param srcX column index whose absolute value is less than width() * @param srcY row index whose absolute value is less than height() * @return pixel data or null */ @Nullable public byte[] readPixels(@NotNull ImageInfo dstInfo, long dstRowBytes, int srcX, int srcY) { try { Stats.onNativeCall(); return _nReadPixels(_ptr, dstInfo._width, dstInfo._height, dstInfo._colorInfo._colorType.ordinal(), dstInfo._colorInfo._alphaType.ordinal(), Native.getPtr(dstInfo._colorInfo._colorSpace), dstRowBytes, srcX, srcY); } finally { Reference.reachabilityFence(this); Reference.reachabilityFence(dstInfo._colorInfo._colorSpace); } } /** *

Sets dst to alpha described by pixels. Returns false if dst cannot * be written to or dst pixels cannot be allocated.

* * @param dst holds PixelRef to fill with alpha layer * @return true if alpha layer was not constructed in dst PixelRef */ public boolean extractAlpha(@NotNull Bitmap dst) { return extractAlpha(dst, null) != null; } /** *

Sets dst to alpha described by pixels. Returns false if dst cannot * be written to or dst pixels cannot be allocated.

* *

If paint is not null and contains MaskFilter, MaskFilter * generates mask alpha from Bitmap. Returns offset to top-left position for dst * for alignment with Bitmap; (0, 0) unless MaskFilter generates mask.

* * @param dst holds PixelRef to fill with alpha layer * @param paint holds optional MaskFilter; may be null * @return null if alpha layer was not constructed in dst PixelRef, IPoint otherwise */ @Nullable public IPoint extractAlpha(@NotNull Bitmap dst, @Nullable Paint paint) { try { Stats.onNativeCall(); return _nExtractAlpha(_ptr, Native.getPtr(dst), Native.getPtr(paint)); } finally { Reference.reachabilityFence(this); Reference.reachabilityFence(dst); Reference.reachabilityFence(paint); } } /** * If pixel address is available, return ByteBuffer wrapping it. * If pixel address is not available, return null. * * @return ByteBuffer with direct access to pixels, or null * * @see https://fiddle.skia.org/c/@Bitmap_peekPixels */ @Nullable public ByteBuffer peekPixels() { try { Stats.onNativeCall(); return _nPeekPixels(_ptr); } finally { Reference.reachabilityFence(this); } } @NotNull public Shader makeShader() { return makeShader(FilterTileMode.CLAMP, FilterTileMode.CLAMP, SamplingMode.DEFAULT, null); } @NotNull public Shader makeShader(@Nullable Matrix33 localMatrix) { return makeShader(FilterTileMode.CLAMP, FilterTileMode.CLAMP, SamplingMode.DEFAULT, localMatrix); } @NotNull public Shader makeShader(@NotNull FilterTileMode tm) { return makeShader(tm, tm, SamplingMode.DEFAULT, null); } @NotNull public Shader makeShader(@NotNull FilterTileMode tmx, @NotNull FilterTileMode tmy) { return makeShader(tmx, tmy, SamplingMode.DEFAULT, null); } @NotNull public Shader makeShader(@NotNull FilterTileMode tmx, @NotNull FilterTileMode tmy, @Nullable Matrix33 localMatrix) { return makeShader(tmx, tmy, SamplingMode.DEFAULT, localMatrix); } @NotNull public Shader makeShader(@NotNull FilterTileMode tmx, @NotNull FilterTileMode tmy, @NotNull SamplingMode sampling, @Nullable Matrix33 localMatrix) { try { assert tmx != null : "Can’t Bitmap.makeShader with tmx == null"; assert tmy != null : "Can’t Bitmap.makeShader with tmy == null"; assert sampling != null : "Can’t Bitmap.makeShader with sampling == null"; Stats.onNativeCall(); return new Shader(_nMakeShader(_ptr, tmx.ordinal(), tmy.ordinal(), sampling._pack(), localMatrix == null ? null : localMatrix._mat)); } finally { Reference.reachabilityFence(this); } } @ApiStatus.Internal public static class _FinalizerHolder { public static final long PTR = _nGetFinalizer(); } @ApiStatus.Internal public static native long _nGetFinalizer(); @ApiStatus.Internal public static native long _nMake(); @ApiStatus.Internal public static native long _nMakeClone(long ptr); @ApiStatus.Internal public static native void _nSwap(long ptr, long otherPtr); @ApiStatus.Internal public static native long _nGetPixmap(long ptr); @ApiStatus.Internal public static native ImageInfo _nGetImageInfo(long ptr); @ApiStatus.Internal public static native int _nGetRowBytesAsPixels(long ptr); @ApiStatus.Internal public static native boolean _nIsNull(long ptr); @ApiStatus.Internal public static native long _nGetRowBytes(long ptr); @ApiStatus.Internal public static native boolean _nSetAlphaType(long ptr, int alphaType); @ApiStatus.Internal public static native long _nComputeByteSize(long ptr); @ApiStatus.Internal public static native boolean _nIsImmutable(long ptr); @ApiStatus.Internal public static native void _nSetImmutable(long ptr); @ApiStatus.Internal public static native boolean _nIsVolatile(long ptr); @ApiStatus.Internal public static native void _nSetVolatile(long ptr, boolean value); @ApiStatus.Internal public static native void _nReset(long ptr); @ApiStatus.Internal public static native boolean _nComputeIsOpaque(long ptr); @ApiStatus.Internal public static native boolean _nSetImageInfo(long ptr, int width, int height, int colorType, int alphaType, long colorSpacePtr, long rowBytes); @ApiStatus.Internal public static native boolean _nAllocPixelsFlags(long ptr, int width, int height, int colorType, int alphaType, long colorSpacePtr, int flags); @ApiStatus.Internal public static native boolean _nAllocPixelsRowBytes(long ptr, int width, int height, int colorType, int alphaType, long colorSpacePtr, long rowBytes); @ApiStatus.Internal public static native boolean _nInstallPixels(long ptr, int width, int height, int colorType, int alphaType, long colorSpacePtr, byte[] pixels, long rowBytes); @ApiStatus.Internal public static native boolean _nAllocPixels(long ptr); @ApiStatus.Internal public static native long _nGetPixelRef(long ptr); @ApiStatus.Internal public static native long _nGetPixelRefOrigin(long ptr); @ApiStatus.Internal public static native void _nSetPixelRef(long ptr, long pixelRefPtr, int dx, int dy); @ApiStatus.Internal public static native boolean _nIsReadyToDraw(long ptr); @ApiStatus.Internal public static native int _nGetGenerationId(long ptr); @ApiStatus.Internal public static native void _nNotifyPixelsChanged(long ptr); @ApiStatus.Internal public static native void _nErase4f(long ptr, float r, float g, float b, float a, long colorSpacePtr); @ApiStatus.Internal public static native void _nEraseRect4f(long ptr, float r, float g, float b, float a, long colorSpacePtr, int left, int top, int right, int bottom); @ApiStatus.Internal public static native void _nErase(long ptr, int color); @ApiStatus.Internal public static native void _nEraseRect(long ptr, int color, int left, int top, int right, int bottom); @ApiStatus.Internal public static native int _nGetColor(long ptr, int x, int y); @ApiStatus.Internal public static native Color4f _nGetColor4f(long ptr, int x, int y); @ApiStatus.Internal public static native float _nGetAlphaf(long ptr, int x, int y); @ApiStatus.Internal public static native boolean _nExtractSubset(long ptr, long dstPtr, int left, int top, int right, int bottom); @ApiStatus.Internal public static native byte[] _nReadPixels(long ptr, int width, int height, int colorType, int alphaType, long colorSpacePtr, long dstRowBytes, int srcX, int srcY); @ApiStatus.Internal public static native IPoint _nExtractAlpha(long ptr, long dstPtr, long paintPtr); @ApiStatus.Internal public static native ByteBuffer _nPeekPixels(long ptr); @ApiStatus.Internal public static native long _nMakeShader(long ptr, int tmx, int tmy, long samplingMode, float[] localMatrix); }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy