2013-04-18 62 views
10

Có thể hiển thị hình ảnh được chia tỷ lệ trong ImageView trong JavaFX 2.2 mà không có bất kỳ thao tác làm mịn nào không? Tôi đang hiển thị hình ảnh 50x50 thành một ImageView 200x200, với setSmooth (sai), do đó, mỗi pixel trong hình ảnh nguồn sẽ ánh xạ tới hình vuông 4x4 trên màn hình.JavaFX ImageView mà không có bất kỳ làm mịn nào

Tuy nhiên, kết quả hiển thị vẫn làm mịn pixel nguồn trên tất cả 16 pixel đích. Có ai biết một cách để làm điều này mà không cần sao chép theo cách thủ công trên mỗi pixel vào một hình ảnh mới?

+0

Bạn có thể thử Canvas để kiểm soát tối đa. –

+0

Thật không may, tôi không nghĩ rằng có một cách để làm điều đó trong một khung. Những gì họ thực sự cần làm là cho phép chúng tôi tạo các bộ lọc 2D của riêng mình (tôi đoán chúng được gọi là "Hiệu ứng" trong JavaFX). – ajselvig

+0

Đã cập nhật câu trả lời của tôi với các ý tưởng về triển khai bộ lọc hình ảnh của riêng bạn. – jewelsea

Trả lời

15

Trong JavaFX 2.2 ImageView luôn thực hiện làm mịn bất kể gợi ý smooth mà bạn cung cấp cho ImageView.

(Dựa trên thử nghiệm sử dụng Java 7u15 và Windows 7 có thẻ đồ họa ATI HD4600).

Có lẽ đó là lỗi mà ImageView sẽ luôn làm mịn Image, nhưng tài liệu không thực sự xác định chính xác những gì làm mịn hoặc không làm, vì vậy thật khó để nói ý định thực sự của nó là gì. Bạn có thể muốn đăng một tham chiếu đến câu hỏi này đến openjfx-dev mailing list hoặc đăng nhập một vấn đề trong JavaFX issue tracker để có thêm ý kiến ​​chuyên gia từ nhà phát triển.


Tôi đã thử một vài phương pháp khác nhau để điều chỉnh tỷ lệ hình ảnh:

  1. Scale trong Image constructor.
  2. Quy mô trong ImageView với fitWidth/fitHeight.
  3. Quy mô bằng cách sử dụng các thuộc tính scaleX/scaleY trên ImageView.
  4. Quy mô bằng cách lấy mẫu Image bằng PixelReader và tạo Hình ảnh mới với PixelWriter.

Tôi phát hiện ra rằng các phương pháp 1 & 4 dẫn đến hình ảnh được đánh dấu sắc nét như bạn muốn và 2 & 3 dẫn đến hình ảnh có hình mờ.

robot-sampling

Sample code để tạo ra sản lượng cao hơn.


Cập nhật với những ý tưởng về việc thực hiện bộ lọc hình ảnh của riêng bạn

Một JavaFX Effect là không giống như các bộ lọc sử dụng cho các thói quen tải hình ảnh, mặc dù một hiệu ứng để lọc một hình ảnh có thể được tạo ra. Trong JavaFX 2.2 công khai tài liệu API để hỗ trợ tạo ra các hiệu ứng tùy chỉnh, do đó, việc tạo ra một hiệu ứng tùy chỉnh có thể chứng minh khó khăn.

native code for image support gần đây đã được mở nguồn dưới dạng một phần của openjfx project, vì vậy bạn có thể xem điều đó để xem cách lọc hiện được triển khai.

Bạn cũng có thể muốn gửi feature request against the JavaFX runtime project để "cho phép chúng tôi tạo bộ lọc 2D của riêng mình".

+1

Bạn luôn đưa ra câu trả lời ấn tượng như vậy: D –

+1

Có, cảm ơn câu trả lời chi tiết. Tôi đã đi đến cùng một kết luận, và kết thúc việc thực hiện # 4. Việc thực hiện chính nó là tầm thường, nhưng tôi sợ rằng nó chậm hơn nhiều so với # 2 hoặC# 3 (mặc dù tôi chưa xác minh điều này). – ajselvig

+2

Đã hai năm kể từ câu trả lời này. Có ai biết nếu điều này đã được cố định trong JavaFX? –

1

Tôi biết điều này là cũ hơn một chút, nhưng gần đây tôi đã có nhu cầu cho ImageView như vậy, và sau đây ít hack thực hiện chính xác những gì tôi muốn trên máy (Windows) của tôi. Không đảm bảo rằng nó hoạt động ở khắp mọi nơi.

import com.sun.javafx.sg.prism.NGImageView; 
import com.sun.javafx.sg.prism.NGNode; 
import com.sun.prism.Graphics; 
import com.sun.prism.Texture; 
import com.sun.prism.impl.BaseResourceFactory; 

import com.sun.prism.Image; 
import javafx.scene.image.ImageView; 

@SuppressWarnings("restriction") 
public class PixelatedImageView extends ImageView { 
    @Override protected NGNode impl_createPeer() { 
     return new NGImageView() { 
      private Image image; 

      @Override public void setImage(Object img) { 
       super.setImage(img); 
       image = (Image) img; 
      } 

      @Override protected void renderContent(Graphics g) { 
       BaseResourceFactory factory = (BaseResourceFactory) g.getResourceFactory(); 
       Texture tex = factory.getCachedTexture(image, Texture.WrapMode.CLAMP_TO_EDGE); 
       tex.setLinearFiltering(false); 
       tex.unlock(); 
       super.renderContent(g); 
      } 
     }; 
    } 
} 

Bí quyết ở đây là kết cấu được sử dụng lại, do đó cài đặt lọc tuyến tính vẫn "dính". Tại sao NGImageView không thể chỉ đơn giản là vượt qua lá cờ "mịn" để thiết lập lọc tuyến tính của kết cấu là vượt ra ngoài tôi tuy nhiên.

+0

Có vẻ như họ không muốn bạn làm điều này. – Nolan

+0

Điều này làm việc cho Java 8, nhưng có vẻ như các chức năng được đề cập ở đây đã được đổi tên và đặt thành các chức năng riêng trong Java 9. Không giống như nó có thể bị ghi đè theo cùng một cách mà không thay đổi đáng kể đối với 'ImageView' và' ImageViewHelper' . Bất kỳ ai đã tìm ra cách giải quyết các hạn chế mới trong Java 9? – ddukki

0

Khi bạn thêm hàm tạo sau vào câu trả lời của Martin Sojka, bạn có thể chỉ cần chuyển hình ảnh javafx tới hàm tạo. Ngoài ra bất chấp những cảnh báo về các chức năng không được chấp nhận, câu trả lời của anh vẫn hoạt động tốt (trên JDK 1.8_121).

public PixelatedImageView (javafx.scene.image.Image image) { 
    super(image); 
} 
Các vấn đề liên quan