Package tvbrowserdataservice.file

Source Code of tvbrowserdataservice.file.ProgramField

/*
* TV-Browser
* Copyright (C) 04-2003 Martin Oberhauser (darras@users.sourceforge.net)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*
* CVS information:
*  $RCSfile$
*   $Source$
*     $Date: 2010-06-28 19:33:48 +0200 (Mon, 28 Jun 2010) $
*   $Author: bananeweizen $
* $Revision: 6662 $
*/
package tvbrowserdataservice.file;

import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.plugins.jpeg.JPEGImageWriteParam;
import javax.imageio.stream.ImageOutputStream;

import org.apache.commons.lang.StringUtils;

import util.io.FileFormatException;
import util.io.IOUtilities;
import util.misc.HashCodeUtilities;
import util.ui.UiUtilities;
import devplugin.ProgramFieldType;

/**
* @author Til Schneider, www.murfman.de
*/
public class ProgramField implements Cloneable {

    private static final Logger mLog
            = Logger.getLogger(ProgramField.class.getName());

    private static final String TEXT_CHARSET = "UTF-8";

    private int mTypeId;

    private ProgramFieldType mType;

    private byte[] mData;

    private int mDataFormat;

    /**
     * Maximum Size of Images. Images get resized to this
     * size if they exceed the limit
     */
    private static final int MAX_IMAGE_SIZE_X = 150;
    /**
     * Maximum Size of Images. Images get resized to this
     * size if they exceed the limit
     */
    private static final int MAX_IMAGE_SIZE_Y = 150;


    public ProgramField() {
        mDataFormat = ProgramFieldType.UNKNOWN_FORMAT;
        mType = null;
    }

    /**
     * Used for creating an instance of ProgramField to
     * read/store the additional ProgramFrame id in.
     *
     * @param o Dummy parameter.
     * @since 2.2.2
     */
    protected ProgramField(Object o) {
      mDataFormat = ProgramFieldType.UNKNOWN_FORMAT;
      mTypeId = 255;
    }

    public static ProgramField create(ProgramFieldType type, String text) {
        if (StringUtils.isEmpty(text)) {
            return null;
        }

        ProgramField p = new ProgramField();
        p.setType(type);
        p.setTextData(text);
        return p;
    }

    public static ProgramField create(ProgramFieldType type, byte[] data) {
        if ((data == null) || (data.length == 0)) {
            return null;
        }

        ProgramField p = new ProgramField();
        p.setType(type);

        if (type == ProgramFieldType.PICTURE_TYPE) {
            // If the FieldType is a Picture it has to be resized and recompressed

            byte[] newdata = recreateImage(data);
            if (newdata == null) {
              return null;
            }

            p.setBinaryData(newdata);

        } else {
            p.setBinaryData(data);
        }

        return p;
    }

    /**
     * This Function loads an image using imageio,
     * resizes it to the Max-Size of Images in TVBrowser and
     * stores it as an compressed jpg.
     * <p/>
     * If the Image is smaller than the Max-Size, it isn't altered
     *
     * @param data Image-Data
     * @return resized Image-Data
     */
    private static byte[] recreateImage(byte[] data) {
        byte[] newdata = null;
        BufferedImage image = null;
        try {
            // Read Image
            image = ImageIO.read(new ByteArrayInputStream(data));

            int curx = image.getWidth(null);
            int cury = image.getHeight(null);

            // If the Size is < than max, use the original Data to reduce compression
            // artefacts
            if ((curx <= MAX_IMAGE_SIZE_X) && (cury <= MAX_IMAGE_SIZE_Y)) {
                return data;
            }

            int newx = MAX_IMAGE_SIZE_X;
            int newy = (int)((MAX_IMAGE_SIZE_X/(float)curx) * cury);

            if (newy > MAX_IMAGE_SIZE_Y) {
                newy = MAX_IMAGE_SIZE_Y;
                newx = (int)((MAX_IMAGE_SIZE_Y/(float)cury) * curx);
            }

            BufferedImage tempPic = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB);
            Graphics2D g2d = tempPic.createGraphics();
            g2d.drawImage(image, null, null);
            g2d.dispose();

            BufferedImage newImage = UiUtilities.scaleIconToBufferedImage(tempPic, newx, newy);

            ByteArrayOutputStream out = new ByteArrayOutputStream();

            // Find a jpeg writer
            ImageWriter writer = null;
            Iterator<ImageWriter> iter = ImageIO.getImageWritersByFormatName("jpg");
            if (iter.hasNext()) {
                writer = iter.next();
            }

            if (writer != null) {
                // Prepare output file
                ImageOutputStream ios = ImageIO.createImageOutputStream(out);
                writer.setOutput(ios);

                JPEGImageWriteParam param = new JPEGImageWriteParam(null);

                param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
                param.setCompressionQuality(0.85f);

                // Write the image
                writer.write(null, new IIOImage(newImage, null, null), param);

                // Cleanup
                ios.flush();
                writer.dispose();
                ios.close();

                newdata = out.toByteArray();
            } else {
                mLog.severe("No JPEG-Exporter found. Image is not stored in Data");
            }

        } catch (IOException e) {
            e.printStackTrace();
            newdata = null;
        }

        return newdata;
    }

    public static ProgramField create(ProgramFieldType type, int value) {
        ProgramField p = new ProgramField();
        p.setType(type);
        if (type.getFormat() == ProgramFieldType.TIME_FORMAT) {
            p.setTimeData(value);
        } else {
            p.setIntData(value);
        }
        return p;
    }


    public Object clone() {
        try {
            return super.clone();
        }
        catch (CloneNotSupportedException exc) {
            // This will never happen, since this class implements Cloneable
            return null;
        }
    }


    public int getTypeId() {
        return mTypeId;
    }


    public ProgramFieldType getType() {
        if (mType == null) {
            mType = ProgramFieldType.getTypeForId(mTypeId);
        }

        return mType;
    }


    /**
     * @param type
     */
    public void setType(ProgramFieldType type) {
        mType = type;
        mTypeId = type.getTypeId();
    }


    /**
     * Is used for a field in an update file that should be deleted.
     */
    public void removeData() {
        mDataFormat = ProgramFieldType.UNKNOWN_FORMAT;
        mData = null;
    }


    public byte[] getBinaryData() {
        return mData;
    }


    /**
     * @param data
     */
    public void setBinaryData(byte[] data) {
        mDataFormat = ProgramFieldType.BINARY_FORMAT;

        mData = data;
    }


    public String getTextData() {
        if (mData == null) {
            return null;
        }

        try {
            return new String(mData, TEXT_CHARSET);
        }
        catch (UnsupportedEncodingException exc) {
            // This will never happen, because UTF-8 is always supported
            mLog.log(Level.SEVERE, "Charset " + TEXT_CHARSET + " is not supported", exc);

            return null;
        }
    }


    public void setTextData(String text) {
        mDataFormat = ProgramFieldType.TEXT_FORMAT;

        try {
            mData = text.getBytes(TEXT_CHARSET);
        }
        catch (UnsupportedEncodingException exc) {
            // This will never happen, because UTF-8 is always supported
            mLog.log(Level.SEVERE, "Charset " + TEXT_CHARSET + " is not supported", exc);
        }
    }


    public int getIntData() {
        return dataToInt(mData);
    }


    public void setIntData(int value) {
        mDataFormat = ProgramFieldType.INT_FORMAT;

        mData = intToData(value);
    }


    public int getTimeData() {
        return dataToInt(mData);
    }


    public void setTimeData(int minutesAfter1970) {
        mDataFormat = ProgramFieldType.TIME_FORMAT;

        mData = intToData(minutesAfter1970);
    }


    /**
     * Gets a String representation of the data value.
     *
     * @return the data value as String.
     */
    public String getDataAsString() {
        if (mDataFormat == ProgramFieldType.TEXT_FORMAT) {
            return new StringBuilder("'").append(getTextData()).append("'")
          .toString();
        } else if (mDataFormat == ProgramFieldType.INT_FORMAT) {
            return Integer.toString(getIntData());
        } else if (mDataFormat == ProgramFieldType.TIME_FORMAT) {
            int time = getTimeData();
            int hours = time / 60;
            int minutes = time % 60;
            return new StringBuilder().append(hours).append(':').append(
          (minutes < 10) ? "0" : "").append(minutes).toString();
        } else if (mDataFormat == ProgramFieldType.BINARY_FORMAT) {
            return "(binary)";
        } else {
            return "(unknown)";
        }
    }


    private static int dataToInt(byte[] data) {
        if (data == null) {
            return 0;
        }

        return ((data[0] & 0xFF) << (3 * 8))
                | ((data[1] & 0xFF) << (2 * 8))
                | ((data[2] & 0xFF) << (1 * 8))
                | ((data[3] & 0xFF) << (0 * 8));
    }


    private static byte[] intToData(int value) {
        byte[] data = new byte[4];

        data[0] = (byte) (value >> (3 * 8));
        data[1] = (byte) (value >> (2 * 8));
        data[2] = (byte) (value >> (1 * 8));
        data[3] = (byte) (value >> (0 * 8));

        return data;
    }


    private void checkFormat() throws FileFormatException {
        // Check whether the field data has the right format
        if (!getType().isRightFormat(mDataFormat)) {
            throw new FileFormatException("The field '" + getType().getName()
                    + "' must have the " + ProgramFieldType.getFormatName(getType().getFormat())
                    + " but it has the " + ProgramFieldType.getFormatName(mDataFormat));
        }
    }


    public void readFromStream(InputStream stream)
            throws IOException, FileFormatException {
        mTypeId = stream.read();
        mType = null;

        mDataFormat = ProgramFieldType.UNKNOWN_FORMAT;

        int dataLength = ((stream.read() & 0xFF) << 16)
                | ((stream.read() & 0xFF) << 8)
                | (stream.read() & 0xFF);

        if (dataLength == 0) {
            mData = null;
        } else {
            mData = IOUtilities.readBinaryData(stream, dataLength);
        }
    }


    public void writeToStream(OutputStream stream)
      throws IOException, FileFormatException {
      writeToStream(stream, true);
    }

    /**
     * Writes the data to a stream.
     *
     * @param stream The stream to write on
     * @param check If the format should be checked
     * @throws IOException Thrown if something goes wrong.
     * @throws FileFormatException Thrown if something goes wrong.
     * @since 2.2.2
     */
    protected void writeToStream(OutputStream stream, boolean check)
            throws IOException, FileFormatException {
        // Check whether the field has the right format
      if(check) {
        checkFormat();
      }

        stream.write(mTypeId);

        if (mData == null) {
            stream.write(0); // Length highest byte
            stream.write(0); // Length middle byte
            stream.write(0); // Length lowest byte
        } else {
            // Write the data length
            stream.write((byte) (mData.length >> 16));
            stream.write((byte) (mData.length >> 8));
            stream.write((byte) (mData.length));

            // Write the data
            stream.write(mData);
        }
    }

    public boolean equals(Object obj) {
        if (obj instanceof ProgramField) {
            ProgramField field = (ProgramField) obj;

            if (getTypeId() != field.getTypeId()) {
                return false;
            }

            return Arrays.equals(mData, field.mData);
        } else {
            return false;
        }
    }

    @Override
    public int hashCode() {
      int result = HashCodeUtilities.hash(getTypeId());
      result = HashCodeUtilities.hash(result, mData);
      return result;
    }
}
TOP

Related Classes of tvbrowserdataservice.file.ProgramField

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.