Package org.apache.commons.imaging.formats.wbmp

Source Code of org.apache.commons.imaging.formats.wbmp.WbmpImageParser$WbmpHeader

/*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*       http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*  under the License.
*/

package org.apache.commons.imaging.formats.wbmp;

import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.IndexColorModel;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.imaging.ImageFormat;
import org.apache.commons.imaging.ImageFormats;
import org.apache.commons.imaging.ImageInfo;
import org.apache.commons.imaging.ImageParser;
import org.apache.commons.imaging.ImageReadException;
import org.apache.commons.imaging.ImageWriteException;
import org.apache.commons.imaging.common.IImageMetadata;
import org.apache.commons.imaging.common.bytesource.ByteSource;
import org.apache.commons.imaging.util.IoUtils;

import static org.apache.commons.imaging.ImagingConstants.*;
import static org.apache.commons.imaging.common.BinaryFunctions.*;

public class WbmpImageParser extends ImageParser {
    private static final String DEFAULT_EXTENSION = ".wbmp";
    private static final String[] ACCEPTED_EXTENSIONS = { ".wbmp", };

    @Override
    public String getName() {
        return "Wireless Application Protocol Bitmap Format";
    }

    @Override
    public String getDefaultExtension() {
        return DEFAULT_EXTENSION;
    }

    @Override
    protected String[] getAcceptedExtensions() {
        return ACCEPTED_EXTENSIONS;
    }

    @Override
    protected ImageFormat[] getAcceptedTypes() {
        return new ImageFormat[] { ImageFormats.WBMP, //
        };
    }

    @Override
    public IImageMetadata getMetadata(final ByteSource byteSource, final Map<String, Object> params)
            throws ImageReadException, IOException {
        return null;
    }

    @Override
    public ImageInfo getImageInfo(final ByteSource byteSource, final Map<String, Object> params)
            throws ImageReadException, IOException {
        final WbmpHeader wbmpHeader = readWbmpHeader(byteSource);
        return new ImageInfo("WBMP", 1, new ArrayList<String>(),
                ImageFormats.WBMP,
                "Wireless Application Protocol Bitmap", wbmpHeader.height,
                "image/vnd.wap.wbmp", 1, 0, 0, 0, 0, wbmpHeader.width, false,
                false, false, ImageInfo.COLOR_TYPE_BW,
                ImageInfo.COMPRESSION_ALGORITHM_NONE);
    }

    @Override
    public Dimension getImageSize(final ByteSource byteSource, final Map<String, Object> params)
            throws ImageReadException, IOException {
        final WbmpHeader wbmpHeader = readWbmpHeader(byteSource);
        return new Dimension(wbmpHeader.width, wbmpHeader.height);
    }

    @Override
    public byte[] getICCProfileBytes(final ByteSource byteSource, final Map<String, Object> params)
            throws ImageReadException, IOException {
        return null;
    }

    static class WbmpHeader {
        int typeField;
        byte fixHeaderField;
        int width;
        int height;

        public WbmpHeader(final int typeField, final byte fixHeaderField, final int width,
                final int height) {
            this.typeField = typeField;
            this.fixHeaderField = fixHeaderField;
            this.width = width;
            this.height = height;
        }

        public void dump(final PrintWriter pw) {
            pw.println("WbmpHeader");
            pw.println("TypeField: " + typeField);
            pw.println("FixHeaderField: 0x"
                    + Integer.toHexString(0xff & fixHeaderField));
            pw.println("Width: " + width);
            pw.println("Height: " + height);
        }
    }

    private int readMultiByteInteger(final InputStream is) throws ImageReadException,
            IOException {
        int value = 0;
        int nextByte;
        int totalBits = 0;
        do {
            nextByte = readByte("Header", is, "Error reading WBMP header");
            value <<= 7;
            value |= nextByte & 0x7f;
            totalBits += 7;
            if (totalBits > 31) {
                throw new ImageReadException(
                        "Overflow reading WBMP multi-byte field");
            }
        } while ((nextByte & 0x80) != 0);
        return value;
    }

    private void writeMultiByteInteger(final OutputStream os, final int value)
            throws IOException {
        boolean wroteYet = false;
        for (int position = 4 * 7; position > 0; position -= 7) {
            final int next7Bits = 0x7f & (value >>> position);
            if (next7Bits != 0 || wroteYet) {
                os.write(0x80 | next7Bits);
                wroteYet = true;
            }
        }
        os.write(0x7f & value);
    }

    private WbmpHeader readWbmpHeader(final ByteSource byteSource)
            throws ImageReadException, IOException {
        InputStream is = null;
        boolean canThrow = false;
        try {
            is = byteSource.getInputStream();
            final WbmpHeader ret = readWbmpHeader(is);
            canThrow = true;
            return ret;
        } finally {
            IoUtils.closeQuietly(canThrow, is);
        }
    }

    private WbmpHeader readWbmpHeader(final InputStream is)
            throws ImageReadException, IOException {
        final int typeField = readMultiByteInteger(is);
        if (typeField != 0) {
            throw new ImageReadException("Invalid/unsupported WBMP type "
                    + typeField);
        }

        final byte fixHeaderField = readByte("FixHeaderField", is,
                "Invalid WBMP File");
        if ((fixHeaderField & 0x9f) != 0) {
            throw new ImageReadException(
                    "Invalid/unsupported WBMP FixHeaderField 0x"
                            + Integer.toHexString(0xff & fixHeaderField));
        }

        final int width = readMultiByteInteger(is);

        final int height = readMultiByteInteger(is);

        return new WbmpHeader(typeField, fixHeaderField, width, height);
    }

    @Override
    public boolean dumpImageFile(final PrintWriter pw, final ByteSource byteSource)
            throws ImageReadException, IOException {
        readWbmpHeader(byteSource).dump(pw);
        return true;
    }

    private BufferedImage readImage(final WbmpHeader wbmpHeader, final InputStream is)
            throws IOException {
        final int rowLength = (wbmpHeader.width + 7) / 8;
        final byte[] image = readBytes("Pixels", is,
                rowLength * wbmpHeader.height, "Error reading image pixels");
        final DataBufferByte dataBuffer = new DataBufferByte(image, image.length);
        final WritableRaster raster = Raster.createPackedRaster(dataBuffer,
                wbmpHeader.width, wbmpHeader.height, 1, null);
        final int[] palette = { 0x000000, 0xffffff };
        final IndexColorModel colorModel = new IndexColorModel(1, 2, palette, 0,
                false, -1, DataBuffer.TYPE_BYTE);
        return new BufferedImage(colorModel, raster,
                colorModel.isAlphaPremultiplied(), new Properties());
    }

    @Override
    public final BufferedImage getBufferedImage(final ByteSource byteSource,
            final Map<String, Object> params) throws ImageReadException, IOException {
        InputStream is = null;
        boolean canThrow = false;
        try {
            is = byteSource.getInputStream();
            final WbmpHeader wbmpHeader = readWbmpHeader(is);
            final BufferedImage ret = readImage(wbmpHeader, is);
            canThrow = true;
            return ret;
        } finally {
            IoUtils.closeQuietly(canThrow, is);
        }
    }

    @Override
    public void writeImage(final BufferedImage src, final OutputStream os, Map<String, Object> params)
            throws ImageWriteException, IOException {
        // make copy of params; we'll clear keys as we consume them.
        params = (params == null) ? new HashMap<String, Object>() : new HashMap<String, Object>(params);

        // clear format key.
        if (params.containsKey(PARAM_KEY_FORMAT)) {
            params.remove(PARAM_KEY_FORMAT);
        }

        if (!params.isEmpty()) {
            final Object firstKey = params.keySet().iterator().next();
            throw new ImageWriteException("Unknown parameter: " + firstKey);
        }

        writeMultiByteInteger(os, 0); // typeField
        os.write(0); // fixHeaderField
        writeMultiByteInteger(os, src.getWidth());
        writeMultiByteInteger(os, src.getHeight());

        for (int y = 0; y < src.getHeight(); y++) {
            int pixel = 0;
            int nextBit = 0x80;
            for (int x = 0; x < src.getWidth(); x++) {
                final int argb = src.getRGB(x, y);
                final int red = 0xff & (argb >> 16);
                final int green = 0xff & (argb >> 8);
                final int blue = 0xff & (argb >> 0);
                final int sample = (red + green + blue) / 3;
                if (sample > 127) {
                    pixel |= nextBit;
                }
                nextBit >>>= 1;
                if (nextBit == 0) {
                    os.write(pixel);
                    pixel = 0;
                    nextBit = 0x80;
                }
            }
            if (nextBit != 0x80) {
                os.write(pixel);
            }
        }
    }

    /**
     * Extracts embedded XML metadata as XML string.
     * <p>
     *
     * @param byteSource
     *            File containing image data.
     * @param params
     *            Map of optional parameters, defined in ImagingConstants.
     * @return Xmp Xml as String, if present. Otherwise, returns null.
     */
    @Override
    public String getXmpXml(final ByteSource byteSource, final Map<String, Object> params)
            throws ImageReadException, IOException {
        return null;
    }
}
TOP

Related Classes of org.apache.commons.imaging.formats.wbmp.WbmpImageParser$WbmpHeader

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.