Java AWT/ImageIO: Bilinear and Bicubic scaling of a JPEG image result in completely black output -
nearest neighbor scaling works: entire picture stays intact when use type_nearest_neighbor
.
even though scala code, used libraries standard java libraries.
functions:
def getbufferedimage(imagefile: java.io.file): bufferedimage = { imageio.read(imagefile) } def scaleimage(image: bufferedimage, minsize: double): bufferedimage = { val before: bufferedimage = image val w = before.getwidth() val h = before.getheight() val affit = new affinetransform() var scale = 1.0 if(h < w) { if(h > 0) { scale = minsize / h } } else { if(w > 0) { scale = minsize / w } } affit.scale(scale, scale) val affitop = new affinetransformop(affit, affinetransformop.type_bicubic) affitop.filter(before, null) } def getimagejpegbytearray(image: bufferedimage): array[byte] = { val baos = new java.io.bytearrayoutputstream() val mcios = new memorycacheimageoutputstream(baos) imageio.write(image, "jpeg", mcios) mcios.close() baos.tobytearray }
calling code snippet:
val img = getbufferedimage(imagefile) val scaledimg = scaleimage(img, 512) val result = getimagejpegbytearray(scaledimg) // result written sqlite database
result
written sqlite database. if download database , save jpeg file, resulting jpeg is
- as expected if use
affinetransformop.type_nearest_neighbor
- completely black if use
affinetransformop.type_bilinear
- completely black if use
affinetransformop.type_bicubic
consequently, accuse affinetransformop
of being buggy... how can solve problem?
file magic number of result
ff d8 ff
expected jpeg.
details
java version: java hotspot(tm) 64-bit server vm, java 1.7.0_71
operating system: apple, os x 10.9.5
test image: http://www.photos-public-domain.com/wp-content/uploads/2012/05/thundercloud-plum-blossoms.jpg
i able reproduce issue on java 1.7.0_71 on os x 10.10.4 (i rewrote code in java, can post full code if interested).
in case, problem not affinetransformop
buggy in itself. in test program displayed image using minimal swing jframe
, scaled image looked there. why people in comments did not understand problem.
part of issue bufferedimage
returned affinetransformop
when don't provide destination filter
method (the second parameter, null
in case), create 1 you. image type bufferedimage.type_int_argb
. here relevant code affinetransformop.createcompatibledestimage()
(lines 456-468, kept formatting, make easier spot):
colormodel cm = src.getcolormodel(); if (interpolationtype != type_nearest_neighbor && (cm instanceof indexcolormodel || cm.gettransparency() == transparency.opaque) { image = new bufferedimage(w, h, bufferedimage.type_int_argb); } else { image = new bufferedimage(cm, src.getraster().createcompatiblewritableraster(w,h), cm.isalphapremultiplied(), null); }
notice special case type_nearest_neighbor
, explains why you'll different behavior when using nearest neighbor algorithm. good, (as said, image displays fine in swing component).
the problem arises when try store image jpeg. during years, there's been lot of confusion , issues related imageio jpeg plugin , whether allow write images alpha channel (like type_int_argb
image). allow that. but, argb jpegs misinterpreted cmyk jpegs (as 4 channels, , storing argb data in jpeg exotic) , displayed in funky colors. in case though, seems black...
so, there 2 possible solutions:
either write image in file format supports alpha channel, png or tiff (tiff requires plugin, might not best choice). this:
imageio.write(image, "png", mcios);
or, make sure
bufferedimage
in pixel format without alpha channel before storing jpeg. can after scaling, easiest (and fastest) provideaffinetransformop
explicit destination image, this:rectangle newsize = affitop.getbounds2d(before).getbounds(); return affitop.filter(before, new bufferedimage(newsize.width, newsize.height, bufferedimage.type_3byte_bgr));
here image, scaled program, using jpeg format , type_3byte_bgr
:
i'm sure can rewrite java code scala. :-)
Comments
Post a Comment