Why do I have to register an ImageReader?

968 views
Skip to first unread message

larry google groups

unread,
Feb 27, 2014, 3:09:53 PM2/27/14
to clo...@googlegroups.com
I have no background with Java so I tend to suffer pain when dealing with it. I am trying to create a thumbnail for an image, but my code dies on the :post assertion of this function: 

(defn get-file-as-image [filename]
  {:pre [(= (type filename) java.lang.String)
         (fs/exists? filename)
         (fs/file? (io/as-file filename))]
   :post [(do (pp/pprint %) true)
          (= (type %) BufferedImage)]}
  (javax.imageio.ImageIO/read (io/as-file filename)))


The :pre assertions are all apparently true, so the file exists and returns as a file when run through (io/as-file). 

I looked here for the documentation on javax.imageio.ImageIO/read:


It reads:

"Returns a BufferedImage as the result of decoding a supplied File with an ImageReader chosen automatically from among those currently registered. The File is wrapped in an ImageInputStream. If no registeredImageReader claims to be able to read the resulting stream, null is returned."

I added the pprint into my :post and it prints nil. So I assume the problem is this: 

"If no registeredImageReader claims to be able to read the resulting stream, null is returned."

What does it mean to register an ImageReader? 







larry google groups

unread,
Feb 27, 2014, 3:44:55 PM2/27/14
to clo...@googlegroups.com
I tried this too:

(ns tma-make-thumbnails.make-images
  (:import
   (java.util UUID)
   (javax.imageio ImageIO)
   (java.awt.image BufferedImage)
   (javax.imageio ImageReader))



(defn get-file-as-image [filename]
  {:pre [(= (type filename) java.lang.String)
         (fs/exists? filename)
         (fs/file? (io/as-file filename))]
   :post [(do (pp/pprint %) true)
          (= (type %) java.awt.image.BufferedImage)]}
  (.read ImageIO (io/as-file filename)))


but that only gives me: 

Exception in thread "Thread-1" java.lang.IllegalArgumentException: No matching method found: read for class java.lang.Class

I don't get why ImageIO is java.lang.Class after I imported it. 

Aaron Cohen

unread,
Feb 27, 2014, 3:52:09 PM2/27/14
to clo...@googlegroups.com
On Thu, Feb 27, 2014 at 3:44 PM, larry google groups <lawrenc...@gmail.com> wrote:
I tried this too:

(ns tma-make-thumbnails.make-images
  (:import
   (java.util UUID)
   (javax.imageio ImageIO)
   (java.awt.image BufferedImage)
   (javax.imageio ImageReader))



(defn get-file-as-image [filename]
  {:pre [(= (type filename) java.lang.String)
         (fs/exists? filename)
         (fs/file? (io/as-file filename))]
   :post [(do (pp/pprint %) true)
          (= (type %) java.awt.image.BufferedImage)]}
  (.read ImageIO (io/as-file filename)))

This is trying to invoke the "read" method of the Class instance representing "javax.imageio.ImageIO". This is surely not what you want.


but that only gives me: 

Exception in thread "Thread-1" java.lang.IllegalArgumentException: No matching method found: read for class java.lang.Class

I don't get why ImageIO is java.lang.Class after I imported it. 





On Thursday, February 27, 2014 3:09:53 PM UTC-5, larry google groups wrote:
I have no background with Java so I tend to suffer pain when dealing with it. I am trying to create a thumbnail for an image, but my code dies on the :post assertion of this function: 

(defn get-file-as-image [filename]
  {:pre [(= (type filename) java.lang.String)
         (fs/exists? filename)
         (fs/file? (io/as-file filename))]
   :post [(do (pp/pprint %) true)
          (= (type %) BufferedImage)]}
  (javax.imageio.ImageIO/read (io/as-file filename)))


This is the correct syntax for invoking a static method of a class. I'm not sure why it's not working for you. What kind of file are you trying to load?
 

larry google groups

unread,
Feb 27, 2014, 4:09:10 PM2/27/14
to clo...@googlegroups.com

Ah, I see what happened. There was a Microsoft Word document in my folder of images. It was causing the problems. I had no error handling for non-images. 

larry google groups

unread,
Feb 27, 2014, 4:47:31 PM2/27/14
to clo...@googlegroups.com

Hmm, I made it a little further. Now I am trying to write a thumbnail to disk. I have copied the code from StackOverflow. I am using this function: 

(defn make-thumbnail [filename path-to-new-file-including-file-name width]
  {:pre [(= (type filename) java.lang.String)
         (fs/exists? filename)
         (= (type path-to-new-file-including-file-name) java.lang.String)
         (number? width)]}
  (println " we will write thumbnails to here: " (str path-to-new-file-including-file-name))
  (let [ext (fs/extension filename)
        img (get-file-as-image filename)
        imgtype (java.awt.image.BufferedImage/TYPE_INT_ARGB)
        width (min (.getWidth img) width)
        height (* (/ width (.getWidth img)) (.getHeight img))
        simg (java.awt.image.BufferedImage. width height imgtype)
        g (.createGraphics simg)]
    (.drawImage g img 0 0 width height nil)
    (.dispose g)
    (pp/pprint simg)
    (javax.imageio.ImageIO/write simg ext (io/as-file path-to-new-file-including-file-name))))


This line:

  (println " we will write thumbnails to here: " (str path-to-new-file-including-file-name))

shows me this, which is the path I want:

we will write thumbnails to here:  /Users/larry/tma_files/processed/b5838394-a86c-411f-b556-94b30c26a553IMG_1175_180.JPG

This line:

    (pp/pprint simg)

gives me: 

#<BufferedImage BufferedImage@7ac84a5b: type = 2 DirectColorModel: rmask=ff0000 gmask=ff00 bmask=ff amask=ff000000 IntegerInterleavedRaster: width = 125 height = 93 #Bands = 4 xOff = 0 yOff = 0 dataOffset[0] 0>

I do not get any errors or exceptions, but nothing gets written to disk. Can anyone suggest why? 

If I look here:


Writes an image using an arbitrary ImageWriter that supports the given format to a File. If there is already a Filepresent, its contents are discarded.
Parameters:
im - a RenderedImage to be written.
formatName - a String containg the informal name of the format.
output - a File to be written to.
Returns:
false if no appropriate writer is found.

I am unsure what "false if no appropriate writer is found" means. I have added code to be sure that only jpeg, gif and png files get to this function. 

Any suggestions why nothing gets written to disk? 

larry google groups

unread,
Feb 27, 2014, 5:04:50 PM2/27/14
to clo...@googlegroups.com
I wanted to see what Format strings I am allowed, so at the repl: 


user> (import 'javax.imageio.ImageIO)
javax.imageio.ImageIO

user> (require '[clojure.pprint :as pp])

user> (pp/pprint (javax.imageio.ImageIO/getReaderFormatNames))["BMP", "bmp", "jpg", "JPG", "wbmp", "jpeg", "png", "JPEG", "PNG", "WBMP", "GIF", "gif"]

(fs/extension) was returning ".JPG" with a period. I thought that might be the problem so I removed it:

(defn make-thumbnail [filename path-to-new-file-including-file-name width]
  {:pre [(= (type filename) java.lang.String)
         (fs/exists? filename)
         (= (type path-to-new-file-including-file-name) java.lang.String)
         (number? width)]}
  (println " we will write thumbnails to here: " (str path-to-new-file-including-file-name))
  (let [ext (st/replace (fs/extension filename) #"\." "")
        img (get-file-as-image filename)
        imgtype (java.awt.image.BufferedImage/TYPE_INT_ARGB)
        width (min (.getWidth img) width)
        height (* (/ width (.getWidth img)) (.getHeight img))
        simg (java.awt.image.BufferedImage. width height imgtype)
        g (.createGraphics simg)]
    (.drawImage g img 0 0 width height nil)
    (.dispose g)
    (pp/pprint simg)
    (println "the extension we use:")
    (pp/pprint ext)
    (javax.imageio.ImageIO/write simg ext (io/as-file path-to-new-file-including-file-name))))

So the final println gives me:

the extension we use:
"JPG"

and yet now I get:

Exception in thread "Thread-1" javax.imageio.IIOException: Invalid argument to native writeImage
at com.sun.imageio.plugins.jpeg.JPEGImageWriter.writeImage(Native Method)

which is surprising since the Format string, without the period, should be more correct. 

larry google groups

unread,
Feb 27, 2014, 5:17:08 PM2/27/14
to clo...@googlegroups.com
and if I look here:


I see this example:


ImageIO.write(image, "jpg",new File("C:\\out.jpg")); ImageIO.write(image, "gif",new File("C:\\out.gif")); ImageIO.write(image, "png",new File("C:\\out.png"));

None of those formatting strings have a period in them. And yet when I remove the period from my extension, I get an error. And even with it, nothing happens and nothing gets written to disk. 

Aaron Cohen

unread,
Feb 27, 2014, 5:17:20 PM2/27/14
to clo...@googlegroups.com
This is going to result in a pretty ugly thumbnail because you're missing the hints java needs to do high quality resizing. Java's shrinking also doesn't really have a nice smoothing mode.

I'd actually recommend you look into https://github.com/mikera/imagez. It has a resize function in core which does what you want. It uses Scalr internally which has some good quality options.

As for why your code isn't working, it's hard to say. Can you try just writing out the file you read (before resizing) and make sure that it's actually loaded correctly?




--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups "Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojure+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Aaron Cohen

unread,
Feb 27, 2014, 5:20:07 PM2/27/14
to clo...@googlegroups.com
You definitely don't want a period in your format string.

Why are you calling    (.drawImage g img 0 0 width height nil). What's the nil for? I'd try dropping it.


--

larry google groups

unread,
Feb 27, 2014, 5:25:07 PM2/27/14
to clo...@googlegroups.com

Thanks for the tip about imagez. I wanted to get something basic working today, but I'll give imagez a look tomorrow. As for now, I feel like I should not give up till I have figured out what the problem is. 

larry google groups

unread,
Feb 27, 2014, 5:26:32 PM2/27/14
to clo...@googlegroups.com
I found this:


So I changed this:

        imgtype (java.awt.image.BufferedImage/TYPE_INT_ARGB)

to this:

        imgtype (java.awt.image.BufferedImage/TYPE_3BYTE_BGR)

and that worked for one image. The next image died, for reasons I'm still investigating. 

larry google groups

unread,
Feb 27, 2014, 5:41:14 PM2/27/14
to clo...@googlegroups.com

Okay, everything works now. Apparently that last problem had something to do with differences between OpenJDK and the SunJDK. I have:

java -version
openjdk version "1.7.0-ea"
OpenJDK Runtime Environment (build 1.7.0-ea-b222)
OpenJDK 64-Bit Server VM (build 21.0-b17, mixed mode)

I don't recall why I installed OpenJDK on my Mac. Do people on this mailist feel that the Sun JDK is better? 

I'm going to give the imagez library a try tomorrow. 
Reply all
Reply to author
Forward
0 new messages