I want to create a serve resampled (downsized) version of images using jsp. The original images are stored in the database as blobs. I want to to create a jsp that serves a downsampled image with decent quality (not pixelated) as per the passed image width/height (e.g. getimage.jsp?imageid=xxxx&maxside=200) . Can you point me to a opensource api or code that I can call from the jsp page?
Java already contains libraries for image manipulation. It should be easy to resize an image and output it from a JSP.
This servlet looks like it does a very similar thing to what you want your JSP to do.
Is there anything wrong with the built-in Image.getScaledInstance(w, h, hints)? (*)
Use hints=Image.SCALE_SMOOTH to get non-horrible thumbnailing. Then use an ImageIO to convert to the required format for output.
*: well yes, there is something wrong with it, it's a bit slow, but really with all the other web overhead to worry about that's not likely to be much of an issue. It's also not the best quality for when upscaling images, where a drawImage with BICUBIC renderinghint is more suitable. But you're talking about downscaling only at the moment.
Be sure to check the sizes passed in so that you can't DoS your servlet by passing in enormous sizes causing a memory-eatingly-huge image to be created.
Related
I have a website that lets users generate an image. I then provide an embed link
which they can paste on their blog/website. The link conists of a simple html img
element which calls and then returns the image from my webapp to their website.
Currently, I'm reading the image from the file system and returning it via
the response outputstream.
My question is, is there a better more efficient way of doing this? I mostly would like
to keep the top 10 images in memory for faster access.
I currently have a singleton object that stores some data during app startup. My idea was to create a Map/List object and then store the image bytes in there. My images have unique names so that should make it a bit simpler.
I'd imagnie I'd need to store the image name, the last time accessesed, frequencey accessed and then kick out the images that were last accessed or have low times accessed.
I'd rather not re-invent the wheel if there is already a design pattern for this. Anyone ever implement something similar? Any general idea of what is the best way to implement this would be helpful.
I use Tomact 7, Java 7
What you're looking for is a caching library.
Check out:
Guava
Commons JCS
EHCache
Did you already take a look to the Guava-Libraries from Google? You can find a LoadingCache there, which maybe makes exactly what you want. Look at the CachesExplained Wiki page.
I have an image file (for example img.png) which is updated (overwritten) every 20-30ms using a java program.
Now, I want the client to be able to 'watch' the image as it changing (it will look like a video streaming).
I used Javascript to update the image every 20-30ms but it is not that efficient as it consumes a lot of processing power. I also tried to use Ajax and jQuery.
Any suggestions on how to improve the performance? Can I use a player like jwPlayer or Flow Player? Should I use something different and more efficient?
Thanks.
PS. I have already implemented it using JApplet but I would like to avoid that solution.
You can update image by appending a random string at the end.
function update(){
$('#image').attr('src', $('#image').attr('src')+'?'+Math.random());
}
setTimeout("update()",150);
sounds like you just want a slideshow; there are super fast efficient slideshows in JavaScript, i'm lazy so here's the jQuery version:http://mathiasbynens.be/demo/slideshow if you're having performance issues using this, it's not because of the slideshow
You can update image using javascript timer (setTimeout) eg url
..it consumes a lot of processing power
Note that 'processing power' is not the same as 'bandwidth'.
To save bandwidth, it would make more sense to assemble the images into a video at the server side, and stream the video to the client. Video compression formats generally save a lot of bytes over a series of images, because they can compress images taking into account similar parts of different frames.
first I'd like to explain the situation/requirements that lead to the question:
In our web application we can't support CMYK images (JPEG) since IE 8 and below can't display them.
Thus we need to detect when someone wants to upload such an image and deny it.
Unfortunately, Java's ImageIO won't read those images or would not enable me to get the detected color space. From debugging it seems like JPEGImageReader internally gets the color space code 11 (which would mean JCS_YCCK) but I can't safely access that information.
When querying the reader for the image types I get nothing for CMYK, so I might assume no image types = unsupported image.
I converted the source CMYK image to RGB using an imaging tool in order to test whether it would then be readable (I tried to simulate the admin's steps when getting the message "No CMYK supported"). However, JPEGImageReader would not read that image, since it assumes (comment in the source!)3-component RGB color space but the image header reports 4 components (maybe RGBA or ARGB) and thus an IllegalArgumentException is thrown.
Thus, ImageIO is not an option since I can't reliably get the color space of an image and I can't tell the admin why an otherwise fine image (it can be displayed by the browser) would not be accepted due to some internal error.
This led me to try JAI ImageIO whose CLibJPEGImageReader does an excellent job and correctly reads all my test images.
However, since we're deploying our application in a JBoss that might host other applications as well, we'd like to keep them as isolated as possible. AFAIK, I'd need to install JAI ImageIO to the JRE or otherwise make the native libs available in order to use them, and thus other applications might get access to them as well, which might cause side effects (at least we'd have to test a lot to ensure that's not the case).
That's the explanation for the question, and here it comes again:
Is there any pure Java alternative to JAI ImageIO which reliably detects and possibly converts CMYK images?
Thanks in advance,
Thomas
I found a solution that is ok for our needs: Apache Commons Sanselan. This library reads JPEG headers quite fast and accurate (at least all my test images) as well as a number of other image formats.
The downside is that it won't read JPEG image data, but I can do that with the basic JRE tools.
Reading JPEG images for conversion is quite easy (the ones that ImageIO refuses to read, too):
JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(new FileInputStream( new File(pFilename) ) );
BufferedImage sourceImg = decoder.decodeAsBufferedImage();
Then if Sanselan tells me the image is actually CMYK, I get the source image's raster and convert myself:
for( /*each pixel in the raster, which is represented as int[4]*/ )
{
double k = pixel[3] / 255.0;
double r = (255.0 - pixel[0])*k;
double g = (255.0 - pixel[1])*k;
double b = (255.0 - pixel[2])*k;
}
This give quite good results in the RGB images not being too bright or dark. However, I'm not sure why multiplying with k prevents the brightening. The JPEG is actually decoded in native code and the CMYK->RGB conversion I got states something different, I just tried the multiply to see the visual result.
If anybody could shed some light on this, I'd be grateful.
I've posted a pure Java solution for reading all sorts of JPEG images and converting them to RGB.
It's built on the following facts:
While ImageIO cannot read JPEG images with CMYK as a buffered image, it can read the raw pixel data (raster).
Sanselan (or Apache Commons Imaging as it's called now) can be used to read the details of CMYK images.
There are images with inverted CMYK values (an old Photoshop bug).
There are images with YCCK instead of CMYK (can easily be converted).
Beware of another post as the Java 7 does not allow to use directly Sun's implementation without special parameters as indicated in import com.sun.image.codec.jpeg.*.
In our web application we can't support CMYK images (JPEG) since
IE 8 and below can't display them. Thus we need to detect when someone
wants to upload such an image and deny it.
I don't agree with your "Thus we need to detect when someone wants to upload such an image and deny it". A much more user-friendly policy would be to convert it to something else than CMYK.
The rest of your post is a bit confusing in that regards seen that you ask both for detection and conversion, which are two different things. Once again, I think converting the image is much more user-friendly.
No need to write in bold btw:
Is there any pure Java alternative to JAI ImageIO which reliably
detects and possibly converts CMYK images?
Pure Java I don't know, but ImageMagick works fine to convert CMYK image to RGB ones. Calling ImageMagick on the server-side from Java really isn't complicated. I used to do it manually by calling an external process but nowadays there are wrappers like JMagick and im4java.
I am trying to do some manipulation (specifically, conversion to a different type of splitting into tiles) on a set of very large (a few GB) BMP image files.
I'm not sure I understand the BMP file format, but is it necessary to load the entire file into memory? I was unable to find any API that didn't require loading the entire file at some point. ImageMagick wasn't able to do it either.
Java would be the best tool of choice for me, but any other solution including command line tools or desktop software would be acceptable.
Based on this, it should be reasonably apparent that you can use the fact that it's row-packed. You should be able to read part of a row, store it, advance to the same position in the next row and repeat until you have completed a tile of the desired size. Obviously you may be able to do multiple tiles at once if you can store an entire row worth of tiles in memory all at once.
It is not necessary to load more than the header of the file at once. The header format is describe in the linked Wikipedia entry. It's probably worth paying attention to any compression schemes being used - compression is likely to make this task a bit harder (though still not impossible) :)
Not sure about 2011 year of this questing, but Java 7 (and possibly 6) has good approach for such pleasure.
Use ImageReader and ImageReadParam classes, they allow to read any rectangular part of source image if needed. Set source rectangle and read
... // initialization
private javax.imageio.ImageReadParam m_params;
private javax.imageio.ImageReader m_reader;
... // reading
m_params.setSourceRegion( readRect );
BufferedImage rdImg = m_reader.read( i, m_params );
... // processing/displaying etc
As BMP (it works too for any standard Java image type) is very planar format without any compression in 99.99% cases, to read any its part such way is very fast process with low memory consumption except resulted BufferedImage. Or you can even reuse previous BufferedImage on consequent request with the rect of same dimensions. See ImageReadParam.setDestination(BufferedImage destination). But I didn't test this option.
Also I found one small reading bug namely in BMP reader class implementation of Java runtime lib. If somebody be interested in this, I'll show simple way to correct it.
My program produces 10 x 10 tiles images of 3000x3000 pixel, one by one (currently saved to 100 files named image_x_y.jpg)
I want to assemble these 100 images into one big image, without loading everything in memory. My goal is to create one big image file, of 30'000 * 30'000 pixels.
I'm looking for a way to do this without using JAI (which cannot be installed from public maven repositories, I don't understand why)
Is there a way to do this with pure java2D ? Or does another library exist, able to handle this ?
My original idea was to create a very big buffered image, from a DataBuffer backed to a file on the disk. But i'm not sure that this is possible. Did anybody ever do this ?
I want to assemble these 100 images into one big image, without loading everything in memory. My goal is to create one big image file, of 30'000 * 30'000 pixels.
I believe there is a class in JAI that does this. Whatever problems you are having with integrating JAI into your project I would persevere with that rather than roll your own version. There is nothing like this in Java2D.
My original idea was to create a very big buffered image, from a DataBuffer backed to a file on the disk. But i'm not sure that this is possible. Did anybody ever do this ?
Yes I have written an incomplete implementation of this. It consists of
A DataBuffer that is backed by a ByteBuffer instead of an array (if the buffer is direct it can be mapped to a file.)
A WritableRaster similar to the standard rasters but using my implementation of DataBuffer (the standard rasters in the JDK cheat by holding a reference to the backing array. There is no array in the case of a direct ByteBuffer so unfortunately you must re-implement most Raster methods.)
I do not recommend extending SampleModel because your class will not work with the JDK rasters (various methods in Java2D including the Raster factory methods switch on the type of the SampleModel assuming it is one of the standard ones. Bad design IMHO but not much you can do about it except follow the same pattern.)
I don't know if it is possible without loading everything into memory. You can dump all your images to an uncompressed bmp, and then use some external tool to convert it to jpg.
If you have trouble using a resource from a public maven repository you might want to use Nexus, a maven proxy, and manually add the JAI jar there (and add that to your list of repositories).
The advantage of chosing this solution is that you would have JAI, and would have a standard way to use non-maven resources (all the javax libraries) in a maven way.
Don't fiddle with this around yourself, the imaging matter is complex due to all the compression involved and dealing with BMPs on disk is, given your image sizes (about 100 * 30MB = 3GB) probably not optimal nor fast.