    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}