JAVA: Image and Pixel Processing PART III
Java
222
White

Nobody viết ngày 31/12/2021

PART III

There are two possibilities to process a Pixel or RGB/ARGB/RGBA:

  • Via a Pixel-Array (or int[ ])
  • Via a Direct Pixel Access

Both achieve the same result. It depends fully on the working environment of your application. An element of Pixel-Array can be quickly accessed, but it requires in advance a huge memory in reserve. Imagine that an image has merely 4 Mega Pixels and each Pixel is an int (4 bytes). That means the app eats up 16 MB. Quite a lot, isn't it? All the examples in Part I and Part II work with Pixel array. The way to work with Direct Pixel Access can be implemented, for example, as following:

    BufferedImage img = ImageIO.read(new File(parms[1]));
    int width  = img.getWidth();
    int height = img.getHeight();
    //
    BufferedImage bImg = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
    int RGB   = pixel & 0x00FFFFFF;  // 100% translucent

    /* Pixel Array
    int[] pixels  = img.getRGB(0, 0, width, height, null, 0, width);
    for(int y = 0, i = 0; y < height; y++)
    for(int x = 0, l = 0; x < width; ++x, ++i) {
      int rgb   = pixels[i] & 0x00FFFFFF;
      if (rgb == RGB) bImg.setRGB(x, y, rgb); // 100% transparent
      else bImg.setRGB(x, y,  pixels[i]); // let it be
    }
    */

    // Direct Pixel access
    for(int y = 0; y < height; y++)
    for(int x = 0, l = 0; x < width; ++x) {
      int pixel = img.getRGB(x, y); // direct access
      int rgb   = pixel & 0x00FFFFFF;
      if (rgb == RGB) bImg.setRGB(x, y, rgb); // 100% transparent
      else bImg.setRGB(x, y,  pixel); // let it be
    }

You may wonder where is the (dis)advantage of Direct Pixel Access, am I right? Well, the advantage is the request of memory on demand and the disadvantage is the high accessing activity between the BufferedImage and the processing loop. In essence:

// Pixel Array
int[] pixels  = img.getRGB(0, 0, width, height, null, 0, width); // ALL at a Time
// Direct Pixel Access
int pixel = img.get(x, y); // ONE by ONE

So far and so good. What's about JavaFX? Java Image (SWING and AWT) is TOTALLY INCOMPATIBLE with JavaFX counterpart. But: where there's an effort it is there a solution. The commonness between JavaFX and "normal" Java is the IO/NIO. SWING and AWT require the Image object java.awt.Image while JavaFX demands javafx.scene.image.Image. What you have to do is to bring the awt.Image into a buffer (e.g. java.awt.image.BufferedImage) and then use the buffer as an INPUT to create a JavaFX Image. Example:

  /**
  @param color int 6-digits hex-String beginning with 0x.... for the to be made transparent<br>
  @param imgFile String  Image file name
  @exception Exception thrown by JAVA
  */
  public static BufferedImage transparentColor(int color, String imgFile) throws Exception {
    BufferedImage img = ImageIO.read(new File(imgFile));
    int width  = img.getWidth();
    int height = img.getHeight();
    // Create a BufferImage with 4 bytes ARGB format
    BufferedImage bImg = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
    int RGB   = color & 0x00FFFFFF;
    for(int y = 0; y < height; y++)
    for(int x = 0; x < width; ++x) {
      int p = img.getRGB(x,y);
      int rgb = p & 0x00FFFFFF;
      if (rgb == RGB) bImg.setRGB(x, y, rgb); // 100% transparent
      else bImg.setRGB(x, y, p); // let it be
    }
    return bImg;
  }
  // JavaFX: return a JavaFX Image
  public static javafx.scene.image.Image transparentJFXColor(int color, String imgFile) throws Exception {
    ByteArrayOutputStream bao = new ByteArrayOutputStream();
    ImageIO.write(transparentColor(color, imgFile), "png", bao);
    return new javafx.scene.image.Image(new ByteArrayInputStream(bao.toByteArray()));
  }
  ...

The awt.image.BufferedImage is buffered in ByteArrayOutputStream and then its content is used as the data for an INPUT STREAM (ByteArrayInputStream) to instantiate JavaFX Image.

The reverse way from JavaFX to SWING/AWT Image is a bit simpler, but somehow more cumbersome. Example:

    javafx.scene.image.Image image = new javafx.scene.image.Image(imgFile);
    //
    int width = (int)image.getWidth();
    int height = (int)image.getHeight();
    byte[] buf = new byte[width * height * 4]; // 4 for ARGB
    // ARGB instance from PixelReader
    javafx.scene.image.PixelReader reader = image.getPixelReader();
    reader.getPixels(0, 0, w, h, PixelFormat.getIntArgbInstance(), buf, 0, w * 4); // load the buffer
    // save the buffer in ByteArrayInputStream  and use it as INPUT STREAM for ImageIO
    java.io.ByteArrayInputStream bai = new java.io.ByteArrayInputStream(buf);
    // convert to BufferedImage for SWING/AWT
    java.awt.image.BufferedImage = javax.imageio.ImageIO.read(bai);

Let try to scale the RED element in JavaFX by turn-off of GREEN and BLUE. The codes:

public  static javafx.scene.image.Image  scalingJFX(int pattern, String imgFile) throws Exception {
    BufferedImage img = ImageIO.read(new File(imgFile));
    int width  = img.getWidth();
    int height = img.getHeight();
    //make sure that the ALPHA element is kept
    pattern |= 0xFF000000; // keep ALPHA
    for(int y = 0; y < height; ++y)
    for(int x = 0; x < width; ++x) {
      img.setRGB(x, y, img.getRGB(x,y) & pattern);
    }
    ByteArrayOutputStream bao = new ByteArrayOutputStream();
    ImageIO.write(scaling(pattern, imgFile), suffix(imgFile), bao);
    return new javafx.scene.image.Image(new ByteArrayInputStream(bao.toByteArray()));
}

the invocation with a pattern in 6 hex: 0xFF0000

redView = new ImageView(ImageTool.scalingJFX(0xFF0000, imgFile)); // Keep RED and turn off GREEN and BLUE

And that is what we get.
alt text

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

Nobody

7 bài viết.
482 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Bài viết liên quan
White
2 0
Trong bài viết này, một số hình ảnh hoặc nọi dung có thể bị thiếu do quá trình chế bản. Vui lòng xem nội dung ở blog gốc sau: (Link) (Link), chúng...
programmerit viết hơn 6 năm trước
2 0
White
0 0
Giới thiệu Trong bài hôm nay chúng ta sẽ tìm hiểu cách handle request POST của Spring Boot. Trước đó, bạn nên biết 1. 「Spring Boot 8」Tạo Web He...
https://loda.me viết hơn 2 năm trước
0 0
Male avatar
0 0
https://grokonez.com/deployment/vultr/howtoinstalljavainubunturemoteservervutrhostingvpsexample How to install Java on Ubuntu Remote Server – Vutr...
loveprogramming viết 9 tháng trước
0 0
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
7 bài viết.
482 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!