簡體   English   中英

如何創建JavaFX 16位灰度圖像

[英]How to Create JavaFX 16 bit Greyscale Images

我有一個生成16位灰度圖像的應用程序。 目前,這些圖像是作為具有數據類型DataBuffer.TYPE_USHORT的awt BufferedImage生成的。

在我的應用程序中,我從BufferedImage中提取16位數據,規范化為8位,然后使用canvas.getGraphicsContext2D()將其渲染到FX Canvas中.getPixelWriter()。setPixels(...)

它工作但看起來很亂我想知道是否有可能實現JavaFX Image或WritableImage,讓我們稱之為由我的16位數據支持的UShortImage。 UShortImage可以具有規范化級別的FX屬性,但是可以與任何JavaFX Image完全一樣使用。

任何有關如何以良好的運行時效率實現此目的的幫助或指示將不勝感激!

我不知道這是不是你正在尋找的,也許我不明白你的問題。 但是,您可以使用ColorAdjust效果通過去飽和顏色將彩色圖像轉換為灰色圖像。

ColorAdjust monochrome = new ColorAdjust();
monochrome.setSaturation(-1);
ImageView gray = new ImageView(new Image(IMAGE_LOC));
gray.setEffect(monochrome);

我不確定為什么貧窮的奶奶和爺爺必須褪色為黑白,但一定是這樣。

coloradjust

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.effect.ColorAdjust;
import javafx.scene.image.*;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class GrayScale extends Application {

    @Override
    public void start(Stage stage) {
        ColorAdjust monochrome = new ColorAdjust();
        monochrome.setSaturation(-1);
        Image image = new Image(IMAGE_LOC);
        ImageView color = new ImageView(image);
        ImageView gray = new ImageView(image);
        gray.setEffect(monochrome);

        HBox layout = new HBox(10, color, gray);
        layout.setPadding(new Insets(10));

        Scene scene = new Scene(layout);
        scene.setFill(Color.BLACK);
        stage.setScene(scene);

        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }

    // source: http://www.photoshopessentials.com/photo-editing/black-and-white-tutorials/desaturate/
    private static final String IMAGE_LOC =
            "http://pe-images.s3.amazonaws.com/photo-effects/black-and-white/grandparents.jpg";
}

如果ColorAdjust不適合你,那么你可以在WritableImage上使用PixelReaders和PixelWriters在逐個像素的基礎上進行操作。 (我沒有看到你在問題中提到畫布的原因)。 有關使用WritableImage的相關實現,請參閱:


也許您也希望使用新類型擴展PixelFormat並擴展PixelReader以讀取您的數據緩沖區,這可能是可能的,但我想這不是必要的,以實現您想要的:

PixelReader reader = new GrayScalePixelReader(); 
reader.getPixels(0, 0, W, H, 
    GrayScalePixelFormat.instance(), grayScaleByteBuffer, 0, scanlineStride); 
Image img = new WritableImage(reader, W, H); 

其中GrayScalePixelReader和GrayScalePixelFormat是您通過擴展創建的新類。

FX支持PixelFormat定義的像素類型,如BYTE_BGRA和BYTE_BGRA_PRE; 我希望添加對新像素類型的支持,每個像素具有單個樣本,這是16個無符號數據值。

 pixelFormat = PixelFormat.createByteIndexedInstance(LUT); getPixelWriter().setPixels(0, 0, w, h, pixelFormat, normalisedImageData, 0, w); 

是的,你幾乎可以做到,但這有點棘手。 我同意Java 8中現有的PixelFormat並不是非常容易用戶擴展,原因就像你提到的那樣:

一些方法,例如WritabelImage類的getPixelWriter()是最終的,所以你甚至不能覆蓋它們。 Image基礎架構看起來不像是以這種方式擴展。

通常,當談到JavaFX時,缺乏可擴展性是故意構建的。 一些原因是:

  1. 安全性,通過覆蓋核心功能以執行惡意副作用,使人們更難以破壞平台做惡意的事情。
  2. 向應用程序開發人員提供簡化的界面,以便更容易理解和使用API​​。
  3. 故意使平台的某些部分不透明,以便庫開發人員更容易維護核心庫實現並隨意更改它而不會影響用戶程序。

當然,權衡(在這種情況下)可能是缺乏靈活性來嘗試完成你想要的。

如果你看一下JavaFX中的Image實現,它有四種不同的組件:

  1. javafx.scene.image API
  2. 支持圖像API的平台實現( prism )(參見源代碼 )。
  3. 用於讀取常見圖像格式(png,jpg等)的圖像io庫
  4. 與圖形硬件加速器API或軟件渲染API的接口,例如es2 ,它最終通常將圖像視為硬件圖形API(如OpenGL或Direct3D)的紋理輸入。

關於灰度像素格式的有趣之處在於它們不直接暴露在(1)javafx.scene.image API中。 但是,棱鏡平台實現,圖像io庫和硬件加速器(2,3和4)確實具有一定程度的內置灰度支持。 例如,PNG文件可以具有灰度格式,imageIO將識別格式並將灰度緩沖區直接傳遞給要進行交互的棱鏡Image類

硬件加速層也支持灰度緩沖區,如ES2Texture實現中所示。 因此,這給出了灰度像素格式編碼緩沖器的理想情況,該圖像緩沖器能夠直接渲染到硬件加速紋理。 但請注意,Prism / ES2渲染系統支持的灰度字節緩沖區當前像素格式是8位編碼,而不是理想情況下要求的16位編碼(盡管對棱鏡像素格式的注釋不是將來可能需要16位類型;-):

// L8, A8 types:
// NOTE : we might need L8A8 16-bit type
BYTE_GRAY    (DataType.BYTE,  1, true,  true), 

因此,這意味着您正在尋找的大部分基礎結構允許JavaFX運行時直接解釋灰度編碼圖像緩沖區,但是它放在com.sun類和私有API中,而不是直接暴露給用戶在公共javafx.scene.image API中。

可以創建功能請求以啟用灰度像素格式的公共API,或者您可以在openjfx-dev郵件列表中詢問它。 實現此類功能的最短時間范圍是Java 10.看起來這樣的請求可能已經存在,因此您可以對其進行評論或將其提交到openjfx-dev郵件列表以幫助推進它:

以上信息是否可以幫助您解決當前的問題 - >可能不會:-)但希望它有助於理解平台及其功能,限制和未來擴展的潛在機制,以完全支持您的需求。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM