All,
I'm doing some image manipulation in Scala by making use of BufferedImages and Raster objects. I am attempting to get all the pixels in the buffered image with the following code.
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)
Now, when I read in relatively large files, this works fine. When I read in 20x20 PNG files, I get an ArrayIndexOutOfBoundsException:
java.lang.ArrayIndexOutOfBoundsException: 1200
at sun.awt.image.ByteInterleavedRaster.getPixels(ByteInterleavedRaster.java:1050)
I've read online that the way around this problem is to NOT preallocate the pixelBuffer, but instead to pass in a null value and use the one returned by the Raster.getPixels method.
Here's my problem. When I do the naive approach and just pass Nil as the last argument:
val pixels = raster.getPixels(0,0,width,height,Nil)
I get the error
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)
So obviously the compiler cannot determine which of the two methods I'm trying to call; it's ambiguous. If I were using Java, I would cast the null to make my intent explicit. I can't quite figure out how to get the same effect in Scala. Things I've tried:
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
Any idea how to tell the compiler explicitly that I want the method with the Int array as last parameter rather than a Float array?
EDIT: As an answer points out, I was getting Nil mixed up with null. Nil is an empty list. See the following blog post
Also, I should point out that the array out of bounds exception was my fault (as these things often are). The problem was I was assuming that the raster had 3 channels, but my image had 4 channels, since I had created it that way. I instead preallocate the array as follows:
val numChannels = raster.getNumBands()
val pixelBuffer = new Array[Int](width*height*numChannels)
val pixels = raster.getPixels(minX,minY,width,height,pixelBuffer)
Thanks for the help