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.webp.chunks;
018
019import java.io.IOException;
020import java.io.PrintWriter;
021
022import org.apache.commons.imaging.ImagingException;
023
024/**
025 * VP8X (descriptions of features used) chunk.
026 *
027 * <pre>{@code
028 *  0                   1                   2                   3
029 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
030 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
031 * |                                                               |
032 * |                   WebP file header (12 bytes)                 |
033 * |                                                               |
034 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
035 * |                      ChunkHeader('VP8X')                      |
036 * |                                                               |
037 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
038 * |Rsv|I|L|E|X|A|R|                   Reserved                    |
039 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
040 * |          Canvas Width Minus One               |             ...
041 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
042 * ...  Canvas Height Minus One    |
043 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
044 * }</pre>
045 *
046 * @see <a href="https://developers.google.com/speed/webp/docs/riff_container#extended_file_format">Extended File Format</a>
047 * @since 1.0.0-alpha4
048 */
049public final class WebPChunkVp8x extends AbstractWebPChunk {
050    private final boolean hasIcc;
051    private final boolean hasAlpha;
052    private final boolean hasExif;
053    private final boolean hasXmp;
054    private final boolean hasAnimation;
055    private final int canvasWidth;
056    private final int canvasHeight;
057
058    /**
059     * Create a VP8x chunk.
060     *
061     * @param type  VP8X chunk type
062     * @param size  VP8X chunk size
063     * @param bytes VP8X chunk data
064     * @throws ImagingException if the chunk data and the size provided do not match, or if the other parameters provided are invalid.
065     */
066    public WebPChunkVp8x(final int type, final int size, final byte[] bytes) throws ImagingException {
067        super(type, size, bytes);
068
069        if (size != 10) {
070            throw new ImagingException("VP8X chunk size must be 10");
071        }
072
073        final int mark = bytes[0] & 0xFF;
074        this.hasIcc = (mark & 0b0010_0000) != 0;
075        this.hasAlpha = (mark & 0b0001_0000) != 0;
076        this.hasExif = (mark & 0b0000_1000) != 0;
077        this.hasXmp = (mark & 0b0000_0100) != 0;
078        this.hasAnimation = (mark & 0b0000_0010) != 0;
079
080        this.canvasWidth = (bytes[4] & 0xFF) + ((bytes[5] & 0xFF) << 8) + ((bytes[6] & 0xFF) << 16) + 1;
081        this.canvasHeight = (bytes[7] & 0xFF) + ((bytes[8] & 0xFF) << 8) + ((bytes[9] & 0xFF) << 16) + 1;
082
083        if (canvasWidth * canvasHeight < 0) {
084            throw new ImagingException("Illegal canvas size");
085        }
086    }
087
088    @Override
089    public void dump(final PrintWriter pw, final int offset) throws ImagingException, IOException {
090        super.dump(pw, offset);
091        pw.println("  ICCP: " + hasIcc());
092        pw.println("  Alpha: " + hasAlpha());
093        pw.println("  EXIF: " + hasExif());
094        pw.println("  XMP: " + hasXmp());
095        pw.println("  Animation: " + hasAnimation());
096        pw.println("  Canvas Width: " + getCanvasWidth());
097        pw.println("  Canvas Height: " + getCanvasHeight());
098    }
099
100    /**
101     * @return the canvas height.
102     */
103    public int getCanvasHeight() {
104        return canvasHeight;
105    }
106
107    /**
108     * @return the canvas width.
109     */
110    public int getCanvasWidth() {
111        return canvasWidth;
112    }
113
114    /**
115     * @return whether the chunk has alpha enabled.
116     */
117    public boolean hasAlpha() {
118        return hasAlpha;
119    }
120
121    /**
122     * @return if the chunk contains an animation.
123     */
124    public boolean hasAnimation() {
125        return hasAnimation;
126    }
127
128    /**
129     * @return whether the chunk has EXIF data.
130     */
131    public boolean hasExif() {
132        return hasExif;
133    }
134
135    /**
136     * @return whether the chunk has ICC enabled.
137     */
138    public boolean hasIcc() {
139        return hasIcc;
140    }
141
142    /**
143     * @return whether the chunk has XMP.
144     */
145    public boolean hasXmp() {
146        return hasXmp;
147    }
148}