⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cpchibifile.java

📁 this is best wamp jkbkgnkldjkb jkfbjdksgkjl bjkgsbkjfdb gjdsblkj gbfkjsd
💻 JAVA
字号:
/*
	ChibiPaint
    Copyright (c) 2006-2008 Marc Schefer

    This file is part of ChibiPaint.

    ChibiPaint is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    ChibiPaint is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with ChibiPaint. If not, see <http://www.gnu.org/licenses/>.

 */

package chibipaint.engine;

import java.io.*;
import java.util.*;
import java.util.zip.*;

public class CPChibiFile {

	protected static final byte CHIB[] = { 67, 72, 73, 66 };
	protected static final byte IOEK[] = { 73, 79, 69, 75 };
	protected static final byte HEAD[] = { 72, 69, 65, 68 };
	protected static final byte LAYR[] = { 76, 65, 89, 82 };
	protected static final byte ZEND[] = { 90, 69, 78, 68 };

	static public boolean write(OutputStream os, CPArtwork a) {
		try {
			writeMagic(os);
			os.flush();

			Deflater def = new Deflater(7);
			DeflaterOutputStream dos = new DeflaterOutputStream(os, def);
			// OutputStream dos = os;

			writeHeader(dos, a);

			for (Object l : a.layers) {
				writeLayer(dos, (CPLayer) l);
			}

			writeEnd(dos);

			dos.flush();
			dos.close();
			return true;
		} catch (IOException e) {
			return false;
		}
	}

	static public void writeInt(OutputStream os, int i) throws IOException {
		byte[] temp = { (byte) (i >>> 24), (byte) ((i >>> 16) & 0xff), (byte) ((i >>> 8) & 0xff), (byte) (i & 0xff) };
		os.write(temp);
	}

	static public void writeIntArray(OutputStream os, int arr[]) throws IOException {
		byte[] temp = new byte[arr.length * 4];
		int idx = 0;
		for (int i : arr) {
			temp[idx++] = (byte) (i >>> 24);
			temp[idx++] = (byte) ((i >>> 16) & 0xff);
			temp[idx++] = (byte) ((i >>> 8) & 0xff);
			temp[idx++] = (byte) (i & 0xff);
		}

		os.write(temp);
	}

	static public void writeMagic(OutputStream os) throws IOException {
		os.write(CHIB);
		os.write(IOEK);
	}

	static public void writeEnd(OutputStream os) throws IOException {
		os.write(ZEND);
		writeInt(os, 0);
	}

	static public void writeHeader(OutputStream os, CPArtwork a) throws IOException {
		os.write(HEAD); // Chunk ID
		writeInt(os, 16); // ChunkSize

		writeInt(os, 0); // Current Version: Major: 0 Minor: 0
		writeInt(os, a.width);
		writeInt(os, a.height);
		writeInt(os, a.getLayersNb());
	}

	static public void writeLayer(OutputStream os, CPLayer l) throws IOException {
		byte[] title = l.name.getBytes("UTF-8");

		os.write(LAYR); // Chunk ID
		writeInt(os, 20 + l.data.length * 4 + title.length); // ChunkSize

		writeInt(os, 20 + title.length); // Data offset from start of header
		writeInt(os, l.blendMode); // layer blend mode
		writeInt(os, l.alpha); // layer opacity
		writeInt(os, l.visible ? 1 : 0); // layer visibility and future flags

		writeInt(os, title.length);
		os.write(title);

		writeIntArray(os, l.data);
	}

	static public CPArtwork read(InputStream is) {
		try {
			if (!readMagic(is)) {
				return null; // not a ChibiPaint file
			}

			InflaterInputStream iis = new InflaterInputStream(is);
			CPChibiChunk chunk = new CPChibiChunk(iis);
			if (!chunk.is(HEAD)) {
				return null; // not a valid file
			}

			CPChibiHeader header = new CPChibiHeader(iis, chunk);
			if ((header.version >>> 16) > 0) {
				return null; // the file version is higher than what we can deal with, bail out
			}

			CPArtwork a = new CPArtwork(header.width, header.height);
			a.layers.remove(0); // FIXME: it would be better not to have created it in the first place

			while (true) {
				chunk = new CPChibiChunk(iis);

				if (chunk.is(ZEND)) {
					break;
				} else if (chunk.is(LAYR)) {
					readLayer(iis, chunk, a);
				} else {
					realSkip(iis, chunk.chunkSize);
				}
			}

			a.setActiveLayer(0);
			return a;

		} catch (IOException e) {
			return null;
		} catch (Exception e) {
			return null;
		}
	}

	static private void readLayer(InputStream is, CPChibiChunk chunk, CPArtwork a) throws IOException {
		CPLayer l = new CPLayer(a.width, a.height);

		int offset = readInt(is);
		l.blendMode = readInt(is); // layer blend mode
		l.alpha = readInt(is);
		l.visible = (readInt(is) & 1) != 0;

		int titleLength = readInt(is);
		byte[] title = new byte[titleLength];
		realRead(is, title, titleLength);
		l.name = new String(title, "UTF-8");

		realSkip(is, offset - 20 - titleLength);
		readIntArray(is, l.data, l.width * l.height);

		a.layers.add(l);

		realSkip(is, chunk.chunkSize - offset - l.width * l.height * 4);
	}

	static private void readIntArray(InputStream is, int[] intArray, int size) throws IOException {
		byte[] buffer = new byte[size * 4];

		realRead(is, buffer, size * 4);

		int off = 0;
		for (int i = 0; i < size; i++) {
			intArray[i] = ((buffer[off++] & 0xff) << 24) | ((buffer[off++] & 0xff) << 16)
					| ((buffer[off++] & 0xff) << 8) | (buffer[off++] & 0xff);
		}
	}

	static public int readInt(InputStream is) throws IOException {
		return is.read() << 24 | is.read() << 16 | is.read() << 8 | is.read();
	}

	static void realSkip(InputStream is, long bytesToSkip) throws IOException {
		long skipped = 0, value;
		while (skipped < bytesToSkip) {
			value = is.read();
			if (value < 0) {
				throw new RuntimeException("EOF!");
			}

			skipped++;
			skipped += is.skip(bytesToSkip - skipped);
		}
	}

	static void realRead(InputStream is, byte[] buffer, int bytesToRead) throws IOException {
		int read = 0, value;
		while (read < bytesToRead) {
			value = is.read();
			if (value < 0) {
				throw new RuntimeException("EOF!");
			}

			buffer[read++] = (byte) value;
			read += is.read(buffer, read, bytesToRead - read);
		}
	}

	static public boolean readMagic(InputStream is) throws IOException {
		byte[] buffer = new byte[4];

		realRead(is, buffer, 4);
		if (!Arrays.equals(buffer, CHIB)) {
			return false;
		}

		realRead(is, buffer, 4);
		if (!Arrays.equals(buffer, IOEK)) {
			return false;
		}

		return true;
	}

	static class CPChibiChunk {

		byte[] chunkType = new byte[4];
		int chunkSize;

		public CPChibiChunk(InputStream is) throws IOException {
			realRead(is, chunkType, 4);
			chunkSize = readInt(is);
		}

		private boolean is(byte[] chunkType) {
			return Arrays.equals(this.chunkType, chunkType);
		}
	}

	static class CPChibiHeader {

		int version, width, height, layersNb;

		public CPChibiHeader(InputStream is, CPChibiChunk chunk) throws IOException {
			version = readInt(is);
			width = readInt(is);
			height = readInt(is);
			layersNb = readInt(is);

			realSkip(is, chunk.chunkSize - 16);
		}
	}

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -