2016-08-04 3 views
0

のピクセルは、画像の画素データを読み取るためのJavaの相互運用に次の簡単なClojureのを考えてみなさい:サブイメージ

(def all-pixels (get-pixels (read-image "path/to/img.jpg"))) 
(nth all-pixels 0) 
;; [34 56 7] 
(count all-pixels) 
;; 122343 

(import java.awt.image.BufferedImage) 
(import javax.imageio.ImageIO) 
(require '[clojure.java.io :as io]) 

(defn read-image [path] 
    (ImageIO/read (io/file path))) 

(defn get-sub-image [img x y w h] 
    (.getSubimage img x y w h)) 

;; this assumes that images have no fourth alpha channel: 
(defn get-pixels 
    ([img x y w h] (get-pixels (get-sub-image img x y w h))) 
    ([img] (let [bytes (-> img .getRaster .getDataBuffer .getData)] 
      (map vec (partition 3 bytes))))) 

これはそうのように、画像全体のピクセルを取得するため正常に動作します

取得するピクセルの追加座標の引数とを呼び出そうとするときしかし、結果はまだ全体のデータが含まれています

(def some-pixels (get-pixels (read-image "path/to/img.jpg") 0 0 2 2)) 
(count some-pixels) 
;; 122343 

ここでは、4ピクセルしか受け取らないと予想しています。欠陥はどこですか?

また、レイジーシーケンスとして画像データを処理する一般的なアプローチに関するコメントはすべて歓迎します。

+0

「getSubImage」のドキュメントから:返されたBufferedImageは元の画像と同じデータ配列を共有します。その理由はありませんか? https://docs.oracle.com/javase/7/docs/api/java/awt/image/BufferedImage.html#getSubimage(int,%20int,%20int,%20int) – OlegTheCat

答えて

0

は、それがコードを読み取ることが少し難しいですが、我々はトラフソースコードを歩けば:

public BufferedImage More ...getSubimage (int x, int y, int w, int h) { 
     return new BufferedImage (colorModel, 
            raster.createWritableChild(x, y, w, h, 
                  0, 0, null), 
            colorModel.isAlphaPremultiplied(), 
            properties); 
    } 

この方法は... raster.createWritableChild を見てみましょう呼び出す

public WritableRaster More ...createWritableChild(int parentX, int parentY, 
               int w, int h, 
              int childMinX, int childMinY, 
              int bandList[]) { 
     if (parentX < this.minX) { 
      throw new RasterFormatException("parentX lies outside raster"); 
     } 
     if (parentY < this.minY) { 
      throw new RasterFormatException("parentY lies outside raster"); 
     } 
     if ((parentX+w < parentX) || (parentX+w > this.width + this.minX)) { 
      throw new RasterFormatException("(parentX + width) is outside raster"); 
     } 
     if ((parentY+h < parentY) || (parentY+h > this.height + this.minY)) { 
      throw new RasterFormatException("(parentY + height) is outside raster"); 
     } 

     SampleModel sm; 
     // Note: the SampleModel for the child Raster should have the same 
     // width and height as that for the parent, since it represents 
     // the physical layout of the pixel data. The child Raster's width 
     // and height represent a "virtual" view of the pixel data, so 
     // they may be different than those of the SampleModel. 
     if (bandList != null) { 
      sm = sampleModel.createSubsetSampleModel(bandList); 
     } 
     else { 
      sm = sampleModel; 
     } 

     int deltaX = childMinX - parentX; 
     int deltaY = childMinY - parentY; 

     return new WritableRaster(sm, 
            getDataBuffer(), 
            new Rectangle(childMinX,childMinY, 
               w, h), 
            new Point(sampleModelTranslateX+deltaX, 
              sampleModelTranslateY+deltaY), 
           this); 
    } 

あなたが見ることができるように 、作成された新しいラスタは親と同じDataBufferを持ちます(サブイメージを更新すると画像全体を変更できるようになります)。

img .getRaster .getDataBuffer 

イメージ全体のデータバッファを取得します。

私はもちろんのテストではありませんでしたが、BufferedImage.getData(Rectangle rect)は、独自のDataBufferで新しいラスタを返し、その後、あなたが

http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/awt/image/BufferedImage.java#BufferedImage.getData%28%29

EDITを参照してください行ったように実行する必要があります。アントン・ハラルドの(OP)最終テストの答え

(defn get-data [img x y w h] 
    (-> (.getData img (Rectangle. x y w h)) 
     .getDataBuffer 
     .getData)) 
+0

あなたの答えは本当に役に立ちました。特に、サブ画像の異なる意味を指摘しているからです。あなたが望むなら、これをあなたの答えに加えることができます:(defn get-data [img xywh]( - > .getData img(Rectangle。xywh)).getDataBuffer .getData))これは、あなたの提案。 –

+0

フィードバックいただきありがとうございます、私はあなたの答えを追加 –

関連する問題