001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.imaging.formats.tiff.fieldtypes;
018
019import java.nio.ByteOrder;
020import java.nio.charset.StandardCharsets;
021
022import org.apache.commons.imaging.ImageWriteException;
023import org.apache.commons.imaging.formats.tiff.TiffField;
024
025public class FieldTypeAscii extends FieldType {
026    public FieldTypeAscii(final int type, final String name) {
027        super(type, name, 1);
028    }
029
030    @Override
031    public Object getValue(final TiffField entry) {
032        // According to EXIF specification
033        // "2 = ASCII An 8-bit byte containing one 7-bit ASCII code. The final byte is terminated with NULL."
034        final byte[] bytes = entry.getByteArrayValue();
035        int nullCount = 1;
036        for (int i = 0; i < bytes.length - 1; i++) {
037            if (bytes[i] == 0) {
038                nullCount++;
039            }
040        }
041        final String[] strings = new String[nullCount];
042        int stringsAdded = 0;
043        strings[0] = ""; // if we have a 0 length string
044        int nextStringPos = 0;
045        // According to the Exiftool FAQ, http://www.metadataworkinggroup.org
046        // specifies that the TIFF ASCII fields are actually UTF-8.
047        // Exiftool however allows you to configure the charset used.
048        for (int i = 0; i < bytes.length; i++) {
049            if (bytes[i] == 0) {
050                final String string = new String(bytes, nextStringPos, i
051                        - nextStringPos, StandardCharsets.UTF_8);
052                strings[stringsAdded++] = string;
053                nextStringPos = i + 1;
054            }
055        }
056        if (nextStringPos < bytes.length) {
057            // Buggy file, string wasn't null terminated
058            final String string = new String(bytes, nextStringPos, bytes.length
059                    - nextStringPos, StandardCharsets.UTF_8);
060            strings[stringsAdded++] = string;
061        }
062        if (strings.length == 1) {
063            return strings[0];
064        }
065        return strings;
066    }
067
068    @Override
069    public byte[] writeData(final Object o, final ByteOrder byteOrder) throws ImageWriteException {
070        if (o instanceof byte[]) {
071            final byte[] bytes = (byte[]) o;
072            final byte[] result = new byte[bytes.length + 1];
073            System.arraycopy(bytes, 0, result, 0, bytes.length);
074            result[result.length - 1] = 0;
075            return result;
076        } else if (o instanceof String) {
077            final byte[] bytes = ((String) o).getBytes(StandardCharsets.UTF_8);
078            final byte[] result = new byte[bytes.length + 1];
079            System.arraycopy(bytes, 0, result, 0, bytes.length);
080            result[result.length - 1] = 0;
081            return result;
082        } else if (o instanceof String[]) {
083            final String[] strings = (String[]) o;
084            int totalLength = 0;
085            for (final String string : strings) {
086                final byte[] bytes = string.getBytes(StandardCharsets.UTF_8);
087                totalLength += (bytes.length + 1);
088            }
089            final byte[] result = new byte[totalLength];
090            int position = 0;
091            for (final String string : strings) {
092                final byte[] bytes = string.getBytes(StandardCharsets.UTF_8);
093                System.arraycopy(bytes, 0, result, position, bytes.length);
094                position += (bytes.length + 1);
095            }
096            return result;
097        } else {
098            throw new ImageWriteException("Unknown data type: " + o);
099        }
100    }
101
102}