9

全て、

BufferedImages と Raster オブジェクトを使用して、Scala で画像操作を行っています。次のコードを使用して、バッファリングされた画像のすべてのピクセルを取得しようとしています。

val raster = f.getRaster()

// Preallocating the array causes ArrayIndexOutOfBoundsException .. http://forums.sun.com/thread.jspa?threadID=5297789
// RGB channels;
val pixelBuffer = new Array[Int](width*height*3)
val pixels = raster.getPixels(0,0,width,height,pixelBuffer)

これで、比較的大きなファイルを読み込むと、これで問題なく動作します。20x20 の PNG ファイルを読み込むと、ArrayIndexOutOfBoundsException が発生します。

java.lang.ArrayIndexOutOfBoundsException: 1200
at sun.awt.image.ByteInterleavedRaster.getPixels(ByteInterleavedRaster.java:1050)

この問題を回避する方法は、pixelBuffer を事前に割り当てるのではなく、null 値を渡し、Raster.getPixels メソッドによって返された値を使用することであるとオンラインで読みました。

これが私の問題です。単純なアプローチを行い、最後の引数として Nil を渡すだけの場合:

val pixels = raster.getPixels(0,0,width,height,Nil)

エラーが発生します

error: overloaded method value getPixels with alternatives (Int,Int,Int,Int,Array[Double])Array[Double] <and> (Int,Int,Int,Int,Array[Float])Array[Float] <and> (Int,Int,Int,Int,Array[Int])Array[Int] cannot be applied to (Int,Int,Int,Int,Nil.type)
val pixels = raster.getPixels(0,0,width,height,Nil)

したがって、コンパイラは、2 つのメソッドのどちらを呼び出そうとしているのかを判断できません。あいまいです。Java を使用している場合は、意図を明示するために null をキャストします。Scalaで同じ効果を得る方法がよくわかりません。私が試したこと:

 val pixelBuffer:Array[Int] = Nil // Cannot instantiate an Array to Nil for some reason
 Nil.asInstanceOf(Array[Int]) // asInstanceOf is not a member of Nil

Float 配列ではなく Int 配列を最後のパラメーターとして使用するメソッドが必要であることをコンパイラーに明示的に伝える方法はありますか?

編集:答えが指摘するように、私はNilをnullと混同していました。Nil は空のリストです。次のブログ記事を参照してください

また、配列の範囲外の例外は私のせいだったことを指摘しておく必要があります (これらはよくあることです)。問題は、ラスターに 3 つのチャネルがあると想定していたのに、そのように作成したため、イメージに 4 つのチャネルがあることでした。代わりに、次のように配列を事前に割り当てます。

val numChannels = raster.getNumBands() 

val pixelBuffer = new Array[Int](width*height*numChannels)
val pixels = raster.getPixels(minX,minY,width,height,pixelBuffer)

助けてくれてありがとう

4

2 に答える 2

17

(nullを渡す必要があるときにオーバーロードを解決する方法の問題が必要だと仮定します):

Java で行うのと同じように、呼び出したいオーバーロードに対応する型を割り当てることによって (Java ではキャストしますが、それは同じことになります: に割り当てる静的型のアサーションnull):

scala> object O { def m(i: Int, s: String): String = s * i; def m(i: Int, l: List[String]): String = l.mkString(":") * i }
defined module O

scala> O.m(23, null)
<console>:7: error: ambiguous reference to overloaded definition,
both method m in object O of type (i: Int,l: List[String])String
and  method m in object O of type (i: Int,s: String)String
match argument types (Int,Null)
       O.m(23, null)
         ^

scala> O.m(23, null: String)
res4: String = nullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnull

scala> O.m(23, null: List[String])
java.lang.NullPointerException
        at O$.m(<console>:5)
        at .<init>(<console>:7)
        at .<clinit>(<console>)
        at RequestResult$.<init>(<console>:9)
        at RequestResult$.<clinit>(<console>)
        at RequestResult$scala_repl_result(<console>)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at scala.tools.nsc.Interpreter$Request$$anonfun$loadAndRun$1$$anonfun$apply$18.apply(Interpreter.scala:981)
        at scala.tools.nsc.Interpreter$Request$$anonfun$loadAndRun$1$$anonfun$apply$18.apply(Interpreter.scala:981)
        at scala.util.control.Exception$Catch.apply(Exception.scala:7...
scala>
于 2010-07-02T21:16:27.073 に答える
5

と混同Nilしましnullた。

于 2010-07-02T21:06:07.503 に答える