blob: 27755bf289c1daf6c55e1ff7bf45ef62e28f89d7 [file] [edit]
/*
* Copyright (c) 2014-2021 by Wen Yu
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License, v. 2.0 are satisfied: GNU General Public License, version 2
* or any later version.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
*/
package pixy.image.png;
import java.io.BufferedWriter;
import java.io.OutputStreamWriter;
import java.util.zip.DeflaterOutputStream;
import java.io.ByteArrayOutputStream;
import pixy.util.Builder;
/**
* Builder for PNG textual chunks: iTXT, zTXT, and tEXT.
*
* @author Wen Yu, yuwen_66@yahoo.com
* @version 1.0 12/31/2012
*/
public class TextBuilder extends ChunkBuilder implements Builder<Chunk> {
// Whether or not iTXT should be compressed. iTXT is uncompressed by default
private boolean compressed;
private String keyword;
private String text;
public TextBuilder(ChunkType chunkType) {
super(chunkType);
if((chunkType != ChunkType.TEXT) && (chunkType != ChunkType.ITXT)
&& (chunkType != ChunkType.ZTXT))
throw new IllegalArgumentException("Expect Textual chunk!");
}
protected byte[] buildData() {
byte[] data = null;
ChunkType chunkType = getChunkType();
StringBuilder sb = new StringBuilder(this.keyword);
sb.append('\0');
switch (chunkType) {
case TEXT:
sb.append(this.text);
try {
data = sb.toString().getBytes("iso-8859-1");
} catch (Exception ex) {
ex.printStackTrace();
}
break;
case ZTXT:
try {
ByteArrayOutputStream bo = new ByteArrayOutputStream(1024);
sb.append('\0');
bo.write(sb.toString().getBytes("iso-8859-1"));
DeflaterOutputStream ds = new DeflaterOutputStream(bo);
OutputStreamWriter or = new OutputStreamWriter(ds, "iso-8859-1");
BufferedWriter br = new BufferedWriter(or);
br.write(this.text);
br.flush();
br.close();
data = bo.toByteArray();
} catch (Exception ex) {
ex.printStackTrace();
}
break;
case ITXT:
try {
ByteArrayOutputStream bo = new ByteArrayOutputStream(1024);
bo.write(sb.toString().getBytes("iso-8859-1"));
OutputStreamWriter or = null;
if(compressed) {
bo.write(new byte[]{1, 0, 0, 0});
or = new OutputStreamWriter(new DeflaterOutputStream(bo), "UTF-8");
} else {
bo.write(new byte[]{0, 0, 0, 0});
or = new OutputStreamWriter(bo, "UTF-8");
}
BufferedWriter br = new BufferedWriter(or);
br.write(this.text);
br.flush();
br.close();
data = bo.toByteArray();
} catch (Exception ex) {
ex.printStackTrace();
}
break;
default: // It will never come this far!
}
return data;
}
/**
* The keyword must be at least one character and less than 80 characters long.
* <p>
* Keywords are always interpreted according to the ISO/IEC 8859-1 (Latin-1)
* character set [ISO/IEC-8859-1].
* <p>
* They must contain only printable Latin-1 characters and spaces; that is,
* only character codes 32-126 and 161-255 decimal are allowed.
* <p>
* To reduce the chances for human misreading of a keyword, leading and
* trailing spaces are forbidden, as are consecutive spaces.
* <p>
* Note also that the non-breaking space (code 160) is not permitted in keywords,
* since it is visually indistinguishable from an ordinary space.
*/
public TextBuilder keyword(String keyword) {
this.keyword = keyword.trim().replaceAll("\\s+", " ");
return this;
}
public void setCompressed(boolean compressed) {
this.compressed = compressed;
}
/**
* The tExt chunk is interpreted according to the ISO/IEC 8859-1 (Latin-1) character
* set [ISO/IEC-8859-1].
*
* The text string can contain any Latin-1 character. Newlines in the text string
* should be represented by a single line feed character (decimal 10); use of other
* control characters in the text is discouraged.
* <p>
* The zTXt chunk contains textual data, just as tEXt does; however, zTXt takes
* advantage of compression. The zTXt and tEXt chunks are semantically equivalent,
* but zTXt is recommended for storing large blocks of text.
* A zTXt chunk contains:
* Keyword: 1-79 bytes (character string)
* Null separator: 1 byte
* Compression method: 1 byte
* Compressed text: n bytes
* <p>
* iTXt International textual data
* This chunk is semantically equivalent to the tEXt and zTXt chunks, but the textual
* data is in the UTF-8 encoding of the Unicode character set instead of Latin-1.
* This chunk contains:
* Keyword: 1-79 bytes (character string)
* Null separator: 1 byte
* Compression flag: 1 byte
* Compression method: 1 byte
* Language tag: 0 or more bytes (character string)
* Null separator: 1 byte
* Translated keyword: 0 or more bytes
* Null separator: 1 byte
* Text: 0 or more bytes
*/
public TextBuilder text(String text) {
this.text = text;
return this;
}
}