TIF合并Java代码

目录

■合并后的效果

​编辑

■代码实现

1.Maven

2.代码

3.测试类

4.坑,windows下,ImageIO 不支持真正的tif文件

■如何判断图片文件真实的类型

■解决

■Jar中的一部分代码

com.sun.media.jai.codec.ImageCodec;

com.sun.media.jai.codec;

com.sun.media.jai.codecimpl.TIFFCodec;

■TIF图像的读取

・TIF的存储结构

【1.⽂件头(IFH)】

【2.图像⽂件⽬录(IFD)】

【 3.图像数据】


■合并后的效果

===

3.png,4.png  ⇒ 12.tif

■代码实现

1.Maven

<!-- tif 合并 -->
  <dependencies>	
   <dependency>
       <groupId>com.sun.media</groupId>
       <artifactId>jai-codec</artifactId>
       <version>1.1.3</version>
   </dependency>
</dependencies>

<repositories>
  <repository>
    <id>mvnrepository</id>
    <name>mvnrepository</name>
    <url>https://repository.jboss.org/maven2/</url>
  </repository>
</repositories>

Index of /com/sun/media/jai-codec/1.1.3

---

可以正常下载到本地

2.代码

package com.sxz.test;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;

import com.sun.media.jai.codec.ImageCodec;
import com.sun.media.jai.codec.ImageEncoder;
import com.sun.media.jai.codec.TIFFEncodeParam;

public class TifUtils {

    /**
     * tif合并
     **/
    public static byte[] margerTif(List<byte[]> bytes){
        ByteArrayInputStream bin = null;
        List<BufferedImage> images = new ArrayList<BufferedImage> ();
        for(byte[] b : bytes) {
            try {
                bin = new ByteArrayInputStream(b);
                BufferedImage image = ImageIO.read(bin);
                images.add(image);
                bin.close();
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
 
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try{
            TIFFEncodeParam params = new TIFFEncodeParam();
            params.setCompression(TIFFEncodeParam.COMPRESSION_JPEG_TTN2);
            ImageEncoder encoder = ImageCodec.createImageEncoder("tiff", out, params);
            List<BufferedImage> imageList = new ArrayList<BufferedImage>();
            for (int i = 1; i < images.size(); i++){
                imageList.add(images.get(i));
            }
            params.setExtraImages(imageList.iterator());
            encoder.encode(images.get(0));
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return out.toByteArray();
    }
	
}

3.测试类

package com.sxz.test;

import java.io.File;
import java.io.FileOutputStream;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;

public class Test {

	public static void main(String[] args) {
        File file1 = new File("C:\\TIF\\1.tif");
        File file2 = new File("C:\\TIF\\2.tif");
        FileOutputStream os;
        try {
            List<byte[]> list = new ArrayList();
            list.add(Files.readAllBytes(file1.toPath()));
            list.add(Files.readAllBytes(file2.toPath()));
            byte[] b = TifUtils.margerTif(list);
            os = new FileOutputStream(new File("C:\\TIF\\12.tif"));
            os.write(b);
            os.flush();
            os.close();
   
        }catch (Exception e){
            e.printStackTrace();
        } finally{
        }

	}

}

4.坑,windows下,ImageIO 不支持真正的tif文件

BufferedImage image = ImageIO.read(bin);

       判断图片文件真实类型---通过文件表头判断。_sun0322-CSDN博客

返回值为null,出错原因

ImageIO.read() 返回 null_复利人生的博客-CSDN博客_imageio.read

		for (int i = 0; i < ImageIO.getReaderFormatNames().length; i++) {
		    System.out.println(ImageIO.getReaderFormatNames()[i]);
		}

---运行输出如下结果

JPG
jpg
bmp
BMP
gif
GIF
WBMP
png
PNG
jpeg
wbmp
JPEG

---linux中也不支持

sxz001@sxzap01:~$ cat /etc/redhat-release
cat: /etc/redhat-release: No such file or directory
sxz001@sxzap01:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.2 LTS
Release:        20.04
Codename:       focal
sxz001@sxzap01:~$
sxz001@sxzap01:~$
sxz001@sxzap01:~$ clear

sxz001@sxzap01:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.2 LTS
Release:        20.04
Codename:       focal
sxz001@sxzap01:~$
sxz001@sxzap01:~$
sxz001@sxzap01:~$ java com.sxz.test.Test
JPG
jpg
bmp
BMP
gif
GIF
WBMP
png
PNG
wbmp
jpeg
JPEG
sxz001@sxzap01:~$
sxz001@sxzap01:~$
sxz001@sxzap01:~$  uname -a
Linux sxzap01 5.4.0-72-generic #80-Ubuntu SMP Mon Apr 12 17:35:00 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
sxz001@sxzap01:~$

■如何判断图片文件真实的类型

判断图片文件真实类型---通过文件表头判断。_sun0322-CSDN博客

■解决

解决ImageIO.read返回为null的问题_wxmgcs的专栏-CSDN博客_imageio.read返回null

■Jar中的一部分代码

com.sun.media.jai.codec.ImageCodec;

package com.sun.media.jai.codec;

import com.sun.media.jai.codecimpl.BMPCodec;
import com.sun.media.jai.codecimpl.FPXCodec;
import com.sun.media.jai.codecimpl.GIFCodec;
import com.sun.media.jai.codecimpl.ImagingListenerProxy;
import com.sun.media.jai.codecimpl.JPEGCodec;
import com.sun.media.jai.codecimpl.PNGCodec;
import com.sun.media.jai.codecimpl.PNMCodec;
import com.sun.media.jai.codecimpl.TIFFCodec;
import com.sun.media.jai.codecimpl.WBMPCodec;
import com.sun.media.jai.codecimpl.util.FloatDoubleColorModel;
import com.sun.media.jai.util.SimpleCMYKColorSpace;
import java.awt.color.ColorSpace;
import java.awt.image.ColorModel;
import java.awt.image.ComponentColorModel;
import java.awt.image.IndexColorModel;
import java.awt.image.RenderedImage;
import java.awt.image.SampleModel;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

public abstract class ImageCodec {
	private static Hashtable codecs = new Hashtable();
	private static final byte[][] grayIndexCmaps;
	private static final int[] GrayBits8;
	private static final ComponentColorModel colorModelGray8;
	private static final int[] GrayAlphaBits8;
	private static final ComponentColorModel colorModelGrayAlpha8;
	private static final int[] GrayBits16;
	private static final ComponentColorModel colorModelGray16;
	private static final int[] GrayAlphaBits16;
	private static final ComponentColorModel colorModelGrayAlpha16;
	private static final int[] GrayBits32;
	private static final ComponentColorModel colorModelGray32;
	private static final int[] GrayAlphaBits32;
	private static final ComponentColorModel colorModelGrayAlpha32;
	private static final int[] RGBBits8;
	private static final ComponentColorModel colorModelRGB8;
	private static final int[] RGBABits8;
	private static final ComponentColorModel colorModelRGBA8;
	private static final int[] RGBBits16;
	private static final ComponentColorModel colorModelRGB16;
	private static final int[] RGBABits16;
	private static final ComponentColorModel colorModelRGBA16;
	private static final int[] RGBBits32;
	private static final ComponentColorModel colorModelRGB32;
	private static final int[] RGBABits32;
	private static final ComponentColorModel colorModelRGBA32;

	public static ImageCodec getCodec(String name) {
		return (ImageCodec) codecs.get(name.toLowerCase());
	}

	public static void registerCodec(ImageCodec codec) {
		codecs.put(codec.getFormatName().toLowerCase(), codec);
	}

	public static void unregisterCodec(String name) {
		codecs.remove(name.toLowerCase());
	}

	public static Enumeration getCodecs() {
		return codecs.elements();
	}

	public static ImageEncoder createImageEncoder(String name, OutputStream dst, ImageEncodeParam param) {
		ImageCodec codec = getCodec(name);
		return codec == null ? null : codec.createImageEncoder(dst, param);
	}

	public static ImageDecoder createImageDecoder(String name, InputStream src, ImageDecodeParam param) {
		ImageCodec codec = getCodec(name);
		return codec == null ? null : codec.createImageDecoder(src, param);
	}

	public static ImageDecoder createImageDecoder(String name, File src, ImageDecodeParam param) throws IOException {
		ImageCodec codec = getCodec(name);
		return codec == null ? null : codec.createImageDecoder(src, param);
	}

	public static ImageDecoder createImageDecoder(String name, SeekableStream src, ImageDecodeParam param) {
		ImageCodec codec = getCodec(name);
		return codec == null ? null : codec.createImageDecoder(src, param);
	}

	private static String[] vectorToStrings(Vector nameVec) {
		int count = nameVec.size();
		String[] names = new String[count];

		for (int i = 0; i < count; ++i) {
			names[i] = (String) nameVec.elementAt(i);
		}

		return names;
	}

	public static String[] getDecoderNames(SeekableStream src) {
		if (!src.canSeekBackwards() && !src.markSupported()) {
			throw new IllegalArgumentException(JaiI18N.getString("ImageCodec2"));
		} else {
			Enumeration enumeration = codecs.elements();
			Vector nameVec = new Vector();
			Object var3 = null;

			while (true) {
				ImageCodec codec;
				int bytesNeeded;
				do {
					if (!enumeration.hasMoreElements()) {
						return vectorToStrings(nameVec);
					}

					codec = (ImageCodec) enumeration.nextElement();
					bytesNeeded = codec.getNumHeaderBytes();
				} while (bytesNeeded == 0 && !src.canSeekBackwards());

				try {
					if (bytesNeeded > 0) {
						src.mark(bytesNeeded);
						byte[] header = new byte[bytesNeeded];
						src.readFully(header);
						src.reset();
						if (codec.isFormatRecognized(header)) {
							nameVec.add(codec.getFormatName());
						}
					} else {
						long pointer = src.getFilePointer();
						src.seek(0L);
						if (codec.isFormatRecognized(src)) {
							nameVec.add(codec.getFormatName());
						}

						src.seek(pointer);
					}
				} catch (IOException var8) {
					ImagingListenerProxy.errorOccurred(JaiI18N.getString("ImageCodec3"), var8,
							class$com$sun$media$jai$codec$ImageCodec == null
									? (class$com$sun$media$jai$codec$ImageCodec = class$(
											"com.sun.media.jai.codec.ImageCodec"))
									: class$com$sun$media$jai$codec$ImageCodec,
							false);
				}
			}
		}
	}

	public static String[] getEncoderNames(RenderedImage im, ImageEncodeParam param) {
		Enumeration enumeration = codecs.elements();
		Vector nameVec = new Vector();
		Object var4 = null;

		while (enumeration.hasMoreElements()) {
			ImageCodec codec = (ImageCodec) enumeration.nextElement();
			if (codec.canEncodeImage(im, param)) {
				nameVec.add(codec.getFormatName());
			}
		}

		return vectorToStrings(nameVec);
	}

	public abstract String getFormatName();

	public int getNumHeaderBytes() {
		return 0;
	}

	public boolean isFormatRecognized(byte[] header) {
		throw new RuntimeException(JaiI18N.getString("ImageCodec0"));
	}

	public boolean isFormatRecognized(SeekableStream src) throws IOException {
		throw new RuntimeException(JaiI18N.getString("ImageCodec1"));
	}

	protected abstract Class getEncodeParamClass();

	protected abstract Class getDecodeParamClass();

	protected abstract ImageEncoder createImageEncoder(OutputStream var1, ImageEncodeParam var2);

	public abstract boolean canEncodeImage(RenderedImage var1, ImageEncodeParam var2);

	protected ImageDecoder createImageDecoder(InputStream src, ImageDecodeParam param) {
		SeekableStream stream = SeekableStream.wrapInputStream(src, true);
		return this.createImageDecoder(stream, param);
	}

	protected ImageDecoder createImageDecoder(File src, ImageDecodeParam param) throws IOException {
		return this.createImageDecoder((SeekableStream) (new FileSeekableStream(src)), param);
	}

	protected abstract ImageDecoder createImageDecoder(SeekableStream var1, ImageDecodeParam var2);

	public static ColorModel createGrayIndexColorModel(SampleModel sm, boolean blackIsZero) {
		if (sm.getNumBands() != 1) {
			throw new IllegalArgumentException();
		} else {
			int sampleSize = sm.getSampleSize(0);
			byte[] cmap = null;
			int length;
			byte[] cmap;
			if (sampleSize < 8) {
				cmap = grayIndexCmaps[sampleSize];
				if (!blackIsZero) {
					length = cmap.length;
					byte[] newCmap = new byte[length];

					for (int i = 0; i < length; ++i) {
						newCmap[i] = cmap[length - i - 1];
					}

					cmap = newCmap;
				}
			} else {
				cmap = new byte[256];
				if (blackIsZero) {
					for (length = 0; length < 256; ++length) {
						cmap[length] = (byte) length;
					}
				} else {
					for (length = 0; length < 256; ++length) {
						cmap[length] = (byte) (255 - length);
					}
				}
			}

			return new IndexColorModel(sampleSize, cmap.length, cmap, cmap, cmap);
		}
	}

	public static ColorModel createComponentColorModel(SampleModel sm) {
		int type = sm.getDataType();
		int bands = sm.getNumBands();
		ComponentColorModel cm = null;
		if (type == 0) {
			switch (bands) {
				case 1 :
					cm = colorModelGray8;
					break;
				case 2 :
					cm = colorModelGrayAlpha8;
					break;
				case 3 :
					cm = colorModelRGB8;
					break;
				case 4 :
					cm = colorModelRGBA8;
			}
		} else if (type == 1) {
			switch (bands) {
				case 1 :
					cm = colorModelGray16;
					break;
				case 2 :
					cm = colorModelGrayAlpha16;
					break;
				case 3 :
					cm = colorModelRGB16;
					break;
				case 4 :
					cm = colorModelRGBA16;
			}
		} else if (type == 3) {
			switch (bands) {
				case 1 :
					cm = colorModelGray32;
					break;
				case 2 :
					cm = colorModelGrayAlpha32;
					break;
				case 3 :
					cm = colorModelRGB32;
					break;
				case 4 :
					cm = colorModelRGBA32;
			}
		} else if (type == 4 && bands >= 1 && bands <= 4) {
			ColorSpace cs = bands <= 2 ? ColorSpace.getInstance(1003) : ColorSpace.getInstance(1000);
			boolean hasAlpha = bands % 2 == 0;
			cm = new FloatDoubleColorModel(cs, hasAlpha, false, hasAlpha ? 3 : 1, 4);
		}

		return (ColorModel) cm;
	}

	public static ColorModel createComponentColorModel(SampleModel sm, ColorSpace cp) {
		if (cp == null) {
			return createComponentColorModel(sm);
		} else {
			int type = sm.getDataType();
			int bands = sm.getNumBands();
			ComponentColorModel cm = null;
			int[] bits = null;
			int transferType = -1;
			boolean hasAlpha = bands % 2 == 0;
			if (cp instanceof SimpleCMYKColorSpace) {
				hasAlpha = false;
			}

			int transparency = hasAlpha ? 3 : 1;
			if (type == 0) {
				transferType = 0;
				switch (bands) {
					case 1 :
						bits = GrayBits8;
						break;
					case 2 :
						bits = GrayAlphaBits8;
						break;
					case 3 :
						bits = RGBBits8;
						break;
					case 4 :
						bits = RGBABits8;
				}
			} else if (type == 1) {
				transferType = 1;
				switch (bands) {
					case 1 :
						bits = GrayBits16;
						break;
					case 2 :
						bits = GrayAlphaBits16;
						break;
					case 3 :
						bits = RGBBits16;
						break;
					case 4 :
						bits = RGBABits16;
				}
			} else if (type == 3) {
				transferType = 3;
				switch (bands) {
					case 1 :
						bits = GrayBits32;
						break;
					case 2 :
						bits = GrayAlphaBits32;
						break;
					case 3 :
						bits = RGBBits32;
						break;
					case 4 :
						bits = RGBABits32;
				}
			}

			if (type == 4 && bands >= 1 && bands <= 4) {
				cm = new FloatDoubleColorModel(cp, hasAlpha, false, transparency, 4);
			} else {
				cm = new ComponentColorModel(cp, bits, hasAlpha, false, transparency, transferType);
			}

			return (ColorModel) cm;
		}
	}

	public static boolean isIndicesForGrayscale(byte[] r, byte[] g, byte[] b) {
		if (r.length == g.length && r.length == b.length) {
			int size = r.length;
			if (size != 256) {
				return false;
			} else {
				for (int i = 0; i < size; ++i) {
					byte temp = (byte) i;
					if (r[i] != temp || g[i] != temp || b[i] != temp) {
						return false;
					}
				}

				return true;
			}
		} else {
			return false;
		}
	}

	static {
		registerCodec(new BMPCodec());
		registerCodec(new GIFCodec());
		registerCodec(new FPXCodec());
		registerCodec(new JPEGCodec());
		registerCodec(new PNGCodec());
		registerCodec(new PNMCodec());
		registerCodec(new TIFFCodec());
		registerCodec(new WBMPCodec());
		grayIndexCmaps = new byte[][]{null, {0, -1}, {0, 85, -86, -1}, null,
				{0, 17, 34, 51, 68, 85, 102, 119, -120, -103, -86, -69, -52, -35, -18, -1}};
		GrayBits8 = new int[]{8};
		colorModelGray8 = new ComponentColorModel(ColorSpace.getInstance(1003), GrayBits8, false, false, 1, 0);
		GrayAlphaBits8 = new int[]{8, 8};
		colorModelGrayAlpha8 = new ComponentColorModel(ColorSpace.getInstance(1003), GrayAlphaBits8, true, false, 3, 0);
		GrayBits16 = new int[]{16};
		colorModelGray16 = new ComponentColorModel(ColorSpace.getInstance(1003), GrayBits16, false, false, 1, 1);
		GrayAlphaBits16 = new int[]{16, 16};
		colorModelGrayAlpha16 = new ComponentColorModel(ColorSpace.getInstance(1003), GrayAlphaBits16, true, false, 3,
				1);
		GrayBits32 = new int[]{32};
		colorModelGray32 = new ComponentColorModel(ColorSpace.getInstance(1003), GrayBits32, false, false, 1, 3);
		GrayAlphaBits32 = new int[]{32, 32};
		colorModelGrayAlpha32 = new ComponentColorModel(ColorSpace.getInstance(1003), GrayAlphaBits32, true, false, 3,
				3);
		RGBBits8 = new int[]{8, 8, 8};
		colorModelRGB8 = new ComponentColorModel(ColorSpace.getInstance(1000), RGBBits8, false, false, 1, 0);
		RGBABits8 = new int[]{8, 8, 8, 8};
		colorModelRGBA8 = new ComponentColorModel(ColorSpace.getInstance(1000), RGBABits8, true, false, 3, 0);
		RGBBits16 = new int[]{16, 16, 16};
		colorModelRGB16 = new ComponentColorModel(ColorSpace.getInstance(1000), RGBBits16, false, false, 1, 1);
		RGBABits16 = new int[]{16, 16, 16, 16};
		colorModelRGBA16 = new ComponentColorModel(ColorSpace.getInstance(1000), RGBABits16, true, false, 3, 1);
		RGBBits32 = new int[]{32, 32, 32};
		colorModelRGB32 = new ComponentColorModel(ColorSpace.getInstance(1000), RGBBits32, false, false, 1, 3);
		RGBABits32 = new int[]{32, 32, 32, 32};
		colorModelRGBA32 = new ComponentColorModel(ColorSpace.getInstance(1000), RGBABits32, true, false, 3, 3);
	}
}

---

com.sun.media.jai.codec;

package com.sun.media.jai.codec;

import com.sun.media.jai.codecimpl.BMPCodec;
import com.sun.media.jai.codecimpl.FPXCodec;
import com.sun.media.jai.codecimpl.GIFCodec;
import com.sun.media.jai.codecimpl.ImagingListenerProxy;
import com.sun.media.jai.codecimpl.JPEGCodec;
import com.sun.media.jai.codecimpl.PNGCodec;
import com.sun.media.jai.codecimpl.PNMCodec;
import com.sun.media.jai.codecimpl.TIFFCodec;
import com.sun.media.jai.codecimpl.WBMPCodec;
import com.sun.media.jai.codecimpl.util.FloatDoubleColorModel;
import com.sun.media.jai.util.SimpleCMYKColorSpace;
import java.awt.color.ColorSpace;
import java.awt.image.ColorModel;
import java.awt.image.ComponentColorModel;
import java.awt.image.IndexColorModel;
import java.awt.image.RenderedImage;
import java.awt.image.SampleModel;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

public abstract class ImageCodec {
	private static Hashtable codecs = new Hashtable();
	private static final byte[][] grayIndexCmaps;
	private static final int[] GrayBits8;
	private static final ComponentColorModel colorModelGray8;
	private static final int[] GrayAlphaBits8;
	private static final ComponentColorModel colorModelGrayAlpha8;
	private static final int[] GrayBits16;
	private static final ComponentColorModel colorModelGray16;
	private static final int[] GrayAlphaBits16;
	private static final ComponentColorModel colorModelGrayAlpha16;
	private static final int[] GrayBits32;
	private static final ComponentColorModel colorModelGray32;
	private static final int[] GrayAlphaBits32;
	private static final ComponentColorModel colorModelGrayAlpha32;
	private static final int[] RGBBits8;
	private static final ComponentColorModel colorModelRGB8;
	private static final int[] RGBABits8;
	private static final ComponentColorModel colorModelRGBA8;
	private static final int[] RGBBits16;
	private static final ComponentColorModel colorModelRGB16;
	private static final int[] RGBABits16;
	private static final ComponentColorModel colorModelRGBA16;
	private static final int[] RGBBits32;
	private static final ComponentColorModel colorModelRGB32;
	private static final int[] RGBABits32;
	private static final ComponentColorModel colorModelRGBA32;

	public static ImageCodec getCodec(String name) {
		return (ImageCodec) codecs.get(name.toLowerCase());
	}

	public static void registerCodec(ImageCodec codec) {
		codecs.put(codec.getFormatName().toLowerCase(), codec);
	}

	public static void unregisterCodec(String name) {
		codecs.remove(name.toLowerCase());
	}

	public static Enumeration getCodecs() {
		return codecs.elements();
	}

	public static ImageEncoder createImageEncoder(String name, OutputStream dst, ImageEncodeParam param) {
		ImageCodec codec = getCodec(name);
		return codec == null ? null : codec.createImageEncoder(dst, param);
	}

	public static ImageDecoder createImageDecoder(String name, InputStream src, ImageDecodeParam param) {
		ImageCodec codec = getCodec(name);
		return codec == null ? null : codec.createImageDecoder(src, param);
	}

	public static ImageDecoder createImageDecoder(String name, File src, ImageDecodeParam param) throws IOException {
		ImageCodec codec = getCodec(name);
		return codec == null ? null : codec.createImageDecoder(src, param);
	}

	public static ImageDecoder createImageDecoder(String name, SeekableStream src, ImageDecodeParam param) {
		ImageCodec codec = getCodec(name);
		return codec == null ? null : codec.createImageDecoder(src, param);
	}

	private static String[] vectorToStrings(Vector nameVec) {
		int count = nameVec.size();
		String[] names = new String[count];

		for (int i = 0; i < count; ++i) {
			names[i] = (String) nameVec.elementAt(i);
		}

		return names;
	}

	public static String[] getDecoderNames(SeekableStream src) {
		if (!src.canSeekBackwards() && !src.markSupported()) {
			throw new IllegalArgumentException(JaiI18N.getString("ImageCodec2"));
		} else {
			Enumeration enumeration = codecs.elements();
			Vector nameVec = new Vector();
			Object var3 = null;

			while (true) {
				ImageCodec codec;
				int bytesNeeded;
				do {
					if (!enumeration.hasMoreElements()) {
						return vectorToStrings(nameVec);
					}

					codec = (ImageCodec) enumeration.nextElement();
					bytesNeeded = codec.getNumHeaderBytes();
				} while (bytesNeeded == 0 && !src.canSeekBackwards());

				try {
					if (bytesNeeded > 0) {
						src.mark(bytesNeeded);
						byte[] header = new byte[bytesNeeded];
						src.readFully(header);
						src.reset();
						if (codec.isFormatRecognized(header)) {
							nameVec.add(codec.getFormatName());
						}
					} else {
						long pointer = src.getFilePointer();
						src.seek(0L);
						if (codec.isFormatRecognized(src)) {
							nameVec.add(codec.getFormatName());
						}

						src.seek(pointer);
					}
				} catch (IOException var8) {
					ImagingListenerProxy.errorOccurred(JaiI18N.getString("ImageCodec3"), var8,
							class$com$sun$media$jai$codec$ImageCodec == null
									? (class$com$sun$media$jai$codec$ImageCodec = class$(
											"com.sun.media.jai.codec.ImageCodec"))
									: class$com$sun$media$jai$codec$ImageCodec,
							false);
				}
			}
		}
	}

	public static String[] getEncoderNames(RenderedImage im, ImageEncodeParam param) {
		Enumeration enumeration = codecs.elements();
		Vector nameVec = new Vector();
		Object var4 = null;

		while (enumeration.hasMoreElements()) {
			ImageCodec codec = (ImageCodec) enumeration.nextElement();
			if (codec.canEncodeImage(im, param)) {
				nameVec.add(codec.getFormatName());
			}
		}

		return vectorToStrings(nameVec);
	}

	public abstract String getFormatName();

	public int getNumHeaderBytes() {
		return 0;
	}

	public boolean isFormatRecognized(byte[] header) {
		throw new RuntimeException(JaiI18N.getString("ImageCodec0"));
	}

	public boolean isFormatRecognized(SeekableStream src) throws IOException {
		throw new RuntimeException(JaiI18N.getString("ImageCodec1"));
	}

	protected abstract Class getEncodeParamClass();

	protected abstract Class getDecodeParamClass();

	protected abstract ImageEncoder createImageEncoder(OutputStream var1, ImageEncodeParam var2);

	public abstract boolean canEncodeImage(RenderedImage var1, ImageEncodeParam var2);

	protected ImageDecoder createImageDecoder(InputStream src, ImageDecodeParam param) {
		SeekableStream stream = SeekableStream.wrapInputStream(src, true);
		return this.createImageDecoder(stream, param);
	}

	protected ImageDecoder createImageDecoder(File src, ImageDecodeParam param) throws IOException {
		return this.createImageDecoder((SeekableStream) (new FileSeekableStream(src)), param);
	}

	protected abstract ImageDecoder createImageDecoder(SeekableStream var1, ImageDecodeParam var2);

	public static ColorModel createGrayIndexColorModel(SampleModel sm, boolean blackIsZero) {
		if (sm.getNumBands() != 1) {
			throw new IllegalArgumentException();
		} else {
			int sampleSize = sm.getSampleSize(0);
			byte[] cmap = null;
			int length;
			byte[] cmap;
			if (sampleSize < 8) {
				cmap = grayIndexCmaps[sampleSize];
				if (!blackIsZero) {
					length = cmap.length;
					byte[] newCmap = new byte[length];

					for (int i = 0; i < length; ++i) {
						newCmap[i] = cmap[length - i - 1];
					}

					cmap = newCmap;
				}
			} else {
				cmap = new byte[256];
				if (blackIsZero) {
					for (length = 0; length < 256; ++length) {
						cmap[length] = (byte) length;
					}
				} else {
					for (length = 0; length < 256; ++length) {
						cmap[length] = (byte) (255 - length);
					}
				}
			}

			return new IndexColorModel(sampleSize, cmap.length, cmap, cmap, cmap);
		}
	}

	public static ColorModel createComponentColorModel(SampleModel sm) {
		int type = sm.getDataType();
		int bands = sm.getNumBands();
		ComponentColorModel cm = null;
		if (type == 0) {
			switch (bands) {
				case 1 :
					cm = colorModelGray8;
					break;
				case 2 :
					cm = colorModelGrayAlpha8;
					break;
				case 3 :
					cm = colorModelRGB8;
					break;
				case 4 :
					cm = colorModelRGBA8;
			}
		} else if (type == 1) {
			switch (bands) {
				case 1 :
					cm = colorModelGray16;
					break;
				case 2 :
					cm = colorModelGrayAlpha16;
					break;
				case 3 :
					cm = colorModelRGB16;
					break;
				case 4 :
					cm = colorModelRGBA16;
			}
		} else if (type == 3) {
			switch (bands) {
				case 1 :
					cm = colorModelGray32;
					break;
				case 2 :
					cm = colorModelGrayAlpha32;
					break;
				case 3 :
					cm = colorModelRGB32;
					break;
				case 4 :
					cm = colorModelRGBA32;
			}
		} else if (type == 4 && bands >= 1 && bands <= 4) {
			ColorSpace cs = bands <= 2 ? ColorSpace.getInstance(1003) : ColorSpace.getInstance(1000);
			boolean hasAlpha = bands % 2 == 0;
			cm = new FloatDoubleColorModel(cs, hasAlpha, false, hasAlpha ? 3 : 1, 4);
		}

		return (ColorModel) cm;
	}

	public static ColorModel createComponentColorModel(SampleModel sm, ColorSpace cp) {
		if (cp == null) {
			return createComponentColorModel(sm);
		} else {
			int type = sm.getDataType();
			int bands = sm.getNumBands();
			ComponentColorModel cm = null;
			int[] bits = null;
			int transferType = -1;
			boolean hasAlpha = bands % 2 == 0;
			if (cp instanceof SimpleCMYKColorSpace) {
				hasAlpha = false;
			}

			int transparency = hasAlpha ? 3 : 1;
			if (type == 0) {
				transferType = 0;
				switch (bands) {
					case 1 :
						bits = GrayBits8;
						break;
					case 2 :
						bits = GrayAlphaBits8;
						break;
					case 3 :
						bits = RGBBits8;
						break;
					case 4 :
						bits = RGBABits8;
				}
			} else if (type == 1) {
				transferType = 1;
				switch (bands) {
					case 1 :
						bits = GrayBits16;
						break;
					case 2 :
						bits = GrayAlphaBits16;
						break;
					case 3 :
						bits = RGBBits16;
						break;
					case 4 :
						bits = RGBABits16;
				}
			} else if (type == 3) {
				transferType = 3;
				switch (bands) {
					case 1 :
						bits = GrayBits32;
						break;
					case 2 :
						bits = GrayAlphaBits32;
						break;
					case 3 :
						bits = RGBBits32;
						break;
					case 4 :
						bits = RGBABits32;
				}
			}

			if (type == 4 && bands >= 1 && bands <= 4) {
				cm = new FloatDoubleColorModel(cp, hasAlpha, false, transparency, 4);
			} else {
				cm = new ComponentColorModel(cp, bits, hasAlpha, false, transparency, transferType);
			}

			return (ColorModel) cm;
		}
	}

	public static boolean isIndicesForGrayscale(byte[] r, byte[] g, byte[] b) {
		if (r.length == g.length && r.length == b.length) {
			int size = r.length;
			if (size != 256) {
				return false;
			} else {
				for (int i = 0; i < size; ++i) {
					byte temp = (byte) i;
					if (r[i] != temp || g[i] != temp || b[i] != temp) {
						return false;
					}
				}

				return true;
			}
		} else {
			return false;
		}
	}

	static {
		registerCodec(new BMPCodec());
		registerCodec(new GIFCodec());
		registerCodec(new FPXCodec());
		registerCodec(new JPEGCodec());
		registerCodec(new PNGCodec());
		registerCodec(new PNMCodec());
		registerCodec(new TIFFCodec());
		registerCodec(new WBMPCodec());
		grayIndexCmaps = new byte[][]{null, {0, -1}, {0, 85, -86, -1}, null,
				{0, 17, 34, 51, 68, 85, 102, 119, -120, -103, -86, -69, -52, -35, -18, -1}};
		GrayBits8 = new int[]{8};
		colorModelGray8 = new ComponentColorModel(ColorSpace.getInstance(1003), GrayBits8, false, false, 1, 0);
		GrayAlphaBits8 = new int[]{8, 8};
		colorModelGrayAlpha8 = new ComponentColorModel(ColorSpace.getInstance(1003), GrayAlphaBits8, true, false, 3, 0);
		GrayBits16 = new int[]{16};
		colorModelGray16 = new ComponentColorModel(ColorSpace.getInstance(1003), GrayBits16, false, false, 1, 1);
		GrayAlphaBits16 = new int[]{16, 16};
		colorModelGrayAlpha16 = new ComponentColorModel(ColorSpace.getInstance(1003), GrayAlphaBits16, true, false, 3,
				1);
		GrayBits32 = new int[]{32};
		colorModelGray32 = new ComponentColorModel(ColorSpace.getInstance(1003), GrayBits32, false, false, 1, 3);
		GrayAlphaBits32 = new int[]{32, 32};
		colorModelGrayAlpha32 = new ComponentColorModel(ColorSpace.getInstance(1003), GrayAlphaBits32, true, false, 3,
				3);
		RGBBits8 = new int[]{8, 8, 8};
		colorModelRGB8 = new ComponentColorModel(ColorSpace.getInstance(1000), RGBBits8, false, false, 1, 0);
		RGBABits8 = new int[]{8, 8, 8, 8};
		colorModelRGBA8 = new ComponentColorModel(ColorSpace.getInstance(1000), RGBABits8, true, false, 3, 0);
		RGBBits16 = new int[]{16, 16, 16};
		colorModelRGB16 = new ComponentColorModel(ColorSpace.getInstance(1000), RGBBits16, false, false, 1, 1);
		RGBABits16 = new int[]{16, 16, 16, 16};
		colorModelRGBA16 = new ComponentColorModel(ColorSpace.getInstance(1000), RGBABits16, true, false, 3, 1);
		RGBBits32 = new int[]{32, 32, 32};
		colorModelRGB32 = new ComponentColorModel(ColorSpace.getInstance(1000), RGBBits32, false, false, 1, 3);
		RGBABits32 = new int[]{32, 32, 32, 32};
		colorModelRGBA32 = new ComponentColorModel(ColorSpace.getInstance(1000), RGBABits32, true, false, 3, 3);
	}
}

---

com.sun.media.jai.codecimpl.TIFFCodec;

package com.sun.media.jai.codecimpl;

import com.sun.media.jai.codec.ImageCodec;
import com.sun.media.jai.codec.ImageDecodeParam;
import com.sun.media.jai.codec.ImageDecoder;
import com.sun.media.jai.codec.ImageEncodeParam;
import com.sun.media.jai.codec.ImageEncoder;
import com.sun.media.jai.codec.SeekableStream;
import java.awt.image.RenderedImage;
import java.io.OutputStream;

public final class TIFFCodec extends ImageCodec {
	public String getFormatName() {
		return "tiff";
	}

	public Class getEncodeParamClass() {
		return class$com$sun$media$jai$codec$TIFFEncodeParam == null
				? (class$com$sun$media$jai$codec$TIFFEncodeParam = class$("com.sun.media.jai.codec.TIFFEncodeParam"))
				: class$com$sun$media$jai$codec$TIFFEncodeParam;
	}

	public Class getDecodeParamClass() {
		return class$com$sun$media$jai$codec$TIFFDecodeParam == null
				? (class$com$sun$media$jai$codec$TIFFDecodeParam = class$("com.sun.media.jai.codec.TIFFDecodeParam"))
				: class$com$sun$media$jai$codec$TIFFDecodeParam;
	}

	public boolean canEncodeImage(RenderedImage im, ImageEncodeParam param) {
		return true;
	}

	protected ImageEncoder createImageEncoder(OutputStream dst, ImageEncodeParam param) {
		return new TIFFImageEncoder(dst, param);
	}

	protected ImageDecoder createImageDecoder(SeekableStream src, ImageDecodeParam param) {
		return new TIFFImageDecoder(src, param);
	}

	public int getNumHeaderBytes() {
		return 4;
	}

	public boolean isFormatRecognized(byte[] header) {
		if (header[0] == 73 && header[1] == 73 && header[2] == 42 && header[3] == 0) {
			return true;
		} else {
			return header[0] == 77 && header[1] == 77 && header[2] == 0 && header[3] == 42;
		}
	}
}

---

■TIF图像的读取

====

・TIF的存储结构

TIFF⽂件以.tif为扩展名。其数据格式是⼀种3级体系结构,从⾼到低依次为:⽂件头、⼀个或多个称为IFD的包含标记指针的⽬录和数据。
====

【1.⽂件头(IFH)】

  在每⼀个TIFF⽂件中第⼀个数据结构称为图像⽂件头或IFH,它是图像⽂件体系结构的最⾼层。这个结构在⼀个TIFF⽂件中是惟⼀的,
有固定的位置。它位于⽂件的开始部分,包含了正确解释TIFF⽂件的其他部分所需的必要信息。
        IFH数据结构包含3个成员共计8个字节,Byte order成员可能是“MM”(0x4d4d)或“II”(0x4949),0x4d4d表⽰该TIFF图是摩托罗拉整数格式
0x4949表⽰该图是Intel整数格式;Version成员总是包含⼗进制42(0x2a),它⽤于进⼀步校验该⽂件是否为TIF格式,42这个数并不是⼀般
⼈想象中的那样认为是tif软件的版本,实际上,42这个数⼤概永远不会变化;第三个成员是IFD(接下来要说的第⼆个数据结构)相对⽂件
开始处的偏移量。


【2.图像⽂件⽬录(IFD)】

IFD是TIFF⽂件中第2个数据结构,它是⼀个名为标记(tag)的⽤于区分⼀个或多个可变长度数据块的表,标记中包含了有关于图像的所
有信息。IFD提供了⼀系列的指针(索引),这些指针告诉我们各种有关的数据字段在⽂件中的开始位置,并给出每个字段的数据类型及长度。
这种⽅法允许数据字段定位在⽂件的任何地⽅,且可以是任意长度,因此⽂件格式⼗分灵活。
     IFD是TIF图中最重要的数据结构,它包含了⼀个TIF⽂件中最重要的信息,★★⼀个TIF图可能有多个IFD,这说明⽂件中有多个图像★★★
每个IFD标识1个图像的基本属性。 IFD结构中包含了三类成员,Directory Entry Count指出该结构⾥⾯有多少个⽬录⼊⼝;接下来就是N个线性
排列的DE序列,数量不定(这就是为什么称TIF格式⽂件为可扩充标记的⽂件,甚⾄⽤户可以添加⾃定义的标记属性),每个DE标识了图
像的某⼀个属性;最后就是⼀个偏移量,标识下⼀个⽂件⽬录相对于⽂件开始处的位置,当然,如果该TIF⽂件只包含了⼀幅图像,那么就
只有⼀个IFD,显然,这个偏移量就等于0;
共12个字节,。简单说,⼀个DE就是⼀幅图像的某⼀个属性。例如图像的⼤⼩、分辨率、是否压缩、像素的⾏列数、⼀个像素由⼏
位表⽰(1位代表⿊⽩两⾊,8位代表256⾊等等)等。其中:tag成员是该属性的编号,在图像⽂件⽬录中,它是按照升序排列的。我们可
以通过读这些编号,然后到TIF格式官⽅⽩⽪书中查找相应的含义。属性是⽤数据来表⽰的,那么type就是代表着该数据的类型,TIF官⽅指
定的有5种数据类型。type=1就是BYTE类型(8位⽆标记整数)、type=2是ASCII类型(7位ASCII码加1位⼆进制0)、type=3是SHORT类
型(16位⽆标记整数)、type=4是LONG 类型(32位⽆标记整数)、type=5是RATIONAL类型(2个LONG,第⼀个是分⼦,第⼆个是分
母)。length成员是数据的数量⽽不是数据类型的长度。第4个成员valueOffset很重要,它是tag标识的属性代表的变量值相对⽂件开始处的
偏移量。如果变量值占⽤的空间⼩于4个字节,那么该值就存放在 valueOffset中即可,没必要再另外指向⼀个地⽅了。


【 3.图像数据】

  根据IFD所指向的地址.存储相关的图像信

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值