如何在不丢失字节数组的颜色的情况下保存tiff文件?

时间:2014-03-28 00:43:30

标签: image hdfs tiff gdal jai

我需要使用JAI保存tif图像的字节数组,我从gdal获取了我的tif字节数组。我有以下代码:

 BufferedImage bufferedImage = new BufferedImage( fullWidthSize/2, fullHeightSize/2, BufferedImage.TYPE_BYTE_BINARY);
 WritableRaster raster = bufferedImage.getRaster(); 
 raster.setDataElements(0, 0, fullWidthSize/2, fullHeightSize/2, bytes);

 TIFFEncodeParam params = new TIFFEncodeParam();
 params.setCompression( TIFFEncodeParam.COMPRESSION_NONE );
 String filenametiff = "/mnt/hdfs/user/hdfs/inImage/haw2_smallJAI.tif";
 JAI.create("filestore", bufferedImage, filenametiff, "TIFF", params);

但不幸的是它保存了tif图像,但是在灰度级,我也尝试了TYPE_BYTE_INDEXED,但它保存的图像有奇怪的颜色,有点阴天,并且使用TYPE_CUSTOM我得到以下错误:

java.lang.IllegalArgumentException:未知图像类型0

你可以给我一些指导,以便正确地写出图像吗?

P.S。我没有使用gdal来保存图像的原因是因为某种程度上它不能用hdfs编写,使用" _tiffSeekProc:不支持操作"消息,我使用FUSE挂载了hdfs。

1 个答案:

答案 0 :(得分:0)

这对于评论来说有点太长了,抱歉。 ; - )

这里有一些示例代码,应该正确评论,以帮助您了解它的作用。好好写它......

它的作用是创建和显示6个图像(随机噪声)。将有3个不同的图像,每个图像以两种不同的方式创建。 4将使用带状模型和2交错模型。对于带状模型,它展示了如何使用单维和多维数组创建它们。

import java.awt.Point;
import java.awt.Transparency;
import java.awt.Window;
import java.awt.color.ColorSpace;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BandedSampleModel;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.ComponentColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.PixelInterleavedSampleModel;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.util.Arrays;
import java.util.Random;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;

public class BufferedImageTester {
    public static void main(String[] args) {
        // Part I
        // Dimensions, number of bands and other setup
        int width = 300;
        int height = 200;
        int bands = 3; // 4 works too, if you want alpha
        int bandSize = width * height;
        Point origin = new Point(0, 0);

        // Create backing data for single array banded model
        byte[] singleData = new byte[bandSize * bands];
        int[] singleBankIndices = createIndices(bands, 0, 0); // 0, 0, 0
        int[] singleBandOffsets = createIndices(bands, 0, bandSize); // 0, bandSize, 2 * bandSize

        // Create buffer for single array
        DataBufferByte singleBuffer = new DataBufferByte(singleData, singleData.length, 0);

        // Create raster directly from buffer
        WritableRaster bandedRaster1 = Raster.createBandedRaster(singleBuffer, width, height, width, singleBankIndices, singleBandOffsets, origin);
        System.out.println("bandedRaster1: " + bandedRaster1);

        // Create raster from sample model and buffer
        BandedSampleModel singleModel = new BandedSampleModel(DataBuffer.TYPE_BYTE, width, height, width, singleBankIndices, singleBandOffsets);
        WritableRaster bandedRaster2 = Raster.createWritableRaster(singleModel, singleBuffer, origin);
        System.out.println("bandedRaster2: " + bandedRaster2);

        // Create backing data for multiple arrays banded model
        byte[][] multiData = new byte[bands][bandSize];
        int[] multiBankIndices = createIndices(bands, 0, 1); // 0, 1, 2
        int[] multiBandOffsets = createIndices(bands, 0, 0); // 0, 0, 0

        // Create buffer for multiple arrays
        DataBufferByte multiBuffer = new DataBufferByte(multiData, bandSize, multiBandOffsets);

        // Create raster directly from buffer
        WritableRaster bandedRaster3 = Raster.createBandedRaster(multiBuffer, width, height, width, multiBankIndices, multiBandOffsets, origin);
        System.out.println("bandedRaster3: " + bandedRaster3);

        // Create raster from sample model and buffer
        BandedSampleModel multiModel = new BandedSampleModel(DataBuffer.TYPE_BYTE, width, height, width, multiBankIndices, multiBandOffsets);
        WritableRaster bandedRaster4 = Raster.createWritableRaster(multiModel, multiBuffer, origin);
        System.out.println("bandedRaster4: " + bandedRaster4);

        // Now let's create a suitable color model for these kinds of rasters,  with default sRGB color space
        ColorModel colorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), bands > 3, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);

        // Create images for all of the raster types
        BufferedImage image1 = new BufferedImage(colorModel, bandedRaster1, colorModel.isAlphaPremultiplied(), null);
        System.out.println("image1: " + image1);
        BufferedImage image2 = new BufferedImage(colorModel, bandedRaster2, colorModel.isAlphaPremultiplied(), null);
        System.out.println("image2: " + image2);
        BufferedImage image3 = new BufferedImage(colorModel, bandedRaster3, colorModel.isAlphaPremultiplied(), null);
        System.out.println("image3: " + image3);
        BufferedImage image4 = new BufferedImage(colorModel, bandedRaster4, colorModel.isAlphaPremultiplied(), null);
        System.out.println("image4: " + image4);

        // Fill with randomness to make it less dull
        Random random = new Random();
        random.nextBytes(singleData);
        for (byte[] bytes : multiData) {
            random.nextBytes(bytes);
        }

        // And finally display to prove it works just fine
        showIt(image1, "Image 1: Single bank, banded raster");
        showIt(image2, "Image 2: Single bank, banded, generic raster");
        showIt(image3, "Image 3: Multibank, banded raster");
        showIt(image4, "Image 4: Multibank, banded, generic raster");

        // Part II
        // Now, the single array image, could also be used to create somehting more standard (the images will *NOT* look the same, despite sharing data)

        // Create raster directly from buffer
        int[] interleavedOffsets = createIndices(bands, bands - 1, -1); // 2, 1, 0 (BufferedImage.TYPE_3BYTE_BGR has this order)
        WritableRaster interleavedRaster1 = Raster.createInterleavedRaster(singleBuffer, width, height, bands * width, bands, interleavedOffsets, origin);
        System.out.println("interleavedRaster1: " + interleavedRaster1);

        // Create raster from sample model and buffer
        PixelInterleavedSampleModel interleavedModel = new PixelInterleavedSampleModel(DataBuffer.TYPE_BYTE, width, height, bands, bands * width, interleavedOffsets);
        WritableRaster interleavedRaster2 = Raster.createWritableRaster(interleavedModel, singleBuffer, origin);
        System.out.println("interleavedRaster2: " + interleavedRaster2);

        // Create images for all of the raster types
        BufferedImage image5 = new BufferedImage(colorModel, interleavedRaster1, colorModel.isAlphaPremultiplied(), null);
        System.out.println("image5: " + image5);
        BufferedImage image6 = new BufferedImage(colorModel, interleavedRaster2, colorModel.isAlphaPremultiplied(), null);
        System.out.println("image6: " + image6);

        // Uncomment these lines, to better understand the difference between banded and interleaved :-)
//        Arrays.fill(singleData, bandSize, 2 * bandSize, (byte) 255);
//        Arrays.fill(multiData[1], (byte) 255);

        // And finally display to prove it works just fine
        showIt(image5, "Image 5: Single bank, interleaved raster");
        showIt(image6, "Image 6: Single bank, interleaved raster");
    }

    private static int[] createIndices(final int count, final int start, final int increment) {
        int[] indices = new int[count];

        for (int i = 0; i < count; i++) {
            indices[i] = start + i * increment;
        }

        return indices;
    }

    private static void showIt(final BufferedImage image, final String title) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JFrame frame = new JFrame(title);
                frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
                frame.addWindowListener(new WindowAdapter() {
                    @Override public void windowClosed(final WindowEvent e) {
                        if (Window.getWindows() == null || Window.getWindows().length == 0) {
                            System.exit(0);
                        }
                    }
                });
                frame.add(new JLabel(new ImageIcon(image)));
                frame.pack();
                frame.setLocationByPlatform(true);
                frame.setVisible(true);
            }
        });
    }
}

这是测试输出的样子:

bandedRaster1: ByteBandedRaster: width = 300 height = 200 #bands 3 minX = 0 minY = 0
bandedRaster2: sun.awt.image.SunWritableRaster@450cceb3
bandedRaster3: ByteBandedRaster: width = 300 height = 200 #bands 3 minX = 0 minY = 0
bandedRaster4: sun.awt.image.SunWritableRaster@4bd66d2f
image1: BufferedImage@1e8ee5c0: type = 0 ColorModel: #pixelBits = 24 numComponents = 3 color space = java.awt.color.ICC_ColorSpace@378dafec transparency = 1 has alpha = false isAlphaPre = false ByteBandedRaster: width = 300 height = 200 #bands 3 minX = 0 minY = 0
image2: BufferedImage@3718cb72: type = 0 ColorModel: #pixelBits = 24 numComponents = 3 color space = java.awt.color.ICC_ColorSpace@378dafec transparency = 1 has alpha = false isAlphaPre = false sun.awt.image.SunWritableRaster@450cceb3
image3: BufferedImage@3cd4c5a0: type = 0 ColorModel: #pixelBits = 24 numComponents = 3 color space = java.awt.color.ICC_ColorSpace@378dafec transparency = 1 has alpha = false isAlphaPre = false ByteBandedRaster: width = 300 height = 200 #bands 3 minX = 0 minY = 0
image4: BufferedImage@34faaa93: type = 0 ColorModel: #pixelBits = 24 numComponents = 3 color space = java.awt.color.ICC_ColorSpace@378dafec transparency = 1 has alpha = false isAlphaPre = false sun.awt.image.SunWritableRaster@4bd66d2f
interleavedRaster1: ByteInterleavedRaster: width = 300 height = 200 #numDataElements 3 dataOff[0] = 2
interleavedRaster2: ByteInterleavedRaster: width = 300 height = 200 #numDataElements 3 dataOff[0] = 2
image5: BufferedImage@39a44220: type = 5 ColorModel: #pixelBits = 24 numComponents = 3 color space = java.awt.color.ICC_ColorSpace@378dafec transparency = 1 has alpha = false isAlphaPre = false ByteInterleavedRaster: width = 300 height = 200 #numDataElements 3 dataOff[0] = 2
image6: BufferedImage@4ef16070: type = 5 ColorModel: #pixelBits = 24 numComponents = 3 color space = java.awt.color.ICC_ColorSpace@378dafec transparency = 1 has alpha = false isAlphaPre = false ByteInterleavedRaster: width = 300 height = 200 #numDataElements 3 dataOff[0] = 2
PS:奖励指向任何可以解释为什么带状栅格1&amp; 2和3&amp; 4分别不相同或相同类型......我认为它们应该是交错的光栅1和1。 2是相等的。