javax.imageio.IIOException:在向JPG图像添加文本时缺少哈夫曼编码表条目

11

我正在使用以下代码在Android中向图像添加文本:

public Bitmap drawTextToBitmap(Context gContext, Bitmap image, String gText) {

    Resources resources = gContext.getResources();
    float scale = resources.getDisplayMetrics().density;

    android.graphics.Bitmap.Config bitmapConfig =
            image.getConfig();
    // set default bitmap config if none
    if(bitmapConfig == null) {
        bitmapConfig = android.graphics.Bitmap.Config.ARGB_8888;
    }
    // resource bitmaps are imutable,
    // so we need to convert it to mutable one

    Bitmap bitmap = null;

    try{
        bitmap = image.copy(bitmapConfig, true);
        image.recycle();

        Canvas canvas = new Canvas(bitmap);
        // new antialised Paint
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        // text color - #3D3D3D
        paint.setColor(Color.WHITE);
        // text size in pixels
        paint.setTextSize((int) (50 * scale));
        // text shadow
        paint.setShadowLayer(1f, 0f, 1f, Color.BLACK);

        // draw text to the Canvas center
        Rect bounds = new Rect();
        paint.getTextBounds(gText, 0, gText.length(), bounds);
        int padding = bounds.height()/2;
        int x = bitmap.getWidth() - (bounds.width()+padding);
        int y = (bitmap.getHeight() - (bounds.height()+padding));

        canvas.drawText(gText, x, y, paint);
    }catch (Throwable e){
        AppLog.e("DrawingBitmap","error while adding timestamp",e);
    }
    return bitmap;
}
然后我用转换后的位图创建了一个新文件。
storeImage(newBitmap, newFileName);

 private File storeImage(Bitmap image, String nameFile) {

    File pictureFile = new File(getExternalCacheDir(), nameFile);

    try {
        FileOutputStream fos = new FileOutputStream(pictureFile);
        image.compress(Bitmap.CompressFormat.JPEG, 100, fos);
        fos.close();
    } catch (FileNotFoundException e) {
        AppLog.e("error creating bitmap", "File not found: " + e.getMessage());
    } catch (IOException e) {
        AppLog.e("error creating bitmap", "Error accessing file: " + e.getMessage());
    }

    return pictureFile;
}

我将文件发送到服务器,接收输入流,创建一个文件,按比例缩放它,并创建一个带有缩放图像的新文件:

ImageWriter.write(metadata, new IIOImage(image, null, metadata), param);

我收到了一个IIOException错误:

 javax.imageio.IIOException: Missing Huffman code table entry
    at com.sun.imageio.plugins.jpeg.JPEGImageWriter.writeImage(Native Method)
    at com.sun.imageio.plugins.jpeg.JPEGImageWriter.writeOnThread(JPEGImageWriter.java:1067)
    at com.sun.imageio.plugins.jpeg.JPEGImageWriter.write(JPEGImageWriter.java:363)
    at com.twelvemonkeys.imageio.plugins.jpeg.JPEGImageWriter.write(JPEGImageWriter.java:162)

如果我不从安卓中调用drawTextToBitmap(),就不会出现那个错误。

如果有人能帮忙...谢谢

编辑:这是我用来获取文件元数据的方式。

    private static IIOMetadata readMetaData(File source)  {
    try {
        ImageInputStream stream = ImageIO.createImageInputStream(source);
        Iterator<ImageReader> readers = ImageIO.getImageReaders(stream);
        IIOMetadata metadata = null;
        if (readers.hasNext()) {
            ImageReader reader = readers.next();
            reader.setInput(stream);
            metadata = reader.getImageMetadata(0);
        }
        return metadata;
    }catch (Exception e){
        _logger.error(e);
        e.printStackTrace();
    }
    return null;
}

编辑2:

使用jpegParams.setOptimizeHuffmanTables(true);可以解决问题,但会重置所有元数据,我想保留它们,例如GPS位置...


1
尝试在传递给ImageWriter.write()方法的JPEG参数上设置setOptimizeHuffmanTables(true)的值。 - Nikolay
如果可能,请发布相关的服务器代码。 - kamyar haqqani
我已经发布了服务器代码:ImageWriter.write(metadata, new IIOImage(image, null, metadata), param);,如果我在Android上不调用drawTextToBitmap,它可以工作,但是如果我在Android上调用drawTextToBitmap,则在ImageWriter.write(metadata, new IIOImage(image, null, metadata), param);的服务器端会出现IIOException。 - Alays
在调用 storeImage 方法后,发送到服务器之前,您能否在 Android 端打开文件? - Ferran
是的,结果就是图像加上绘制在上面的文本。 - Alays
显示剩余6条评论
1个回答

5
ImageWriteParam param = writer.getDefaultWriteParam();
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionQuality(quality);
if (param instanceof JPEGImageWriteParam) {
    ((JPEGImageWriteParam) param).setOptimizeHuffmanTables(true);
}
IIOImage image = new IIOImage(reader.read(0), null, reader.getImageMetadata(0));
writer.write(null, image, param);

这是我的代码,它保存图像的元数据并且去除了"缺少哈夫曼码表"的内容。

哇,这个解决方案拯救了我的应用程序。我将添加赏金以表达我的感激之情。但实际上,这只是一种解决某些图像下的潜在问题的方法。有没有什么办法可以事先检查以确定是否需要使用此解决方案? - Garret Wilson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接