Author: alexsmirnov
Date: 2007-07-10 15:07:38 -0400 (Tue, 10 Jul 2007)
New Revision: 1588
Added:
trunk/framework/impl/src/main/java/org/ajax4jsf/resource/image/
trunk/framework/impl/src/main/java/org/ajax4jsf/resource/image/DiffusionFilterOp.java
trunk/framework/impl/src/main/java/org/ajax4jsf/resource/image/GIFEncoder.java
trunk/framework/impl/src/main/java/org/ajax4jsf/resource/image/ImageInfo.java
trunk/framework/impl/src/main/java/org/ajax4jsf/resource/image/Quantize.java
trunk/framework/test/src/test/java/org/richfaces/skin/
trunk/framework/test/src/test/java/org/richfaces/skin/Bean.java
trunk/framework/test/src/test/java/org/richfaces/skin/SkinTestCase.java
trunk/framework/test/src/test/java/org/richfaces/skin/SkinTests.java
trunk/framework/test/src/test/java/org/richfaces/skin/SkinThreadsTestCase.java
trunk/framework/test/src/test/java/org/richfaces/skin/TestApplicationFactory.java
Removed:
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/DiffusionFilterOp.java
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/GIFEncoder.java
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/ImageFilterOp.java
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/ImageGenerator.java
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/ImageInfo.java
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/ImageWaiter.java
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/ImageWrapper.java
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/IndexImage.java
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/Quantize.java
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/RoundGradientContext.java
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/RoundGradientPaint.java
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/SimpleGIFEncoder.java
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/imageio/ImageIOGenerator.java
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/imageio/gif/
trunk/framework/impl/src/main/resources/META-INF/services/javax.imageio.spi.ImageWriterSpi
trunk/framework/test/src/test/java/org/ajax4jsf/framework/skin/
trunk/framework/test/src/test/java/org/richfaces/skin/Bean.java
trunk/framework/test/src/test/java/org/richfaces/skin/SkinTestCase.java
trunk/framework/test/src/test/java/org/richfaces/skin/SkinTests.java
trunk/framework/test/src/test/java/org/richfaces/skin/SkinThreadsTestCase.java
trunk/framework/test/src/test/java/org/richfaces/skin/TestApplicationFactory.java
Modified:
trunk/framework/impl/src/main/java/org/ajax4jsf/resource/GifRenderer.java
trunk/framework/test/src/test/java/org/ajax4jsf/resource/CSSTemplateTestCase.java
trunk/framework/test/src/test/java/org/ajax4jsf/resource/InternetResourceServiceTestCase.java
trunk/framework/test/src/test/java/org/ajax4jsf/resource/MockCacheableResource.java
trunk/framework/test/src/test/java/org/ajax4jsf/resource/ParametersEncodingTestCase.java
trunk/framework/test/src/test/java/org/ajax4jsf/resource/ResourceServiceThreadsTestCase.java
trunk/samples/useCases/src/main/java/control/test/ControlBackingBean.java
trunk/samples/useCases/src/test/java/org/ajax4jsf/BeanTest.java
trunk/ui/dataFilterSlider/src/main/java/org/richfaces/component/UIDataFltrSlider.java
trunk/ui/dataFilterSlider/src/main/java/org/richfaces/taglib/DataFilterSliderListenerTagHandler.java
trunk/ui/dataFilterSlider/src/test/java/org/richfaces/component/DataFilterSliderComponentTest.java
trunk/ui/dropdown-menu/src/test/java/org/richfaces/component/DropDownMenuComponentTest.java
trunk/ui/inputnumber-slider/src/test/java/org/richfaces/component/InputNumberSliderComponentTest.java
trunk/ui/inputnumber-spinner/src/main/java/org/richfaces/renderkit/html/images/background/SpinnerButtonGradient.java
trunk/ui/inputnumber-spinner/src/main/java/org/richfaces/renderkit/html/images/background/SpinnerFieldGradient.java
trunk/ui/inputnumber-spinner/src/test/java/org/richfaces/component/InputNumberSpinnerComponentTest.java
trunk/ui/menu-components/src/main/java/org/richfaces/renderkit/html/MenuGroupRendererBase.java
trunk/ui/menu-components/src/test/java/org/richfaces/component/MenuGroupComponentTest.java
trunk/ui/menu-components/src/test/java/org/richfaces/component/MenuItemComponentTest.java
trunk/ui/menu-components/src/test/java/org/richfaces/component/MenuSeparatorComponentTest.java
trunk/ui/separator/src/main/java/org/richfaces/renderkit/html/images/BevelSeparatorImage.java
trunk/ui/separator/src/main/java/org/richfaces/renderkit/html/images/SimpleSeparatorImage.java
trunk/ui/separator/src/test/java/org/richfaces/component/SeparatorComponentTest.java
trunk/ui/tabPanel/src/main/java/org/richfaces/renderkit/images/TabStripeImage.java
trunk/ui/tabPanel/src/test/java/org/richfaces/component/TabPanelComponentTest.java
trunk/ui/toolBar/src/test/java/org/richfaces/component/ToolBarComponentTest.java
trunk/ui/tree/src/test/java/org/richfaces/component/TreeComponentTest.java
trunk/ui/tree/src/test/java/org/richfaces/component/state/events/CollapseAllCommandEventTest.java
trunk/ui/tree/src/test/java/org/richfaces/component/state/events/CollapseNodeCommandEventTest.java
trunk/ui/tree/src/test/java/org/richfaces/component/state/events/ExpandAllCommandEventTest.java
trunk/ui/tree/src/test/java/org/richfaces/component/state/events/ExpandNodeCommandEventTest.java
Log:
packages and classes refactor in the "impl" project
Deleted:
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/DiffusionFilterOp.java
===================================================================
---
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/DiffusionFilterOp.java 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/DiffusionFilterOp.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -1,268 +0,0 @@
-/**
- * License Agreement.
- *
- * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/*
- * Helma License Notice
- *
- * The contents of this file are subject to the Helma License
- * Version 2.0 (the "License"). You may not use this file except in
- * compliance with the License. A copy of the License is available at
- *
http://adele.helma.org/download/helma/license.txt
- *
- * Copyright 1998-2003 Helma Software. All Rights Reserved.
- *
- * $RCSfile: DiffusionFilterOp.java,v $
- * $Author: alexsmirnov $
- * $Revision: 1.1.2.1 $
- * $Date: 2007/01/09 18:59:06 $
- */
-
-/*
- * Code from com.jhlabs.image.DiffusionFilter, Java Image Processing
- * Copyright (C) Jerry Huxtable 1998
- *
http://www.jhlabs.com/ip/
- *
- * Conversion to a BufferedImageOp inspired by:
- *
http://www.peter-cockerell.net:8080/java/FloydSteinberg/FloydSteinbergFil...
- *
- */
-
-package org.ajax4jsf.framework.util.image;
-
-import java.awt.RenderingHints;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import java.awt.image.BufferedImage;
-import java.awt.image.BufferedImageOp;
-import java.awt.image.ColorModel;
-import java.awt.image.DataBufferByte;
-import java.awt.image.DataBufferInt;
-import java.awt.image.IndexColorModel;
-
-import org.ajax4jsf.Messages;
-
-public class DiffusionFilterOp implements BufferedImageOp {
-
- protected final static int[] diffusionMatrix = {
- 0, 0, 0,
- 0, 0, 7,
- 3, 5, 1,
- };
-
- private int[] matrix;
- private int sum;
- private boolean serpentine = true;
- private int[] colorMap;
-
- /**
- * Construct a DiffusionFilter
- */
- public DiffusionFilterOp() {
- setMatrix(diffusionMatrix);
- }
-
- /**
- * Set whether to use a serpentine pattern for return or not. This can reduce
'avalanche' artifacts in the output.
- * @param serpentine true to use serpentine pattern
- */
- public void setSerpentine(boolean serpentine) {
- this.serpentine = serpentine;
- }
-
- /**
- * Return the serpentine setting
- * @return the current setting
- */
- public boolean getSerpentine() {
- return serpentine;
- }
-
- public void setMatrix(int[] matrix) {
- this.matrix = matrix;
- sum = 0;
- for (int i = 0; i < matrix.length; i++)
- sum += matrix[i];
- }
-
- public int[] getMatrix() {
- return matrix;
- }
-
- /**
- * Do the filter operation
- *
- * @param src The source BufferedImage. Can be any type.
- * @param dst The destination image. If not null, must be of type TYPE_BYTE_INDEXED
- * @return A dithered version of src in a BufferedImage of type TYPE_BYTE_INDEXED
- */
- public BufferedImage filter(BufferedImage src, BufferedImage dst) {
-
- // If there's no dest. create one
- if (dst == null)
- dst = createCompatibleDestImage(src, null);
-
- // Otherwise check that the provided dest is an indexed image
- else if (dst.getType() != BufferedImage.TYPE_BYTE_INDEXED) {
- throw new
IllegalArgumentException(Messages.getMessage(Messages.BUFFER_TYPE_ERROR));
- }
-
- DataBufferByte dstBuffer = (DataBufferByte) dst.getRaster().getDataBuffer();
- byte dstData[] = dstBuffer.getData();
-
- // Other things to test are pixel bit strides, scanline stride and transfer type
- // Same goes for the source image
-
- IndexColorModel icm = (IndexColorModel) dst.getColorModel();
- colorMap = new int[icm.getMapSize()];
- icm.getRGBs(colorMap);
-
- int width = src.getWidth();
- int height = src.getHeight();
-
- DataBufferInt srcBuffer = (DataBufferInt) src.getRaster().getDataBuffer();
- int srcData[] = srcBuffer.getData();
-
- // This is the offset into the buffer of the current source pixel
- int index = 0;
-
- // Loop through each pixel
- for (int y = 0; y < height; y++) {
- boolean reverse = serpentine && (y & 1) == 1;
- int direction;
- if (reverse) {
- index = y * width + width - 1;
- direction = -1;
- } else {
- index = y * width;
- direction = 1;
- }
- for (int x = 0; x < width; x++) {
- int rgb1 = srcData[index];
- int a1 = (rgb1 >> 24) & 0xff;
- int r1 = (rgb1 >> 16) & 0xff;
- int g1 = (rgb1 >> 8) & 0xff;
- int b1 = rgb1 & 0xff;
-
- int idx = findIndex(r1, g1, b1, a1);
- dstData[index] = (byte) idx;
-
- int rgb2 = colorMap[idx];
- int a2 = (rgb2 >> 24) & 0xff;
- int r2 = (rgb2 >> 16) & 0xff;
- int g2 = (rgb2 >> 8) & 0xff;
- int b2 = rgb2 & 0xff;
-
- int er = r1 - r2;
- int eg = g1 - g2;
- int eb = b1 - b2;
- int ea = a1 - a2;
-
- for (int i = -1; i <= 1; i++) {
- int iy = i + y;
- if (0 <= iy && iy < height) {
- for (int j = -1; j <= 1; j++) {
- int jx = j + x;
- if (0 <= jx && jx < width) {
- int w;
- if (reverse)
- w = matrix[(i + 1) * 3 - j + 1];
- else
- w = matrix[(i + 1) * 3 + j + 1];
- if (w != 0) {
- int k = reverse ? index - j : index + j;
- rgb1 = srcData[k];
- a1 = ((rgb1 >> 24) & 0xff) + ea * w / sum;
- r1 = ((rgb1 >> 16) & 0xff) + er * w / sum;
- g1 = ((rgb1 >> 8) & 0xff) + eg * w / sum;
- b1 = (rgb1 & 0xff) + eb * w / sum;
-
- srcData[k] = ((clamp(a1) << 24) | clamp(r1)
<< 16)
- | (clamp(g1) << 8) | clamp(b1);
- }
- }
- }
- }
- }
- index += direction;
- }
- }
-
- return dst;
- }
-
- private static int clamp(int c) {
- if (c < 0)
- return 0;
- if (c > 255)
- return 255;
- return c;
- }
-
- int findIndex(int r1, int g1, int b1, int a1)
- throws ArrayIndexOutOfBoundsException {
- int idx = 0;
- long dist = Long.MAX_VALUE;
- for (int i = 0; i < colorMap.length; i++) {
- int rgb2 = colorMap[i];
- int a2 = (rgb2 >> 24) & 0xff;
- int r2 = (rgb2 >> 16) & 0xff;
- int g2 = (rgb2 >> 8) & 0xff;
- int b2 = rgb2 & 0xff;
-
- int da = a1 - a2;
- int dr = r1 - r2;
- int dg = g1 - g2;
- int db = b1 - b2;
-
- long newdist = da * da + dr * dr + dg * dg + db * db;
- if (newdist < dist) {
- idx = i;
- dist = newdist;
- }
- }
- return idx;
- }
-
- // This always returns an indexed image
- public BufferedImage createCompatibleDestImage(BufferedImage src,
- ColorModel destCM) {
- return new BufferedImage(src.getWidth(), src.getHeight(),
- BufferedImage.TYPE_BYTE_INDEXED);
- }
-
- // There are no rendering hints
- public RenderingHints getRenderingHints() {
- return null;
- }
-
- // No transformation, so return the source point
- public Point2D getPoint2D(Point2D srcPt, Point2D dstPt) {
- if (dstPt == null)
- dstPt = new Point2D.Float();
- dstPt.setLocation(srcPt.getX(), srcPt.getY());
- return dstPt;
- }
-
- // No transformation, so return the source bounds
- public Rectangle2D getBounds2D(BufferedImage src) {
- return src.getRaster().getBounds();
- }
-}
\ No newline at end of file
Deleted:
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/GIFEncoder.java
===================================================================
---
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/GIFEncoder.java 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/GIFEncoder.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -1,554 +0,0 @@
-/**
- * License Agreement.
- *
- * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/*
- * Helma License Notice
- *
- * The contents of this file are subject to the Helma License
- * Version 2.0 (the "License"). You may not use this file except in
- * compliance with the License. A copy of the License is available at
- *
http://adele.helma.org/download/helma/license.txt
- *
- * Copyright 1998-2003 Helma Software. All Rights Reserved.
- *
- * $RCSfile: GIFEncoder.java,v $
- * $Author: alexsmirnov $
- * $Revision: 1.1.2.1 $
- * $Date: 2007/01/09 18:59:03 $
- */
-
-/*
- * The GIF encoding routines are based on the Acme libary
- *
- * The following addaptions and extensions were added by Joerg Lehni:
- *
- * - encode now directly works on BufferedImage objects, the ImageEncoder
- * and ImageConsumer oriented frameworks has been removed.
- * - Only BufferedImages with IndexColorModel are taken, so no more
- * palette optimization with IntHashtable objects are necessary. If the
- * BufferedImage is in wrong format, helma.image.Quantizie is used to
- * convert it into a index based image.
- * - This version is much less space consuming as it only takes one sample
- * row of the rastered image at a time into memory during compression.
- * - The overall time for color reduction and gif compression should
- * therefore be greatly reduced.
- *
- * Acme Disclaimer:
- *
- * Transparency handling and variable bit size courtesy of Jack Palevich.
- *
- * Copyright (C)1996,1998 by Jef Poskanzer <jef(a)acme.com>. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * Visit the ACME Labs Java page for up-to-date versions of this and other
- * fine Java utilities:
http://www.acme.com/java/
- *
- * GifEncoder is adapted from ppmtogif, which is based on GIFENCOD by David
- * Rowley <mgardi(a)watdscu.waterloo.edu>. Lempel-Zim compression
- * based on "compress".
- *
- */
-
-package org.ajax4jsf.framework.util.image;
-
-import java.awt.image.BufferedImage;
-import java.awt.image.IndexColorModel;
-import java.awt.image.Raster;
-import java.io.DataOutput;
-import java.io.IOException;
-
-public class GIFEncoder {
- private boolean interlace = false;
-
- private int width, height;
- private Raster raster;
- // DataOutput is used for compatibility with ImageIO (see
helma.image.imageio.gif.GIFImageWriter)
- // otherwise, OutputStream would make much more sense here:
- private DataOutput out;
-
- private int curx, cury;
- private int countdown;
- private int pass;
- private int[] row;
-
- public void encode(BufferedImage bi, DataOutput out) throws IOException {
- encode(bi, out, false, null);
- }
-
- public void encode(BufferedImage bi, DataOutput out, boolean interlace,
- String comment) throws IOException {
- this.out = out;
- this.interlace = interlace;
-
- // make sure it's index colors:
- if (bi.getType() != BufferedImage.TYPE_BYTE_INDEXED)
- bi = Quantize.process(bi, 256, false, true);
-
- raster = bi.getRaster();
-
- width = bi.getWidth();
- height = bi.getHeight();
-
- int numPixels = width * height;
-
- IndexColorModel icm = (IndexColorModel) bi.getColorModel();
- int transparentIndex = icm.getTransparentPixel();
- int numColors = icm.getMapSize();
-
- // Figure out how many bits to use.
- int bitsPerPixel;
- if (numColors <= 2)
- bitsPerPixel = 1;
- else if (numColors <= 4)
- bitsPerPixel = 2;
- else if (numColors <= 16)
- bitsPerPixel = 4;
- else
- bitsPerPixel = 8;
-
- int initCodeSize;
-
- // Calculate number of bits we are expecting
- countdown = numPixels;
-
- // Indicate which pass we are on (if interlace)
- pass = 0;
-
- // The initial code size
- if (bitsPerPixel <= 1)
- initCodeSize = 2;
- else
- initCodeSize = bitsPerPixel;
-
- // Set up the current x and y position
- curx = 0;
- cury = 0;
- row = new int[width];
-
- // Write the Magic header
- writeString("GIF89a");
-
- // Write out the screen width and height
- writeWord(width);
- writeWord(height);
-
- // Indicate that there is a global colour map
- byte flags = (byte) 0x80; // Yes, there is a color map
- // OR in the resolution
- flags |= (byte) ((8 - 1) << 4);
- // Not sorted
- // OR in the Bits per Pixel
- flags |= (byte) ((bitsPerPixel - 1));
- // Write it out
- out.write(flags);
-
- // Write out the Background colour
- out.write((byte) 0);
-
- // Pixel aspect ratio - 1:1.
- //out.write((byte) 49);
- // Java's GIF reader currently has a bug, if the aspect ratio byte is
- // not zero it throws an ImageFormatException. It doesn't know that
- // 49 means a 1:1 aspect ratio. Well, whatever, zero works with all
- // the other decoders I've tried so it probably doesn't hurt.
- out.write((byte) 0);
-
- // Write out the Global Colour Map
- // Turn colors into colormap entries.
- int mapSize = 1 << bitsPerPixel;
- byte[] reds = new byte[mapSize], greens = new byte[mapSize], blues = new
byte[mapSize];
- icm.getReds(reds);
- icm.getGreens(greens);
- icm.getBlues(blues);
-
- for (int i = 0; i < mapSize; ++i) {
- out.write(reds[i]);
- out.write(greens[i]);
- out.write(blues[i]);
- }
-
- // Write out extension for transparent colour index, if necessary.
- if (transparentIndex != -1) {
- out.write((byte) '!');
- out.write((byte) 0xf9);
- out.write((byte) 4);
- out.write((byte) 1);
- out.write((byte) 0);
- out.write((byte) 0);
- out.write((byte) transparentIndex);
- out.write((byte) 0);
- }
-
- // Write an Image separator
- out.write((byte) ',');
-
- // Write the Image header
- writeWord(0); // leftOfs
- writeWord(0); // topOfs
- writeWord(width);
- writeWord(height);
-
- // Write out whether or not the image is interlaced
- if (interlace)
- out.write((byte) 0x40);
- else
- out.write((byte) 0x00);
-
- // Write out the initial code size
- out.write((byte) initCodeSize);
-
- // Go and actually compress the data
- compress(initCodeSize + 1);
-
- // Write out a Zero-length packet (to end the series)
- out.write((byte) 0);
-
- // Write out the comment
- if (comment != null && comment.length() > 0) {
- out.write((byte) 0x21);
- out.write((byte) 0xFE);
- out.write((byte) comment.length());
- writeString(comment);
- out.write((byte) 0);
- }
-
- // Write the GIF file terminator
- out.write((byte) ';');
- }
-
- // Return the next pixel from the image
- int getNextPixel() throws IOException {
- if (countdown == 0)
- return -1;
-
- --countdown;
-
- if (curx == 0)
- row = raster.getSamples(0, cury, width, 1, 0, row);
- int index = row[curx];
-
- // Bump the current X position
- ++curx;
-
- // If we are at the end of a scan line, set curx back to the beginning
- // If we are interlaced, bump the cury to the appropriate spot,
- // otherwise, just increment it.
- if (curx == width) {
- curx = 0;
-
- if (!interlace) {
- ++cury;
- } else {
- switch (pass) {
- case 0:
- cury += 8;
- if (cury >= height) {
- ++pass;
- cury = 4;
- }
- break;
-
- case 1:
- cury += 8;
- if (cury >= height) {
- ++pass;
- cury = 2;
- }
- break;
-
- case 2:
- cury += 4;
- if (cury >= height) {
- ++pass;
- cury = 1;
- }
- break;
-
- case 3:
- cury += 2;
- break;
- }
- }
- }
- return index;
- }
-
- void writeString(String str) throws IOException {
- byte[] buf = str.getBytes();
- out.write(buf);
- }
-
- // Write out a word to the GIF file
- void writeWord(int w) throws IOException {
- out.write((byte) (w & 0xff));
- out.write((byte) ((w >> 8) & 0xff));
- }
-
- // GIFCOMPR.C - GIF Image compression routines
- //
- // Lempel-Ziv compression based on 'compress'. GIF modifications by
- // David Rowley (mgardi(a)watdcsu.waterloo.edu)
-
- // General DEFINEs
-
- static final int BITS = 12;
-
- static final int HASH_SIZE = 5003; // 80% occupancy
-
- // GIF Image compression - modified 'compress'
- //
- // Based on: compress.c - File compression ala IEEE Computer, June 1984.
- //
- // By Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas)
- // Jim McKie (decvax!mcvax!jim)
- // Steve Davies (decvax!vax135!petsd!peora!srd)
- // Ken Turkowski (decvax!decwrl!turtlevax!ken)
- // James A. Woods (decvax!ihnp4!ames!jaw)
- // Joe Orost (decvax!vax135!petsd!joe)
-
- private int numBits; // number of bits/code
- private int maxBits = BITS; // user settable max # bits/code
- private int maxCode; // maximum code, given numBits
- private int maxMaxCode = 1 << BITS; // should NEVER generate this code
-
- final int getMaxCode(int numBits) {
- return (1 << numBits) - 1;
- }
-
- private int[] hashTable = new int[HASH_SIZE];
- private int[] codeTable = new int[HASH_SIZE];
-
- private int freeEntry = 0; // first unused entry
-
- // block compression parameters -- after all codes are used up,
- // and compression rate changes, start over.
- private boolean clearFlag = false;
-
- // Algorithm: use open addressing double hashing (no chaining) on the
- // prefix code / next character combination. We do a variant of Knuth's
- // algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
- // secondary probe. Here, the modular division first probe is gives way
- // to a faster exclusive-or manipulation. Also do block compression with
- // an adaptive reset, whereby the code table is cleared when the compression
- // ratio decreases, but after the table fills. The variable-length output
- // codes are re-sized at this point, and a special CLEAR code is generated
- // for the decompressor. Late addition: construct the table according to
- // file size for noticeable speed improvement on small files. Please direct
- // questions about this implementation to ames!jaw.
-
- private int initBits;
-
- private int clearCode;
- private int EOFCode;
-
- void compress(int initBits) throws IOException {
- // Set up the globals: initBits - initial number of bits
- this.initBits = initBits;
-
- // Set up the necessary values
- clearFlag = false;
- numBits = initBits;
- maxCode = getMaxCode(numBits);
-
- clearCode = 1 << (initBits - 1);
- EOFCode = clearCode + 1;
- freeEntry = clearCode + 2;
-
- charInit();
-
- int ent = getNextPixel();
-
- int hashShift = 0;
- for (int fcode = HASH_SIZE; fcode < 65536; fcode *= 2)
- ++hashShift;
- hashShift = 8 - hashShift; // set hash code range bound
-
- clearHash(); // clear hash table
-
- output(clearCode);
-
- int c;
- outerLoop: while ((c = getNextPixel()) != -1) {
- int fcode = (c << maxBits) + ent;
- int i = (c << hashShift) ^ ent; // xor hashing
-
- if (hashTable[i] == fcode) {
- ent = codeTable[i];
- continue;
- } else if (hashTable[i] >= 0) { // non-empty slot
- int disp = HASH_SIZE - i; // secondary hash (after G. Knott)
- if (i == 0)
- disp = 1;
- do {
- if ((i -= disp) < 0)
- i += HASH_SIZE;
-
- if (hashTable[i] == fcode) {
- ent = codeTable[i];
- continue outerLoop;
- }
- } while (hashTable[i] >= 0);
- }
- output(ent);
- ent = c;
- if (freeEntry < maxMaxCode) {
- codeTable[i] = freeEntry++; // code -> hashtable
- hashTable[i] = fcode;
- } else
- clearBlock();
- }
- // Put out the final code.
- output(ent);
- output(EOFCode);
- }
-
- // output
- //
- // Output the given code.
- // Inputs:
- // code: A numBits-bit integer. If == -1, then EOF. This assumes
- // that numBits =< wordsize - 1.
- // Outputs:
- // Outputs code to the file.
- // Assumptions:
- // Chars are 8 bits long.
- // Algorithm:
- // Maintain a BITS character long buffer (so that 8 codes will
- // fit in it exactly). Use the VAX insv instruction to insert each
- // code in turn. When the buffer fills up empty it and start over.
-
- int curAccum = 0;
- int curBits = 0;
-
- int masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F,
- 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF,
- 0x7FFF, 0xFFFF };
-
- void output(int code) throws IOException {
- curAccum &= masks[curBits];
-
- if (curBits > 0)
- curAccum |= (code << curBits);
- else
- curAccum = code;
-
- curBits += numBits;
-
- while (curBits >= 8) {
- charOut((byte) (curAccum & 0xff));
- curAccum >>= 8;
- curBits -= 8;
- }
-
- // If the next entry is going to be too big for the code size,
- // then increase it, if possible.
- if (freeEntry > maxCode || clearFlag) {
- if (clearFlag) {
- maxCode = getMaxCode(numBits = initBits);
- clearFlag = false;
- } else {
- ++numBits;
- if (numBits == maxBits)
- maxCode = maxMaxCode;
- else
- maxCode = getMaxCode(numBits);
- }
- }
-
- if (code == EOFCode) {
- // At EOF, write the rest of the buffer.
- while (curBits > 0) {
- charOut((byte) (curAccum & 0xff));
- curAccum >>= 8;
- curBits -= 8;
- }
-
- charFlush();
- }
- }
-
- // Clear out the hash table
-
- // table clear for block compress
- void clearBlock() throws IOException {
- clearHash();
- freeEntry = clearCode + 2;
- clearFlag = true;
-
- output(clearCode);
- }
-
- // reset code table
- void clearHash() {
- for (int i = 0; i < HASH_SIZE; ++i)
- hashTable[i] = -1;
- }
-
- // GIF Specific routines
-
- // Number of characters so far in this 'packet'
- private int a_count;
-
- // Set up the 'byte output' routine
- void charInit() {
- a_count = 0;
- }
-
- // Define the storage for the packet accumulator
- private byte[] accum = new byte[256];
-
- // Add a character to the end of the current packet, and if it is 254
- // characters, flush the packet to disk.
- void charOut(byte c) throws IOException {
- accum[a_count++] = c;
- if (a_count >= 254)
- charFlush();
- }
-
- // Flush the packet to disk, and reset the accumulator
- void charFlush() throws IOException {
- if (a_count > 0) {
- out.write(a_count);
- out.write(accum, 0, a_count);
- a_count = 0;
- }
- }
-}
\ No newline at end of file
Deleted:
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/ImageFilterOp.java
===================================================================
---
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/ImageFilterOp.java 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/ImageFilterOp.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -1,287 +0,0 @@
-/**
- * License Agreement.
- *
- * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/*
- * Helma License Notice
- *
- * The contents of this file are subject to the Helma License Version 2.0 (the
- * "License"). You may not use this file except in compliance with the
License.
- * A copy of the License is available at
- *
http://adele.helma.org/download/helma/license.txt
- *
- * Copyright 1998-2003 Helma Software. All Rights Reserved.
- *
- * $RCSfile: ImageFilterOp.java,v $
- * $Author: alexsmirnov $
- * $Revision: 1.1.2.1 $
- * $Date: 2007/01/09 18:59:04 $
- */
-
-/**
- * This class does pretty much the opposite of java.awt.image.BufferedImageFilter:
- * It wraps an ImageFilter in a BufferedImageOp
- * Optimizations have been added, like the ignoring of color models
- * and the assumption of INT_RGB type for destination buffers in
- * order to speed things up by almost a factor of 4.
- */
-
-package org.ajax4jsf.framework.util.image;
-
-import java.awt.AlphaComposite;
-import java.awt.Graphics2D;
-import java.awt.RenderingHints;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import java.awt.image.BufferedImage;
-import java.awt.image.BufferedImageOp;
-import java.awt.image.ColorModel;
-import java.awt.image.DataBufferInt;
-import java.awt.image.ImageConsumer;
-import java.awt.image.ImageFilter;
-import java.util.Hashtable;
-
-public class ImageFilterOp implements BufferedImageOp {
- ImageFilter filter;
-
- /**
- * Construct a ImageFilterOp
- */
- public ImageFilterOp(ImageFilter filter) {
- this.filter = filter;
- }
-
- /**
- * Do the filter operation
- *
- * @param src The source BufferedImage. Can be any type.
- * @param dst The destination image. If not null, must be of type
- * TYPE_INT_RGB, TYPE_INT_ARGB or TYPE_INT_ARGB_PRE
- * @return the filtered image
- */
- public BufferedImage filter(BufferedImage src, BufferedImage dst) {
- int width = src.getWidth();
- int height = src.getHeight();
-
- BufferedImageConsumer consumer = new BufferedImageConsumer(dst);
-
- ImageFilter fltr = filter.getFilterInstance(consumer);
- fltr.setDimensions(width, height);
-
- /*
- ColorModel cm = src.getColorModel();
- if (cm.getPixelSize() == 8) {
- // byte. indexed or gray:
- WritableRaster raster = src.getRaster();
- byte pixels[] = new byte[width];
- // calculate scanline by scanline in order to safe memory.
- // It also seems to run faster like that
- for (int y = 0; y < height; y++) {
- raster.getDataElements(0, y, width, 1, pixels);
- fltr.setPixels(0, y, width, 1, cm, pixels, 0, width);
- }
- } else {
- // integer, use the simple rgb mode:
- WritableRaster raster = src.getRaster();
- int pixels[] = new int[width];
- // calculate scanline by scanline in order to safe memory.
- // It also seems to run faster like that
- for (int y = 0; y < height; y++) {
- raster.getDataElements(0, y, width, 1, pixels);
- fltr.setPixels(0, y, width, 1, cm, pixels, 0, width);
- }
- }
- */
-
- // allways work in integer mode. this is more effective, and most
- // filters convert to integer internally anyhow
- ColorModel cm = new SimpleColorModel();
-
- // create a BufferedImage of only 1 pixel height for fetching the rows of the
image in the correct format (ARGB)
- // This speeds up things by more than factor 2, compared to the standard
BufferedImage.getRGB solution,
- // which is supposed to be fast too. This is probably the case because drawing to
BufferedImages uses
- // very optimized code which may even be hardware accelerated.
- BufferedImage row = new BufferedImage(width, 1, BufferedImage.TYPE_INT_ARGB);
- Graphics2D g2d = row.createGraphics();
- int pixels[] = ((DataBufferInt)row.getRaster().getDataBuffer()).getData();
-
- // make sure alpha values do not add up for each row:
- g2d.setComposite(AlphaComposite.Src);
- // calculate scanline by scanline in order to safe memory.
- // It also seems to run faster like that
- for (int y = 0; y < height; y++) {
- g2d.drawImage(src, null, 0, -y);
- // now pixels contains the rgb values of the row y!
- // filter this row now:
- fltr.setPixels(0, y, width, 1, cm, pixels, 0, width);
- }
- g2d.dispose();
-
- // the consumer now contains the filtered image, return it.
- return consumer.getImage();
- }
-
- public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel destCM)
{
- return null;
- }
-
- public RenderingHints getRenderingHints() {
- return null;
- }
-
- public Point2D getPoint2D(Point2D srcPt, Point2D dstPt) {
- return null;
- }
-
- public Rectangle2D getBounds2D(BufferedImage src) {
- return null;
- }
-
- /**
- * This is a dummy ColorModel that does nothing else than returning an
- * unchanged rgb value in getRGB, getRed, getGreen, getBlue, getAlpha.
- * This speeds up things for BufferedImages by at least a factor 1.5!
- */
- class SimpleColorModel extends ColorModel {
- public SimpleColorModel() {
- this(32);
- }
-
- public SimpleColorModel(int bits) {
- super(bits);
- }
-
- public int getRGB(int rgb) {
- // this is the part that speeds up most.
- // java.awt.image.ColorModel would return the same value, but with
- // 4 function calls and a lot of shifts and ors per color!
- return rgb;
- }
-
- public int getAlpha(int pixel) {
- return pixel >> 24;
- }
-
- public int getRed(int pixel) {
- return (pixel >> 16) & 0xff;
- }
-
- public int getGreen(int pixel) {
- return (pixel >> 8) & 0xff;
- }
-
- public int getBlue(int pixel) {
- return pixel & 0xff;
- }
- }
-
- /**
- * This is a dummy ImageConsumser that does nothing else than writing
- * The resulting rows from the ImageFilter into the image
- * If the image was not specified in the constructor, setDimensions
- * creates it with the given dimensions.
- */
- class BufferedImageConsumer implements ImageConsumer {
- BufferedImage image;
- BufferedImage compatible;
- int width;
- int height;
- boolean first = true;
-
- /*
- * Constructor with no compatible image. if image is null, setDimensions
- * will create a default INT_ARGB image of the size defined by the filter.
- */
- public BufferedImageConsumer(BufferedImage image) {
- this(image, null);
- }
-
- /*
- * Constructor with a compatible image. if image is null, setDimensions
- * will create a compatible image of the size defined by the filter.
- */
- public BufferedImageConsumer(BufferedImage image, BufferedImage compatible) {
- this.image = image;
- this.compatible = compatible;
- }
-
- public BufferedImage getImage() {
- return image;
- }
-
- public void setDimensions(int w, int h) {
- if (image == null) {
- if (compatible != null) {
- // create a compatible image with the new dimensions:
- image = new BufferedImage(
- compatible.getColorModel(),
- compatible.getRaster().createCompatibleWritableRaster(w, h),
- compatible.isAlphaPremultiplied(),
- null
- );
- } else {
- // assume standard format:
- image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
- }
- }
- width = image.getWidth();
- height = image.getHeight();
- }
-
- public void setPixels(int x, int y, int w, int h, ColorModel model, int[] pixels,
int off, int scansize) {
- // Cropping may be necessary: It's possible that the size of the
- // specified destination image is not the same as the size the
- // ImageFilter would produce!
- if (x < width && y < height) {
- if (x + w > width)
- w = width - x;
- if (y + h > height)
- h = height - y;
-
- if (w > 0 && h > 0)
- image.setRGB(x, y, w, h, pixels, off, scansize);
- }
- }
-
- public void setPixels(int x, int y, int w, int h, ColorModel model, byte[]
pixels, int off, int scansize) {
- if (x < width && y < height) {
- if (x + w > width)
- w = width - x;
- if (y + h > height)
- h = height - y;
-
- if (w > 0 && h > 0)
- image.getRaster().setDataElements(x, y, w, h, pixels);
- }
- }
-
- public void setProperties(Hashtable props) {
- }
-
- public void setColorModel(ColorModel model) {
- }
-
- public void setHints(int hintflags) {
- }
-
- public void imageComplete(int status) {
- }
- }
-}
\ No newline at end of file
Deleted:
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/ImageGenerator.java
===================================================================
---
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/ImageGenerator.java 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/ImageGenerator.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -1,232 +0,0 @@
-/**
- * License Agreement.
- *
- * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/*
- * Helma License Notice
- *
- * The contents of this file are subject to the Helma License
- * Version 2.0 (the "License"). You may not use this file except in
- * compliance with the License. A copy of the License is available at
- *
http://adele.helma.org/download/helma/license.txt
- *
- * Copyright 1998-2003 Helma Software. All Rights Reserved.
- *
- * $RCSfile: ImageGenerator.java,v $
- * $Author: alexsmirnov $
- * $Revision: 1.1.2.1 $
- * $Date: 2007/01/09 18:59:06 $
- */
-
-package org.ajax4jsf.framework.util.image;
-
-import java.awt.Image;
-import java.awt.Toolkit;
-import java.awt.image.BufferedImage;
-import java.awt.image.BufferedImageOp;
-import java.awt.image.ImageFilter;
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URL;
-
-import org.ajax4jsf.Messages;
-
-/**
- * Factory class for generating Image objects from various sources.
- *
- */
-public abstract class ImageGenerator {
- protected static ImageGenerator generator = null;
-
- /**
- * Returns an ImageGenerator singleton, creating it if necessary. If the JIMI
- * package is installed, an instance of {@link helma.image.jimi.JimiGenerator
JimiGenerator}
- * will be returned. Otherwise, if the javax.imageio package is available,
- * an instance of {@link helma.image.imageio.ImageIOGenerator ImageIOGenerator}
- * is returned. Additionally, the class of the ImageGenerator implementation
- * to be used can be set using the <code>imageGenerator</code> property
in either
- * the app.properties or server.properties file.
- *
- * @return a new ImageGenerator instance
- */
- public static ImageGenerator getInstance() {
- if (generator == null) {
- // first see wether an image wrapper class was specified in
- // server.properties:
- String className = null;
-// if (Server.getServer() != null) {
-// className =
Server.getServer().getProperty("imageGenerator");
-// }
-
- Class generatorClass = null;
- if (className == null) {
- // if no class is defined, try the default ones:
- try {
- Class.forName("com.sun.jimi.core.Jimi");
- // if we're still here, JimiWrapper can be used
- className = "helma.image.jimi.JimiGenerator";
- } catch (ClassNotFoundException e1) {
- try {
- Class.forName("javax.imageio.ImageIO");
- // if we're still here, ImageIOWrapper can be used
- className =
"org.ajax4jsf.framework.util.image.imageio.ImageIOGenerator";
- } catch (ClassNotFoundException e2) {
- }
- }
- }
- // now let's get the generator class and create an instance:
- try {
- generatorClass = Class.forName(className);
- } catch (ClassNotFoundException e) {
- throw new
RuntimeException(Messages.getMessage(Messages.IMAGE_GENERATOR_CLASS_NOT_FOUND,
className));
- }
- try {
- generator = (ImageGenerator)generatorClass.newInstance();
- } catch (Exception e) {
- throw new
RuntimeException(Messages.getMessage(Messages.CREATING_IMAGE_GENERATOR_ERROR,
className));
- }
- }
- return generator;
- }
-
- /**
- * @param w ...
- * @param h ...
- *
- * @return ...
- */
- public ImageWrapper createImage(int w, int h) {
- BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
- return new ImageWrapper(img, w, h, this);
- }
-
- /**
- * @param src ...
- *
- * @return ...
- * @throws IOException
- */
- public ImageWrapper createImage(byte[] src) throws IOException {
- Image img = read(src);
- return img != null ? new ImageWrapper(img, this) : null;
- }
-
- /**
- * @param filenamne ...
- *
- * @return ...
- * @throws IOException
- */
- public ImageWrapper createImage(String filenamne)
- throws IOException {
- Image img = read(filenamne);
- return img != null ? new ImageWrapper(img, this) : null;
- }
-
- /**
- * @param url ...
- *
- * @return ...
- * @throws MalformedURLException
- * @throws IOException
- */
- public ImageWrapper createImage(URL url)
- throws MalformedURLException, IOException {
- Image img = read(url);
- return img != null ? new ImageWrapper(img, this) : null;
- }
-
- /**
- * @param iw ...
- * @param filter ...
- *
- * @return ...
- */
- public ImageWrapper createImage(ImageWrapper iw, ImageFilter filter) {
- // use the ImagFilterOp wrapper for ImageFilters that works directly
- // on BufferedImages. The filtering is much faster like that.
- // Attention: needs testing with all the filters!
-
- return createImage(iw, new ImageFilterOp(filter));
-// Image img = ImageWaiter.waitForImage(
-// Toolkit.getDefaultToolkit().createImage(
-// new FilteredImageSource(iw.getSource(), filter)));
-// return img != null ? new ImageWrapper(img, this) : null;
- }
-
- /**
- * @param iw ...
- * @param imageOp ...
- *
- * @return ...
- */
- public ImageWrapper createImage(ImageWrapper iw, BufferedImageOp imageOp) {
- Image img = imageOp.filter(iw.getBufferedImage(), null);
- return img != null ? new ImageWrapper(img, this) : null;
- }
-
- /**
- * @param filename the filename of the image to create
- *
- * @return the newly created image
- * @throws IOException
- */
- public Image read(String filename) throws IOException {
- return ImageWaiter.waitForImage(
- Toolkit.getDefaultToolkit().createImage(filename)
- );
- }
-
- /**
- * @param url the URL the filename of the image to create
- *
- * @return the newly created image
- * @throws IOException
- */
- public Image read(URL url) throws IOException {
- return ImageWaiter.waitForImage(
- Toolkit.getDefaultToolkit().createImage(url)
- );
- }
-
- /**
- * @param src the data of the image to create
- *
- * @return the newly created image
- * @throws IOException
- */
- public Image read(byte[] src) throws IOException {
- return ImageWaiter.waitForImage(
- Toolkit.getDefaultToolkit().createImage(src)
- );
- }
-
- /**
- * Saves the image. Image format is deduced from filename.
- *
- * @param wrapper
- * @param filename
- * @param quality
- * @param alpha
- * @throws IOException
- */
- public abstract void write(ImageWrapper wrapper, String filename,
- float quality, boolean alpha) throws IOException;
-}
\ No newline at end of file
Deleted:
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/ImageInfo.java
===================================================================
---
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/ImageInfo.java 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/ImageInfo.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -1,1309 +0,0 @@
-/**
- * License Agreement.
- *
- * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/*
- * ImageInfo.java
- *
- * Version 1.5
- *
- * A Java class to determine image width, height and color depth for
- * a number of image file formats.
- *
- * Written by Marco Schmidt
- * <
http://www.geocities.com/marcoschmidt.geo/contact.html>.
- *
- * Contributed to the Public Domain.
- *
- * Last modification 2004-02-29
- */
-
-package org.ajax4jsf.framework.util.image;
-
-import java.io.DataInput;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.Vector;
-
-import org.ajax4jsf.Messages;
-
-/**
- * Get file format, image resolution, number of bits per pixel and optionally
- * number of images, comments and physical resolution from
- * JPEG, GIF, BMP, PCX, PNG, IFF, RAS, PBM, PGM, PPM, PSD and SWF files
- * (or input streams).
- * <p>
- * Use the class like this:
- * <pre>
- * ImageInfo ii = new ImageInfo();
- * ii.setInput(in); // in can be InputStream or RandomAccessFile
- * ii.setDetermineImageNumber(true); // default is false
- * ii.setCollectComments(true); // default is false
- * if (!ii.check()) {
- * System.err.println("Not a supported image file format.");
- * return;
- * }
- * System.out.println(ii.getFormatName() + ", " + ii.getMimeType() +
- * ", " + ii.getWidth() + " x " + ii.getHeight() + " pixels,
" +
- * ii.getBitsPerPixel() + " bits per pixel, " + ii.getNumberOfImages() +
- * " image(s), " + ii.getNumberOfComments() + " comment(s).");
- * // there are other properties, check out the API documentation
- * </pre>
- * You can also use this class as a command line program.
- * Call it with a number of image file names and URLs as parameters:
- * <pre>
- * java ImageInfo *.jpg *.png *.gif
http://somesite.tld/image.jpg
- * </pre>
- * or call it without parameters and pipe data to it:
- * <pre>
- * java ImageInfo < image.jpg
- * </pre>
- * <p>
- * Known limitations:
- * <ul>
- * <li>When the determination of the number of images is turned off, GIF bits
- * per pixel are only read from the global header.
- * For some GIFs, local palettes change this to a typically larger
- * value. To be certain to get the correct color depth, call
- * setDetermineImageNumber(true) before calling check().
- * The complete scan over the GIF file will take additional time.</li>
- * <li>Transparency information is not included in the bits per pixel count.
- * Actually, it was my decision not to include those bits, so it's a feature!
;-)</li>
- * </ul>
- * <p>
- * Requirements:
- * <ul>
- * <li>Java 1.1 or higher</li>
- * </ul>
- * <p>
- * The latest version can be found at <a
href="http://www.geocities.com/marcoschmidt.geo/image-info.html"...;.
- * <p>
- * Written by <a
href="http://www.geocities.com/marcoschmidt.geo/contact.html"&g...
Schmidt</a>.
- * <p>
- * This class is contributed to the Public Domain.
- * Use it at your own risk.
- * <p>
- * Last modification 2004-02-29.
- * <p>
- * History:
- * <ul>
- * <li><strong>2001-08-24</strong> Initial version.</li>
- * <li><strong>2001-10-13</strong> Added support for the file formats
BMP and PCX.</li>
- * <li><strong>2001-10-16</strong> Fixed bug in read(int[], int, int)
that returned
- * <li><strong>2002-01-22</strong> Added support for file formats Amiga
IFF and Sun Raster (RAS).</li>
- * <li><strong>2002-01-24</strong> Added support for file formats
Portable Bitmap / Graymap / Pixmap (PBM, PGM, PPM) and Adobe Photoshop (PSD).
- * Added new method getMimeType() to return the MIME type associated with a particular
file format.</li>
- * <li><strong>2002-03-15</strong> Added support to recognize number of
images in file. Only works with GIF.
- * Use {@link #setDetermineImageNumber} with <code>true</code> as argument
to identify animated GIFs
- * ({@link #getNumberOfImages()} will return a value larger than
<code>1</code>).</li>
- * <li><strong>2002-04-10</strong> Fixed a bug in the feature
'determine number of images in animated GIF' introduced with version 1.1.
- * Thanks to Marcelo P. Lima for sending in the bug report.
- * Released as 1.1.1.</li>
- * <li><strong>2002-04-18</strong> Added {@link
#setCollectComments(boolean)}.
- * That new method lets the user specify whether textual comments are to be
- * stored in an internal list when encountered in an input image file / stream.
- * Added two methods to return the physical width and height of the image in dpi:
- * {@link #getPhysicalWidthDpi()} and {@link #getPhysicalHeightDpi()}.
- * If the physical resolution could not be retrieved, these methods return
<code>-1</code>.
- * </li>
- * <li><strong>2002-04-23</strong> Added support for the new properties
physical resolution and
- * comments for some formats. Released as 1.2.</li>
- * <li><strong>2002-06-17</strong> Added support for SWF, sent in by
Michael Aird.
- * Changed checkJpeg() so that other APP markers than APP0 will not lead to a failure
anymore.
- * Released as 1.3.</li>
- * <li><strong>2003-07-28</strong> Bug fix - skip method now takes
return values into consideration.
- * Less bytes than necessary may have been skipped, leading to flaws in the retrieved
information in some cases.
- * Thanks to Bernard Bernstein for pointing that out.
- * Released as 1.4.</li>
- * <li><strong>2004-02-29</strong> Added support for recognizing
progressive JPEG and
- * interlaced PNG and GIF. A new method {@link #isProgressive()} returns whether
ImageInfo
- * has found that the storage type is progressive (or interlaced).
- * Thanks to Joe Germuska for suggesting the feature.
- * Bug fix: BMP physical resolution is now correctly determined.
- * Released as 1.5.</li>
- * </ul>
- */
-public class ImageInfo {
- /**
- * Return value of {@link #getFormat()} for JPEG streams.
- * ImageInfo can extract physical resolution and comments
- * from JPEGs (only from APP0 headers).
- * Only one image can be stored in a file.
- * It is determined whether the JPEG stream is progressive
- * (see {@link #isProgressive()}).
- */
- public static final int FORMAT_JPEG = 0;
-
- /**
- * Return value of {@link #getFormat()} for GIF streams.
- * ImageInfo can extract comments from GIFs and count the number
- * of images (GIFs with more than one image are animations).
- * If you know of a place where GIFs store the physical resolution
- * of an image, please
- * <a
href="http://www.geocities.com/marcoschmidt.geo/contact.html"&g...
me a mail</a>!
- * It is determined whether the GIF stream is interlaced (see {@link
#isProgressive()}).
- */
- public static final int FORMAT_GIF = 1;
-
- /**
- * Return value of {@link #getFormat()} for PNG streams.
- * PNG only supports one image per file.
- * Both physical resolution and comments can be stored with PNG,
- * but ImageInfo is currently not able to extract those.
- * It is determined whether the PNG stream is interlaced (see {@link
#isProgressive()}).
- */
- public static final int FORMAT_PNG = 2;
-
- /**
- * Return value of {@link #getFormat()} for BMP streams.
- * BMP only supports one image per file.
- * BMP does not allow for comments.
- * The physical resolution can be stored.
- */
- public static final int FORMAT_BMP = 3;
-
- /**
- * Return value of {@link #getFormat()} for PCX streams.
- * PCX does not allow for comments or more than one image per file.
- * However, the physical resolution can be stored.
- */
- public static final int FORMAT_PCX = 4;
-
- /**
- * Return value of {@link #getFormat()} for IFF streams.
- */
- public static final int FORMAT_IFF = 5;
-
- /**
- * Return value of {@link #getFormat()} for RAS streams.
- * Sun Raster allows for one image per file only and is not able to
- * store physical resolution or comments.
- */
- public static final int FORMAT_RAS = 6;
-
- /** Return value of {@link #getFormat()} for PBM streams. */
- public static final int FORMAT_PBM = 7;
-
- /** Return value of {@link #getFormat()} for PGM streams. */
- public static final int FORMAT_PGM = 8;
-
- /** Return value of {@link #getFormat()} for PPM streams. */
- public static final int FORMAT_PPM = 9;
-
- /** Return value of {@link #getFormat()} for PSD streams. */
- public static final int FORMAT_PSD = 10;
-
- /** Return value of {@link #getFormat()} for SWF (Shockwave) streams. */
- public static final int FORMAT_SWF = 11;
-
- public static final int COLOR_TYPE_UNKNOWN = -1;
- public static final int COLOR_TYPE_TRUECOLOR_RGB = 0;
- public static final int COLOR_TYPE_PALETTED = 1;
- public static final int COLOR_TYPE_GRAYSCALE= 2;
- public static final int COLOR_TYPE_BLACK_AND_WHITE = 3;
-
- /**
- * The names of all supported file formats.
- * The FORMAT_xyz int constants can be used as index values for
- * this array.
- */
- private static final String[] FORMAT_NAMES =
- {"JPEG", "GIF", "PNG", "BMP", "PCX",
- "IFF", "RAS", "PBM", "PGM", "PPM",
- "PSD", "SWF"};
-
- /**
- * The names of the MIME types for all supported file formats.
- * The FORMAT_xyz int constants can be used as index values for
- * this array.
- */
- private static final String[] MIME_TYPE_STRINGS =
- {"image/jpeg", "image/gif", "image/png",
"image/bmp", "image/pcx",
- "image/iff", "image/ras", "image/x-portable-bitmap",
"image/x-portable-graymap", "image/x-portable-pixmap",
- "image/psd", "application/x-shockwave-flash"};
-
- private int width;
- private int height;
- private int bitsPerPixel;
- private int colorType = COLOR_TYPE_UNKNOWN;
- private boolean progressive;
- private int format;
- private InputStream in;
- private DataInput din;
- private boolean collectComments = true;
- private Vector comments;
- private boolean determineNumberOfImages;
- private int numberOfImages;
- private int physicalHeightDpi;
- private int physicalWidthDpi;
- private int bitBuf;
- private int bitPos;
-
- private void addComment(String s) {
- if (comments == null) {
- comments = new Vector();
- }
- comments.addElement(s);
- }
-
- /**
- * Call this method after you have provided an input stream or file
- * using {@link #setInput(InputStream)} or {@link #setInput(DataInput)}.
- * If true is returned, the file format was known and information
- * on the file's content can be retrieved using the various getXyz methods.
- * @return if information could be retrieved from input
- */
- public boolean check() {
- format = -1;
- width = -1;
- height = -1;
- bitsPerPixel = -1;
- numberOfImages = 1;
- physicalHeightDpi = -1;
- physicalWidthDpi = -1;
- comments = null;
- try {
- int b1 = read() & 0xff;
- int b2 = read() & 0xff;
- if (b1 == 0x47 && b2 == 0x49) {
- return checkGif();
- }
- else
- if (b1 == 0x89 && b2 == 0x50) {
- return checkPng();
- }
- else
- if (b1 == 0xff && b2 == 0xd8) {
- return checkJpeg();
- }
- else
- if (b1 == 0x42 && b2 == 0x4d) {
- return checkBmp();
- }
- else
- if (b1 == 0x0a && b2 < 0x06) {
- return checkPcx();
- }
- else
- if (b1 == 0x46 && b2 == 0x4f) {
- return checkIff();
- }
- else
- if (b1 == 0x59 && b2 == 0xa6) {
- return checkRas();
- }
- else
- if (b1 == 0x50 && b2 >= 0x31 && b2 <= 0x36) {
- return checkPnm(b2 - '0');
- }
- else
- if (b1 == 0x38 && b2 == 0x42) {
- return checkPsd();
- }
- else
- if (b1 == 0x46 && b2 == 0x57) {
- return checkSwf();
- }
- else {
- return false;
- }
- } catch (IOException ioe) {
- return false;
- }
- }
-
- private boolean checkBmp() throws IOException {
- byte[] a = new byte[44];
- if (read(a) != a.length) {
- return false;
- }
- width = getIntLittleEndian(a, 16);
- height = getIntLittleEndian(a, 20);
- if (width < 1 || height < 1) {
- return false;
- }
- bitsPerPixel = getShortLittleEndian(a, 26);
- if (bitsPerPixel != 1 && bitsPerPixel != 4 &&
- bitsPerPixel != 8 && bitsPerPixel != 16 &&
- bitsPerPixel != 24 && bitsPerPixel != 32) {
- return false;
- }
- int x = (int)(getIntLittleEndian(a, 36) * 0.0254);
- if (x > 0) {
- setPhysicalWidthDpi(x);
- }
- int y = (int)(getIntLittleEndian(a, 40) * 0.0254);
- if (y > 0) {
- setPhysicalHeightDpi(y);
- }
- format = FORMAT_BMP;
- return true;
- }
-
- private boolean checkGif() throws IOException {
- final byte[] GIF_MAGIC_87A = {0x46, 0x38, 0x37, 0x61};
- final byte[] GIF_MAGIC_89A = {0x46, 0x38, 0x39, 0x61};
- byte[] a = new byte[11]; // 4 from the GIF signature + 7 from the global header
- if (read(a) != 11) {
- return false;
- }
- if ((!equals(a, 0, GIF_MAGIC_89A, 0, 4)) &&
- (!equals(a, 0, GIF_MAGIC_87A, 0, 4))) {
- return false;
- }
- format = FORMAT_GIF;
- width = getShortLittleEndian(a, 4);
- height = getShortLittleEndian(a, 6);
- int flags = a[8] & 0xff;
- bitsPerPixel = ((flags >> 4) & 0x07) + 1;
- progressive = (flags & 0x02) != 0;
- if (!determineNumberOfImages) {
- return true;
- }
- // skip global color palette
- if ((flags & 0x80) != 0) {
- int tableSize = (1 << ((flags & 7) + 1)) * 3;
- skip(tableSize);
- }
- numberOfImages = 0;
- int blockType;
- do
- {
- blockType = read();
- switch(blockType)
- {
- case(0x2c): // image separator
- {
- if (read(a, 0, 9) != 9) {
- return false;
- }
- flags = a[8] & 0xff;
- int localBitsPerPixel = (flags & 0x07) + 1;
- if (localBitsPerPixel > bitsPerPixel) {
- bitsPerPixel = localBitsPerPixel;
- }
- if ((flags & 0x80) != 0) {
- skip((1 << localBitsPerPixel) * 3);
- }
- skip(1); // initial code length
- int n;
- do
- {
- n = read();
- if (n > 0) {
- skip(n);
- }
- else
- if (n == -1) {
- return false;
- }
- }
- while (n > 0);
- numberOfImages++;
- break;
- }
- case(0x21): // extension
- {
- int extensionType = read();
- if (collectComments && extensionType == 0xfe) {
- StringBuffer sb = new StringBuffer();
- int n;
- do
- {
- n = read();
- if (n == -1) {
- return false;
- }
- if (n > 0) {
- for (int i = 0; i < n; i++) {
- int ch = read();
- if (ch == -1) {
- return false;
- }
- sb.append((char)ch);
- }
- }
- }
- while (n > 0);
- } else {
- int n;
- do
- {
- n = read();
- if (n > 0) {
- skip(n);
- }
- else
- if (n == -1) {
- return false;
- }
- }
- while (n > 0);
- }
- break;
- }
- case(0x3b): // end of file
- {
- break;
- }
- default:
- {
- return false;
- }
- }
- }
- while (blockType != 0x3b);
- return true;
- }
-
- private boolean checkIff() throws IOException {
- byte[] a = new byte[10];
- // read remaining 2 bytes of file id, 4 bytes file size
- // and 4 bytes IFF subformat
- if (read(a, 0, 10) != 10) {
- return false;
- }
- final byte[] IFF_RM = {0x52, 0x4d};
- if (!equals(a, 0, IFF_RM, 0, 2)) {
- return false;
- }
- int type = getIntBigEndian(a, 6);
- if (type != 0x494c424d && // type must be ILBM...
- type != 0x50424d20) { // ...or PBM
- return false;
- }
- // loop chunks to find BMHD chunk
- do {
- if (read(a, 0, 8) != 8) {
- return false;
- }
- int chunkId = getIntBigEndian(a, 0);
- int size = getIntBigEndian(a, 4);
- if ((size & 1) == 1) {
- size++;
- }
- if (chunkId == 0x424d4844) { // BMHD chunk
- if (read(a, 0, 9) != 9) {
- return false;
- }
- format = FORMAT_IFF;
- width = getShortBigEndian(a, 0);
- height = getShortBigEndian(a, 2);
- bitsPerPixel = a[8] & 0xff;
- return (width > 0 && height > 0 && bitsPerPixel > 0
&& bitsPerPixel < 33);
- } else {
- skip(size);
- }
- } while (true);
- }
-
- private boolean checkJpeg() throws IOException {
- byte[] data = new byte[12];
- while (true) {
- if (read(data, 0, 4) != 4) {
- return false;
- }
- int marker = getShortBigEndian(data, 0);
- int size = getShortBigEndian(data, 2);
- if ((marker & 0xff00) != 0xff00) {
- return false; // not a valid marker
- }
- if (marker == 0xffe0) { // APPx
- if (size < 14) {
- return false; // APPx header must be >= 14 bytes
- }
- if (read(data, 0, 12) != 12) {
- return false;
- }
- final byte[] APP0_ID = {0x4a, 0x46, 0x49, 0x46, 0x00};
- if (equals(APP0_ID, 0, data, 0, 5)) {
- //System.out.println("data 7=" + data[7]);
- if (data[7] == 1) {
- setPhysicalWidthDpi(getShortBigEndian(data, 8));
- setPhysicalHeightDpi(getShortBigEndian(data, 10));
- }
- else
- if (data[7] == 2) {
- int x = getShortBigEndian(data, 8);
- int y = getShortBigEndian(data, 10);
- setPhysicalWidthDpi((int)(x * 2.54f));
- setPhysicalHeightDpi((int)(y * 2.54f));
- }
- }
- skip(size - 14);
- }
- else
- if (collectComments && size > 2 && marker == 0xfffe) { // comment
- size -= 2;
- byte[] chars = new byte[size];
- if (read(chars, 0, size) != size) {
- return false;
- }
- String comment = new String(chars, "iso-8859-1");
- comment = comment.trim();
- addComment(comment);
- }
- else
- if (marker >= 0xffc0 && marker <= 0xffcf && marker != 0xffc4
&& marker != 0xffc8) {
- if (read(data, 0, 6) != 6) {
- return false;
- }
- format = FORMAT_JPEG;
- bitsPerPixel = (data[0] & 0xff) * (data[5] & 0xff);
- progressive = marker == 0xffc2 || marker == 0xffc6 ||
- marker == 0xffca || marker == 0xffce;
- width = getShortBigEndian(data, 3);
- height = getShortBigEndian(data, 1);
- return true;
- } else {
- skip(size - 2);
- }
- }
- }
-
- private boolean checkPcx() throws IOException {
- byte[] a = new byte[64];
- if (read(a) != a.length) {
- return false;
- }
- if (a[0] != 1) { // encoding, 1=RLE is only valid value
- return false;
- }
- // width / height
- int x1 = getShortLittleEndian(a, 2);
- int y1 = getShortLittleEndian(a, 4);
- int x2 = getShortLittleEndian(a, 6);
- int y2 = getShortLittleEndian(a, 8);
- if (x1 < 0 || x2 < x1 || y1 < 0 || y2 < y1) {
- return false;
- }
- width = x2 - x1 + 1;
- height = y2 - y1 + 1;
- // color depth
- int bits = a[1];
- int planes = a[63];
- if (planes == 1 &&
- (bits == 1 || bits == 2 || bits == 4 || bits == 8)) {
- // paletted
- bitsPerPixel = bits;
- } else
- if (planes == 3 && bits == 8) {
- // RGB truecolor
- bitsPerPixel = 24;
- } else {
- return false;
- }
- setPhysicalWidthDpi(getShortLittleEndian(a, 10));
- setPhysicalHeightDpi(getShortLittleEndian(a, 10));
- format = FORMAT_PCX;
- return true;
- }
-
- private boolean checkPng() throws IOException {
- final byte[] PNG_MAGIC = {0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a};
- byte[] a = new byte[27];
- if (read(a) != 27) {
- return false;
- }
- if (!equals(a, 0, PNG_MAGIC, 0, 6)) {
- return false;
- }
- format = FORMAT_PNG;
- width = getIntBigEndian(a, 14);
- height = getIntBigEndian(a, 18);
- bitsPerPixel = a[22] & 0xff;
- int colorType = a[23] & 0xff;
- if (colorType == 2 || colorType == 6) {
- bitsPerPixel *= 3;
- }
- progressive = (a[26] & 0xff) != 0;
- return true;
- }
-
- private boolean checkPnm(int id) throws IOException {
- if (id < 1 || id > 6) {
- return false;
- }
- final int[] PNM_FORMATS = {FORMAT_PBM, FORMAT_PGM, FORMAT_PPM};
- format = PNM_FORMATS[(id - 1) % 3];
- boolean hasPixelResolution = false;
- String s;
- while (true)
- {
- s = readLine();
- if (s != null) {
- s = s.trim();
- }
- if (s == null || s.length() < 1) {
- continue;
- }
- if (s.charAt(0) == '#') { // comment
- if (collectComments && s.length() > 1) {
- addComment(s.substring(1));
- }
- continue;
- }
- if (!hasPixelResolution) { // split "343 966" into width=343, height=966
- int spaceIndex = s.indexOf(' ');
- if (spaceIndex == -1) {
- return false;
- }
- String widthString = s.substring(0, spaceIndex);
- spaceIndex = s.lastIndexOf(' ');
- if (spaceIndex == -1) {
- return false;
- }
- String heightString = s.substring(spaceIndex + 1);
- try {
- width = Integer.parseInt(widthString);
- height = Integer.parseInt(heightString);
- } catch (NumberFormatException nfe) {
- return false;
- }
- if (width < 1 || height < 1) {
- return false;
- }
- if (format == FORMAT_PBM) {
- bitsPerPixel = 1;
- return true;
- }
- hasPixelResolution = true;
- }
- else
- {
- int maxSample;
- try {
- maxSample = Integer.parseInt(s);
- } catch (NumberFormatException nfe) {
- return false;
- }
- if (maxSample < 0) {
- return false;
- }
- for (int i = 0; i < 25; i++) {
- if (maxSample < (1 << (i + 1))) {
- bitsPerPixel = i + 1;
- if (format == FORMAT_PPM) {
- bitsPerPixel *= 3;
- }
- return true;
- }
- }
- return false;
- }
- }
- }
-
- private boolean checkPsd() throws IOException {
- byte[] a = new byte[24];
- if (read(a) != a.length) {
- return false;
- }
- final byte[] PSD_MAGIC = {0x50, 0x53};
- if (!equals(a, 0, PSD_MAGIC, 0, 2)) {
- return false;
- }
- format = FORMAT_PSD;
- width = getIntBigEndian(a, 16);
- height = getIntBigEndian(a, 12);
- int channels = getShortBigEndian(a, 10);
- int depth = getShortBigEndian(a, 20);
- bitsPerPixel = channels * depth;
- return (width > 0 && height > 0 && bitsPerPixel > 0 &&
bitsPerPixel <= 64);
- }
-
- private boolean checkRas() throws IOException {
- byte[] a = new byte[14];
- if (read(a) != a.length) {
- return false;
- }
- final byte[] RAS_MAGIC = {0x6a, (byte)0x95};
- if (!equals(a, 0, RAS_MAGIC, 0, 2)) {
- return false;
- }
- format = FORMAT_RAS;
- width = getIntBigEndian(a, 2);
- height = getIntBigEndian(a, 6);
- bitsPerPixel = getIntBigEndian(a, 10);
- return (width > 0 && height > 0 && bitsPerPixel > 0 &&
bitsPerPixel <= 24);
- }
-
- // Written by Michael Aird.
- private boolean checkSwf() throws IOException {
- //get rid of the last byte of the signature, the byte of the version and 4 bytes of the
size
- byte[] a = new byte[6];
- if (read(a) != a.length) {
- return false;
- }
- format = FORMAT_SWF;
- int bitSize = (int)readUBits( 5 );
- int minX = (int)readSBits( bitSize );
- int maxX = (int)readSBits( bitSize );
- int minY = (int)readSBits( bitSize );
- int maxY = (int)readSBits( bitSize );
- width = maxX/20; //cause we're in twips
- height = maxY/20; //cause we're in twips
- setPhysicalWidthDpi(72);
- setPhysicalHeightDpi(72);
- return (width > 0 && height > 0);
- }
-
- /**
- * Run over String list, return false iff at least one of the arguments
- * equals <code>-c</code>.
- */
- private static boolean determineVerbosity(String[] args) {
- if (args != null && args.length > 0) {
- for (int i = 0; i < args.length; i++) {
- if ("-c".equals(args[i])) {
- return false;
- }
- }
- }
- return true;
- }
-
- private boolean equals(byte[] a1, int offs1, byte[] a2, int offs2, int num) {
- while (num-- > 0) {
- if (a1[offs1++] != a2[offs2++]) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * If {@link #check()} was successful, returns the image's number of bits per
pixel.
- * Does not include transparency information like the alpha channel.
- * @return number of bits per image pixel
- */
- public int getBitsPerPixel() {
- return bitsPerPixel;
- }
-
- /**
- * Returns the index'th comment retrieved from the image.
- * @throws IllegalArgumentException if index is smaller than 0 or larger than or equal
- * to the number of comments retrieved
- * @see #getNumberOfComments
- */
- public String getComment(int index) {
- if (comments == null || index < 0 || index >= comments.size()) {
- throw new IllegalArgumentException(Messages.getMessage(Messages.INVALID_COMMENT_INDEX,
"" + index));
- }
- return (String)comments.elementAt(index);
- }
-
- /**
- * If {@link #check()} was successful, returns the image format as one
- * of the FORMAT_xyz constants from this class.
- * Use {@link #getFormatName()} to get a textual description of the file format.
- * @return file format as a FORMAT_xyz constant
- */
- public int getFormat() {
- return format;
- }
-
- /**
- * If {@link #check()} was successful, returns the image format's name.
- * Use {@link #getFormat()} to get a unique number.
- * @return file format name
- */
- public String getFormatName() {
- if (format >= 0 && format < FORMAT_NAMES.length) {
- return FORMAT_NAMES[format];
- } else {
- return "?";
- }
- }
-
- /**
- * If {@link #check()} was successful, returns one the image's vertical
- * resolution in pixels.
- * @return image height in pixels
- */
- public int getHeight() {
- return height;
- }
-
- private int getIntBigEndian(byte[] a, int offs) {
- return
- (a[offs] & 0xff) << 24 |
- (a[offs + 1] & 0xff) << 16 |
- (a[offs + 2] & 0xff) << 8 |
- a[offs + 3] & 0xff;
- }
-
- private int getIntLittleEndian(byte[] a, int offs) {
- return
- (a[offs + 3] & 0xff) << 24 |
- (a[offs + 2] & 0xff) << 16 |
- (a[offs + 1] & 0xff) << 8 |
- a[offs] & 0xff;
- }
-
- /**
- * If {@link #check()} was successful, returns a String with the
- * MIME type of the format.
- * @return MIME type, e.g. <code>image/jpeg</code>
- */
- public String getMimeType() {
- if (format >= 0 && format < MIME_TYPE_STRINGS.length) {
- if (format == FORMAT_JPEG && progressive)
- {
- return "image/pjpeg";
- }
- return MIME_TYPE_STRINGS[format];
- } else {
- return null;
- }
- }
-
- /**
- * If {@link #check()} was successful and {@link #setCollectComments(boolean)} was
called with
- * <code>true</code> as argument, returns the number of comments retrieved
- * from the input image stream / file.
- * Any number >= 0 and smaller than this number of comments is then a
- * valid argument for the {@link #getComment(int)} method.
- * @return number of comments retrieved from input image
- */
- public int getNumberOfComments()
- {
- if (comments == null) {
- return 0;
- } else {
- return comments.size();
- }
- }
-
- /**
- * Returns the number of images in the examined file.
- * Assumes that <code>setDetermineImageNumber(true);</code> was called
before
- * a successful call to {@link #check()}.
- * This value can currently be only different from <code>1</code> for GIF
images.
- * @return number of images in file
- */
- public int getNumberOfImages()
- {
- return numberOfImages;
- }
-
- /**
- * Returns the physical height of this image in dots per inch (dpi).
- * Assumes that {@link #check()} was successful.
- * Returns <code>-1</code> on failure.
- * @return physical height (in dpi)
- * @see #getPhysicalWidthDpi()
- * @see #getPhysicalHeightInch()
- */
- public int getPhysicalHeightDpi() {
- return physicalHeightDpi;
- }
-
- /**
- * If {@link #check()} was successful, returns the physical width of this image in dpi
(dots per inch)
- * or -1 if no value could be found.
- * @return physical height (in dpi)
- * @see #getPhysicalHeightDpi()
- * @see #getPhysicalWidthDpi()
- * @see #getPhysicalWidthInch()
- */
- public float getPhysicalHeightInch() {
- int h = getHeight();
- int ph = getPhysicalHeightDpi();
- if (h > 0 && ph > 0) {
- return ((float)h) / ((float)ph);
- } else {
- return -1.0f;
- }
- }
-
- /**
- * If {@link #check()} was successful, returns the physical width of this image in dpi
(dots per inch)
- * or -1 if no value could be found.
- * @return physical width (in dpi)
- * @see #getPhysicalHeightDpi()
- * @see #getPhysicalWidthInch()
- * @see #getPhysicalHeightInch()
- */
- public int getPhysicalWidthDpi() {
- return physicalWidthDpi;
- }
-
- /**
- * Returns the physical width of an image in inches, or
- * <code>-1.0f</code> if width information is not available.
- * Assumes that {@link #check} has been called successfully.
- * @return physical width in inches or <code>-1.0f</code> on failure
- * @see #getPhysicalWidthDpi
- * @see #getPhysicalHeightInch
- */
- public float getPhysicalWidthInch() {
- int w = getWidth();
- int pw = getPhysicalWidthDpi();
- if (w > 0 && pw > 0) {
- return ((float)w) / ((float)pw);
- } else {
- return -1.0f;
- }
- }
-
- private int getShortBigEndian(byte[] a, int offs) {
- return
- (a[offs] & 0xff) << 8 |
- (a[offs + 1] & 0xff);
- }
-
- private int getShortLittleEndian(byte[] a, int offs) {
- return (a[offs] & 0xff) | (a[offs + 1] & 0xff) << 8;
- }
-
- /**
- * If {@link #check()} was successful, returns one the image's horizontal
- * resolution in pixels.
- * @return image width in pixels
- */
- public int getWidth() {
- return width;
- }
-
- /**
- * Returns whether the image is stored in a progressive (also called: interlaced) way.
- * @return true for progressive/interlaced, false otherwise
- */
- public boolean isProgressive()
- {
- return progressive;
- }
-
- /**
- * To use this class as a command line application, give it either
- * some file names as parameters (information on them will be
- * printed to standard output, one line per file) or call
- * it with no parameters. It will then check data given to it
- * via standard input.
- * @param args the program arguments which must be file names
- */
- public static void main(String[] args) {
- ImageInfo imageInfo = new ImageInfo();
- imageInfo.setDetermineImageNumber(true);
- boolean verbose = determineVerbosity(args);
- if (args.length == 0) {
- run(null, System.in, imageInfo, verbose);
- } else {
- int index = 0;
- while (index < args.length) {
- InputStream in = null;
- try {
- String name = args[index++];
- System.out.print(name + ";");
- if (name.startsWith("http://")) {
- in = new URL(name).openConnection().getInputStream();
- } else {
- in = new FileInputStream(name);
- }
- run(name, in, imageInfo, verbose);
- in.close();
- } catch (Exception e) {
- System.out.println(e);
- try {
- in.close();
- } catch (Exception ee) {
- }
- }
- }
- }
- }
-
- private static void print(String sourceName, ImageInfo ii, boolean verbose) {
- if (verbose) {
- printVerbose(sourceName, ii);
- } else {
- printCompact(sourceName, ii);
- }
- }
-
- private static void printCompact(String sourceName, ImageInfo imageInfo) {
- System.out.println(
- imageInfo.getFormatName() + ";" +
- imageInfo.getMimeType() + ";" +
- imageInfo.getWidth() + ";" +
- imageInfo.getHeight() + ";" +
- imageInfo.getBitsPerPixel() + ";" +
- imageInfo.getNumberOfImages() + ";" +
- imageInfo.getPhysicalWidthDpi() + ";" +
- imageInfo.getPhysicalHeightDpi() + ";" +
- imageInfo.getPhysicalWidthInch() + ";" +
- imageInfo.getPhysicalHeightInch() + ";" +
- imageInfo.isProgressive()
- );
- }
-
- private static void printLine(int indentLevels, String text, float value, float
minValidValue) {
- if (value < minValidValue) {
- return;
- }
- printLine(indentLevels, text, Float.toString(value));
- }
-
- private static void printLine(int indentLevels, String text, int value, int
minValidValue) {
- if (value >= minValidValue) {
- printLine(indentLevels, text, Integer.toString(value));
- }
- }
-
- private static void printLine(int indentLevels, String text, String value) {
- if (value == null || value.length() == 0) {
- return;
- }
- while (indentLevels-- > 0) {
- System.out.print("\t");
- }
- if (text != null && text.length() > 0) {
- System.out.print(text);
- System.out.print(" ");
- }
- System.out.println(value);
- }
-
- private static void printVerbose(String sourceName, ImageInfo ii) {
- printLine(0, null, sourceName);
- printLine(1, "File format: ", ii.getFormatName());
- printLine(1, "MIME type: ", ii.getMimeType());
- printLine(1, "Width (pixels): ", ii.getWidth(), 1);
- printLine(1, "Height (pixels): ", ii.getHeight(), 1);
- printLine(1, "Bits per pixel: ", ii.getBitsPerPixel(), 1);
- printLine(1, "Progressive: ", Boolean.toString(ii.isProgressive()));
- printLine(1, "Number of images: ", ii.getNumberOfImages(), 1);
- printLine(1, "Physical width (dpi): ", ii.getPhysicalWidthDpi(), 1);
- printLine(1, "Physical height (dpi): ", ii.getPhysicalHeightDpi(), 1);
- printLine(1, "Physical width (inches): ", ii.getPhysicalWidthInch(), 1.0f);
- printLine(1, "Physical height (inches): ", ii.getPhysicalHeightInch(),
1.0f);
- int numComments = ii.getNumberOfComments();
- printLine(1, "Number of textual comments: ", numComments, 1);
- if (numComments > 0) {
- for (int i = 0; i < numComments; i++) {
- printLine(2, null, ii.getComment(i));
- }
- }
- }
-
- private int read() throws IOException {
- if (in != null) {
- return in.read();
- } else {
- return din.readByte();
- }
- }
-
- private int read(byte[] a) throws IOException {
- if (in != null) {
- return in.read(a);
- } else {
- din.readFully(a);
- return a.length;
- }
- }
-
- private int read(byte[] a, int offset, int num) throws IOException {
- if (in != null) {
- return in.read(a, offset, num);
- } else {
- din.readFully(a, offset, num);
- return num;
- }
- }
-
- private String readLine() throws IOException {
- return readLine(new StringBuffer());
- }
-
- private String readLine(StringBuffer sb) throws IOException {
- boolean finished;
- do {
- int value = read();
- finished = (value == -1 || value == 10);
- if (!finished) {
- sb.append((char)value);
- }
- } while (!finished);
- return sb.toString();
- }
-
- private long readUBits( int numBits ) throws IOException
- {
- if (numBits == 0) {
- return 0;
- }
- int bitsLeft = numBits;
- long result = 0;
- if (bitPos == 0) { //no value in the buffer - read a byte
- if (in != null) {
- bitBuf = in.read();
- } else {
- bitBuf = din.readByte();
- }
- bitPos = 8;
- }
-
- while( true )
- {
- int shift = bitsLeft - bitPos;
- if( shift > 0 )
- {
- // Consume the entire buffer
- result |= bitBuf << shift;
- bitsLeft -= bitPos;
-
- // Get the next byte from the input stream
- if (in != null) {
- bitBuf = in.read();
- } else {
- bitBuf = din.readByte();
- }
- bitPos = 8;
- }
- else
- {
- // Consume a portion of the buffer
- result |= bitBuf >> -shift;
- bitPos -= bitsLeft;
- bitBuf &= 0xff >> (8 - bitPos); // mask off the consumed bits
-
- return result;
- }
- }
- }
-
- /**
- * Read a signed value from the given number of bits
- */
- private int readSBits( int numBits ) throws IOException
- {
- // Get the number as an unsigned value.
- long uBits = readUBits( numBits );
-
- // Is the number negative?
- if( ( uBits & (1L << (numBits - 1))) != 0 )
- {
- // Yes. Extend the sign.
- uBits |= -1L << numBits;
- }
-
- return (int)uBits;
- }
-
- private void synchBits()
- {
- bitBuf = 0;
- bitPos = 0;
- }
-
- private String readLine(int firstChar) throws IOException {
- StringBuffer result = new StringBuffer();
- result.append((char)firstChar);
- return readLine(result);
- }
-
- private static void run(String sourceName, InputStream in, ImageInfo imageInfo, boolean
verbose) {
- imageInfo.setInput(in);
- imageInfo.setDetermineImageNumber(false);
- imageInfo.setCollectComments(verbose);
- if (imageInfo.check()) {
- print(sourceName, imageInfo, verbose);
- }
- }
-
- /**
- * Specify whether textual comments are supposed to be extracted from input.
- * Default is <code>false</code>.
- * If enabled, comments will be added to an internal list.
- * @param newValue if <code>true</code>, this class will read comments
- * @see #getNumberOfComments
- * @see #getComment
- */
- public void setCollectComments(boolean newValue)
- {
- collectComments = newValue;
- }
-
- /**
- * Specify whether the number of images in a file is to be
- * determined - default is <code>false</code>.
- * This is a special option because some file formats require running over
- * the entire file to find out the number of images, a rather time-consuming
- * task.
- * Not all file formats support more than one image.
- * If this method is called with <code>true</code> as argument,
- * the actual number of images can be queried via
- * {@link #getNumberOfImages()} after a successful call to
- * {@link #check()}.
- * @param newValue will the number of images be determined?
- * @see #getNumberOfImages
- */
- public void setDetermineImageNumber(boolean newValue)
- {
- determineNumberOfImages = newValue;
- }
-
- /**
- * Set the input stream to the argument stream (or file).
- * Note that {@link java.io.RandomAccessFile} implements
- * {@link java.io.DataInput}.
- * @param dataInput the input stream to read from
- */
- public void setInput(DataInput dataInput) {
- din = dataInput;
- in = null;
- }
-
- /**
- * Set the input stream to the argument stream (or file).
- * @param inputStream the input stream to read from
- */
- public void setInput(InputStream inputStream) {
- in = inputStream;
- din = null;
- }
-
- private void setPhysicalHeightDpi(int newValue) {
- physicalWidthDpi = newValue;
- }
-
- private void setPhysicalWidthDpi(int newValue) {
- physicalHeightDpi = newValue;
- }
-
- private void skip(int num) throws IOException {
- while (num > 0) {
- long result;
- if (in != null) {
- result = in.skip(num);
- } else {
- result = din.skipBytes(num);
- }
- if (result > 0) {
- num -= result;
- }
- }
- }
-}
Deleted:
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/ImageWaiter.java
===================================================================
---
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/ImageWaiter.java 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/ImageWaiter.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -1,133 +0,0 @@
-/**
- * License Agreement.
- *
- * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/*
- * Helma License Notice
- *
- * The contents of this file are subject to the Helma License
- * Version 2.0 (the "License"). You may not use this file except in
- * compliance with the License. A copy of the License is available at
- *
http://adele.helma.org/download/helma/license.txt
- *
- * Copyright 1998-2003 Helma Software. All Rights Reserved.
- *
- * $RCSfile: ImageWaiter.java,v $
- * $Author: alexsmirnov $
- * $Revision: 1.1.2.1 $
- * $Date: 2007/01/09 18:59:07 $
- */
-
-package org.ajax4jsf.framework.util.image;
-
-import java.awt.Image;
-import java.awt.image.ImageObserver;
-
-import org.ajax4jsf.Messages;
-
-/**
- * The ImageWaiter will only be used like this:
- * image = ImageWaiter.waitForImage(image);
- */
-public class ImageWaiter implements ImageObserver {
- Image image;
- int width;
- int height;
- boolean waiting;
- boolean firstFrameLoaded;
-
- private ImageWaiter(Image image) {
- this.image = image;
- waiting = true;
- firstFrameLoaded = false;
- }
-
- public static Image waitForImage(Image image) {
- ImageWaiter waiter = new ImageWaiter(image);
- try {
- waiter.waitForImage();
- } finally {
- waiter.done();
- }
- return waiter.width == -1 || waiter.height == -1 ? null : image;
- }
-
- private synchronized void waitForImage() {
- width = image.getWidth(this);
- height = image.getHeight(this);
-
- if (width == -1 || height == -1) {
- try {
- wait(45000);
- } catch (InterruptedException x) {
- waiting = false;
- return;
- } finally {
- waiting = false;
- }
- }
-
- // if width and height haven't been set, throw tantrum
- if (width == -1 || height == -1) {
- throw new
RuntimeException(Messages.getMessage(Messages.LOADING_IMAGE_ERROR));
- }
- }
-
- private synchronized void done() {
- waiting = false;
- notifyAll();
- }
-
- public synchronized boolean imageUpdate(Image img, int infoflags, int x,
- int y, int w, int h) {
- // check if there was an error
- if (!waiting || (infoflags & ERROR) > 0 || (infoflags & ABORT) > 0)
{
- // we either timed out or there was an error.
- notifyAll();
-
- return false;
- }
-
- if ((infoflags & WIDTH) > 0 || (infoflags & HEIGHT) > 0) {
- if ((infoflags & WIDTH) > 0) {
- width = w;
- }
-
- if ((infoflags & HEIGHT) > 0) {
- height = h;
- }
-
- if (width > -1 && h > -1 && firstFrameLoaded) {
- notifyAll();
-
- return false;
- }
- }
-
- if ((infoflags & ALLBITS) > 0 || (infoflags & FRAMEBITS) > 0) {
- firstFrameLoaded = true;
- notifyAll();
-
- return false;
- }
-
- return true;
- }
-}
\ No newline at end of file
Deleted:
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/ImageWrapper.java
===================================================================
---
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/ImageWrapper.java 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/ImageWrapper.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -1,531 +0,0 @@
-/**
- * License Agreement.
- *
- * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/*
- * Helma License Notice
- *
- * The contents of this file are subject to the Helma License
- * Version 2.0 (the "License"). You may not use this file except in
- * compliance with the License. A copy of the License is available at
- *
http://adele.helma.org/download/helma/license.txt
- *
- * Copyright 1998-2003 Helma Software. All Rights Reserved.
- *
- * $RCSfile: ImageWrapper.java,v $
- * $Author: alexsmirnov $
- * $Revision: 1.1.2.1 $
- * $Date: 2007/01/09 18:59:05 $
- */
-
-/*
- * A few explanations:
- *
- * - this.image is either an AWT Image or a BufferedImage.
- * It depends on the ImageGenerator in what form the Image initially is.
- * (the ImageIO implementation only uses BufferedImages for example.)
- *
- * As soon as some action that needs the graphics object is performed and the
- * image is still in AWT format, it is converted to a BufferedImage
- *
- * Any internal function that performs graphical actions needs to call
- * getGraphics, never rely on this.graphics being set correctly!
- *
- * - ImageWrapper objects are created and safed by the ImageGenerator class
- * all different implementations of Imaging functionallity are implemented
- * as a ImageGenerator extending class.
- *
- */
-
-package org.ajax4jsf.framework.util.image;
-
-import java.awt.Color;
-import java.awt.Font;
-import java.awt.Graphics;
-import java.awt.Graphics2D;
-import java.awt.Image;
-import java.awt.RenderingHints;
-import java.awt.geom.AffineTransform;
-import java.awt.image.AreaAveragingScaleFilter;
-import java.awt.image.BufferedImage;
-import java.awt.image.ColorModel;
-import java.awt.image.ImageProducer;
-import java.awt.image.IndexColorModel;
-import java.io.IOException;
-
-import org.ajax4jsf.Messages;
-
-/**
- * Abstract base class for Image Wrappers.
- */
-public class ImageWrapper {
- protected Image image;
- protected int width;
- protected int height;
- protected ImageGenerator generator;
- private Graphics2D graphics;
-
- /**
- * Creates a new ImageWrapper object.
- *
- * @param image ...
- * @param width ...
- * @param height ...
- */
- public ImageWrapper(Image image, int width, int height,
- ImageGenerator generator) {
- this.image = image;
- this.width = width;
- this.height = height;
- this.generator = generator;
- // graphics are turned off by default. getGraphics activates it if necessary.
- this.graphics = null;
- }
-
- public ImageWrapper(Image image, ImageGenerator generator) {
- this(image, image.getWidth(null), image.getHeight(null), generator);
- }
-
- /**
- * Converts the internal image object to a BufferedImage (if it's not
- * already) and returns it. this is necessary as not all images are of type
- * BufferedImage. e.g. images loaded from a resource with the Toolkit are
- * not. By using getBufferedImage, images are only converted to a
- * getBufferedImage when this is actually needed, which is better than
- * storing images as BufferedImage in general.
- *
- * @return the Image object as a BufferedImage
- */
- public BufferedImage getBufferedImage() {
- if (!(image instanceof BufferedImage)) {
- BufferedImage buffered = new BufferedImage(width, height,
- BufferedImage.TYPE_INT_ARGB);
- buffered.createGraphics().drawImage(image, 0, 0, null);
- setImage(buffered);
- }
- return (BufferedImage)image;
- }
-
- /**
- * Returns the Graphics object to directly paint to this Image. Converts the
- * internal image to a BufferedImage if necessary.
- *
- * @return the Graphics object for drawing into this image
- */
- public Graphics getGraphics() {
- if (graphics == null) {
- // make sure the image is a BufferedImage and then create a graphics object
- BufferedImage img = getBufferedImage();
- graphics = img.createGraphics();
- }
- return graphics;
- }
-
- /**
- * Sets the internal image and clears the stored graphics object.
- * Any code that is changing the internal image should do it through this function
- * to make sure getGraphcis() returns a valid graphics object the next time it is
called.
- */
- protected void setImage(Image image) {
- this.image = image;
- graphics = null;
- }
-
- /**
- * Creates and returns a copy of this image.
- *
- * @return a clone of this image.
- */
- public Object clone() {
- ImageWrapper wrapper = generator.createImage(this.width,
- this.height);
- wrapper.getGraphics().drawImage(image, 0, 0, null);
- return wrapper;
- }
-
- /**
- * Returns the Image object represented by this ImageWrapper.
- *
- * @return the image object
- */
- public Image getImage() {
- return image;
- }
-
- /**
- * Returns the ImageProducer of the wrapped image
- *
- * @return the images's ImageProducer
- */
- public ImageProducer getSource() {
- return image.getSource();
- }
-
- /**
- * Dispose the Graphics context and null out the image.
- */
- public void dispose() {
- image = null;
- if (graphics != null) {
- graphics.dispose();
- graphics = null;
- }
- }
-
- /**
- * Set the font used to write on this image.
- */
- public void setFont(String name, int style, int size) {
- getGraphics().setFont(new Font(name, style, size));
- }
-
- /**
- * Sets the color used to write/paint to this image.
- *
- * @param red ...
- * @param green ...
- * @param blue ...
- */
- public void setColor(int red, int green, int blue) {
- getGraphics().setColor(new Color(red, green, blue));
- }
-
- /**
- * Sets the color used to write/paint to this image.
- *
- * @param color ...
- */
- public void setColor(int color) {
- getGraphics().setColor(new Color(color));
- }
-
- /**
- * Sets the color used to write/paint to this image.
- *
- * @param color ...
- */
- public void setColor(Color color) {
- getGraphics().setColor(color);
- }
-
- /**
- * Sets the color used to write/paint to this image.
- *
- * @param color ...
- */
- public void setColor(String color) {
- getGraphics().setColor(Color.decode(color));
- }
- /**
- * Draws a string to this image at the given coordinates.
- *
- * @param str ...
- * @param x ...
- * @param y ...
- */
- public void drawString(String str, int x, int y) {
- getGraphics().drawString(str, x, y);
- }
-
- /**
- * Draws a line to this image from x1/y1 to x2/y2.
- *
- * @param x1 ...
- * @param y1 ...
- * @param x2 ...
- * @param y2 ...
- */
- public void drawLine(int x1, int y1, int x2, int y2) {
- getGraphics().drawLine(x1, y1, x2, y2);
- }
-
- /**
- * Draws a rectangle to this image.
- *
- * @param x ...
- * @param y ...
- * @param w ...
- * @param h ...
- */
- public void drawRect(int x, int y, int w, int h) {
- getGraphics().drawRect(x, y, w, h);
- }
-
- /**
- * Draws another image to this image.
- *
- * @param filename ...
- * @param x ...
- * @param y ...
- */
- public void drawImage(String filename, int x, int y)
- throws IOException {
- Image img = generator.read(filename);
- if (img != null)
- getGraphics().drawImage(img, x, y, null);
- }
-
- /**
- * Draws another image to this image.
- *
- * @param filename ...
- * @param x ...
- * @param y ...
- */
- public void drawImage(ImageWrapper image, int x, int y)
- throws IOException {
- getGraphics().drawImage(image.getImage(), x, y, null);
- }
-
- /**
- * Draws a filled rectangle to this image.
- *
- * @param x ...
- * @param y ...
- * @param w ...
- * @param h ...
- */
- public void fillRect(int x, int y, int w, int h) {
- getGraphics().fillRect(x, y, w, h);
- }
-
- /**
- * Returns the width of this image.
- *
- * @return the width of this image
- */
- public int getWidth() {
- return width;
- }
-
- /**
- * Returns the height of this image.
- *
- * @return the height of this image
- */
- public int getHeight() {
- return height;
- }
-
- /**
- * Crops the image.
- *
- * @param x ...
- * @param y ...
- * @param w ...
- * @param h ...
- */
- public void crop(int x, int y, int w, int h) {
- // do not use the CropFilter any longer:
- if (image instanceof BufferedImage) {
- // BufferedImages define their own function for cropping:
- setImage(((BufferedImage)image).getSubimage(x, y, w, h));
- } else {
- // The internal image will be a BufferedImage after this.
- // Simply create it with the cropped dimensions and draw the image into it:
- BufferedImage buffered = new BufferedImage(w, h,
BufferedImage.TYPE_INT_ARGB);
- Graphics2D g2d = buffered.createGraphics();
- g2d.drawImage(image, -x, -y, null);
- g2d.dispose();
- setImage(buffered);
- }
- }
-
- /**
- * resizes the image using the Graphics2D approach
- */
- protected BufferedImage resize(int w, int h, boolean smooth) {
- BufferedImage buffered = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
- Graphics2D g2d = buffered.createGraphics();
-
- g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
- smooth ? RenderingHints.VALUE_INTERPOLATION_BICUBIC :
- RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR
- );
-
- g2d.setRenderingHint(RenderingHints.KEY_RENDERING,
- smooth ? RenderingHints.VALUE_RENDER_QUALITY :
- RenderingHints.VALUE_RENDER_SPEED
- );
-
- AffineTransform at = AffineTransform.getScaleInstance(
- (double) w / width,
- (double) h / height
- );
- g2d.drawImage(image, at, null);
- g2d.dispose();
- return buffered;
- }
-
- /**
- * Resize the image
- *
- * @param w ...
- * @param h ...
- */
-
- public void resize(int w, int h) {
- double factor = Math.max(
- (double) w / width,
- (double) h / height
- );
- // if the image is scaled, used the Graphcis2D method, otherwise use AWT:
- if (factor > 1f) {
- // scalie it with the Graphics2D approach for supperiour quality.
- setImage(resize(w, h, true));
- } else {
- // Area averaging has the best results for shrinking of images:
-
- // as getScaledInstance is asynchronous, the ImageWaiter is needed here too:
- // Image scaled = ImageWaiter.waitForImage(image.getScaledInstance(w, h,
Image.SCALE_AREA_AVERAGING));
- // if (scaled == null)
- // throw new RuntimeException("Image cannot be resized.");
-
- // this version is up to 4 times faster than getScaledInstance:
- ImageFilterOp filter = new ImageFilterOp(new AreaAveragingScaleFilter(w,
h));
- setImage(filter.filter(getBufferedImage(), null));
- }
- width = w;
- height = h;
- }
-
- /**
- * Resize the image, using a fast and cheap algorithm
- *
- * @param w ...
- * @param h ...
- */
- public void resizeFast(int w, int h) {
- image = resize(w, h, false);
- width = w;
- height = h;
- }
-
- /**
- * Reduces the colors used in the image. Necessary before saving as GIF.
- *
- * @param colors colors the number of colors to use, usually <= 256.
- */
- public void reduceColors(int colors) {
- reduceColors(colors, false);
- }
-
- /**
- * Reduces the colors used in the image. Necessary before saving as GIF.
- *
- * @param colors colors the number of colors to use, usually <= 256.
- * @param dither ...
- */
- public void reduceColors(int colors, boolean dither) {
- reduceColors(colors, dither, true);
- }
-
- /**
- * Reduce the colors used in this image. Useful and necessary before saving
- * the image as GIF file.
- *
- * @param colors the number of colors to use, usually <= 256.
- * @param dither ...
- * @param alphaToBitmask ...
- */
-
- public void reduceColors(int colors, boolean dither, boolean alphaToBitmask) {
- setImage(Quantize.process(getBufferedImage(), colors, dither,
- alphaToBitmask));
- }
-
- /**
- * Save the image. Image format is deduced from filename.
- *
- * @param filename ...
- * @throws IOException
- */
- public void saveAs(String filename)
- throws IOException {
- saveAs(filename, -1f, false); // -1 means default quality
- }
-
- /**
- * Saves the image. Image format is deduced from filename.
- *
- * @param filename ...
- * @param quality ...
- * @throws IOException
- */
- public void saveAs(String filename, float quality)
- throws IOException {
- saveAs(filename, quality, false);
- }
-
- /**
- * Saves the image. Image format is deduced from filename.
- *
- * @param filename ...
- * @param quality ...
- * @param alpha ...
- * @throws IOException
- */
- public void saveAs(String filename, float quality, boolean alpha)
- throws IOException {
- generator.write(this, filename, quality, alpha);
- }
-
- /**
- * Sets the palette index of the transparent color for Images with an
- * IndexColorModel. This can be used together with
- * {@link helma.image.ImageWrapper#getPixel}.
- */
- public void setTransparentPixel(int trans) {
- BufferedImage bi = this.getBufferedImage();
- ColorModel cm = bi.getColorModel();
- if (!(cm instanceof IndexColorModel))
- throw new
RuntimeException(Messages.getMessage(Messages.NOT_INDEXED_IMAGE_ERROR));
- IndexColorModel icm = (IndexColorModel) cm;
- int mapSize = icm.getMapSize();
- byte reds[] = new byte[mapSize];
- byte greens[] = new byte[mapSize];
- byte blues[] = new byte[mapSize];
- icm.getReds(reds);
- icm.getGreens(greens);
- icm.getBlues(blues);
- // create the new IndexColorModel with the changed transparentPixel:
- icm = new IndexColorModel(icm.getPixelSize(), mapSize, reds, greens,
- blues, trans);
- // create a new BufferedImage with the new IndexColorModel and the old
- // raster:
- setImage(new BufferedImage(icm, bi.getRaster(), false, null));
- }
-
- /**
- * Returns the pixel at x, y. If the image is indexed, it returns the
- * palette index, otherwise the rgb code of the color is returned.
- *
- * @param x the x coordinate of the pixel
- * @param y the y coordinate of the pixel
- * @return the pixel at x, y
- */
- public int getPixel(int x, int y) {
- BufferedImage bi = this.getBufferedImage();
- if (bi.getColorModel() instanceof IndexColorModel)
- return bi.getRaster().getSample(x, y, 0);
- else
- return bi.getRGB(x, y);
- }
-}
\ No newline at end of file
Deleted:
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/IndexImage.java
===================================================================
---
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/IndexImage.java 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/IndexImage.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -1,886 +0,0 @@
-/**
- * License Agreement.
- *
- * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/*
-
- Copyright 2002-2003 The Apache Software Foundation
-
- 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.
-
- */
-package org.ajax4jsf.framework.util.image;
-
-import java.awt.Graphics2D;
-import java.awt.Point;
-import java.awt.Rectangle;
-import java.awt.RenderingHints;
-import java.awt.image.BufferedImage;
-import java.awt.image.ColorModel;
-import java.awt.image.DataBuffer;
-import java.awt.image.DataBufferInt;
-import java.awt.image.IndexColorModel;
-import java.awt.image.MultiPixelPackedSampleModel;
-import java.awt.image.Raster;
-import java.awt.image.SampleModel;
-import java.awt.image.SinglePixelPackedSampleModel;
-import java.awt.image.WritableRaster;
-import java.util.Iterator;
-import java.util.Vector;
-
-/**
- * This implements an adaptive pallete generator to reduce images to a
- * specified number of colors.
- *
- * Ideally this would also support a better dither option than just
- * the JDK's pattern dither.
- *
- * @author <a href="mailto:deweese@apache.org">Thomas DeWeese</a>
- * @author <a href="mailto:jun@oop-reserch.com">Jun Inamori</a>
- * @version $Id: IndexImage.java,v 1.1.2.1 2007/01/09 18:59:03 alexsmirnov Exp $ */
-public class IndexImage{
-
- /**
- * Used to track a color and the number of pixels of that colors
- */
- private static class Counter {
- public int val;
- public int count=1;
- public Counter(int val) { this.val = val; }
- public boolean add(int val) {
- // See if the value matches us...
- if (this.val != val)
- return false;
- count++;
- return true;
- }
- }
-
- /**
- * Used to define a cube of the colorspace. The cube can be split
- * approximagely in half to generate two cubes.
- */
- private static class Cube {
- int []min={0, 0, 0}, max={255,255,255};
-
- boolean done = false;
-
- Vector []colors = null;
- int count=0;
- static final int RED = 0;
- static final int GRN = 1;
- static final int BLU = 2;
-
- /**
- * Define a new cube.
- * @param colors contains the 3D color histogram to be subdivided
- * @param count the total number of pixels in the 3D histogram.
- */
- public Cube(Vector []colors, int count) {
- this.colors = colors;
- this.count = count;
- }
-
- /**
- * If this returns true then the cube can not be subdivided any
- * further
- */
- public boolean isDone() { return done; }
- /**
- * Splits the cube into two parts. This cube is
- * changed to be one half and the returned cube is the other half.
- * This tries to pick the right channel to split on.
- */
- public Cube split() {
- int dr = max[0]-min[0]+1;
- int dg = max[1]-min[1]+1;
- int db = max[2]-min[2]+1;
- int c0, c1, splitChannel;
-
- // Figure out which axis is the longest and split along
- // that axis (this tries to keep cubes square-ish).
- if (dr >= dg) {
- c0 = GRN;
- if (dr >= db) { splitChannel = RED; c1=BLU; }
- else { splitChannel = BLU; c1=RED; }
- } else if (dg >= db) {
- splitChannel = GRN;
- c0=RED;
- c1=BLU;
- } else {
- splitChannel = BLU;
- c0=RED;
- c1=GRN;
- }
-
- Cube ret;
- ret = splitChannel(splitChannel, c0, c1);
- if (ret != null ) return ret;
-
- ret = splitChannel(c0, splitChannel, c1);
- if (ret != null ) return ret;
-
- ret = splitChannel(c1, splitChannel, c0);
- if (ret != null) return ret;
-
- done = true;
- return null;
- }
-
- /**
- * Splits the image according to the parameters. It tries
- * to find a location where half the pixels are on one side
- * and half the pixels are on the other.
- */
- public Cube splitChannel(int splitChannel, int c0, int c1) {
- if (min[splitChannel] == max[splitChannel]) return null;
-
- int splitSh4 = (2-splitChannel)*4;
- int c0Sh4 = (2-c0)*4;
- int c1Sh4 = (2-c1)*4;
-
- int half = count/2;
- // Each entry is the number of pixels that have that value
- // in the split channel within the cube (so pixels
- // that have that value in the split channel aren't counted
- // if they are outside the cube in the other color channels.
- int counts [] = new int[256];
- int tcount = 0;
-
- // System.out.println("Cube: [" +
- // min[0] + "-" + max[0] + "] [" +
- // min[1] + "-" + max[1] + "] [" +
- // min[2] + "-" + max[2] + "]");
-
- int [] minIdx = {min[0]>>4, min[1]>>4, min[2]>>4};
- int [] maxIdx = {max[0]>>4, max[1]>>4, max[2]>>4};
- int minR=min[0], minG=min[1], minB=min[2];
- int maxR=max[0], maxG=max[1], maxB=max[2];
- int val = 0;
- int [] vals = {0, 0, 0};
- for (int i=minIdx[splitChannel]; i<=maxIdx[splitChannel]; i++) {
- int idx1 = i<<splitSh4;
- for (int j=minIdx[c0]; j<=maxIdx[c0]; j++) {
- int idx2 = idx1 | (j<<c0Sh4);
- for (int k=minIdx[c1]; k<=maxIdx[c1]; k++) {
- int idx = idx2 | (k<<c1Sh4);
- Vector v = colors[idx];
- if (v==null) continue;
- Iterator itr = v.iterator();
- Counter c;
- while (itr.hasNext()) {
- c = (Counter)itr.next();
- val = c.val;
- vals[0] = (val&0xFF0000)>>16;
- vals[1] = (val&0xFF00)>>8;
- vals[2] = (val&0xFF);
- if (((vals[0] >= minR) && (vals[0] <=
maxR))&&
- ((vals[1] >= minG) && (vals[1] <=
maxG))&&
- ((vals[2] >= minB) && (vals[2] <= maxB)))
{
- // The val lies within this cube so count it.
- counts[vals[splitChannel]] += c.count;
- tcount += c.count;
- }
- }
- }
- }
- // We've found the half way point. Note that the
- // rest of counts is not filled out.
- if (tcount >= half) break;
- }
-
- tcount=0;
- int lastAdd=-1;
- // These indicate what the top value for the low cube and
- // the low value of the high cube should be in the split channel
- // (they may not be one off if there are 'dead' spots in the
- // counts array.
- int splitLo=min[splitChannel], splitHi=max[splitChannel];
- for (int i=min[splitChannel]; i<=max[splitChannel]; i++) {
- int c = counts[i];
- if (c == 0) {
- // No counts below this so move up bottom of cube.
- if ((tcount == 0) && (i < max[splitChannel]))
- this.min[splitChannel] = i+1;
- continue;
- }
-
- if (tcount+c < half) {
- lastAdd = i;
- tcount+=c;
- continue;
- }
- if ((half-tcount) <= ((tcount+c)-half)) {
- // Then lastAdd is a better top idx for this then i.
- if (lastAdd == -1) {
- // No lower place to break.
- if (c == this.count) {
- // All pixels are at this value so make min/max
- // reflect that.
- this.max[splitChannel] = i;
- return null; // no split to make.
- } else {
- // There are values about this one so
- // split above.
- splitLo = i;
- splitHi = i+1;
- break;
- }
- }
- splitLo = lastAdd;
- splitHi = i;
- } else {
- if (i == this.max[splitChannel]) {
- if ( c == this.count) {
- // would move min up but that should
- // have happened already.
- return null; // no split to make.
- } else {
- // Would like to break between i and i+1
- // but no i+1 so use lastAdd and i;
- splitLo = lastAdd;
- splitHi = i;
- break;
- }
- }
- // Include c in counts
- tcount += c;
- splitLo = i;
- splitHi = i+1;
- }
- break;
- }
-
- // System.out.println("Split: " + splitChannel + "@"
- // + splitLo + "-"+splitHi +
- // " Count: " + tcount + " of " +
count +
- // " LA: " + lastAdd);
-
- // Create the new cube and update everone's bounds & counts.
- Cube ret = new Cube(colors, tcount);
- this.count = this.count-tcount;
- ret.min[splitChannel] = this.min[splitChannel];
- ret.max[splitChannel] = splitLo;
- this.min[splitChannel] = splitHi;
- ret.min[c0] = this.min[c0];
- ret.max[c0] = this.max[c0];
- ret.min[c1] = this.min[c1];
- ret.max[c1] = this.max[c1];
- return ret;
- }
-
- /**
- * Returns the average color for this cube
- */
- public int averageColor() {
- if (this.count == 0) return 0;
-
- float red=0, grn=0, blu=0;
-
- int minR=min[0], minG=min[1], minB=min[2];
- int maxR=max[0], maxG=max[1], maxB=max[2];
- int [] minIdx = {minR>>4, minG>>4, minB>>4};
- int [] maxIdx = {maxR>>4, maxG>>4, maxB>>4};
- int val, ired, igrn, iblu;
- float weight;
- for (int i=minIdx[0]; i<=maxIdx[0]; i++) {
- int idx1 = i<<8;
- for (int j=minIdx[1]; j<=maxIdx[1]; j++) {
- int idx2 = idx1 | (j<<4);
- for (int k=minIdx[2]; k<=maxIdx[2]; k++) {
- int idx = idx2 | k;
- Vector v = colors[idx];
- if (v==null) continue;
- Iterator itr = v.iterator();
- Counter c;
- while (itr.hasNext()) {
- c = (Counter)itr.next();
- val = c.val;
- ired = (val&0xFF0000)>>16;
- igrn = (val&0x00FF00)>>8;
- iblu = (val&0x0000FF);
- if (((ired >= minR) && (ired <=
maxR))&&
- ((igrn >= minG) && (igrn <=
maxG))&&
- ((iblu >= minB) && (iblu <= maxB))) {
- weight = (c.count/(float)this.count);
- red += (ired*weight);
- grn += (igrn*weight);
- blu += (iblu*weight);
- }
- }
- }
- }
- }
- // System.out.println("RGB: [" + red + ", " +
- // grn + ", " + blu + "]");
- return (((int)(red+0.5))<<16 |
- ((int)(grn+0.5))<<8 |
- ((int)(blu+0.5)));
- }
- }
-
- /**
- * Converts the input image (must be TYPE_INT_RGB or
- * TYPE_INT_ARGB) to an indexed image. Generating an adaptive
- * palette with number of colors specified.
- * @param bi the image to be processed.
- * @param nColors number of colors in the palette
- */
- static public BufferedImage getIndexedImage
- (BufferedImage bi, int nColors) {
- int w=bi.getWidth();
- int h=bi.getHeight();
-
- // Using 4 bits from RG & B.
- Vector [] colors = new Vector[1<<12];
-
- int rgb=0;
- for(int i_w=0; i_w<w; i_w++){
- for(int i_h=0; i_h<h; i_h++){
- rgb=(bi.getRGB(i_w,i_h) & 0xFFFFFF);
- // Get index from high four bits of each component.
- int idx = (((rgb&0xF00000)>>> 12) |
- ((rgb&0x00F000)>>> 8) |
- ((rgb&0x0000F0)>>> 4));
-
- // Get the 'hash vector' for that key.
- Vector v = colors[idx];
- if (v == null) {
- // No colors in this bin yet so create vector and
- // add color.
- v = new Vector();
- v.add(new Counter(rgb));
- colors[idx] = v;
- } else {
- // find our color in the bin or create a counter for it.
- Iterator i = v.iterator();
- while (true) {
- if (i.hasNext()) {
- // try adding our color to each counter...
- if (((Counter)i.next()).add(rgb)) break;
- } else {
- v.add(new Counter(rgb));
- break;
- }
- }
- }
- }
- }
-
- int nCubes=1;
- int fCube=0;
- Cube [] cubes = new Cube[nColors];
- cubes[0] = new Cube(colors, w*h);
-
- while (nCubes < nColors) {
- while (cubes[fCube].isDone()) {
- fCube++;
- if (fCube == nCubes) break;
- }
- if (fCube == nCubes) break;
- Cube c = cubes[fCube];
- Cube nc = c.split();
- if (nc != null) {
- if (nc.count > c.count) {
- Cube tmp = c; c= nc; nc = tmp;
- }
- int j = fCube;
- int cnt = c.count;
- for (int i=fCube+1; i<nCubes; i++) {
- if (cubes[i].count < cnt)
- break;
- cubes[j++] = cubes[i];
- }
- cubes[j++] = c;
-
- cnt = nc.count;
- while (j<nCubes) {
- if (cubes[j].count < cnt)
- break;
- j++;
- }
- for (int i=nCubes; i>j; i--)
- cubes[i] = cubes[i-1];
- cubes[j++] = nc;
- nCubes++;
- }
- }
-
- byte [] r = new byte[nCubes];
- byte [] g = new byte[nCubes];
- byte [] b = new byte[nCubes];
- for (int i=0; i<nCubes; i++) {
- int val = cubes[i].averageColor();
- r[i] = (byte)((val>>16)&0xFF);
- g[i] = (byte)((val>> 8)&0xFF);
- b[i] = (byte)((val )&0xFF);
-
- // System.out.println("Color [" + i + "]: #" +
- // (((val>>16)<16)?"0":"") +
- // Integer.toHexString(val));
- }
- BufferedImage indexed;
-
-
- // The JDK doesn't seem to dither the image correctly if I go
- // below 8bits per pixel. So I dither to an 8bit pallete
- // image that only has nCubes colors. Then I copy the data to
- // a lower bit depth image that I return.
- IndexColorModel icm=new IndexColorModel(8,nCubes,r,g,b);
- indexed =new BufferedImage
- (w, h, BufferedImage.TYPE_BYTE_INDEXED, icm);
- Graphics2D g2d=indexed.createGraphics();
- g2d.setRenderingHint
- (RenderingHints.KEY_DITHERING,
- RenderingHints.VALUE_DITHER_ENABLE);
- g2d.drawImage(bi, 0, 0, null);
- g2d.dispose();
-
-
- int bits;
- for (bits=1; bits <=8; bits++) {
- if ((1<<bits) >= nCubes) break;
- }
- // System.out.println("Bits: " + bits + " Cubes: " +
nCubes);
-
- if (bits > 4)
- // 8 bit image we are done...
- return indexed;
-
- // Create our low bit depth image...
- if (bits ==3) bits = 4;
- ColorModel cm=new IndexColorModel(bits,nCubes,r,g,b);
- SampleModel sm = new MultiPixelPackedSampleModel
- (DataBuffer.TYPE_BYTE, w, h, bits);
- WritableRaster ras = Raster.createWritableRaster
- (sm, new Point(0,0));
-
- // Copy the data to the low bitdepth image.
- bi = indexed;
- indexed = new BufferedImage(cm, ras,
- bi.isAlphaPremultiplied(), null);
- copyData(bi, indexed);
- return indexed;
- }
-
- /**
- * An internal optimized version of copyData designed to work on
- * Integer packed data with a SinglePixelPackedSampleModel. Only
- * the region of overlap between src and dst is copied.
- *
- * Calls to this should be preflighted with is_INT_PACK_Data
- * on both src and dest (requireAlpha can be false).
- *
- * @param src The source of the data
- * @param dst The destination for the data.
- */
- public static void copyData_INT_PACK(Raster src, WritableRaster dst) {
- // System.out.println("Fast copyData");
- int x0 = dst.getMinX();
- if (x0 < src.getMinX()) x0 = src.getMinX();
-
- int y0 = dst.getMinY();
- if (y0 < src.getMinY()) y0 = src.getMinY();
-
- int x1 = dst.getMinX()+dst.getWidth()-1;
- if (x1 > src.getMinX()+src.getWidth()-1)
- x1 = src.getMinX()+src.getWidth()-1;
-
- int y1 = dst.getMinY()+dst.getHeight()-1;
- if (y1 > src.getMinY()+src.getHeight()-1)
- y1 = src.getMinY()+src.getHeight()-1;
-
- int width = x1-x0+1;
- int height = y1-y0+1;
-
- SinglePixelPackedSampleModel srcSPPSM;
- srcSPPSM = (SinglePixelPackedSampleModel)src.getSampleModel();
-
- final int srcScanStride = srcSPPSM.getScanlineStride();
- DataBufferInt srcDB = (DataBufferInt)src.getDataBuffer();
- final int [] srcPixels = srcDB.getBankData()[0];
- final int srcBase =
- (srcDB.getOffset() +
- srcSPPSM.getOffset(x0-src.getSampleModelTranslateX(),
- y0-src.getSampleModelTranslateY()));
-
-
- SinglePixelPackedSampleModel dstSPPSM;
- dstSPPSM = (SinglePixelPackedSampleModel)dst.getSampleModel();
-
- final int dstScanStride = dstSPPSM.getScanlineStride();
- DataBufferInt dstDB = (DataBufferInt)dst.getDataBuffer();
- final int [] dstPixels = dstDB.getBankData()[0];
- final int dstBase =
- (dstDB.getOffset() +
- dstSPPSM.getOffset(x0-dst.getSampleModelTranslateX(),
- y0-dst.getSampleModelTranslateY()));
-
- if ((srcScanStride == dstScanStride) &&
- (srcScanStride == width)) {
- // System.out.println("VERY Fast copyData");
-
- System.arraycopy(srcPixels, srcBase, dstPixels, dstBase,
- width*height);
- } else if (width > 128) {
- int srcSP = srcBase;
- int dstSP = dstBase;
- for (int y=0; y<height; y++) {
- System.arraycopy(srcPixels, srcSP, dstPixels, dstSP, width);
- srcSP += srcScanStride;
- dstSP += dstScanStride;
- }
- } else {
- for (int y=0; y<height; y++) {
- int srcSP = srcBase+y*srcScanStride;
- int dstSP = dstBase+y*dstScanStride;
- for (int x=0; x<width; x++)
- dstPixels[dstSP++] = srcPixels[srcSP++];
- }
- }
- }
-
- public static void copyData_FALLBACK(Raster src, WritableRaster dst) {
- // System.out.println("Fallback copyData");
-
- int x0 = dst.getMinX();
- if (x0 < src.getMinX()) x0 = src.getMinX();
-
- int y0 = dst.getMinY();
- if (y0 < src.getMinY()) y0 = src.getMinY();
-
- int x1 = dst.getMinX()+dst.getWidth()-1;
- if (x1 > src.getMinX()+src.getWidth()-1)
- x1 = src.getMinX()+src.getWidth()-1;
-
- int y1 = dst.getMinY()+dst.getHeight()-1;
- if (y1 > src.getMinY()+src.getHeight()-1)
- y1 = src.getMinY()+src.getHeight()-1;
-
- int width = x1-x0+1;
- int [] data = null;
-
- for (int y = y0; y <= y1 ; y++) {
- data = src.getPixels(x0,y,width,1,data);
- dst.setPixels (x0,y,width,1,data);
- }
- }
-
- /**
- * Copies data from one raster to another. Only the region of
- * overlap between src and dst is copied. <tt>Src</tt> and
- * <tt>Dst</tt> must have compatible SampleModels.
- *
- * @param src The source of the data
- * @param dst The destination for the data.
- */
- public static void copyData(Raster src, WritableRaster dst) {
- if (is_INT_PACK_Data(src.getSampleModel(), false) &&
- is_INT_PACK_Data(dst.getSampleModel(), false)) {
- copyData_INT_PACK(src, dst);
- return;
- }
-
- copyData_FALLBACK(src, dst);
- }
-
- /**
- * Copies data from one bufferedImage to another paying attention
- * to the state of AlphaPreMultiplied.
- *
- * @param src The source
- * @param dst The destination
- */
- public static void
- copyData(BufferedImage src, BufferedImage dst) {
- Rectangle srcRect = new Rectangle(0, 0,
- src.getWidth(), src.getHeight());
- copyData(src, srcRect, dst, new Point(0,0));
- }
-
-
- /**
- * Copies data from one bufferedImage to another paying attention
- * to the state of AlphaPreMultiplied.
- *
- * @param src The source
- * @param srcRect The Rectangle of source data to be copied
- * @param dst The destination
- * @param destP The Place for the upper left corner of srcRect in dst.
- */
- public static void
- copyData(BufferedImage src, Rectangle srcRect,
- BufferedImage dst, Point destP) {
-
- /*
- if (srcCS != dstCS)
- throw new IllegalArgumentException
- ("Images must be in the same ColorSpace in order "+
- "to copy Data between them");
- */
- boolean srcAlpha = src.getColorModel().hasAlpha();
- boolean dstAlpha = dst.getColorModel().hasAlpha();
-
- // System.out.println("Src has: " + srcAlpha +
- // " is: " + src.isAlphaPremultiplied());
- //
- // System.out.println("Dst has: " + dstAlpha +
- // " is: " + dst.isAlphaPremultiplied());
-
- if (srcAlpha == dstAlpha)
- if ((srcAlpha == false) ||
- (src.isAlphaPremultiplied() == dst.isAlphaPremultiplied())) {
- // They match one another so just copy everything...
- copyData(src.getRaster(), dst.getRaster());
- return;
- }
-
- // System.out.println("Using Slow CopyData");
-
- int [] pixel = null;
- Raster srcR = src.getRaster();
- WritableRaster dstR = dst.getRaster();
- int bands = dstR.getNumBands();
-
- int dx = destP.x-srcRect.x;
- int dy = destP.y-srcRect.y;
-
- int w = srcRect.width;
- int x0 = srcRect.x;
- int y0 = srcRect.y;
- int y1 = y0+srcRect.height-1;
-
- if (!srcAlpha) {
- // Src has no alpha dest does so set alpha to 1.0 everywhere.
- // System.out.println("Add Alpha");
- int [] oPix = new int[bands*w];
- int out = (w*bands)-1; // The 2 skips alpha channel
- while(out >= 0) {
- // Fill alpha channel with 255's
- oPix[out] = 255;
- out -= bands;
- }
-
- int b, in;
- for (int y=y0; y<=y1; y++) {
- pixel = srcR.getPixels(x0,y,w,1,pixel);
- in = w*(bands-1)-1;
- out = (w*bands)-2; // The 2 skips alpha channel on last pix
- switch (bands) {
- case 4:
- while(in >= 0) {
- oPix[out--] = pixel[in--];
- oPix[out--] = pixel[in--];
- oPix[out--] = pixel[in--];
- out--;
- }
- break;
- default:
- while(in >= 0) {
- for (b=0; b<bands-1; b++)
- oPix[out--] = pixel[in--];
- out--;
- }
- }
- dstR.setPixels(x0+dx, y+dy, w, 1, oPix);
- }
- } else if (dstAlpha && dst.isAlphaPremultiplied()) {
- // Src and dest have Alpha but we need to multiply it for dst.
- // System.out.println("Mult Case");
- int a, b, alpha, in, fpNorm = (1<<24)/255, pt5 = 1<<23;
- for (int y=y0; y<=y1; y++) {
- pixel = srcR.getPixels(x0,y,w,1,pixel);
- in=bands*w-1;
- switch (bands) {
- case 4:
- while(in >= 0) {
- a = pixel[in];
- if (a == 255)
- in -= 4;
- else {
- in--;
- alpha = fpNorm*a;
- pixel[in] = (pixel[in]*alpha+pt5)>>>24; in--;
- pixel[in] = (pixel[in]*alpha+pt5)>>>24; in--;
- pixel[in] = (pixel[in]*alpha+pt5)>>>24; in--;
- }
- }
- break;
- default:
- while(in >= 0) {
- a = pixel[in];
- if (a == 255)
- in -= bands;
- else {
- in--;
- alpha = fpNorm*a;
- for (b=0; b<bands-1; b++) {
- pixel[in] = (pixel[in]*alpha+pt5)>>>24;
- in--;
- }
- }
- }
- }
- dstR.setPixels(x0+dx, y+dy, w, 1, pixel);
- }
- } else if (dstAlpha && !dst.isAlphaPremultiplied()) {
- // Src and dest have Alpha but we need to divide it out for dst.
- // System.out.println("Div Case");
- int a, b, ialpha, in, fpNorm = 0x00FF0000, pt5 = 1<<15;
- for (int y=y0; y<=y1; y++) {
- pixel = srcR.getPixels(x0,y,w,1,pixel);
- in=(bands*w)-1;
- switch(bands) {
- case 4:
- while(in >= 0) {
- a = pixel[in];
- if ((a <= 0) || (a >= 255))
- in -= 4;
- else {
- in--;
- ialpha = fpNorm/a;
- pixel[in] = (pixel[in]*ialpha+pt5)>>>16; in--;
- pixel[in] = (pixel[in]*ialpha+pt5)>>>16; in--;
- pixel[in] = (pixel[in]*ialpha+pt5)>>>16; in--;
- }
- }
- break;
- default:
- while(in >= 0) {
- a = pixel[in];
- if ((a <= 0) || (a >= 255))
- in -= bands;
- else {
- in--;
- ialpha = fpNorm/a;
- for (b=0; b<bands-1; b++) {
- pixel[in] = (pixel[in]*ialpha+pt5)>>>16;
- in--;
- }
- }
- }
- }
- dstR.setPixels(x0+dx, y+dy, w, 1, pixel);
- }
- } else if (src.isAlphaPremultiplied()) {
- int [] oPix = new int[bands*w];
- // Src has alpha dest does not so unpremult and store...
- // System.out.println("Remove Alpha, Div Case");
- int a, b, ialpha, in, out, fpNorm = 0x00FF0000, pt5 = 1<<15;
- for (int y=y0; y<=y1; y++) {
- pixel = srcR.getPixels(x0,y,w,1,pixel);
- in = (bands+1)*w -1;
- out = (bands*w)-1;
- while(in >= 0) {
- a = pixel[in]; in--;
- if (a > 0) {
- if (a < 255) {
- ialpha = fpNorm/a;
- for (b=0; b<bands; b++)
- oPix[out--] = (pixel[in--]*ialpha+pt5)>>>16;
- } else
- for (b=0; b<bands; b++)
- oPix[out--] = pixel[in--];
- } else {
- in -= bands;
- for (b=0; b<bands; b++)
- oPix[out--] = 255;
- }
- }
- dstR.setPixels(x0+dx, y+dy, w, 1, oPix);
- }
- } else {
- // Src has unpremult alpha, dest does not have alpha,
- // just copy the color channels over.
- Rectangle dstRect = new Rectangle(destP.x, destP.y,
- srcRect.width, srcRect.height);
- for (int b=0; b<bands; b++)
- copyBand(srcR, srcRect, b,
- dstR, dstRect, b);
- }
- }
-
- public static void copyBand(Raster src, int srcBand,
- WritableRaster dst, int dstBand) {
-
- Rectangle sR = src.getBounds();
- Rectangle dR = dst.getBounds();
- Rectangle cpR = sR.intersection(dR);
-
- copyBand(src, cpR, srcBand, dst, cpR, dstBand);
- }
-
- public static void copyBand(Raster src, Rectangle sR, int sBand,
- WritableRaster dst, Rectangle dR, int dBand) {
- int dy = dR.y -sR.y;
- int dx = dR.x -sR.x;
- sR = sR.intersection(src.getBounds());
- dR = dR.intersection(dst.getBounds());
- int width, height;
- if (dR.width < sR.width) width = dR.width;
- else width = sR.width;
- if (dR.height < sR.height) height = dR.height;
- else height = sR.height;
-
- int x = sR.x+dx;
- int [] samples = null;
- for (int y=sR.y; y< sR.y+height; y++) {
- samples = src.getSamples(sR.x, y, width, 1, sBand, samples);
- dst.setSamples(x, y+dy, width, 1, dBand, samples);
- }
- }
-
- public static boolean is_INT_PACK_Data(SampleModel sm,
- boolean requireAlpha) {
-// Check ColorModel is of type DirectColorModel
-if(!(sm instanceof SinglePixelPackedSampleModel)) return false;
-
-// Check transfer type
-if(sm.getDataType() != DataBuffer.TYPE_INT) return false;
-
-SinglePixelPackedSampleModel sppsm;
-sppsm = (SinglePixelPackedSampleModel)sm;
-
-int [] masks = sppsm.getBitMasks();
-if (masks.length == 3) {
-if (requireAlpha) return false;
-} else if (masks.length != 4)
-return false;
-
-if(masks[0] != 0x00ff0000) return false;
-if(masks[1] != 0x0000ff00) return false;
-if(masks[2] != 0x000000ff) return false;
-if ((masks.length == 4) &&
-(masks[3] != 0xff000000)) return false;
-
-return true;
-}
-
-}
Deleted:
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/Quantize.java
===================================================================
---
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/Quantize.java 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/Quantize.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -1,840 +0,0 @@
-/**
- * License Agreement.
- *
- * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/*
- * Helma License Notice
- *
- * The contents of this file are subject to the Helma License
- * Version 2.0 (the "License"). You may not use this file except in
- * compliance with the License. A copy of the License is available at
- *
http://adele.helma.org/download/helma/license.txt
- *
- * Copyright 1998-2003 Helma Software. All Rights Reserved.
- *
- * $RCSfile: Quantize.java,v $
- * $Author: alexsmirnov $
- * $Revision: 1.1.2.1 $
- * $Date: 2007/01/09 18:59:05 $
- */
-
-package org.ajax4jsf.framework.util.image;
-
-import java.awt.image.BufferedImage;
-import java.awt.image.DataBufferByte;
-import java.awt.image.DataBufferInt;
-import java.awt.image.IndexColorModel;
-
-/*
- * @(#)Quantize.java 0.90 9/19/00 Adam Doppelt
- *
- * Modifications by Joerg Lehni:
- *
- * - Support for alpha-channels.
- * - Returns a BufferedImage of TYPE_BYTE_INDEXED with a IndexColorModel.
- * - Dithering of images through helma.image.DiffusionFilterOp by setting
- * the dither parameter to true.
- * - Support for a transparent color, which is correctly rendered by GIFEncoder.
- * All pixels with alpha < 0x80 are converted to this color when the parameter
- * alphaToBitmask is set to true.
- * - Removed the SQUARES lookup tables as multiplications of integer values
- * shouldn't take more than one clock nowadays anyhow.
- */
-
-/**
- * An efficient color quantization algorithm, adapted from the C++
- * implementation quantize.c in <a
- *
href="http://www.imagemagick.org/">ImageMagick</a>. The pixels for
- * an image are placed into an oct tree. The oct tree is reduced in
- * size, and the pixels from the original image are reassigned to the
- * nodes in the reduced tree.<p>
- *
- * Here is the copyright notice from ImageMagick:
- *
- * <pre>
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% Permission is hereby granted, free of charge, to any person obtaining a %
-% copy of this software and associated documentation files ("ImageMagick"),
%
-% to deal in ImageMagick without restriction, including without limitation %
-% the rights to use, copy, modify, merge, publish, distribute, sublicense, %
-% and/or sell copies of ImageMagick, and to permit persons to whom the %
-% ImageMagick is furnished to do so, subject to the following conditions: %
-% %
-% The above copyright notice and this permission notice shall be included in %
-% all copies or substantial portions of ImageMagick. %
-% %
-% The software is provided "as is", without warranty of any kind, express or
%
-% implied, including but not limited to the warranties of merchantability, %
-% fitness for a particular purpose and noninfringement. In no event shall %
-% E. I. du Pont de Nemours and Company be liable for any claim, damages or %
-% other liability, whether in an action of contract, tort or otherwise, %
-% arising from, out of or in connection with ImageMagick or the use or other %
-% dealings in ImageMagick. %
-% %
-% Except as contained in this notice, the name of the E. I. du Pont de %
-% Nemours and Company shall not be used in advertising or otherwise to %
-% promote the sale, use or other dealings in ImageMagick without prior %
-% written authorization from the E. I. du Pont de Nemours and Company. %
-% %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-</pre>
- *
- *
- * @version 0.90 19 Sep 2000
- * @author <a
href="http://www.gurge.com/amd/">Adam Doppelt</a>
- */
-public class Quantize {
-
-/*
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% %
-% %
-% %
-% QQQ U U AAA N N TTTTT IIIII ZZZZZ EEEEE %
-% Q Q U U A A NN N T I ZZ E %
-% Q Q U U AAAAA N N N T I ZZZ EEEEE %
-% Q QQ U U A A N NN T I ZZ E %
-% QQQQ UUU A A N N T IIIII ZZZZZ EEEEE %
-% %
-% %
-% Reduce the Number of Unique Colors in an Image %
-% %
-% %
-% Software Design %
-% John Cristy %
-% July 1992 %
-% %
-% %
-% Copyright 1998 E. I. du Pont de Nemours and Company %
-% %
-% Permission is hereby granted, free of charge, to any person obtaining a %
-% copy of this software and associated documentation files ("ImageMagick"),
%
-% to deal in ImageMagick without restriction, including without limitation %
-% the rights to use, copy, modify, merge, publish, distribute, sublicense, %
-% and/or sell copies of ImageMagick, and to permit persons to whom the %
-% ImageMagick is furnished to do so, subject to the following conditions: %
-% %
-% The above copyright notice and this permission notice shall be included in %
-% all copies or substantial portions of ImageMagick. %
-% %
-% The software is provided "as is", without warranty of any kind, express or
%
-% implied, including but not limited to the warranties of merchantability, %
-% fitness for a particular purpose and noninfringement. In no event shall %
-% E. I. du Pont de Nemours and Company be liable for any claim, damages or %
-% other liability, whether in an action of contract, tort or otherwise, %
-% arising from, out of or in connection with ImageMagick or the use or other %
-% dealings in ImageMagick. %
-% %
-% Except as contained in this notice, the name of the E. I. du Pont de %
-% Nemours and Company shall not be used in advertising or otherwise to %
-% promote the sale, use or other dealings in ImageMagick without prior %
-% written authorization from the E. I. du Pont de Nemours and Company. %
-% %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%
-% Realism in computer graphics typically requires using 24 bits/pixel to
-% generate an image. Yet many graphic display devices do not contain
-% the amount of memory necessary to match the spatial and color
-% resolution of the human eye. The QUANTIZE program takes a 24 bit
-% image and reduces the number of colors so it can be displayed on
-% raster device with less bits per pixel. In most instances, the
-% quantized image closely resembles the original reference image.
-%
-% A reduction of colors in an image is also desirable for image
-% transmission and real-time animation.
-%
-% Function Quantize takes a standard RGB or monochrome images and quantizes
-% them down to some fixed number of colors.
-%
-% For purposes of color allocation, an image is a set of n pixels, where
-% each pixel is a point in RGB space. RGB space is a 3-dimensional
-% vector space, and each pixel, pi, is defined by an ordered triple of
-% red, green, and blue coordinates, (ri, gi, bi).
-%
-% Each primary color component (red, green, or blue) represents an
-% intensity which varies linearly from 0 to a maximum value, cmax, which
-% corresponds to full saturation of that color. Color allocation is
-% defined over a domain consisting of the cube in RGB space with
-% opposite vertices at (0,0,0) and (cmax,cmax,cmax). QUANTIZE requires
-% cmax = 255.
-%
-% The algorithm maps this domain onto a tree in which each node
-% represents a cube within that domain. In the following discussion
-% these cubes are defined by the coordinate of two opposite vertices:
-% The vertex nearest the origin in RGB space and the vertex farthest
-% from the origin.
-%
-% The tree's root node represents the the entire domain, (0,0,0) through
-% (cmax,cmax,cmax). Each lower level in the tree is generated by
-% subdividing one node's cube into eight smaller cubes of equal size.
-% This corresponds to bisecting the parent cube with planes passing
-% through the midpoints of each edge.
-%
-% The basic algorithm operates in three phases: Classification,
-% Reduction, and Assignment. Classification builds a color
-% description tree for the image. Reduction collapses the tree until
-% the number it represents, at most, the number of colors desired in the
-% output image. Assignment defines the output image's color map and
-% sets each pixel's color by reclassification in the reduced tree.
-% Our goal is to minimize the numerical discrepancies between the original
-% colors and quantized colors (quantization error).
-%
-% Classification begins by initializing a color description tree of
-% sufficient depth to represent each possible input color in a leaf.
-% However, it is impractical to generate a fully-formed color
-% description tree in the classification phase for realistic values of
-% cmax. If colors components in the input image are quantized to k-bit
-% precision, so that cmax= 2k-1, the tree would need k levels below the
-% root node to allow representing each possible input color in a leaf.
-% This becomes prohibitive because the tree's total number of nodes is
-% 1 + sum(i=1,k,8k).
-%
-% A complete tree would require 19,173,961 nodes for k = 8, cmax = 255.
-% Therefore, to avoid building a fully populated tree, QUANTIZE: (1)
-% Initializes data structures for nodes only as they are needed; (2)
-% Chooses a maximum depth for the tree as a function of the desired
-% number of colors in the output image (currently log2(colorMap size)).
-%
-% For each pixel in the input image, classification scans downward from
-% the root of the color description tree. At each level of the tree it
-% identifies the single node which represents a cube in RGB space
-% containing the pixel's color. It updates the following data for each
-% such node:
-%
-% n1: Number of pixels whose color is contained in the RGB cube
-% which this node represents;
-%
-% n2: Number of pixels whose color is not represented in a node at
-% lower depth in the tree; initially, n2 = 0 for all nodes except
-% leaves of the tree.
-%
-% Sr, Sg, Sb: Sums of the red, green, and blue component values for
-% all pixels not classified at a lower depth. The combination of
-% these sums and n2 will ultimately characterize the mean color of a
-% set of pixels represented by this node.
-%
-% E: The distance squared in RGB space between each pixel contained
-% within a node and the nodes' center. This represents the quantization
-% error for a node.
-%
-% Reduction repeatedly prunes the tree until the number of nodes with
-% n2 > 0 is less than or equal to the maximum number of colors allowed
-% in the output image. On any given iteration over the tree, it selects
-% those nodes whose E count is minimal for pruning and merges their
-% color statistics upward. It uses a pruning threshold, Ep, to govern
-% node selection as follows:
-%
-% Ep = 0
-% while number of nodes with (n2 > 0) > required maximum number of colors
-% prune all nodes such that E <= Ep
-% Set Ep to minimum E in remaining nodes
-%
-% This has the effect of minimizing any quantization error when merging
-% two nodes together.
-%
-% When a node to be pruned has offspring, the pruning procedure invokes
-% itself recursively in order to prune the tree from the leaves upward.
-% n2, Sr, Sg, and Sb in a node being pruned are always added to the
-% corresponding data in that node's parent. This retains the pruned
-% node's color characteristics for later averaging.
-%
-% For each node, n2 pixels exist for which that node represents the
-% smallest volume in RGB space containing those pixel's colors. When n2
-% > 0 the node will uniquely define a color in the output image. At the
-% beginning of reduction, n2 = 0 for all nodes except a the leaves of
-% the tree which represent colors present in the input image.
-%
-% The other pixel count, n1, indicates the total number of colors
-% within the cubic volume which the node represents. This includes n1 -
-% n2 pixels whose colors should be defined by nodes at a lower level in
-% the tree.
-%
-% Assignment generates the output image from the pruned tree. The
-% outpu t image consists of two parts: (1) A color map, which is an
-% array of color descriptions (RGB triples) for each color present in
-% the output image; (2) A pixel array, which represents each pixel as
-% an index into the color map array.
-%
-% First, the assignment phase makes one pass over the pruned color
-% description tree to establish the image's color map. For each node
-% with n2 > 0, it divides Sr, Sg, and Sb by n2 . This produces the
-% mean color of all pixels that classify no lower than this node. Each
-% of these colors becomes an entry in the color map.
-%
-% Finally, the assignment phase reclassifies each pixel in the pruned
-% tree to identify the deepest node containing the pixel's color. The
-% pixel's value in the pixel array becomes the index of this node's mean
-% color in the color map.
-%
-% With the permission of USC Information Sciences Institute, 4676 Admiralty
-% Way, Marina del Rey, California 90292, this code was adapted from module
-% ALCOLS written by Paul Raveling.
-%
-% The names of ISI and USC are not used in advertising or publicity
-% pertaining to distribution of the software without prior specific
-% written permission from ISI.
-%
-*/
-
- final static boolean QUICK = false;
-
- final static int MAX_RGB = 255;
- final static int MAX_NODES = 266817;
- final static int MAX_TREE_DEPTH = 8;
- final static int MAX_CHILDREN = 16;
-
- /**
- * Reduce the image to the given number of colors. The pixels are reduced in
- * place.
- *
- * @return The new color palette.
- */
- public static BufferedImage process(BufferedImage source, int maxColors,
- boolean dither, boolean alphaToBitmask) {
- int type = source.getType();
- int[] pixels;
- // try to get the direct pixels of the BufferedImage
- // this works for images of type INT_RGB, INT_ARGB and INT_ARGB_PRE
- // for all others, a new array with rgb pixels is created!
- if (type == BufferedImage.TYPE_INT_RGB
- || type == BufferedImage.TYPE_INT_ARGB
- || type == BufferedImage.TYPE_INT_ARGB_PRE) {
- pixels = ((DataBufferInt) source.getRaster().getDataBuffer()).getData();
- } else {
- pixels = source.getRGB(0, 0, source.getWidth(), source.getHeight(), null, 0,
source.getWidth());
- }
- Cube cube = new Cube(source, pixels, maxColors, dither, alphaToBitmask);
- cube.classification();
- cube.reduction();
- return cube.assignment();
- }
-
- static class Cube {
- BufferedImage source;
- int[] pixels;
- int maxColors;
- byte colorMap[][];
-
- Node root;
- int depth;
-
- boolean dither;
- boolean alphaToBitmask;
- boolean addTransparency;
- // firstColor is set to 1 when when addTransparency is true!
- int firstColor = 0;
-
- // counter for the number of colors in the cube. this gets
- // recalculated often.
- int numColors;
-
- // counter for the number of nodes in the tree
- int numNodes;
-
- Cube(BufferedImage source, int[] pixels, int maxColors, boolean dither,
- boolean alphaToBitmask) {
- this.source = source;
- this.pixels = pixels;
- this.maxColors = maxColors;
- this.dither = dither;
- this.alphaToBitmask = alphaToBitmask;
-
- int i = maxColors;
- // tree_depth = log maxColors
- // 4
- for (depth = 1; i != 0; depth++) {
- i /= 4;
- }
- if (depth > 1) {
- --depth;
- }
- if (depth > MAX_TREE_DEPTH) {
- depth = MAX_TREE_DEPTH;
- } else if (depth < 2) {
- depth = 2;
- }
-
- root = new Node(this);
- }
-
- /*
- * Procedure Classification begins by initializing a color description
- * tree of sufficient depth to represent each possible input color in a
- * leaf. However, it is impractical to generate a fully-formed color
- * description tree in the classification phase for realistic values of
- * cmax. If colors components in the input image are quantized to k-bit
- * precision, so that cmax= 2k-1, the tree would need k levels below the
- * root node to allow representing each possible input color in a leaf.
- * This becomes prohibitive because the tree's total number of nodes is
- * 1 + sum(i=1,k,8k).
- *
- * A complete tree would require 19,173,961 nodes for k = 8, cmax = 255.
- * Therefore, to avoid building a fully populated tree, QUANTIZE: (1)
- * Initializes data structures for nodes only as they are needed; (2)
- * Chooses a maximum depth for the tree as a function of the desired
- * number of colors in the output image (currently log2(colorMap size)).
- *
- * For each pixel in the input image, classification scans downward from
- * the root of the color description tree. At each level of the tree it
- * identifies the single node which represents a cube in RGB space
- * containing It updates the following data for each such node:
- *
- * numPixels : Number of pixels whose color is contained in the RGB cube
- * which this node represents;
- *
- * unique : Number of pixels whose color is not represented in a node at
- * lower depth in the tree; initially, n2 = 0 for all nodes except
- * leaves of the tree.
- *
- * totalRed/green/blue : Sums of the red, green, and blue component
- * values for all pixels not classified at a lower depth. The
- * combination of these sums and n2 will ultimately characterize the
- * mean color of a set of pixels represented by this node.
- */
- void classification() {
- addTransparency = false;
- firstColor = 0;
- for (int i = 0; i < pixels.length; i++) {
- int pixel = pixels[i];
- int red = (pixel >> 16) & 0xff;
- int green = (pixel >> 8) & 0xff;
- int blue = (pixel >> 0) & 0xff;
- int alpha = (pixel >> 24) & 0xff;
- if (alphaToBitmask)
- alpha = alpha < 0x80 ? 0 : 0xff;
-
- if (alpha > 0) {
- // a hard limit on the number of nodes in the tree
- if (numNodes > MAX_NODES) {
- // System.out.println("pruning");
- root.pruneLevel();
- --depth;
- }
-
- // walk the tree to depth, increasing the
- // numPixels count for each node
- Node node = root;
- for (int level = 1; level <= depth; ++level) {
- int id = (((red > node.midRed ? 1 : 0) << 0)
- | ((green > node.midGreen ? 1 : 0) << 1)
- | ((blue > node.midBlue ? 1 : 0) << 2) | ((alpha
> node.midAlpha ? 1
- : 0) << 3));
- if (node.children[id] == null) {
- node = new Node(node, id, level);
- } else {
- node = node.children[id];
- }
- node.numPixels++;
- }
-
- ++node.unique;
- node.totalRed += red;
- node.totalGreen += green;
- node.totalBlue += blue;
- node.totalAlpha += alpha;
- } else if (!addTransparency) {
- addTransparency = true;
- numColors++;
- firstColor = 1; // start at 1 as 0 will be the transparent
- // color
- }
- }
- }
-
- /*
- * reduction repeatedly prunes the tree until the number of nodes with
- * unique > 0 is less than or equal to the maximum number of colors
- * allowed in the output image.
- *
- * When a node to be pruned has offspring, the pruning procedure invokes
- * itself recursively in order to prune the tree from the leaves upward.
- * The statistics of the node being pruned are always added to the
- * corresponding data in that node's parent. This retains the pruned
- * node's color characteristics for later averaging.
- */
- void reduction() {
- int threshold = 1;
- while (numColors > maxColors) {
- numColors = firstColor;
- threshold = root.reduce(threshold, Integer.MAX_VALUE);
- }
- }
-
- /**
- * The result of a closest color search.
- */
- static class Search {
- int distance;
- int colorIndex;
- }
-
- /*
- * Procedure assignment generates the output image from the pruned tree.
- * The output image consists of two parts: (1) A color map, which is an
- * array of color descriptions (RGB triples) for each color present in
- * the output image; (2) A pixel array, which represents each pixel as
- * an index into the color map array.
- *
- * First, the assignment phase makes one pass over the pruned color
- * description tree to establish the image's color map. For each node
- * with n2 > 0, it divides Sr, Sg, and Sb by n2. This produces the mean
- * color of all pixels that classify no lower than this node. Each of
- * these colors becomes an entry in the color map.
- *
- * Finally, the assignment phase reclassifies each pixel in the pruned
- * tree to identify the deepest node containing the pixel's color. The
- * pixel's value in the pixel array becomes the index of this node's
- * mean color in the color map.
- */
- BufferedImage assignment() {
- colorMap = new byte[4][numColors];
-
- if (addTransparency) {
- // if a transparency color is added, firstColor was set to 1,
- // so color 0 can be used for this
- colorMap[0][0] = 0;
- colorMap[1][0] = 0;
- colorMap[2][0] = 0;
- colorMap[3][0] = 0;
- }
- numColors = firstColor;
- root.mapColors();
-
- // determine bit depth for palette
- int depth;
- for (depth = 1; depth <= 8; depth++)
- if ((1 << depth) >= numColors)
- break;
-
- // create the right color model, depending on transparency settings:
- IndexColorModel icm;
- if (alphaToBitmask) {
- if (addTransparency)
- icm = new IndexColorModel(depth, numColors, colorMap[0],
- colorMap[1], colorMap[2], 0);
- else
- icm = new IndexColorModel(depth, numColors, colorMap[0],
- colorMap[1], colorMap[2]);
- } else {
- icm = new IndexColorModel(depth, numColors, colorMap[0],
- colorMap[1], colorMap[2], colorMap[3]);
- }
- // create the indexed BufferedImage:
- BufferedImage dest = new BufferedImage(source.getWidth(),
- source.getHeight(), BufferedImage.TYPE_BYTE_INDEXED, icm);
-
- boolean firstOut = true;
- if (dither)
- new DiffusionFilterOp().filter(source, dest);
- else {
- Search search = new Search();
- // convert to indexed color
- byte[] dst = ((DataBufferByte)
dest.getRaster().getDataBuffer()).getData();
-
- for (int i = 0; i < pixels.length; i++) {
- int pixel = pixels[i];
- int red = (pixel >> 16) & 0xff;
- int green = (pixel >> 8) & 0xff;
- int blue = (pixel >> 0) & 0xff;
- int alpha = (pixel >> 24) & 0xff;
-
- if (alphaToBitmask)
- alpha = alpha < 128 ? 0 : 0xff;
-
- // this is super weird: on some systems, transparent pixels are
- // not calculated correctly if the following block is taken out.
- // the bug is very strange, isn't related to the code (compiler
error?)
- // but doesn't allways happen. as soon as it does, though, it
doesn't
- // seem to want to go away.
- // This happened at various times on my two different debian systems
- // and i never found out how to really fix it. the following line
seems to
- // prevent it from happening, but i wonder wether there's a
better way
- // to fix it.
- // it looks as if the command forces alpha to take on correct
values.
- // Until now I only knew of effects like that in quantum
mechanics...
- if (i == 0) {
- String fix = "" + alpha;
- }
-
- if (alpha == 0 && addTransparency) {
- dst[i] = 0; // transparency color is at 0
- } else {
- // walk the tree to find the cube containing that color
- Node node = root;
- for (;;) {
- int id = (((red > node.midRed ? 1 : 0) << 0)
- | ((green > node.midGreen ? 1 : 0) << 1)
- | ((blue > node.midBlue ? 1 : 0) << 2) | ((alpha
> node.midAlpha ? 1
- : 0) << 3));
- if (node.children[id] == null) {
- break;
- }
- node = node.children[id];
- }
-
- if (QUICK) {
- // if QUICK is set, just use that
- // node. Strictly speaking, this isn't
- // necessarily best match.
- dst[i] = (byte) node.colorIndex;
- } else {
- // Find the closest color.
- search.distance = Integer.MAX_VALUE;
- node.parent.closestColor(red, green, blue, alpha,
- search);
- dst[i] = (byte) search.colorIndex;
- }
- }
- }
- }
- return dest;
- }
-
- /**
- * A single Node in the tree.
- */
- static class Node {
- Cube cube;
-
- // parent node
- Node parent;
-
- // children nodes
- Node children[];
- int numChildren;
-
- // our index within our parent
- int id;
- // our level within the tree
- int level;
- // our color midpoint
- int midRed;
- int midGreen;
- int midBlue;
- int midAlpha;
-
- // the pixel count for this node and all children
- int numPixels;
-
- // the pixel count for this node
- int unique;
- // the sum of all pixels contained in this node
- int totalRed;
- int totalGreen;
- int totalBlue;
- int totalAlpha;
-
- // used to build the colorMap
- int colorIndex;
-
- Node(Cube cube) {
- this.cube = cube;
- this.parent = this;
- this.children = new Node[MAX_CHILDREN];
- this.id = 0;
- this.level = 0;
-
- this.numPixels = Integer.MAX_VALUE;
-
- this.midRed = (MAX_RGB + 1) >> 1;
- this.midGreen = (MAX_RGB + 1) >> 1;
- this.midBlue = (MAX_RGB + 1) >> 1;
- this.midAlpha = (MAX_RGB + 1) >> 1;
- }
-
- Node(Node parent, int id, int level) {
- this.cube = parent.cube;
- this.parent = parent;
- this.children = new Node[MAX_CHILDREN];
- this.id = id;
- this.level = level;
-
- // add to the cube
- ++cube.numNodes;
- if (level == cube.depth) {
- ++cube.numColors;
- }
-
- // add to the parent
- ++parent.numChildren;
- parent.children[id] = this;
-
- // figure out our midpoint
- int bi = (1 << (MAX_TREE_DEPTH - level)) >> 1;
- midRed = parent.midRed + ((id & 1) > 0 ? bi : -bi);
- midGreen = parent.midGreen + ((id & 2) > 0 ? bi : -bi);
- midBlue = parent.midBlue + ((id & 4) > 0 ? bi : -bi);
- midAlpha = parent.midAlpha + ((id & 8) > 0 ? bi : -bi);
- }
-
- /**
- * Remove this children node, and make sure our parent absorbs our
- * pixel statistics.
- */
- void pruneChild() {
- --parent.numChildren;
- parent.unique += unique;
- parent.totalRed += totalRed;
- parent.totalGreen += totalGreen;
- parent.totalBlue += totalBlue;
- parent.totalAlpha += totalAlpha;
- parent.children[id] = null;
- --cube.numNodes;
- cube = null;
- parent = null;
- }
-
- /**
- * Prune the lowest layer of the tree.
- */
- void pruneLevel() {
- if (numChildren != 0) {
- for (int id = 0; id < MAX_CHILDREN; id++) {
- if (children[id] != null) {
- children[id].pruneLevel();
- }
- }
- }
- if (level == cube.depth) {
- pruneChild();
- }
- }
-
- /**
- * Remove any nodes that have fewer than threshold pixels. Also, as
- * long as we're walking the tree: - figure out the color with the
- * fewest pixels - recalculate the total number of colors in the
- * tree
- */
- int reduce(int threshold, int nextThreshold) {
- if (numChildren != 0) {
- for (int id = 0; id < MAX_CHILDREN; id++) {
- if (children[id] != null) {
- nextThreshold = children[id].reduce(threshold,
- nextThreshold);
- }
- }
- }
- if (numPixels <= threshold) {
- pruneChild();
- } else {
- if (unique != 0) {
- cube.numColors++;
- }
- if (numPixels < nextThreshold) {
- nextThreshold = numPixels;
- }
- }
- return nextThreshold;
- }
-
- /*
- * mapColors traverses the color cube tree and notes each colorMap
- * entry. A colorMap entry is any node in the color cube tree where
- * the number of unique colors is not zero.
- */
- void mapColors() {
- if (numChildren != 0) {
- for (int id = 0; id < MAX_CHILDREN; id++) {
- if (children[id] != null) {
- children[id].mapColors();
- }
- }
- }
- if (unique != 0) {
- int add = unique >> 1;
- cube.colorMap[0][cube.numColors] = (byte) ((totalRed + add) /
unique);
- cube.colorMap[1][cube.numColors] = (byte) ((totalGreen + add) /
unique);
- cube.colorMap[2][cube.numColors] = (byte) ((totalBlue + add) /
unique);
- cube.colorMap[3][cube.numColors] = (byte) ((totalAlpha + add) /
unique);
- colorIndex = cube.numColors++;
- }
- }
-
- /*
- * ClosestColor traverses the color cube tree at a particular node
- * and determines which colorMap entry best represents the input
- * color.
- */
- void closestColor(int red, int green, int blue, int alpha,
- Search search) {
- if (numChildren != 0) {
- for (int id = 0; id < MAX_CHILDREN; id++) {
- if (children[id] != null) {
- children[id].closestColor(red, green, blue, alpha,
- search);
- }
- }
- }
-
- if (unique != 0) {
- int distance = distance(
- cube.colorMap[0][colorIndex] & 0xff,
- cube.colorMap[1][colorIndex] & 0xff,
- cube.colorMap[2][colorIndex] & 0xff,
- cube.colorMap[3][colorIndex] & 0xff, red, green, blue,
- alpha);
- if (distance < search.distance) {
- search.distance = distance;
- search.colorIndex = colorIndex;
- }
- }
- }
-
- /**
- * Figure out the distance between this node and som color.
- */
- final static int distance(int r1, int g1, int b1, int a1, int r2,
- int g2, int b2, int a2) {
- int da = a1 - a2;
- int dr = r1 - r2;
- int dg = g1 - g2;
- int db = b1 - b2;
-
- return da * da + dr * dr + dg * dg + db * db;
-// return (SQUARES[r1 - r2 + MAX_RGB] +
-// SQUARES[g1 - g2 + MAX_RGB] +
-// SQUARES[b1 - b2 + MAX_RGB] +
-// SQUARES[a1 - a2 + MAX_RGB]);
- }
-
- public String toString() {
- StringBuffer buf = new StringBuffer();
- if (parent == this) {
- buf.append("root");
- } else {
- buf.append("node");
- }
- buf.append(' ');
- buf.append(level);
- buf.append(" [");
- buf.append(midRed);
- buf.append(',');
- buf.append(midGreen);
- buf.append(',');
- buf.append(midBlue);
- buf.append(',');
- buf.append(midAlpha);
- buf.append(']');
- return new String(buf);
- }
- }
- }
-}
\ No newline at end of file
Deleted:
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/RoundGradientContext.java
===================================================================
---
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/RoundGradientContext.java 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/RoundGradientContext.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -1,77 +0,0 @@
-/**
- * License Agreement.
- *
- * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-package org.ajax4jsf.framework.util.image;
-
-import java.awt.Color;
-import java.awt.PaintContext;
-import java.awt.geom.Point2D;
-import java.awt.image.ColorModel;
-import java.awt.image.Raster;
-import java.awt.image.WritableRaster;
-/**
- *
- * TODO: provide English Comments
- *
- *
- */
-public class RoundGradientContext implements PaintContext {
- protected Point2D mPoint;
- protected Point2D mRadius;
- protected Color mC1, mC2;
- public RoundGradientContext(Point2D p, Color c1, Point2D r, Color c2) {
- mPoint = p;
- mC1 = c1;
- mRadius = r;
- mC2 = c2;
- }
- public void dispose() {}
- public ColorModel getColorModel() { return ColorModel.getRGBdefault(); }
- /* The get-Raster() method iterates over each point in the requested rectangle,
- calculating the distance from the center point.
- It calculates a weighting factor, from 0.0 to 1.0, based on the ratio of this
- distance and the radius. */
- public Raster getRaster(int x, int y, int w, int h) {
- WritableRaster raster =
- getColorModel().createCompatibleWritableRaster(w, h);
- int[] data = new int[w * h * 4]; //k=4,
- double radius = mRadius.distance(0, 0);
- for (int j = 0; j < h; j++) {
- for (int i = 0; i < w; i++) {
- double distance = mPoint.distance(x + i, y + j);
-
- double ratio = distance/radius;
- if (ratio > 1.0){
- ratio = 1.0;
- }//if
- int base = (j * w + i) * 4;
- //it simply uses the weighting factor to linearly interpolate between the center
color and the background color
- data[base] = (int)(mC1.getRed() + ratio * (mC2.getRed() - mC1.getRed()));
- data[base + 1] = (int)(mC1.getGreen() + ratio * (mC2.getGreen() -
mC1.getGreen()));
- data[base + 2] = (int)(mC1.getBlue() + ratio * (mC2.getBlue() -
mC1.getBlue()));
- data[base + 3] = (int)(mC1.getAlpha() + ratio * (mC2.getAlpha() -
mC1.getAlpha()));
- }
- }
-
- raster.setPixels(0, 0, w, h, data);
- return raster;
- }
-}
Deleted:
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/RoundGradientPaint.java
===================================================================
---
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/RoundGradientPaint.java 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/RoundGradientPaint.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -1,58 +0,0 @@
-/**
- * License Agreement.
- *
- * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-package org.ajax4jsf.framework.util.image;
-
-import java.awt.Color;
-import java.awt.Paint;
-import java.awt.PaintContext;
-import java.awt.Rectangle;
-import java.awt.RenderingHints;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import java.awt.image.ColorModel;
-
-import org.ajax4jsf.Messages;
-public class RoundGradientPaint implements Paint {
- protected Point2D mPoint;
- protected Point2D mRadius;
- protected Color mPointColor, mBackgroundColor;
- public RoundGradientPaint(double x, double y, Color pointColor,
- Point2D radius, Color backgroundColor) {
- if (radius.distance(0, 0) <= 0) throw new
IllegalArgumentException(Messages.getMessage(Messages.INVALID_RADIUS));
- mPoint = new Point2D.Double(x, y);
- mPointColor = pointColor;
- mRadius = radius;
- mBackgroundColor = backgroundColor;
- }
- public PaintContext createContext(ColorModel cm, Rectangle deviceBounds, Rectangle2D
userBounds,
- AffineTransform xform, RenderingHints hints) {
- Point2D transformedPoint = xform.transform(mPoint, null);
- Point2D transformedRadius = xform.deltaTransform(mRadius, null);
- return new RoundGradientContext(transformedPoint, mPointColor, transformedRadius,
mBackgroundColor);
- }
- public int getTransparency() {
- int a1 = mPointColor.getAlpha();
- int a2 = mBackgroundColor.getAlpha();
- return (((a1 & a2) == 0xff) ? OPAQUE : TRANSLUCENT);
- }
-}
Deleted:
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/SimpleGIFEncoder.java
===================================================================
---
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/SimpleGIFEncoder.java 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/SimpleGIFEncoder.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -1,499 +0,0 @@
-/**
- * License Agreement.
- *
- * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-package org.ajax4jsf.framework.util.image;
-
-import java.awt.AWTException;
-import java.awt.Image;
-import java.awt.image.PixelGrabber;
-import java.io.IOException;
-import java.io.OutputStream;
-
-import org.ajax4jsf.Messages;
-
-/**
- * GIFEncoder is a class which takes an image and saves it to a stream
- * using the GIF file format (<A
- * HREF="http://www.dcs.ed.ac.uk/%7Emxr/gfx/">Graphics Interchange
- * Format</A>). A GIFEncoder
- * is constructed with either an AWT Image (which must be fully
- * loaded) or a set of RGB arrays. The image can be written out with a
- * call to <CODE>Write</CODE>.<P>
- *
- * Three caveats:
- * <UL>
- * <LI>GIFEncoder will convert the image to indexed color upon
- * construction. This will take some time, depending on the size of
- * the image. Also, actually writing the image out (Write) will take
- * time.<P>
- *
- * <LI>The image cannot have more than 256 colors, since GIF is an 8
- * bit format. For a 24 bit to 8 bit quantization algorithm, see
- * Graphics Gems II III.2 by Xialoin Wu. Or check out his <A
- * HREF="http://www.csd.uwo.ca/faculty/wu/cq.c">C
source</A>.<P>
- *
- * <LI>Since the image must be completely loaded into memory,
- * GIFEncoder may have problems with large images. Attempting to
- * encode an image which will not fit into memory will probably
- * result in the following exception:<P>
- * <CODE>java.awt.AWTException: Grabber returned false:
192</CODE><P>
- * </UL><P>
- *
- * GIFEncoder is based upon gifsave.c, which was written and released
- * by:<P>
- * <CENTER>
- * Sverre H. Huseby<BR>
- * Bjoelsengt. 17<BR>
- * N-0468 Oslo<BR>
- * Norway<P>
- *
- * Phone: +47 2 230539<BR>
- * sverrehu(a)ifi.uio.no<P>
- * </CENTER>
- * @version 0.90 21 Apr 1996
- * @author <A
HREF="http://www.cs.brown.edu/people/amd/">Adam
Doppelt</A> */
-public class SimpleGIFEncoder {
- short width_, height_;
- int numColors_;
- byte pixels_[], colors_[];
-
- ScreenDescriptor sd_;
- ImageDescriptor id_;
-
-/**
- * Construct a GIFEncoder. The constructor will convert the image to
- * an indexed color array. <B>This may take some time.</B><P>
- *
- * @param image The image to encode. The image <B>must</B> be
- * completely loaded.
- * @exception AWTException Will be thrown if the pixel grab fails. This
- * can happen if Java runs out of memory. It may also indicate that the image
- * contains more than 256 colors.
- * */
- public SimpleGIFEncoder(Image image) throws AWTException {
- width_ = (short)image.getWidth(null);
- height_ = (short)image.getHeight(null);
-
- int values[] = new int[width_ * height_];
- PixelGrabber grabber = new PixelGrabber(
- image, 0, 0, width_, height_, values, 0, width_);
-
- try {
- if(grabber.grabPixels() != true)
- throw new AWTException(Messages.getMessage(Messages.GRABBER_ERROR,
"" + grabber.status()));
- }
- catch (InterruptedException e) {
- }
-
- byte r[][] = new byte[width_][height_];
- byte g[][] = new byte[width_][height_];
- byte b[][] = new byte[width_][height_];
- int index = 0;
- for (int y = 0; y < height_; ++y)
- for (int x = 0; x < width_; ++x) {
- r[x][y] = (byte)((values[index] >> 16) & 0xFF);
- g[x][y] = (byte)((values[index] >> 8) & 0xFF);
- b[x][y] = (byte)((values[index]) & 0xFF);
- ++index;
- }
- ToIndexedColor(r, g, b);
- }
-
-/**
- * Construct a GIFEncoder. The constructor will convert the image to
- * an indexed color array. <B>This may take some time.</B><P>
- *
- * Each array stores intensity values for the image. In other words,
- * r[x][y] refers to the red intensity of the pixel at column x, row
- * y.<P>
- *
- * @param r An array containing the red intensity values.
- * @param g An array containing the green intensity values.
- * @param b An array containing the blue intensity values.
- *
- * @exception AWTException Will be thrown if the image contains more than
- * 256 colors.
- * */
- public SimpleGIFEncoder(byte r[][], byte g[][], byte b[][]) throws AWTException {
- width_ = (short)(r.length);
- height_ = (short)(r[0].length);
-
- ToIndexedColor(r, g, b);
- }
-
-/**
- * Writes the image out to a stream in the GIF file format. This will
- * be a single GIF87a image, non-interlaced, with no background color.
- * <B>This may take some time.</B><P>
- *
- * @param output The stream to output to. This should probably be a
- * buffered stream.
- *
- * @exception IOException Will be thrown if a write operation fails.
- * */
- public void Write(OutputStream output) throws IOException {
- BitUtils.WriteString(output, "GIF87a");
-
- ScreenDescriptor sd = new ScreenDescriptor(width_, height_,
- numColors_);
- sd.Write(output);
-
- output.write(colors_, 0, colors_.length);
-
- ImageDescriptor id = new ImageDescriptor(width_, height_, ',');
- id.Write(output);
-
- byte codesize = BitUtils.BitsNeeded(numColors_);
- if (codesize == 1)
- ++codesize;
- output.write(codesize);
-
- LZWCompressor.LZWCompress(output, codesize, pixels_);
- output.write(0);
-
- id = new ImageDescriptor((byte)0, (byte)0, ';');
- id.Write(output);
- output.flush();
- }
-
- void ToIndexedColor(byte r[][], byte g[][],
- byte b[][]) throws AWTException {
- pixels_ = new byte[width_ * height_];
- colors_ = new byte[256 * 3];
- int colornum = 0;
- for (int x = 0; x < width_; ++x) {
- for (int y = 0; y < height_; ++y) {
- int search;
- for (search = 0; search < colornum; ++search)
- if (colors_[search * 3] == r[x][y] &&
- colors_[search * 3 + 1] == g[x][y] &&
- colors_[search * 3 + 2] == b[x][y])
- break;
-
- if (search > 255)
- throw new
AWTException(Messages.getMessage(Messages.TOOMANY_COLORS_ERROR));
-
- pixels_[y * width_ + x] = (byte)search;
-
- if (search == colornum) {
- colors_[search * 3] = r[x][y];
- colors_[search * 3 + 1] = g[x][y];
- colors_[search * 3 + 2] = b[x][y];
- ++colornum;
- }
- }
- }
- numColors_ = 1 << BitUtils.BitsNeeded(colornum);
- byte copy[] = new byte[numColors_ * 3];
- System.arraycopy(colors_, 0, copy, 0, numColors_ * 3);
- colors_ = copy;
- }
-
-}
-
-class BitFile {
- OutputStream output_;
- byte buffer_[];
- int index_, bitsLeft_;
-
- public BitFile(OutputStream output) {
- output_ = output;
- buffer_ = new byte[256];
- index_ = 0;
- bitsLeft_ = 8;
- }
-
- public void Flush() throws IOException {
- int numBytes = index_ + (bitsLeft_ == 8 ? 0 : 1);
- if (numBytes > 0) {
- output_.write(numBytes);
- output_.write(buffer_, 0, numBytes);
- buffer_[0] = 0;
- index_ = 0;
- bitsLeft_ = 8;
- }
- }
-
- public void WriteBits(int bits, int numbits) throws IOException {
- int bitsWritten = 0;
- int numBytes = 255;
- do {
- if ((index_ == 254 && bitsLeft_ == 0) || index_ > 254) {
- output_.write(numBytes);
- output_.write(buffer_, 0, numBytes);
-
- buffer_[0] = 0;
- index_ = 0;
- bitsLeft_ = 8;
- }
-
- if (numbits <= bitsLeft_) {
- buffer_[index_] |= (bits & ((1 << numbits) - 1)) <<
- (8 - bitsLeft_);
- bitsWritten += numbits;
- bitsLeft_ -= numbits;
- numbits = 0;
- }
- else {
- buffer_[index_] |= (bits & ((1 << bitsLeft_) - 1)) <<
- (8 - bitsLeft_);
- bitsWritten += bitsLeft_;
- bits >>= bitsLeft_;
- numbits -= bitsLeft_;
- buffer_[++index_] = 0;
- bitsLeft_ = 8;
- }
- } while (numbits != 0);
- }
-}
-
-class LZWStringTable {
- private final static int RES_CODES = 2;
- private final static short HASH_FREE = (short)0xFFFF;
- private final static short NEXT_FIRST = (short)0xFFFF;
- private final static int MAXBITS = 12;
- private final static int MAXSTR = (1 << MAXBITS);
- private final static short HASHSIZE = 9973;
- private final static short HASHSTEP = 2039;
-
- byte strChr_[];
- short strNxt_[];
- short strHsh_[];
- short numStrings_;
-
- public LZWStringTable() {
- strChr_ = new byte[MAXSTR];
- strNxt_ = new short[MAXSTR];
- strHsh_ = new short[HASHSIZE];
- }
-
- public int AddCharString(short index, byte b) {
- int hshidx;
-
- if (numStrings_ >= MAXSTR)
- return 0xFFFF;
-
- hshidx = Hash(index, b);
- while (strHsh_[hshidx] != HASH_FREE)
- hshidx = (hshidx + HASHSTEP) % HASHSIZE;
-
- strHsh_[hshidx] = numStrings_;
- strChr_[numStrings_] = b;
- strNxt_[numStrings_] = (index != HASH_FREE) ? index : NEXT_FIRST;
-
- return numStrings_++;
- }
-
- public short FindCharString(short index, byte b) {
- int hshidx, nxtidx;
-
- if (index == HASH_FREE)
- return b;
-
- hshidx = Hash(index, b);
- while ((nxtidx = strHsh_[hshidx]) != HASH_FREE) {
- if (strNxt_[nxtidx] == index && strChr_[nxtidx] == b)
- return (short)nxtidx;
- hshidx = (hshidx + HASHSTEP) % HASHSIZE;
- }
-
- return (short)0xFFFF;
- }
-
- public void ClearTable(int codesize) {
- numStrings_ = 0;
-
- for (int q = 0; q < HASHSIZE; q++) {
- strHsh_[q] = HASH_FREE;
- }
-
- int w = (1 << codesize) + RES_CODES;
- for (int q = 0; q < w; q++)
- AddCharString((short)0xFFFF, (byte)q);
- }
-
- static public int Hash(short index, byte lastbyte) {
- return ((int)((short)(lastbyte << 8) ^ index) & 0xFFFF) % HASHSIZE;
- }
-}
-
-class LZWCompressor {
-
- public static void LZWCompress(OutputStream output, int codesize,
- byte toCompress[]) throws IOException {
- byte c;
- short index;
- int clearcode, endofinfo, numbits, limit, errcode;
- short prefix = (short)0xFFFF;
-
- BitFile bitFile = new BitFile(output);
- LZWStringTable strings = new LZWStringTable();
-
- clearcode = 1 << codesize;
- endofinfo = clearcode + 1;
-
- numbits = codesize + 1;
- limit = (1 << numbits) - 1;
-
- strings.ClearTable(codesize);
- bitFile.WriteBits(clearcode, numbits);
-
- for (int loop = 0; loop < toCompress.length; ++loop) {
- c = toCompress[loop];
- if ((index = strings.FindCharString(prefix, c)) != -1)
- prefix = index;
- else {
- bitFile.WriteBits(prefix, numbits);
- if (strings.AddCharString(prefix, c) > limit) {
- if (++numbits > 12) {
- bitFile.WriteBits(clearcode, numbits - 1);
- strings.ClearTable(codesize);
- numbits = codesize + 1;
- }
- limit = (1 << numbits) - 1;
- }
-
- prefix = (short)((short)c & 0xFF);
- }
- }
-
- if (prefix != -1)
- bitFile.WriteBits(prefix, numbits);
-
- bitFile.WriteBits(endofinfo, numbits);
- bitFile.Flush();
- }
-}
-
-class ScreenDescriptor {
- public short localScreenWidth_, localScreenHeight_;
- private byte byte_;
- public byte backgroundColorIndex_, pixelAspectRatio_;
-
- public ScreenDescriptor(short width, short height, int numColors) {
- localScreenWidth_ = width;
- localScreenHeight_ = height;
- SetGlobalColorTableSize((byte)(BitUtils.BitsNeeded(numColors) - 1));
- SetGlobalColorTableFlag((byte)1);
- SetSortFlag((byte)0);
- SetColorResolution((byte)7);
- backgroundColorIndex_ = 0;
- pixelAspectRatio_ = 0;
- }
-
- public void Write(OutputStream output) throws IOException {
- BitUtils.WriteWord(output, localScreenWidth_);
- BitUtils.WriteWord(output, localScreenHeight_);
- output.write(byte_);
- output.write(backgroundColorIndex_);
- output.write(pixelAspectRatio_);
- }
-
- public void SetGlobalColorTableSize(byte num) {
- byte_ |= (num & 7);
- }
-
- public void SetSortFlag(byte num) {
- byte_ |= (num & 1) << 3;
- }
-
- public void SetColorResolution(byte num) {
- byte_ |= (num & 7) << 4;
- }
-
- public void SetGlobalColorTableFlag(byte num) {
- byte_ |= (num & 1) << 7;
- }
-}
-
-class ImageDescriptor {
- public byte separator_;
- public short leftPosition_, topPosition_, width_, height_;
- private byte byte_;
-
- public ImageDescriptor(short width, short height, char separator) {
- separator_ = (byte)separator;
- leftPosition_ = 0;
- topPosition_ = 0;
- width_ = width;
- height_ = height;
- SetLocalColorTableSize((byte)0);
- SetReserved((byte)0);
- SetSortFlag((byte)0);
- SetInterlaceFlag((byte)0);
- SetLocalColorTableFlag((byte)0);
- }
-
- public void Write(OutputStream output) throws IOException {
- output.write(separator_);
- BitUtils.WriteWord(output, leftPosition_);
- BitUtils.WriteWord(output, topPosition_);
- BitUtils.WriteWord(output, width_);
- BitUtils.WriteWord(output, height_);
- output.write(byte_);
- }
-
- public void SetLocalColorTableSize(byte num) {
- byte_ |= (num & 7);
- }
-
- public void SetReserved(byte num) {
- byte_ |= (num & 3) << 3;
- }
-
- public void SetSortFlag(byte num) {
- byte_ |= (num & 1) << 5;
- }
-
- public void SetInterlaceFlag(byte num) {
- byte_ |= (num & 1) << 6;
- }
-
- public void SetLocalColorTableFlag(byte num) {
- byte_ |= (num & 1) << 7;
- }
-}
-
-class BitUtils {
- public static byte BitsNeeded(int n) {
- byte ret = 1;
-
- if (n-- == 0)
- return 0;
-
- while ((n >>= 1) != 0)
- ++ret;
-
- return ret;
- }
-
- public static void WriteWord(OutputStream output,
- short w) throws IOException {
- output.write(w & 0xFF);
- output.write((w >> 8) & 0xFF);
- }
-
- static void WriteString(OutputStream output,
- String string) throws IOException {
- for (int loop = 0; loop < string.length(); ++loop)
- output.write((byte)(string.charAt(loop)));
- }
-}
\ No newline at end of file
Deleted:
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/imageio/ImageIOGenerator.java
===================================================================
---
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/imageio/ImageIOGenerator.java 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/framework/impl/src/main/java/org/ajax4jsf/framework/util/image/imageio/ImageIOGenerator.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -1,175 +0,0 @@
-/**
- * License Agreement.
- *
- * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/*
- * Helma License Notice
- *
- * The contents of this file are subject to the Helma License
- * Version 2.0 (the "License"). You may not use this file except in
- * compliance with the License. A copy of the License is available at
- *
http://adele.helma.org/download/helma/license.txt
- *
- * Copyright 1998-2003 Helma Software. All Rights Reserved.
- *
- * $RCSfile: ImageIOGenerator.java,v $
- * $Author: alexsmirnov $
- * $Revision: 1.1.2.1 $
- * $Date: 2007/01/09 19:00:17 $
- */
-
-/*
- * ImageIOGenerator defines it's own functions for reading from various
- * resources. These return BufferedImages, therefore all the images
- * are from the beginning in that format when working with ImageIO
- */
-
-package org.ajax4jsf.framework.util.image.imageio;
-
-import java.awt.Image;
-import java.awt.image.BufferedImage;
-import java.awt.image.DirectColorModel;
-import java.awt.image.WritableRaster;
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.IOException;
-import java.net.URL;
-import java.util.Iterator;
-
-import javax.imageio.IIOImage;
-import javax.imageio.ImageIO;
-import javax.imageio.ImageWriteParam;
-import javax.imageio.ImageWriter;
-import javax.imageio.stream.ImageOutputStream;
-
-import org.ajax4jsf.framework.util.image.ImageGenerator;
-import org.ajax4jsf.framework.util.image.ImageWrapper;
-
-
-
-/**
- * A wrapper for an image that uses the ImageIO Framework.
- */
-public class ImageIOGenerator extends ImageGenerator {
- /**
- * @param filename the filename of the image to create
- *
- * @return the newly created image
- * @throws IOException
- */
- public Image read(String filename)
- throws IOException {
- return ImageIO.read(new File(filename));
- }
-
- /**
- * @param url the URL the filename of the image to create
- *
- * @return the newly created image
- * @throws IOException
- */
- public Image read(URL url)
- throws IOException {
- return ImageIO.read(url);
- }
-
- /**
- * @param src the data of the image to create
- *
- * @return the newly created image
- * @throws IOException
- */
- public Image read(byte[] src)
- throws IOException {
- return ImageIO.read(new ByteArrayInputStream(src));
- }
-
- /**
- * Saves the image. Image format is deduced from filename.
- *
- * @param filename ...
- * @param quality ...
- * @param alpha ...
- * @throws IOException
- * @see helma.image.ImageGenerator#write(helma.image.ImageWrapper, java.lang.String,
float, boolean)
- */
- public void write(ImageWrapper wrapper, String filename, float quality, boolean
alpha) throws IOException {
- int pos = filename.lastIndexOf('.');
- if (pos != -1) {
- String extension = filename.substring(pos + 1,
- filename.length()).toLowerCase();
-
- // Find a writer for that file extensions
- ImageWriter writer = null;
- Iterator iter = ImageIO.getImageWritersByFormatName(extension);
- if (iter.hasNext())
- writer = (ImageWriter) iter.next();
- if (writer != null) {
- ImageOutputStream ios = null;
- try {
- BufferedImage bi = wrapper.getBufferedImage();
- // Prepare output file
- File file = new File(filename);
- if (file.exists())
- file.delete();
- ios = ImageIO.createImageOutputStream(file);
- writer.setOutput(ios);
- // Set some parameters
- ImageWriteParam param = writer.getDefaultWriteParam();
- if (param.canWriteCompressed() &&
- quality >= 0.0 && quality <= 1.0) {
- param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
- param.setCompressionQuality(quality);
- }
- if (param.canWriteProgressive())
- param.setProgressiveMode(ImageWriteParam.MODE_DISABLED);
- // if bi has type ARGB and alpha is false, we have to tell the writer
to not use the alpha channel:
- // this is especially needed for jpeg files where imageio seems to
produce wrong jpeg files right now...
- if (bi.getType() == BufferedImage.TYPE_INT_ARGB
- && !alpha) {
- // create a new BufferedImage that uses a WritableRaster of bi,
with all the bands except the alpha band:
- WritableRaster raster = bi.getRaster();
- WritableRaster newRaster = raster.createWritableChild(
- 0, 0, wrapper.getWidth(), wrapper.getHeight(),
- 0, 0, new int[] {0, 1, 2 }
- );
- // create a ColorModel that represents the one of the ARGB except
the alpha channel:
- DirectColorModel cm = (DirectColorModel) bi.getColorModel();
- DirectColorModel newCM = new DirectColorModel(
- cm.getPixelSize(), cm.getRedMask(),
- cm.getGreenMask(), cm.getBlueMask());
- // now create the new buffer that is used ot write the image:
- BufferedImage rgbBuffer = new BufferedImage(newCM,
- newRaster, false, null);
- writer.write(null, new IIOImage(rgbBuffer, null,
- null), param);
- } else {
- writer.write(null, new IIOImage(bi, null, null),
- param);
- }
- } finally {
- if (ios != null)
- ios.close();
- writer.dispose();
- }
- }
- }
-}
-}
\ No newline at end of file
Modified: trunk/framework/impl/src/main/java/org/ajax4jsf/resource/GifRenderer.java
===================================================================
--- trunk/framework/impl/src/main/java/org/ajax4jsf/resource/GifRenderer.java 2007-07-10
18:39:35 UTC (rev 1587)
+++ trunk/framework/impl/src/main/java/org/ajax4jsf/resource/GifRenderer.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -26,8 +26,7 @@
import java.io.DataOutputStream;
import java.io.IOException;
-import org.ajax4jsf.framework.util.image.GIFEncoder;
-import org.ajax4jsf.resource.ResourceContext;
+import org.ajax4jsf.resource.image.GIFEncoder;
/**
* @author asmirnov(a)exadel.com (latest modification by $Author: alexsmirnov $)
Added:
trunk/framework/impl/src/main/java/org/ajax4jsf/resource/image/DiffusionFilterOp.java
===================================================================
--- trunk/framework/impl/src/main/java/org/ajax4jsf/resource/image/DiffusionFilterOp.java
(rev 0)
+++
trunk/framework/impl/src/main/java/org/ajax4jsf/resource/image/DiffusionFilterOp.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -0,0 +1,268 @@
+/**
+ * License Agreement.
+ *
+ * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
+ *
+ * Copyright (C) 2007 Exadel, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/*
+ * Helma License Notice
+ *
+ * The contents of this file are subject to the Helma License
+ * Version 2.0 (the "License"). You may not use this file except in
+ * compliance with the License. A copy of the License is available at
+ *
http://adele.helma.org/download/helma/license.txt
+ *
+ * Copyright 1998-2003 Helma Software. All Rights Reserved.
+ *
+ * $RCSfile: DiffusionFilterOp.java,v $
+ * $Author: alexsmirnov $
+ * $Revision: 1.1.2.1 $
+ * $Date: 2007/01/09 18:59:06 $
+ */
+
+/*
+ * Code from com.jhlabs.image.DiffusionFilter, Java Image Processing
+ * Copyright (C) Jerry Huxtable 1998
+ *
http://www.jhlabs.com/ip/
+ *
+ * Conversion to a BufferedImageOp inspired by:
+ *
http://www.peter-cockerell.net:8080/java/FloydSteinberg/FloydSteinbergFil...
+ *
+ */
+
+package org.ajax4jsf.resource.image;
+
+import java.awt.RenderingHints;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+import java.awt.image.BufferedImageOp;
+import java.awt.image.ColorModel;
+import java.awt.image.DataBufferByte;
+import java.awt.image.DataBufferInt;
+import java.awt.image.IndexColorModel;
+
+import org.ajax4jsf.Messages;
+
+public class DiffusionFilterOp implements BufferedImageOp {
+
+ protected final static int[] diffusionMatrix = {
+ 0, 0, 0,
+ 0, 0, 7,
+ 3, 5, 1,
+ };
+
+ private int[] matrix;
+ private int sum;
+ private boolean serpentine = true;
+ private int[] colorMap;
+
+ /**
+ * Construct a DiffusionFilter
+ */
+ public DiffusionFilterOp() {
+ setMatrix(diffusionMatrix);
+ }
+
+ /**
+ * Set whether to use a serpentine pattern for return or not. This can reduce
'avalanche' artifacts in the output.
+ * @param serpentine true to use serpentine pattern
+ */
+ public void setSerpentine(boolean serpentine) {
+ this.serpentine = serpentine;
+ }
+
+ /**
+ * Return the serpentine setting
+ * @return the current setting
+ */
+ public boolean getSerpentine() {
+ return serpentine;
+ }
+
+ public void setMatrix(int[] matrix) {
+ this.matrix = matrix;
+ sum = 0;
+ for (int i = 0; i < matrix.length; i++)
+ sum += matrix[i];
+ }
+
+ public int[] getMatrix() {
+ return matrix;
+ }
+
+ /**
+ * Do the filter operation
+ *
+ * @param src The source BufferedImage. Can be any type.
+ * @param dst The destination image. If not null, must be of type TYPE_BYTE_INDEXED
+ * @return A dithered version of src in a BufferedImage of type TYPE_BYTE_INDEXED
+ */
+ public BufferedImage filter(BufferedImage src, BufferedImage dst) {
+
+ // If there's no dest. create one
+ if (dst == null)
+ dst = createCompatibleDestImage(src, null);
+
+ // Otherwise check that the provided dest is an indexed image
+ else if (dst.getType() != BufferedImage.TYPE_BYTE_INDEXED) {
+ throw new
IllegalArgumentException(Messages.getMessage(Messages.BUFFER_TYPE_ERROR));
+ }
+
+ DataBufferByte dstBuffer = (DataBufferByte) dst.getRaster().getDataBuffer();
+ byte dstData[] = dstBuffer.getData();
+
+ // Other things to test are pixel bit strides, scanline stride and transfer type
+ // Same goes for the source image
+
+ IndexColorModel icm = (IndexColorModel) dst.getColorModel();
+ colorMap = new int[icm.getMapSize()];
+ icm.getRGBs(colorMap);
+
+ int width = src.getWidth();
+ int height = src.getHeight();
+
+ DataBufferInt srcBuffer = (DataBufferInt) src.getRaster().getDataBuffer();
+ int srcData[] = srcBuffer.getData();
+
+ // This is the offset into the buffer of the current source pixel
+ int index = 0;
+
+ // Loop through each pixel
+ for (int y = 0; y < height; y++) {
+ boolean reverse = serpentine && (y & 1) == 1;
+ int direction;
+ if (reverse) {
+ index = y * width + width - 1;
+ direction = -1;
+ } else {
+ index = y * width;
+ direction = 1;
+ }
+ for (int x = 0; x < width; x++) {
+ int rgb1 = srcData[index];
+ int a1 = (rgb1 >> 24) & 0xff;
+ int r1 = (rgb1 >> 16) & 0xff;
+ int g1 = (rgb1 >> 8) & 0xff;
+ int b1 = rgb1 & 0xff;
+
+ int idx = findIndex(r1, g1, b1, a1);
+ dstData[index] = (byte) idx;
+
+ int rgb2 = colorMap[idx];
+ int a2 = (rgb2 >> 24) & 0xff;
+ int r2 = (rgb2 >> 16) & 0xff;
+ int g2 = (rgb2 >> 8) & 0xff;
+ int b2 = rgb2 & 0xff;
+
+ int er = r1 - r2;
+ int eg = g1 - g2;
+ int eb = b1 - b2;
+ int ea = a1 - a2;
+
+ for (int i = -1; i <= 1; i++) {
+ int iy = i + y;
+ if (0 <= iy && iy < height) {
+ for (int j = -1; j <= 1; j++) {
+ int jx = j + x;
+ if (0 <= jx && jx < width) {
+ int w;
+ if (reverse)
+ w = matrix[(i + 1) * 3 - j + 1];
+ else
+ w = matrix[(i + 1) * 3 + j + 1];
+ if (w != 0) {
+ int k = reverse ? index - j : index + j;
+ rgb1 = srcData[k];
+ a1 = ((rgb1 >> 24) & 0xff) + ea * w / sum;
+ r1 = ((rgb1 >> 16) & 0xff) + er * w / sum;
+ g1 = ((rgb1 >> 8) & 0xff) + eg * w / sum;
+ b1 = (rgb1 & 0xff) + eb * w / sum;
+
+ srcData[k] = ((clamp(a1) << 24) | clamp(r1)
<< 16)
+ | (clamp(g1) << 8) | clamp(b1);
+ }
+ }
+ }
+ }
+ }
+ index += direction;
+ }
+ }
+
+ return dst;
+ }
+
+ private static int clamp(int c) {
+ if (c < 0)
+ return 0;
+ if (c > 255)
+ return 255;
+ return c;
+ }
+
+ int findIndex(int r1, int g1, int b1, int a1)
+ throws ArrayIndexOutOfBoundsException {
+ int idx = 0;
+ long dist = Long.MAX_VALUE;
+ for (int i = 0; i < colorMap.length; i++) {
+ int rgb2 = colorMap[i];
+ int a2 = (rgb2 >> 24) & 0xff;
+ int r2 = (rgb2 >> 16) & 0xff;
+ int g2 = (rgb2 >> 8) & 0xff;
+ int b2 = rgb2 & 0xff;
+
+ int da = a1 - a2;
+ int dr = r1 - r2;
+ int dg = g1 - g2;
+ int db = b1 - b2;
+
+ long newdist = da * da + dr * dr + dg * dg + db * db;
+ if (newdist < dist) {
+ idx = i;
+ dist = newdist;
+ }
+ }
+ return idx;
+ }
+
+ // This always returns an indexed image
+ public BufferedImage createCompatibleDestImage(BufferedImage src,
+ ColorModel destCM) {
+ return new BufferedImage(src.getWidth(), src.getHeight(),
+ BufferedImage.TYPE_BYTE_INDEXED);
+ }
+
+ // There are no rendering hints
+ public RenderingHints getRenderingHints() {
+ return null;
+ }
+
+ // No transformation, so return the source point
+ public Point2D getPoint2D(Point2D srcPt, Point2D dstPt) {
+ if (dstPt == null)
+ dstPt = new Point2D.Float();
+ dstPt.setLocation(srcPt.getX(), srcPt.getY());
+ return dstPt;
+ }
+
+ // No transformation, so return the source bounds
+ public Rectangle2D getBounds2D(BufferedImage src) {
+ return src.getRaster().getBounds();
+ }
+}
\ No newline at end of file
Added: trunk/framework/impl/src/main/java/org/ajax4jsf/resource/image/GIFEncoder.java
===================================================================
--- trunk/framework/impl/src/main/java/org/ajax4jsf/resource/image/GIFEncoder.java
(rev 0)
+++
trunk/framework/impl/src/main/java/org/ajax4jsf/resource/image/GIFEncoder.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -0,0 +1,554 @@
+/**
+ * License Agreement.
+ *
+ * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
+ *
+ * Copyright (C) 2007 Exadel, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/*
+ * Helma License Notice
+ *
+ * The contents of this file are subject to the Helma License
+ * Version 2.0 (the "License"). You may not use this file except in
+ * compliance with the License. A copy of the License is available at
+ *
http://adele.helma.org/download/helma/license.txt
+ *
+ * Copyright 1998-2003 Helma Software. All Rights Reserved.
+ *
+ * $RCSfile: GIFEncoder.java,v $
+ * $Author: alexsmirnov $
+ * $Revision: 1.1.2.1 $
+ * $Date: 2007/01/09 18:59:03 $
+ */
+
+/*
+ * The GIF encoding routines are based on the Acme libary
+ *
+ * The following addaptions and extensions were added by Joerg Lehni:
+ *
+ * - encode now directly works on BufferedImage objects, the ImageEncoder
+ * and ImageConsumer oriented frameworks has been removed.
+ * - Only BufferedImages with IndexColorModel are taken, so no more
+ * palette optimization with IntHashtable objects are necessary. If the
+ * BufferedImage is in wrong format, helma.image.Quantizie is used to
+ * convert it into a index based image.
+ * - This version is much less space consuming as it only takes one sample
+ * row of the rastered image at a time into memory during compression.
+ * - The overall time for color reduction and gif compression should
+ * therefore be greatly reduced.
+ *
+ * Acme Disclaimer:
+ *
+ * Transparency handling and variable bit size courtesy of Jack Palevich.
+ *
+ * Copyright (C)1996,1998 by Jef Poskanzer <jef(a)acme.com>. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Visit the ACME Labs Java page for up-to-date versions of this and other
+ * fine Java utilities:
http://www.acme.com/java/
+ *
+ * GifEncoder is adapted from ppmtogif, which is based on GIFENCOD by David
+ * Rowley <mgardi(a)watdscu.waterloo.edu>. Lempel-Zim compression
+ * based on "compress".
+ *
+ */
+
+package org.ajax4jsf.resource.image;
+
+import java.awt.image.BufferedImage;
+import java.awt.image.IndexColorModel;
+import java.awt.image.Raster;
+import java.io.DataOutput;
+import java.io.IOException;
+
+public class GIFEncoder {
+ private boolean interlace = false;
+
+ private int width, height;
+ private Raster raster;
+ // DataOutput is used for compatibility with ImageIO (see
helma.image.imageio.gif.GIFImageWriter)
+ // otherwise, OutputStream would make much more sense here:
+ private DataOutput out;
+
+ private int curx, cury;
+ private int countdown;
+ private int pass;
+ private int[] row;
+
+ public void encode(BufferedImage bi, DataOutput out) throws IOException {
+ encode(bi, out, false, null);
+ }
+
+ public void encode(BufferedImage bi, DataOutput out, boolean interlace,
+ String comment) throws IOException {
+ this.out = out;
+ this.interlace = interlace;
+
+ // make sure it's index colors:
+ if (bi.getType() != BufferedImage.TYPE_BYTE_INDEXED)
+ bi = Quantize.process(bi, 256, false, true);
+
+ raster = bi.getRaster();
+
+ width = bi.getWidth();
+ height = bi.getHeight();
+
+ int numPixels = width * height;
+
+ IndexColorModel icm = (IndexColorModel) bi.getColorModel();
+ int transparentIndex = icm.getTransparentPixel();
+ int numColors = icm.getMapSize();
+
+ // Figure out how many bits to use.
+ int bitsPerPixel;
+ if (numColors <= 2)
+ bitsPerPixel = 1;
+ else if (numColors <= 4)
+ bitsPerPixel = 2;
+ else if (numColors <= 16)
+ bitsPerPixel = 4;
+ else
+ bitsPerPixel = 8;
+
+ int initCodeSize;
+
+ // Calculate number of bits we are expecting
+ countdown = numPixels;
+
+ // Indicate which pass we are on (if interlace)
+ pass = 0;
+
+ // The initial code size
+ if (bitsPerPixel <= 1)
+ initCodeSize = 2;
+ else
+ initCodeSize = bitsPerPixel;
+
+ // Set up the current x and y position
+ curx = 0;
+ cury = 0;
+ row = new int[width];
+
+ // Write the Magic header
+ writeString("GIF89a");
+
+ // Write out the screen width and height
+ writeWord(width);
+ writeWord(height);
+
+ // Indicate that there is a global colour map
+ byte flags = (byte) 0x80; // Yes, there is a color map
+ // OR in the resolution
+ flags |= (byte) ((8 - 1) << 4);
+ // Not sorted
+ // OR in the Bits per Pixel
+ flags |= (byte) ((bitsPerPixel - 1));
+ // Write it out
+ out.write(flags);
+
+ // Write out the Background colour
+ out.write((byte) 0);
+
+ // Pixel aspect ratio - 1:1.
+ //out.write((byte) 49);
+ // Java's GIF reader currently has a bug, if the aspect ratio byte is
+ // not zero it throws an ImageFormatException. It doesn't know that
+ // 49 means a 1:1 aspect ratio. Well, whatever, zero works with all
+ // the other decoders I've tried so it probably doesn't hurt.
+ out.write((byte) 0);
+
+ // Write out the Global Colour Map
+ // Turn colors into colormap entries.
+ int mapSize = 1 << bitsPerPixel;
+ byte[] reds = new byte[mapSize], greens = new byte[mapSize], blues = new
byte[mapSize];
+ icm.getReds(reds);
+ icm.getGreens(greens);
+ icm.getBlues(blues);
+
+ for (int i = 0; i < mapSize; ++i) {
+ out.write(reds[i]);
+ out.write(greens[i]);
+ out.write(blues[i]);
+ }
+
+ // Write out extension for transparent colour index, if necessary.
+ if (transparentIndex != -1) {
+ out.write((byte) '!');
+ out.write((byte) 0xf9);
+ out.write((byte) 4);
+ out.write((byte) 1);
+ out.write((byte) 0);
+ out.write((byte) 0);
+ out.write((byte) transparentIndex);
+ out.write((byte) 0);
+ }
+
+ // Write an Image separator
+ out.write((byte) ',');
+
+ // Write the Image header
+ writeWord(0); // leftOfs
+ writeWord(0); // topOfs
+ writeWord(width);
+ writeWord(height);
+
+ // Write out whether or not the image is interlaced
+ if (interlace)
+ out.write((byte) 0x40);
+ else
+ out.write((byte) 0x00);
+
+ // Write out the initial code size
+ out.write((byte) initCodeSize);
+
+ // Go and actually compress the data
+ compress(initCodeSize + 1);
+
+ // Write out a Zero-length packet (to end the series)
+ out.write((byte) 0);
+
+ // Write out the comment
+ if (comment != null && comment.length() > 0) {
+ out.write((byte) 0x21);
+ out.write((byte) 0xFE);
+ out.write((byte) comment.length());
+ writeString(comment);
+ out.write((byte) 0);
+ }
+
+ // Write the GIF file terminator
+ out.write((byte) ';');
+ }
+
+ // Return the next pixel from the image
+ int getNextPixel() throws IOException {
+ if (countdown == 0)
+ return -1;
+
+ --countdown;
+
+ if (curx == 0)
+ row = raster.getSamples(0, cury, width, 1, 0, row);
+ int index = row[curx];
+
+ // Bump the current X position
+ ++curx;
+
+ // If we are at the end of a scan line, set curx back to the beginning
+ // If we are interlaced, bump the cury to the appropriate spot,
+ // otherwise, just increment it.
+ if (curx == width) {
+ curx = 0;
+
+ if (!interlace) {
+ ++cury;
+ } else {
+ switch (pass) {
+ case 0:
+ cury += 8;
+ if (cury >= height) {
+ ++pass;
+ cury = 4;
+ }
+ break;
+
+ case 1:
+ cury += 8;
+ if (cury >= height) {
+ ++pass;
+ cury = 2;
+ }
+ break;
+
+ case 2:
+ cury += 4;
+ if (cury >= height) {
+ ++pass;
+ cury = 1;
+ }
+ break;
+
+ case 3:
+ cury += 2;
+ break;
+ }
+ }
+ }
+ return index;
+ }
+
+ void writeString(String str) throws IOException {
+ byte[] buf = str.getBytes();
+ out.write(buf);
+ }
+
+ // Write out a word to the GIF file
+ void writeWord(int w) throws IOException {
+ out.write((byte) (w & 0xff));
+ out.write((byte) ((w >> 8) & 0xff));
+ }
+
+ // GIFCOMPR.C - GIF Image compression routines
+ //
+ // Lempel-Ziv compression based on 'compress'. GIF modifications by
+ // David Rowley (mgardi(a)watdcsu.waterloo.edu)
+
+ // General DEFINEs
+
+ static final int BITS = 12;
+
+ static final int HASH_SIZE = 5003; // 80% occupancy
+
+ // GIF Image compression - modified 'compress'
+ //
+ // Based on: compress.c - File compression ala IEEE Computer, June 1984.
+ //
+ // By Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas)
+ // Jim McKie (decvax!mcvax!jim)
+ // Steve Davies (decvax!vax135!petsd!peora!srd)
+ // Ken Turkowski (decvax!decwrl!turtlevax!ken)
+ // James A. Woods (decvax!ihnp4!ames!jaw)
+ // Joe Orost (decvax!vax135!petsd!joe)
+
+ private int numBits; // number of bits/code
+ private int maxBits = BITS; // user settable max # bits/code
+ private int maxCode; // maximum code, given numBits
+ private int maxMaxCode = 1 << BITS; // should NEVER generate this code
+
+ final int getMaxCode(int numBits) {
+ return (1 << numBits) - 1;
+ }
+
+ private int[] hashTable = new int[HASH_SIZE];
+ private int[] codeTable = new int[HASH_SIZE];
+
+ private int freeEntry = 0; // first unused entry
+
+ // block compression parameters -- after all codes are used up,
+ // and compression rate changes, start over.
+ private boolean clearFlag = false;
+
+ // Algorithm: use open addressing double hashing (no chaining) on the
+ // prefix code / next character combination. We do a variant of Knuth's
+ // algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
+ // secondary probe. Here, the modular division first probe is gives way
+ // to a faster exclusive-or manipulation. Also do block compression with
+ // an adaptive reset, whereby the code table is cleared when the compression
+ // ratio decreases, but after the table fills. The variable-length output
+ // codes are re-sized at this point, and a special CLEAR code is generated
+ // for the decompressor. Late addition: construct the table according to
+ // file size for noticeable speed improvement on small files. Please direct
+ // questions about this implementation to ames!jaw.
+
+ private int initBits;
+
+ private int clearCode;
+ private int EOFCode;
+
+ void compress(int initBits) throws IOException {
+ // Set up the globals: initBits - initial number of bits
+ this.initBits = initBits;
+
+ // Set up the necessary values
+ clearFlag = false;
+ numBits = initBits;
+ maxCode = getMaxCode(numBits);
+
+ clearCode = 1 << (initBits - 1);
+ EOFCode = clearCode + 1;
+ freeEntry = clearCode + 2;
+
+ charInit();
+
+ int ent = getNextPixel();
+
+ int hashShift = 0;
+ for (int fcode = HASH_SIZE; fcode < 65536; fcode *= 2)
+ ++hashShift;
+ hashShift = 8 - hashShift; // set hash code range bound
+
+ clearHash(); // clear hash table
+
+ output(clearCode);
+
+ int c;
+ outerLoop: while ((c = getNextPixel()) != -1) {
+ int fcode = (c << maxBits) + ent;
+ int i = (c << hashShift) ^ ent; // xor hashing
+
+ if (hashTable[i] == fcode) {
+ ent = codeTable[i];
+ continue;
+ } else if (hashTable[i] >= 0) { // non-empty slot
+ int disp = HASH_SIZE - i; // secondary hash (after G. Knott)
+ if (i == 0)
+ disp = 1;
+ do {
+ if ((i -= disp) < 0)
+ i += HASH_SIZE;
+
+ if (hashTable[i] == fcode) {
+ ent = codeTable[i];
+ continue outerLoop;
+ }
+ } while (hashTable[i] >= 0);
+ }
+ output(ent);
+ ent = c;
+ if (freeEntry < maxMaxCode) {
+ codeTable[i] = freeEntry++; // code -> hashtable
+ hashTable[i] = fcode;
+ } else
+ clearBlock();
+ }
+ // Put out the final code.
+ output(ent);
+ output(EOFCode);
+ }
+
+ // output
+ //
+ // Output the given code.
+ // Inputs:
+ // code: A numBits-bit integer. If == -1, then EOF. This assumes
+ // that numBits =< wordsize - 1.
+ // Outputs:
+ // Outputs code to the file.
+ // Assumptions:
+ // Chars are 8 bits long.
+ // Algorithm:
+ // Maintain a BITS character long buffer (so that 8 codes will
+ // fit in it exactly). Use the VAX insv instruction to insert each
+ // code in turn. When the buffer fills up empty it and start over.
+
+ int curAccum = 0;
+ int curBits = 0;
+
+ int masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F,
+ 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF,
+ 0x7FFF, 0xFFFF };
+
+ void output(int code) throws IOException {
+ curAccum &= masks[curBits];
+
+ if (curBits > 0)
+ curAccum |= (code << curBits);
+ else
+ curAccum = code;
+
+ curBits += numBits;
+
+ while (curBits >= 8) {
+ charOut((byte) (curAccum & 0xff));
+ curAccum >>= 8;
+ curBits -= 8;
+ }
+
+ // If the next entry is going to be too big for the code size,
+ // then increase it, if possible.
+ if (freeEntry > maxCode || clearFlag) {
+ if (clearFlag) {
+ maxCode = getMaxCode(numBits = initBits);
+ clearFlag = false;
+ } else {
+ ++numBits;
+ if (numBits == maxBits)
+ maxCode = maxMaxCode;
+ else
+ maxCode = getMaxCode(numBits);
+ }
+ }
+
+ if (code == EOFCode) {
+ // At EOF, write the rest of the buffer.
+ while (curBits > 0) {
+ charOut((byte) (curAccum & 0xff));
+ curAccum >>= 8;
+ curBits -= 8;
+ }
+
+ charFlush();
+ }
+ }
+
+ // Clear out the hash table
+
+ // table clear for block compress
+ void clearBlock() throws IOException {
+ clearHash();
+ freeEntry = clearCode + 2;
+ clearFlag = true;
+
+ output(clearCode);
+ }
+
+ // reset code table
+ void clearHash() {
+ for (int i = 0; i < HASH_SIZE; ++i)
+ hashTable[i] = -1;
+ }
+
+ // GIF Specific routines
+
+ // Number of characters so far in this 'packet'
+ private int a_count;
+
+ // Set up the 'byte output' routine
+ void charInit() {
+ a_count = 0;
+ }
+
+ // Define the storage for the packet accumulator
+ private byte[] accum = new byte[256];
+
+ // Add a character to the end of the current packet, and if it is 254
+ // characters, flush the packet to disk.
+ void charOut(byte c) throws IOException {
+ accum[a_count++] = c;
+ if (a_count >= 254)
+ charFlush();
+ }
+
+ // Flush the packet to disk, and reset the accumulator
+ void charFlush() throws IOException {
+ if (a_count > 0) {
+ out.write(a_count);
+ out.write(accum, 0, a_count);
+ a_count = 0;
+ }
+ }
+}
\ No newline at end of file
Added: trunk/framework/impl/src/main/java/org/ajax4jsf/resource/image/ImageInfo.java
===================================================================
--- trunk/framework/impl/src/main/java/org/ajax4jsf/resource/image/ImageInfo.java
(rev 0)
+++
trunk/framework/impl/src/main/java/org/ajax4jsf/resource/image/ImageInfo.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -0,0 +1,1309 @@
+/**
+ * License Agreement.
+ *
+ * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
+ *
+ * Copyright (C) 2007 Exadel, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/*
+ * ImageInfo.java
+ *
+ * Version 1.5
+ *
+ * A Java class to determine image width, height and color depth for
+ * a number of image file formats.
+ *
+ * Written by Marco Schmidt
+ * <
http://www.geocities.com/marcoschmidt.geo/contact.html>.
+ *
+ * Contributed to the Public Domain.
+ *
+ * Last modification 2004-02-29
+ */
+
+package org.ajax4jsf.resource.image;
+
+import java.io.DataInput;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Vector;
+
+import org.ajax4jsf.Messages;
+
+/**
+ * Get file format, image resolution, number of bits per pixel and optionally
+ * number of images, comments and physical resolution from
+ * JPEG, GIF, BMP, PCX, PNG, IFF, RAS, PBM, PGM, PPM, PSD and SWF files
+ * (or input streams).
+ * <p>
+ * Use the class like this:
+ * <pre>
+ * ImageInfo ii = new ImageInfo();
+ * ii.setInput(in); // in can be InputStream or RandomAccessFile
+ * ii.setDetermineImageNumber(true); // default is false
+ * ii.setCollectComments(true); // default is false
+ * if (!ii.check()) {
+ * System.err.println("Not a supported image file format.");
+ * return;
+ * }
+ * System.out.println(ii.getFormatName() + ", " + ii.getMimeType() +
+ * ", " + ii.getWidth() + " x " + ii.getHeight() + " pixels,
" +
+ * ii.getBitsPerPixel() + " bits per pixel, " + ii.getNumberOfImages() +
+ * " image(s), " + ii.getNumberOfComments() + " comment(s).");
+ * // there are other properties, check out the API documentation
+ * </pre>
+ * You can also use this class as a command line program.
+ * Call it with a number of image file names and URLs as parameters:
+ * <pre>
+ * java ImageInfo *.jpg *.png *.gif
http://somesite.tld/image.jpg
+ * </pre>
+ * or call it without parameters and pipe data to it:
+ * <pre>
+ * java ImageInfo < image.jpg
+ * </pre>
+ * <p>
+ * Known limitations:
+ * <ul>
+ * <li>When the determination of the number of images is turned off, GIF bits
+ * per pixel are only read from the global header.
+ * For some GIFs, local palettes change this to a typically larger
+ * value. To be certain to get the correct color depth, call
+ * setDetermineImageNumber(true) before calling check().
+ * The complete scan over the GIF file will take additional time.</li>
+ * <li>Transparency information is not included in the bits per pixel count.
+ * Actually, it was my decision not to include those bits, so it's a feature!
;-)</li>
+ * </ul>
+ * <p>
+ * Requirements:
+ * <ul>
+ * <li>Java 1.1 or higher</li>
+ * </ul>
+ * <p>
+ * The latest version can be found at <a
href="http://www.geocities.com/marcoschmidt.geo/image-info.html"...;.
+ * <p>
+ * Written by <a
href="http://www.geocities.com/marcoschmidt.geo/contact.html"&g...
Schmidt</a>.
+ * <p>
+ * This class is contributed to the Public Domain.
+ * Use it at your own risk.
+ * <p>
+ * Last modification 2004-02-29.
+ * <p>
+ * History:
+ * <ul>
+ * <li><strong>2001-08-24</strong> Initial version.</li>
+ * <li><strong>2001-10-13</strong> Added support for the file formats
BMP and PCX.</li>
+ * <li><strong>2001-10-16</strong> Fixed bug in read(int[], int, int)
that returned
+ * <li><strong>2002-01-22</strong> Added support for file formats Amiga
IFF and Sun Raster (RAS).</li>
+ * <li><strong>2002-01-24</strong> Added support for file formats
Portable Bitmap / Graymap / Pixmap (PBM, PGM, PPM) and Adobe Photoshop (PSD).
+ * Added new method getMimeType() to return the MIME type associated with a particular
file format.</li>
+ * <li><strong>2002-03-15</strong> Added support to recognize number of
images in file. Only works with GIF.
+ * Use {@link #setDetermineImageNumber} with <code>true</code> as argument
to identify animated GIFs
+ * ({@link #getNumberOfImages()} will return a value larger than
<code>1</code>).</li>
+ * <li><strong>2002-04-10</strong> Fixed a bug in the feature
'determine number of images in animated GIF' introduced with version 1.1.
+ * Thanks to Marcelo P. Lima for sending in the bug report.
+ * Released as 1.1.1.</li>
+ * <li><strong>2002-04-18</strong> Added {@link
#setCollectComments(boolean)}.
+ * That new method lets the user specify whether textual comments are to be
+ * stored in an internal list when encountered in an input image file / stream.
+ * Added two methods to return the physical width and height of the image in dpi:
+ * {@link #getPhysicalWidthDpi()} and {@link #getPhysicalHeightDpi()}.
+ * If the physical resolution could not be retrieved, these methods return
<code>-1</code>.
+ * </li>
+ * <li><strong>2002-04-23</strong> Added support for the new properties
physical resolution and
+ * comments for some formats. Released as 1.2.</li>
+ * <li><strong>2002-06-17</strong> Added support for SWF, sent in by
Michael Aird.
+ * Changed checkJpeg() so that other APP markers than APP0 will not lead to a failure
anymore.
+ * Released as 1.3.</li>
+ * <li><strong>2003-07-28</strong> Bug fix - skip method now takes
return values into consideration.
+ * Less bytes than necessary may have been skipped, leading to flaws in the retrieved
information in some cases.
+ * Thanks to Bernard Bernstein for pointing that out.
+ * Released as 1.4.</li>
+ * <li><strong>2004-02-29</strong> Added support for recognizing
progressive JPEG and
+ * interlaced PNG and GIF. A new method {@link #isProgressive()} returns whether
ImageInfo
+ * has found that the storage type is progressive (or interlaced).
+ * Thanks to Joe Germuska for suggesting the feature.
+ * Bug fix: BMP physical resolution is now correctly determined.
+ * Released as 1.5.</li>
+ * </ul>
+ */
+public class ImageInfo {
+ /**
+ * Return value of {@link #getFormat()} for JPEG streams.
+ * ImageInfo can extract physical resolution and comments
+ * from JPEGs (only from APP0 headers).
+ * Only one image can be stored in a file.
+ * It is determined whether the JPEG stream is progressive
+ * (see {@link #isProgressive()}).
+ */
+ public static final int FORMAT_JPEG = 0;
+
+ /**
+ * Return value of {@link #getFormat()} for GIF streams.
+ * ImageInfo can extract comments from GIFs and count the number
+ * of images (GIFs with more than one image are animations).
+ * If you know of a place where GIFs store the physical resolution
+ * of an image, please
+ * <a
href="http://www.geocities.com/marcoschmidt.geo/contact.html"&g...
me a mail</a>!
+ * It is determined whether the GIF stream is interlaced (see {@link
#isProgressive()}).
+ */
+ public static final int FORMAT_GIF = 1;
+
+ /**
+ * Return value of {@link #getFormat()} for PNG streams.
+ * PNG only supports one image per file.
+ * Both physical resolution and comments can be stored with PNG,
+ * but ImageInfo is currently not able to extract those.
+ * It is determined whether the PNG stream is interlaced (see {@link
#isProgressive()}).
+ */
+ public static final int FORMAT_PNG = 2;
+
+ /**
+ * Return value of {@link #getFormat()} for BMP streams.
+ * BMP only supports one image per file.
+ * BMP does not allow for comments.
+ * The physical resolution can be stored.
+ */
+ public static final int FORMAT_BMP = 3;
+
+ /**
+ * Return value of {@link #getFormat()} for PCX streams.
+ * PCX does not allow for comments or more than one image per file.
+ * However, the physical resolution can be stored.
+ */
+ public static final int FORMAT_PCX = 4;
+
+ /**
+ * Return value of {@link #getFormat()} for IFF streams.
+ */
+ public static final int FORMAT_IFF = 5;
+
+ /**
+ * Return value of {@link #getFormat()} for RAS streams.
+ * Sun Raster allows for one image per file only and is not able to
+ * store physical resolution or comments.
+ */
+ public static final int FORMAT_RAS = 6;
+
+ /** Return value of {@link #getFormat()} for PBM streams. */
+ public static final int FORMAT_PBM = 7;
+
+ /** Return value of {@link #getFormat()} for PGM streams. */
+ public static final int FORMAT_PGM = 8;
+
+ /** Return value of {@link #getFormat()} for PPM streams. */
+ public static final int FORMAT_PPM = 9;
+
+ /** Return value of {@link #getFormat()} for PSD streams. */
+ public static final int FORMAT_PSD = 10;
+
+ /** Return value of {@link #getFormat()} for SWF (Shockwave) streams. */
+ public static final int FORMAT_SWF = 11;
+
+ public static final int COLOR_TYPE_UNKNOWN = -1;
+ public static final int COLOR_TYPE_TRUECOLOR_RGB = 0;
+ public static final int COLOR_TYPE_PALETTED = 1;
+ public static final int COLOR_TYPE_GRAYSCALE= 2;
+ public static final int COLOR_TYPE_BLACK_AND_WHITE = 3;
+
+ /**
+ * The names of all supported file formats.
+ * The FORMAT_xyz int constants can be used as index values for
+ * this array.
+ */
+ private static final String[] FORMAT_NAMES =
+ {"JPEG", "GIF", "PNG", "BMP", "PCX",
+ "IFF", "RAS", "PBM", "PGM", "PPM",
+ "PSD", "SWF"};
+
+ /**
+ * The names of the MIME types for all supported file formats.
+ * The FORMAT_xyz int constants can be used as index values for
+ * this array.
+ */
+ private static final String[] MIME_TYPE_STRINGS =
+ {"image/jpeg", "image/gif", "image/png",
"image/bmp", "image/pcx",
+ "image/iff", "image/ras", "image/x-portable-bitmap",
"image/x-portable-graymap", "image/x-portable-pixmap",
+ "image/psd", "application/x-shockwave-flash"};
+
+ private int width;
+ private int height;
+ private int bitsPerPixel;
+ private int colorType = COLOR_TYPE_UNKNOWN;
+ private boolean progressive;
+ private int format;
+ private InputStream in;
+ private DataInput din;
+ private boolean collectComments = true;
+ private Vector comments;
+ private boolean determineNumberOfImages;
+ private int numberOfImages;
+ private int physicalHeightDpi;
+ private int physicalWidthDpi;
+ private int bitBuf;
+ private int bitPos;
+
+ private void addComment(String s) {
+ if (comments == null) {
+ comments = new Vector();
+ }
+ comments.addElement(s);
+ }
+
+ /**
+ * Call this method after you have provided an input stream or file
+ * using {@link #setInput(InputStream)} or {@link #setInput(DataInput)}.
+ * If true is returned, the file format was known and information
+ * on the file's content can be retrieved using the various getXyz methods.
+ * @return if information could be retrieved from input
+ */
+ public boolean check() {
+ format = -1;
+ width = -1;
+ height = -1;
+ bitsPerPixel = -1;
+ numberOfImages = 1;
+ physicalHeightDpi = -1;
+ physicalWidthDpi = -1;
+ comments = null;
+ try {
+ int b1 = read() & 0xff;
+ int b2 = read() & 0xff;
+ if (b1 == 0x47 && b2 == 0x49) {
+ return checkGif();
+ }
+ else
+ if (b1 == 0x89 && b2 == 0x50) {
+ return checkPng();
+ }
+ else
+ if (b1 == 0xff && b2 == 0xd8) {
+ return checkJpeg();
+ }
+ else
+ if (b1 == 0x42 && b2 == 0x4d) {
+ return checkBmp();
+ }
+ else
+ if (b1 == 0x0a && b2 < 0x06) {
+ return checkPcx();
+ }
+ else
+ if (b1 == 0x46 && b2 == 0x4f) {
+ return checkIff();
+ }
+ else
+ if (b1 == 0x59 && b2 == 0xa6) {
+ return checkRas();
+ }
+ else
+ if (b1 == 0x50 && b2 >= 0x31 && b2 <= 0x36) {
+ return checkPnm(b2 - '0');
+ }
+ else
+ if (b1 == 0x38 && b2 == 0x42) {
+ return checkPsd();
+ }
+ else
+ if (b1 == 0x46 && b2 == 0x57) {
+ return checkSwf();
+ }
+ else {
+ return false;
+ }
+ } catch (IOException ioe) {
+ return false;
+ }
+ }
+
+ private boolean checkBmp() throws IOException {
+ byte[] a = new byte[44];
+ if (read(a) != a.length) {
+ return false;
+ }
+ width = getIntLittleEndian(a, 16);
+ height = getIntLittleEndian(a, 20);
+ if (width < 1 || height < 1) {
+ return false;
+ }
+ bitsPerPixel = getShortLittleEndian(a, 26);
+ if (bitsPerPixel != 1 && bitsPerPixel != 4 &&
+ bitsPerPixel != 8 && bitsPerPixel != 16 &&
+ bitsPerPixel != 24 && bitsPerPixel != 32) {
+ return false;
+ }
+ int x = (int)(getIntLittleEndian(a, 36) * 0.0254);
+ if (x > 0) {
+ setPhysicalWidthDpi(x);
+ }
+ int y = (int)(getIntLittleEndian(a, 40) * 0.0254);
+ if (y > 0) {
+ setPhysicalHeightDpi(y);
+ }
+ format = FORMAT_BMP;
+ return true;
+ }
+
+ private boolean checkGif() throws IOException {
+ final byte[] GIF_MAGIC_87A = {0x46, 0x38, 0x37, 0x61};
+ final byte[] GIF_MAGIC_89A = {0x46, 0x38, 0x39, 0x61};
+ byte[] a = new byte[11]; // 4 from the GIF signature + 7 from the global header
+ if (read(a) != 11) {
+ return false;
+ }
+ if ((!equals(a, 0, GIF_MAGIC_89A, 0, 4)) &&
+ (!equals(a, 0, GIF_MAGIC_87A, 0, 4))) {
+ return false;
+ }
+ format = FORMAT_GIF;
+ width = getShortLittleEndian(a, 4);
+ height = getShortLittleEndian(a, 6);
+ int flags = a[8] & 0xff;
+ bitsPerPixel = ((flags >> 4) & 0x07) + 1;
+ progressive = (flags & 0x02) != 0;
+ if (!determineNumberOfImages) {
+ return true;
+ }
+ // skip global color palette
+ if ((flags & 0x80) != 0) {
+ int tableSize = (1 << ((flags & 7) + 1)) * 3;
+ skip(tableSize);
+ }
+ numberOfImages = 0;
+ int blockType;
+ do
+ {
+ blockType = read();
+ switch(blockType)
+ {
+ case(0x2c): // image separator
+ {
+ if (read(a, 0, 9) != 9) {
+ return false;
+ }
+ flags = a[8] & 0xff;
+ int localBitsPerPixel = (flags & 0x07) + 1;
+ if (localBitsPerPixel > bitsPerPixel) {
+ bitsPerPixel = localBitsPerPixel;
+ }
+ if ((flags & 0x80) != 0) {
+ skip((1 << localBitsPerPixel) * 3);
+ }
+ skip(1); // initial code length
+ int n;
+ do
+ {
+ n = read();
+ if (n > 0) {
+ skip(n);
+ }
+ else
+ if (n == -1) {
+ return false;
+ }
+ }
+ while (n > 0);
+ numberOfImages++;
+ break;
+ }
+ case(0x21): // extension
+ {
+ int extensionType = read();
+ if (collectComments && extensionType == 0xfe) {
+ StringBuffer sb = new StringBuffer();
+ int n;
+ do
+ {
+ n = read();
+ if (n == -1) {
+ return false;
+ }
+ if (n > 0) {
+ for (int i = 0; i < n; i++) {
+ int ch = read();
+ if (ch == -1) {
+ return false;
+ }
+ sb.append((char)ch);
+ }
+ }
+ }
+ while (n > 0);
+ } else {
+ int n;
+ do
+ {
+ n = read();
+ if (n > 0) {
+ skip(n);
+ }
+ else
+ if (n == -1) {
+ return false;
+ }
+ }
+ while (n > 0);
+ }
+ break;
+ }
+ case(0x3b): // end of file
+ {
+ break;
+ }
+ default:
+ {
+ return false;
+ }
+ }
+ }
+ while (blockType != 0x3b);
+ return true;
+ }
+
+ private boolean checkIff() throws IOException {
+ byte[] a = new byte[10];
+ // read remaining 2 bytes of file id, 4 bytes file size
+ // and 4 bytes IFF subformat
+ if (read(a, 0, 10) != 10) {
+ return false;
+ }
+ final byte[] IFF_RM = {0x52, 0x4d};
+ if (!equals(a, 0, IFF_RM, 0, 2)) {
+ return false;
+ }
+ int type = getIntBigEndian(a, 6);
+ if (type != 0x494c424d && // type must be ILBM...
+ type != 0x50424d20) { // ...or PBM
+ return false;
+ }
+ // loop chunks to find BMHD chunk
+ do {
+ if (read(a, 0, 8) != 8) {
+ return false;
+ }
+ int chunkId = getIntBigEndian(a, 0);
+ int size = getIntBigEndian(a, 4);
+ if ((size & 1) == 1) {
+ size++;
+ }
+ if (chunkId == 0x424d4844) { // BMHD chunk
+ if (read(a, 0, 9) != 9) {
+ return false;
+ }
+ format = FORMAT_IFF;
+ width = getShortBigEndian(a, 0);
+ height = getShortBigEndian(a, 2);
+ bitsPerPixel = a[8] & 0xff;
+ return (width > 0 && height > 0 && bitsPerPixel > 0
&& bitsPerPixel < 33);
+ } else {
+ skip(size);
+ }
+ } while (true);
+ }
+
+ private boolean checkJpeg() throws IOException {
+ byte[] data = new byte[12];
+ while (true) {
+ if (read(data, 0, 4) != 4) {
+ return false;
+ }
+ int marker = getShortBigEndian(data, 0);
+ int size = getShortBigEndian(data, 2);
+ if ((marker & 0xff00) != 0xff00) {
+ return false; // not a valid marker
+ }
+ if (marker == 0xffe0) { // APPx
+ if (size < 14) {
+ return false; // APPx header must be >= 14 bytes
+ }
+ if (read(data, 0, 12) != 12) {
+ return false;
+ }
+ final byte[] APP0_ID = {0x4a, 0x46, 0x49, 0x46, 0x00};
+ if (equals(APP0_ID, 0, data, 0, 5)) {
+ //System.out.println("data 7=" + data[7]);
+ if (data[7] == 1) {
+ setPhysicalWidthDpi(getShortBigEndian(data, 8));
+ setPhysicalHeightDpi(getShortBigEndian(data, 10));
+ }
+ else
+ if (data[7] == 2) {
+ int x = getShortBigEndian(data, 8);
+ int y = getShortBigEndian(data, 10);
+ setPhysicalWidthDpi((int)(x * 2.54f));
+ setPhysicalHeightDpi((int)(y * 2.54f));
+ }
+ }
+ skip(size - 14);
+ }
+ else
+ if (collectComments && size > 2 && marker == 0xfffe) { // comment
+ size -= 2;
+ byte[] chars = new byte[size];
+ if (read(chars, 0, size) != size) {
+ return false;
+ }
+ String comment = new String(chars, "iso-8859-1");
+ comment = comment.trim();
+ addComment(comment);
+ }
+ else
+ if (marker >= 0xffc0 && marker <= 0xffcf && marker != 0xffc4
&& marker != 0xffc8) {
+ if (read(data, 0, 6) != 6) {
+ return false;
+ }
+ format = FORMAT_JPEG;
+ bitsPerPixel = (data[0] & 0xff) * (data[5] & 0xff);
+ progressive = marker == 0xffc2 || marker == 0xffc6 ||
+ marker == 0xffca || marker == 0xffce;
+ width = getShortBigEndian(data, 3);
+ height = getShortBigEndian(data, 1);
+ return true;
+ } else {
+ skip(size - 2);
+ }
+ }
+ }
+
+ private boolean checkPcx() throws IOException {
+ byte[] a = new byte[64];
+ if (read(a) != a.length) {
+ return false;
+ }
+ if (a[0] != 1) { // encoding, 1=RLE is only valid value
+ return false;
+ }
+ // width / height
+ int x1 = getShortLittleEndian(a, 2);
+ int y1 = getShortLittleEndian(a, 4);
+ int x2 = getShortLittleEndian(a, 6);
+ int y2 = getShortLittleEndian(a, 8);
+ if (x1 < 0 || x2 < x1 || y1 < 0 || y2 < y1) {
+ return false;
+ }
+ width = x2 - x1 + 1;
+ height = y2 - y1 + 1;
+ // color depth
+ int bits = a[1];
+ int planes = a[63];
+ if (planes == 1 &&
+ (bits == 1 || bits == 2 || bits == 4 || bits == 8)) {
+ // paletted
+ bitsPerPixel = bits;
+ } else
+ if (planes == 3 && bits == 8) {
+ // RGB truecolor
+ bitsPerPixel = 24;
+ } else {
+ return false;
+ }
+ setPhysicalWidthDpi(getShortLittleEndian(a, 10));
+ setPhysicalHeightDpi(getShortLittleEndian(a, 10));
+ format = FORMAT_PCX;
+ return true;
+ }
+
+ private boolean checkPng() throws IOException {
+ final byte[] PNG_MAGIC = {0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a};
+ byte[] a = new byte[27];
+ if (read(a) != 27) {
+ return false;
+ }
+ if (!equals(a, 0, PNG_MAGIC, 0, 6)) {
+ return false;
+ }
+ format = FORMAT_PNG;
+ width = getIntBigEndian(a, 14);
+ height = getIntBigEndian(a, 18);
+ bitsPerPixel = a[22] & 0xff;
+ int colorType = a[23] & 0xff;
+ if (colorType == 2 || colorType == 6) {
+ bitsPerPixel *= 3;
+ }
+ progressive = (a[26] & 0xff) != 0;
+ return true;
+ }
+
+ private boolean checkPnm(int id) throws IOException {
+ if (id < 1 || id > 6) {
+ return false;
+ }
+ final int[] PNM_FORMATS = {FORMAT_PBM, FORMAT_PGM, FORMAT_PPM};
+ format = PNM_FORMATS[(id - 1) % 3];
+ boolean hasPixelResolution = false;
+ String s;
+ while (true)
+ {
+ s = readLine();
+ if (s != null) {
+ s = s.trim();
+ }
+ if (s == null || s.length() < 1) {
+ continue;
+ }
+ if (s.charAt(0) == '#') { // comment
+ if (collectComments && s.length() > 1) {
+ addComment(s.substring(1));
+ }
+ continue;
+ }
+ if (!hasPixelResolution) { // split "343 966" into width=343, height=966
+ int spaceIndex = s.indexOf(' ');
+ if (spaceIndex == -1) {
+ return false;
+ }
+ String widthString = s.substring(0, spaceIndex);
+ spaceIndex = s.lastIndexOf(' ');
+ if (spaceIndex == -1) {
+ return false;
+ }
+ String heightString = s.substring(spaceIndex + 1);
+ try {
+ width = Integer.parseInt(widthString);
+ height = Integer.parseInt(heightString);
+ } catch (NumberFormatException nfe) {
+ return false;
+ }
+ if (width < 1 || height < 1) {
+ return false;
+ }
+ if (format == FORMAT_PBM) {
+ bitsPerPixel = 1;
+ return true;
+ }
+ hasPixelResolution = true;
+ }
+ else
+ {
+ int maxSample;
+ try {
+ maxSample = Integer.parseInt(s);
+ } catch (NumberFormatException nfe) {
+ return false;
+ }
+ if (maxSample < 0) {
+ return false;
+ }
+ for (int i = 0; i < 25; i++) {
+ if (maxSample < (1 << (i + 1))) {
+ bitsPerPixel = i + 1;
+ if (format == FORMAT_PPM) {
+ bitsPerPixel *= 3;
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+ }
+
+ private boolean checkPsd() throws IOException {
+ byte[] a = new byte[24];
+ if (read(a) != a.length) {
+ return false;
+ }
+ final byte[] PSD_MAGIC = {0x50, 0x53};
+ if (!equals(a, 0, PSD_MAGIC, 0, 2)) {
+ return false;
+ }
+ format = FORMAT_PSD;
+ width = getIntBigEndian(a, 16);
+ height = getIntBigEndian(a, 12);
+ int channels = getShortBigEndian(a, 10);
+ int depth = getShortBigEndian(a, 20);
+ bitsPerPixel = channels * depth;
+ return (width > 0 && height > 0 && bitsPerPixel > 0 &&
bitsPerPixel <= 64);
+ }
+
+ private boolean checkRas() throws IOException {
+ byte[] a = new byte[14];
+ if (read(a) != a.length) {
+ return false;
+ }
+ final byte[] RAS_MAGIC = {0x6a, (byte)0x95};
+ if (!equals(a, 0, RAS_MAGIC, 0, 2)) {
+ return false;
+ }
+ format = FORMAT_RAS;
+ width = getIntBigEndian(a, 2);
+ height = getIntBigEndian(a, 6);
+ bitsPerPixel = getIntBigEndian(a, 10);
+ return (width > 0 && height > 0 && bitsPerPixel > 0 &&
bitsPerPixel <= 24);
+ }
+
+ // Written by Michael Aird.
+ private boolean checkSwf() throws IOException {
+ //get rid of the last byte of the signature, the byte of the version and 4 bytes of the
size
+ byte[] a = new byte[6];
+ if (read(a) != a.length) {
+ return false;
+ }
+ format = FORMAT_SWF;
+ int bitSize = (int)readUBits( 5 );
+ int minX = (int)readSBits( bitSize );
+ int maxX = (int)readSBits( bitSize );
+ int minY = (int)readSBits( bitSize );
+ int maxY = (int)readSBits( bitSize );
+ width = maxX/20; //cause we're in twips
+ height = maxY/20; //cause we're in twips
+ setPhysicalWidthDpi(72);
+ setPhysicalHeightDpi(72);
+ return (width > 0 && height > 0);
+ }
+
+ /**
+ * Run over String list, return false iff at least one of the arguments
+ * equals <code>-c</code>.
+ */
+ private static boolean determineVerbosity(String[] args) {
+ if (args != null && args.length > 0) {
+ for (int i = 0; i < args.length; i++) {
+ if ("-c".equals(args[i])) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private boolean equals(byte[] a1, int offs1, byte[] a2, int offs2, int num) {
+ while (num-- > 0) {
+ if (a1[offs1++] != a2[offs2++]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * If {@link #check()} was successful, returns the image's number of bits per
pixel.
+ * Does not include transparency information like the alpha channel.
+ * @return number of bits per image pixel
+ */
+ public int getBitsPerPixel() {
+ return bitsPerPixel;
+ }
+
+ /**
+ * Returns the index'th comment retrieved from the image.
+ * @throws IllegalArgumentException if index is smaller than 0 or larger than or equal
+ * to the number of comments retrieved
+ * @see #getNumberOfComments
+ */
+ public String getComment(int index) {
+ if (comments == null || index < 0 || index >= comments.size()) {
+ throw new IllegalArgumentException(Messages.getMessage(Messages.INVALID_COMMENT_INDEX,
"" + index));
+ }
+ return (String)comments.elementAt(index);
+ }
+
+ /**
+ * If {@link #check()} was successful, returns the image format as one
+ * of the FORMAT_xyz constants from this class.
+ * Use {@link #getFormatName()} to get a textual description of the file format.
+ * @return file format as a FORMAT_xyz constant
+ */
+ public int getFormat() {
+ return format;
+ }
+
+ /**
+ * If {@link #check()} was successful, returns the image format's name.
+ * Use {@link #getFormat()} to get a unique number.
+ * @return file format name
+ */
+ public String getFormatName() {
+ if (format >= 0 && format < FORMAT_NAMES.length) {
+ return FORMAT_NAMES[format];
+ } else {
+ return "?";
+ }
+ }
+
+ /**
+ * If {@link #check()} was successful, returns one the image's vertical
+ * resolution in pixels.
+ * @return image height in pixels
+ */
+ public int getHeight() {
+ return height;
+ }
+
+ private int getIntBigEndian(byte[] a, int offs) {
+ return
+ (a[offs] & 0xff) << 24 |
+ (a[offs + 1] & 0xff) << 16 |
+ (a[offs + 2] & 0xff) << 8 |
+ a[offs + 3] & 0xff;
+ }
+
+ private int getIntLittleEndian(byte[] a, int offs) {
+ return
+ (a[offs + 3] & 0xff) << 24 |
+ (a[offs + 2] & 0xff) << 16 |
+ (a[offs + 1] & 0xff) << 8 |
+ a[offs] & 0xff;
+ }
+
+ /**
+ * If {@link #check()} was successful, returns a String with the
+ * MIME type of the format.
+ * @return MIME type, e.g. <code>image/jpeg</code>
+ */
+ public String getMimeType() {
+ if (format >= 0 && format < MIME_TYPE_STRINGS.length) {
+ if (format == FORMAT_JPEG && progressive)
+ {
+ return "image/pjpeg";
+ }
+ return MIME_TYPE_STRINGS[format];
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * If {@link #check()} was successful and {@link #setCollectComments(boolean)} was
called with
+ * <code>true</code> as argument, returns the number of comments retrieved
+ * from the input image stream / file.
+ * Any number >= 0 and smaller than this number of comments is then a
+ * valid argument for the {@link #getComment(int)} method.
+ * @return number of comments retrieved from input image
+ */
+ public int getNumberOfComments()
+ {
+ if (comments == null) {
+ return 0;
+ } else {
+ return comments.size();
+ }
+ }
+
+ /**
+ * Returns the number of images in the examined file.
+ * Assumes that <code>setDetermineImageNumber(true);</code> was called
before
+ * a successful call to {@link #check()}.
+ * This value can currently be only different from <code>1</code> for GIF
images.
+ * @return number of images in file
+ */
+ public int getNumberOfImages()
+ {
+ return numberOfImages;
+ }
+
+ /**
+ * Returns the physical height of this image in dots per inch (dpi).
+ * Assumes that {@link #check()} was successful.
+ * Returns <code>-1</code> on failure.
+ * @return physical height (in dpi)
+ * @see #getPhysicalWidthDpi()
+ * @see #getPhysicalHeightInch()
+ */
+ public int getPhysicalHeightDpi() {
+ return physicalHeightDpi;
+ }
+
+ /**
+ * If {@link #check()} was successful, returns the physical width of this image in dpi
(dots per inch)
+ * or -1 if no value could be found.
+ * @return physical height (in dpi)
+ * @see #getPhysicalHeightDpi()
+ * @see #getPhysicalWidthDpi()
+ * @see #getPhysicalWidthInch()
+ */
+ public float getPhysicalHeightInch() {
+ int h = getHeight();
+ int ph = getPhysicalHeightDpi();
+ if (h > 0 && ph > 0) {
+ return ((float)h) / ((float)ph);
+ } else {
+ return -1.0f;
+ }
+ }
+
+ /**
+ * If {@link #check()} was successful, returns the physical width of this image in dpi
(dots per inch)
+ * or -1 if no value could be found.
+ * @return physical width (in dpi)
+ * @see #getPhysicalHeightDpi()
+ * @see #getPhysicalWidthInch()
+ * @see #getPhysicalHeightInch()
+ */
+ public int getPhysicalWidthDpi() {
+ return physicalWidthDpi;
+ }
+
+ /**
+ * Returns the physical width of an image in inches, or
+ * <code>-1.0f</code> if width information is not available.
+ * Assumes that {@link #check} has been called successfully.
+ * @return physical width in inches or <code>-1.0f</code> on failure
+ * @see #getPhysicalWidthDpi
+ * @see #getPhysicalHeightInch
+ */
+ public float getPhysicalWidthInch() {
+ int w = getWidth();
+ int pw = getPhysicalWidthDpi();
+ if (w > 0 && pw > 0) {
+ return ((float)w) / ((float)pw);
+ } else {
+ return -1.0f;
+ }
+ }
+
+ private int getShortBigEndian(byte[] a, int offs) {
+ return
+ (a[offs] & 0xff) << 8 |
+ (a[offs + 1] & 0xff);
+ }
+
+ private int getShortLittleEndian(byte[] a, int offs) {
+ return (a[offs] & 0xff) | (a[offs + 1] & 0xff) << 8;
+ }
+
+ /**
+ * If {@link #check()} was successful, returns one the image's horizontal
+ * resolution in pixels.
+ * @return image width in pixels
+ */
+ public int getWidth() {
+ return width;
+ }
+
+ /**
+ * Returns whether the image is stored in a progressive (also called: interlaced) way.
+ * @return true for progressive/interlaced, false otherwise
+ */
+ public boolean isProgressive()
+ {
+ return progressive;
+ }
+
+ /**
+ * To use this class as a command line application, give it either
+ * some file names as parameters (information on them will be
+ * printed to standard output, one line per file) or call
+ * it with no parameters. It will then check data given to it
+ * via standard input.
+ * @param args the program arguments which must be file names
+ */
+ public static void main(String[] args) {
+ ImageInfo imageInfo = new ImageInfo();
+ imageInfo.setDetermineImageNumber(true);
+ boolean verbose = determineVerbosity(args);
+ if (args.length == 0) {
+ run(null, System.in, imageInfo, verbose);
+ } else {
+ int index = 0;
+ while (index < args.length) {
+ InputStream in = null;
+ try {
+ String name = args[index++];
+ System.out.print(name + ";");
+ if (name.startsWith("http://")) {
+ in = new URL(name).openConnection().getInputStream();
+ } else {
+ in = new FileInputStream(name);
+ }
+ run(name, in, imageInfo, verbose);
+ in.close();
+ } catch (Exception e) {
+ System.out.println(e);
+ try {
+ in.close();
+ } catch (Exception ee) {
+ }
+ }
+ }
+ }
+ }
+
+ private static void print(String sourceName, ImageInfo ii, boolean verbose) {
+ if (verbose) {
+ printVerbose(sourceName, ii);
+ } else {
+ printCompact(sourceName, ii);
+ }
+ }
+
+ private static void printCompact(String sourceName, ImageInfo imageInfo) {
+ System.out.println(
+ imageInfo.getFormatName() + ";" +
+ imageInfo.getMimeType() + ";" +
+ imageInfo.getWidth() + ";" +
+ imageInfo.getHeight() + ";" +
+ imageInfo.getBitsPerPixel() + ";" +
+ imageInfo.getNumberOfImages() + ";" +
+ imageInfo.getPhysicalWidthDpi() + ";" +
+ imageInfo.getPhysicalHeightDpi() + ";" +
+ imageInfo.getPhysicalWidthInch() + ";" +
+ imageInfo.getPhysicalHeightInch() + ";" +
+ imageInfo.isProgressive()
+ );
+ }
+
+ private static void printLine(int indentLevels, String text, float value, float
minValidValue) {
+ if (value < minValidValue) {
+ return;
+ }
+ printLine(indentLevels, text, Float.toString(value));
+ }
+
+ private static void printLine(int indentLevels, String text, int value, int
minValidValue) {
+ if (value >= minValidValue) {
+ printLine(indentLevels, text, Integer.toString(value));
+ }
+ }
+
+ private static void printLine(int indentLevels, String text, String value) {
+ if (value == null || value.length() == 0) {
+ return;
+ }
+ while (indentLevels-- > 0) {
+ System.out.print("\t");
+ }
+ if (text != null && text.length() > 0) {
+ System.out.print(text);
+ System.out.print(" ");
+ }
+ System.out.println(value);
+ }
+
+ private static void printVerbose(String sourceName, ImageInfo ii) {
+ printLine(0, null, sourceName);
+ printLine(1, "File format: ", ii.getFormatName());
+ printLine(1, "MIME type: ", ii.getMimeType());
+ printLine(1, "Width (pixels): ", ii.getWidth(), 1);
+ printLine(1, "Height (pixels): ", ii.getHeight(), 1);
+ printLine(1, "Bits per pixel: ", ii.getBitsPerPixel(), 1);
+ printLine(1, "Progressive: ", Boolean.toString(ii.isProgressive()));
+ printLine(1, "Number of images: ", ii.getNumberOfImages(), 1);
+ printLine(1, "Physical width (dpi): ", ii.getPhysicalWidthDpi(), 1);
+ printLine(1, "Physical height (dpi): ", ii.getPhysicalHeightDpi(), 1);
+ printLine(1, "Physical width (inches): ", ii.getPhysicalWidthInch(), 1.0f);
+ printLine(1, "Physical height (inches): ", ii.getPhysicalHeightInch(),
1.0f);
+ int numComments = ii.getNumberOfComments();
+ printLine(1, "Number of textual comments: ", numComments, 1);
+ if (numComments > 0) {
+ for (int i = 0; i < numComments; i++) {
+ printLine(2, null, ii.getComment(i));
+ }
+ }
+ }
+
+ private int read() throws IOException {
+ if (in != null) {
+ return in.read();
+ } else {
+ return din.readByte();
+ }
+ }
+
+ private int read(byte[] a) throws IOException {
+ if (in != null) {
+ return in.read(a);
+ } else {
+ din.readFully(a);
+ return a.length;
+ }
+ }
+
+ private int read(byte[] a, int offset, int num) throws IOException {
+ if (in != null) {
+ return in.read(a, offset, num);
+ } else {
+ din.readFully(a, offset, num);
+ return num;
+ }
+ }
+
+ private String readLine() throws IOException {
+ return readLine(new StringBuffer());
+ }
+
+ private String readLine(StringBuffer sb) throws IOException {
+ boolean finished;
+ do {
+ int value = read();
+ finished = (value == -1 || value == 10);
+ if (!finished) {
+ sb.append((char)value);
+ }
+ } while (!finished);
+ return sb.toString();
+ }
+
+ private long readUBits( int numBits ) throws IOException
+ {
+ if (numBits == 0) {
+ return 0;
+ }
+ int bitsLeft = numBits;
+ long result = 0;
+ if (bitPos == 0) { //no value in the buffer - read a byte
+ if (in != null) {
+ bitBuf = in.read();
+ } else {
+ bitBuf = din.readByte();
+ }
+ bitPos = 8;
+ }
+
+ while( true )
+ {
+ int shift = bitsLeft - bitPos;
+ if( shift > 0 )
+ {
+ // Consume the entire buffer
+ result |= bitBuf << shift;
+ bitsLeft -= bitPos;
+
+ // Get the next byte from the input stream
+ if (in != null) {
+ bitBuf = in.read();
+ } else {
+ bitBuf = din.readByte();
+ }
+ bitPos = 8;
+ }
+ else
+ {
+ // Consume a portion of the buffer
+ result |= bitBuf >> -shift;
+ bitPos -= bitsLeft;
+ bitBuf &= 0xff >> (8 - bitPos); // mask off the consumed bits
+
+ return result;
+ }
+ }
+ }
+
+ /**
+ * Read a signed value from the given number of bits
+ */
+ private int readSBits( int numBits ) throws IOException
+ {
+ // Get the number as an unsigned value.
+ long uBits = readUBits( numBits );
+
+ // Is the number negative?
+ if( ( uBits & (1L << (numBits - 1))) != 0 )
+ {
+ // Yes. Extend the sign.
+ uBits |= -1L << numBits;
+ }
+
+ return (int)uBits;
+ }
+
+ private void synchBits()
+ {
+ bitBuf = 0;
+ bitPos = 0;
+ }
+
+ private String readLine(int firstChar) throws IOException {
+ StringBuffer result = new StringBuffer();
+ result.append((char)firstChar);
+ return readLine(result);
+ }
+
+ private static void run(String sourceName, InputStream in, ImageInfo imageInfo, boolean
verbose) {
+ imageInfo.setInput(in);
+ imageInfo.setDetermineImageNumber(false);
+ imageInfo.setCollectComments(verbose);
+ if (imageInfo.check()) {
+ print(sourceName, imageInfo, verbose);
+ }
+ }
+
+ /**
+ * Specify whether textual comments are supposed to be extracted from input.
+ * Default is <code>false</code>.
+ * If enabled, comments will be added to an internal list.
+ * @param newValue if <code>true</code>, this class will read comments
+ * @see #getNumberOfComments
+ * @see #getComment
+ */
+ public void setCollectComments(boolean newValue)
+ {
+ collectComments = newValue;
+ }
+
+ /**
+ * Specify whether the number of images in a file is to be
+ * determined - default is <code>false</code>.
+ * This is a special option because some file formats require running over
+ * the entire file to find out the number of images, a rather time-consuming
+ * task.
+ * Not all file formats support more than one image.
+ * If this method is called with <code>true</code> as argument,
+ * the actual number of images can be queried via
+ * {@link #getNumberOfImages()} after a successful call to
+ * {@link #check()}.
+ * @param newValue will the number of images be determined?
+ * @see #getNumberOfImages
+ */
+ public void setDetermineImageNumber(boolean newValue)
+ {
+ determineNumberOfImages = newValue;
+ }
+
+ /**
+ * Set the input stream to the argument stream (or file).
+ * Note that {@link java.io.RandomAccessFile} implements
+ * {@link java.io.DataInput}.
+ * @param dataInput the input stream to read from
+ */
+ public void setInput(DataInput dataInput) {
+ din = dataInput;
+ in = null;
+ }
+
+ /**
+ * Set the input stream to the argument stream (or file).
+ * @param inputStream the input stream to read from
+ */
+ public void setInput(InputStream inputStream) {
+ in = inputStream;
+ din = null;
+ }
+
+ private void setPhysicalHeightDpi(int newValue) {
+ physicalWidthDpi = newValue;
+ }
+
+ private void setPhysicalWidthDpi(int newValue) {
+ physicalHeightDpi = newValue;
+ }
+
+ private void skip(int num) throws IOException {
+ while (num > 0) {
+ long result;
+ if (in != null) {
+ result = in.skip(num);
+ } else {
+ result = din.skipBytes(num);
+ }
+ if (result > 0) {
+ num -= result;
+ }
+ }
+ }
+}
Added: trunk/framework/impl/src/main/java/org/ajax4jsf/resource/image/Quantize.java
===================================================================
--- trunk/framework/impl/src/main/java/org/ajax4jsf/resource/image/Quantize.java
(rev 0)
+++
trunk/framework/impl/src/main/java/org/ajax4jsf/resource/image/Quantize.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -0,0 +1,840 @@
+/**
+ * License Agreement.
+ *
+ * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
+ *
+ * Copyright (C) 2007 Exadel, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/*
+ * Helma License Notice
+ *
+ * The contents of this file are subject to the Helma License
+ * Version 2.0 (the "License"). You may not use this file except in
+ * compliance with the License. A copy of the License is available at
+ *
http://adele.helma.org/download/helma/license.txt
+ *
+ * Copyright 1998-2003 Helma Software. All Rights Reserved.
+ *
+ * $RCSfile: Quantize.java,v $
+ * $Author: alexsmirnov $
+ * $Revision: 1.1.2.1 $
+ * $Date: 2007/01/09 18:59:05 $
+ */
+
+package org.ajax4jsf.resource.image;
+
+import java.awt.image.BufferedImage;
+import java.awt.image.DataBufferByte;
+import java.awt.image.DataBufferInt;
+import java.awt.image.IndexColorModel;
+
+/*
+ * @(#)Quantize.java 0.90 9/19/00 Adam Doppelt
+ *
+ * Modifications by Joerg Lehni:
+ *
+ * - Support for alpha-channels.
+ * - Returns a BufferedImage of TYPE_BYTE_INDEXED with a IndexColorModel.
+ * - Dithering of images through helma.image.DiffusionFilterOp by setting
+ * the dither parameter to true.
+ * - Support for a transparent color, which is correctly rendered by GIFEncoder.
+ * All pixels with alpha < 0x80 are converted to this color when the parameter
+ * alphaToBitmask is set to true.
+ * - Removed the SQUARES lookup tables as multiplications of integer values
+ * shouldn't take more than one clock nowadays anyhow.
+ */
+
+/**
+ * An efficient color quantization algorithm, adapted from the C++
+ * implementation quantize.c in <a
+ *
href="http://www.imagemagick.org/">ImageMagick</a>. The pixels for
+ * an image are placed into an oct tree. The oct tree is reduced in
+ * size, and the pixels from the original image are reassigned to the
+ * nodes in the reduced tree.<p>
+ *
+ * Here is the copyright notice from ImageMagick:
+ *
+ * <pre>
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Permission is hereby granted, free of charge, to any person obtaining a %
+% copy of this software and associated documentation files ("ImageMagick"),
%
+% to deal in ImageMagick without restriction, including without limitation %
+% the rights to use, copy, modify, merge, publish, distribute, sublicense, %
+% and/or sell copies of ImageMagick, and to permit persons to whom the %
+% ImageMagick is furnished to do so, subject to the following conditions: %
+% %
+% The above copyright notice and this permission notice shall be included in %
+% all copies or substantial portions of ImageMagick. %
+% %
+% The software is provided "as is", without warranty of any kind, express or
%
+% implied, including but not limited to the warranties of merchantability, %
+% fitness for a particular purpose and noninfringement. In no event shall %
+% E. I. du Pont de Nemours and Company be liable for any claim, damages or %
+% other liability, whether in an action of contract, tort or otherwise, %
+% arising from, out of or in connection with ImageMagick or the use or other %
+% dealings in ImageMagick. %
+% %
+% Except as contained in this notice, the name of the E. I. du Pont de %
+% Nemours and Company shall not be used in advertising or otherwise to %
+% promote the sale, use or other dealings in ImageMagick without prior %
+% written authorization from the E. I. du Pont de Nemours and Company. %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+</pre>
+ *
+ *
+ * @version 0.90 19 Sep 2000
+ * @author <a
href="http://www.gurge.com/amd/">Adam Doppelt</a>
+ */
+public class Quantize {
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% QQQ U U AAA N N TTTTT IIIII ZZZZZ EEEEE %
+% Q Q U U A A NN N T I ZZ E %
+% Q Q U U AAAAA N N N T I ZZZ EEEEE %
+% Q QQ U U A A N NN T I ZZ E %
+% QQQQ UUU A A N N T IIIII ZZZZZ EEEEE %
+% %
+% %
+% Reduce the Number of Unique Colors in an Image %
+% %
+% %
+% Software Design %
+% John Cristy %
+% July 1992 %
+% %
+% %
+% Copyright 1998 E. I. du Pont de Nemours and Company %
+% %
+% Permission is hereby granted, free of charge, to any person obtaining a %
+% copy of this software and associated documentation files ("ImageMagick"),
%
+% to deal in ImageMagick without restriction, including without limitation %
+% the rights to use, copy, modify, merge, publish, distribute, sublicense, %
+% and/or sell copies of ImageMagick, and to permit persons to whom the %
+% ImageMagick is furnished to do so, subject to the following conditions: %
+% %
+% The above copyright notice and this permission notice shall be included in %
+% all copies or substantial portions of ImageMagick. %
+% %
+% The software is provided "as is", without warranty of any kind, express or
%
+% implied, including but not limited to the warranties of merchantability, %
+% fitness for a particular purpose and noninfringement. In no event shall %
+% E. I. du Pont de Nemours and Company be liable for any claim, damages or %
+% other liability, whether in an action of contract, tort or otherwise, %
+% arising from, out of or in connection with ImageMagick or the use or other %
+% dealings in ImageMagick. %
+% %
+% Except as contained in this notice, the name of the E. I. du Pont de %
+% Nemours and Company shall not be used in advertising or otherwise to %
+% promote the sale, use or other dealings in ImageMagick without prior %
+% written authorization from the E. I. du Pont de Nemours and Company. %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Realism in computer graphics typically requires using 24 bits/pixel to
+% generate an image. Yet many graphic display devices do not contain
+% the amount of memory necessary to match the spatial and color
+% resolution of the human eye. The QUANTIZE program takes a 24 bit
+% image and reduces the number of colors so it can be displayed on
+% raster device with less bits per pixel. In most instances, the
+% quantized image closely resembles the original reference image.
+%
+% A reduction of colors in an image is also desirable for image
+% transmission and real-time animation.
+%
+% Function Quantize takes a standard RGB or monochrome images and quantizes
+% them down to some fixed number of colors.
+%
+% For purposes of color allocation, an image is a set of n pixels, where
+% each pixel is a point in RGB space. RGB space is a 3-dimensional
+% vector space, and each pixel, pi, is defined by an ordered triple of
+% red, green, and blue coordinates, (ri, gi, bi).
+%
+% Each primary color component (red, green, or blue) represents an
+% intensity which varies linearly from 0 to a maximum value, cmax, which
+% corresponds to full saturation of that color. Color allocation is
+% defined over a domain consisting of the cube in RGB space with
+% opposite vertices at (0,0,0) and (cmax,cmax,cmax). QUANTIZE requires
+% cmax = 255.
+%
+% The algorithm maps this domain onto a tree in which each node
+% represents a cube within that domain. In the following discussion
+% these cubes are defined by the coordinate of two opposite vertices:
+% The vertex nearest the origin in RGB space and the vertex farthest
+% from the origin.
+%
+% The tree's root node represents the the entire domain, (0,0,0) through
+% (cmax,cmax,cmax). Each lower level in the tree is generated by
+% subdividing one node's cube into eight smaller cubes of equal size.
+% This corresponds to bisecting the parent cube with planes passing
+% through the midpoints of each edge.
+%
+% The basic algorithm operates in three phases: Classification,
+% Reduction, and Assignment. Classification builds a color
+% description tree for the image. Reduction collapses the tree until
+% the number it represents, at most, the number of colors desired in the
+% output image. Assignment defines the output image's color map and
+% sets each pixel's color by reclassification in the reduced tree.
+% Our goal is to minimize the numerical discrepancies between the original
+% colors and quantized colors (quantization error).
+%
+% Classification begins by initializing a color description tree of
+% sufficient depth to represent each possible input color in a leaf.
+% However, it is impractical to generate a fully-formed color
+% description tree in the classification phase for realistic values of
+% cmax. If colors components in the input image are quantized to k-bit
+% precision, so that cmax= 2k-1, the tree would need k levels below the
+% root node to allow representing each possible input color in a leaf.
+% This becomes prohibitive because the tree's total number of nodes is
+% 1 + sum(i=1,k,8k).
+%
+% A complete tree would require 19,173,961 nodes for k = 8, cmax = 255.
+% Therefore, to avoid building a fully populated tree, QUANTIZE: (1)
+% Initializes data structures for nodes only as they are needed; (2)
+% Chooses a maximum depth for the tree as a function of the desired
+% number of colors in the output image (currently log2(colorMap size)).
+%
+% For each pixel in the input image, classification scans downward from
+% the root of the color description tree. At each level of the tree it
+% identifies the single node which represents a cube in RGB space
+% containing the pixel's color. It updates the following data for each
+% such node:
+%
+% n1: Number of pixels whose color is contained in the RGB cube
+% which this node represents;
+%
+% n2: Number of pixels whose color is not represented in a node at
+% lower depth in the tree; initially, n2 = 0 for all nodes except
+% leaves of the tree.
+%
+% Sr, Sg, Sb: Sums of the red, green, and blue component values for
+% all pixels not classified at a lower depth. The combination of
+% these sums and n2 will ultimately characterize the mean color of a
+% set of pixels represented by this node.
+%
+% E: The distance squared in RGB space between each pixel contained
+% within a node and the nodes' center. This represents the quantization
+% error for a node.
+%
+% Reduction repeatedly prunes the tree until the number of nodes with
+% n2 > 0 is less than or equal to the maximum number of colors allowed
+% in the output image. On any given iteration over the tree, it selects
+% those nodes whose E count is minimal for pruning and merges their
+% color statistics upward. It uses a pruning threshold, Ep, to govern
+% node selection as follows:
+%
+% Ep = 0
+% while number of nodes with (n2 > 0) > required maximum number of colors
+% prune all nodes such that E <= Ep
+% Set Ep to minimum E in remaining nodes
+%
+% This has the effect of minimizing any quantization error when merging
+% two nodes together.
+%
+% When a node to be pruned has offspring, the pruning procedure invokes
+% itself recursively in order to prune the tree from the leaves upward.
+% n2, Sr, Sg, and Sb in a node being pruned are always added to the
+% corresponding data in that node's parent. This retains the pruned
+% node's color characteristics for later averaging.
+%
+% For each node, n2 pixels exist for which that node represents the
+% smallest volume in RGB space containing those pixel's colors. When n2
+% > 0 the node will uniquely define a color in the output image. At the
+% beginning of reduction, n2 = 0 for all nodes except a the leaves of
+% the tree which represent colors present in the input image.
+%
+% The other pixel count, n1, indicates the total number of colors
+% within the cubic volume which the node represents. This includes n1 -
+% n2 pixels whose colors should be defined by nodes at a lower level in
+% the tree.
+%
+% Assignment generates the output image from the pruned tree. The
+% outpu t image consists of two parts: (1) A color map, which is an
+% array of color descriptions (RGB triples) for each color present in
+% the output image; (2) A pixel array, which represents each pixel as
+% an index into the color map array.
+%
+% First, the assignment phase makes one pass over the pruned color
+% description tree to establish the image's color map. For each node
+% with n2 > 0, it divides Sr, Sg, and Sb by n2 . This produces the
+% mean color of all pixels that classify no lower than this node. Each
+% of these colors becomes an entry in the color map.
+%
+% Finally, the assignment phase reclassifies each pixel in the pruned
+% tree to identify the deepest node containing the pixel's color. The
+% pixel's value in the pixel array becomes the index of this node's mean
+% color in the color map.
+%
+% With the permission of USC Information Sciences Institute, 4676 Admiralty
+% Way, Marina del Rey, California 90292, this code was adapted from module
+% ALCOLS written by Paul Raveling.
+%
+% The names of ISI and USC are not used in advertising or publicity
+% pertaining to distribution of the software without prior specific
+% written permission from ISI.
+%
+*/
+
+ final static boolean QUICK = false;
+
+ final static int MAX_RGB = 255;
+ final static int MAX_NODES = 266817;
+ final static int MAX_TREE_DEPTH = 8;
+ final static int MAX_CHILDREN = 16;
+
+ /**
+ * Reduce the image to the given number of colors. The pixels are reduced in
+ * place.
+ *
+ * @return The new color palette.
+ */
+ public static BufferedImage process(BufferedImage source, int maxColors,
+ boolean dither, boolean alphaToBitmask) {
+ int type = source.getType();
+ int[] pixels;
+ // try to get the direct pixels of the BufferedImage
+ // this works for images of type INT_RGB, INT_ARGB and INT_ARGB_PRE
+ // for all others, a new array with rgb pixels is created!
+ if (type == BufferedImage.TYPE_INT_RGB
+ || type == BufferedImage.TYPE_INT_ARGB
+ || type == BufferedImage.TYPE_INT_ARGB_PRE) {
+ pixels = ((DataBufferInt) source.getRaster().getDataBuffer()).getData();
+ } else {
+ pixels = source.getRGB(0, 0, source.getWidth(), source.getHeight(), null, 0,
source.getWidth());
+ }
+ Cube cube = new Cube(source, pixels, maxColors, dither, alphaToBitmask);
+ cube.classification();
+ cube.reduction();
+ return cube.assignment();
+ }
+
+ static class Cube {
+ BufferedImage source;
+ int[] pixels;
+ int maxColors;
+ byte colorMap[][];
+
+ Node root;
+ int depth;
+
+ boolean dither;
+ boolean alphaToBitmask;
+ boolean addTransparency;
+ // firstColor is set to 1 when when addTransparency is true!
+ int firstColor = 0;
+
+ // counter for the number of colors in the cube. this gets
+ // recalculated often.
+ int numColors;
+
+ // counter for the number of nodes in the tree
+ int numNodes;
+
+ Cube(BufferedImage source, int[] pixels, int maxColors, boolean dither,
+ boolean alphaToBitmask) {
+ this.source = source;
+ this.pixels = pixels;
+ this.maxColors = maxColors;
+ this.dither = dither;
+ this.alphaToBitmask = alphaToBitmask;
+
+ int i = maxColors;
+ // tree_depth = log maxColors
+ // 4
+ for (depth = 1; i != 0; depth++) {
+ i /= 4;
+ }
+ if (depth > 1) {
+ --depth;
+ }
+ if (depth > MAX_TREE_DEPTH) {
+ depth = MAX_TREE_DEPTH;
+ } else if (depth < 2) {
+ depth = 2;
+ }
+
+ root = new Node(this);
+ }
+
+ /*
+ * Procedure Classification begins by initializing a color description
+ * tree of sufficient depth to represent each possible input color in a
+ * leaf. However, it is impractical to generate a fully-formed color
+ * description tree in the classification phase for realistic values of
+ * cmax. If colors components in the input image are quantized to k-bit
+ * precision, so that cmax= 2k-1, the tree would need k levels below the
+ * root node to allow representing each possible input color in a leaf.
+ * This becomes prohibitive because the tree's total number of nodes is
+ * 1 + sum(i=1,k,8k).
+ *
+ * A complete tree would require 19,173,961 nodes for k = 8, cmax = 255.
+ * Therefore, to avoid building a fully populated tree, QUANTIZE: (1)
+ * Initializes data structures for nodes only as they are needed; (2)
+ * Chooses a maximum depth for the tree as a function of the desired
+ * number of colors in the output image (currently log2(colorMap size)).
+ *
+ * For each pixel in the input image, classification scans downward from
+ * the root of the color description tree. At each level of the tree it
+ * identifies the single node which represents a cube in RGB space
+ * containing It updates the following data for each such node:
+ *
+ * numPixels : Number of pixels whose color is contained in the RGB cube
+ * which this node represents;
+ *
+ * unique : Number of pixels whose color is not represented in a node at
+ * lower depth in the tree; initially, n2 = 0 for all nodes except
+ * leaves of the tree.
+ *
+ * totalRed/green/blue : Sums of the red, green, and blue component
+ * values for all pixels not classified at a lower depth. The
+ * combination of these sums and n2 will ultimately characterize the
+ * mean color of a set of pixels represented by this node.
+ */
+ void classification() {
+ addTransparency = false;
+ firstColor = 0;
+ for (int i = 0; i < pixels.length; i++) {
+ int pixel = pixels[i];
+ int red = (pixel >> 16) & 0xff;
+ int green = (pixel >> 8) & 0xff;
+ int blue = (pixel >> 0) & 0xff;
+ int alpha = (pixel >> 24) & 0xff;
+ if (alphaToBitmask)
+ alpha = alpha < 0x80 ? 0 : 0xff;
+
+ if (alpha > 0) {
+ // a hard limit on the number of nodes in the tree
+ if (numNodes > MAX_NODES) {
+ // System.out.println("pruning");
+ root.pruneLevel();
+ --depth;
+ }
+
+ // walk the tree to depth, increasing the
+ // numPixels count for each node
+ Node node = root;
+ for (int level = 1; level <= depth; ++level) {
+ int id = (((red > node.midRed ? 1 : 0) << 0)
+ | ((green > node.midGreen ? 1 : 0) << 1)
+ | ((blue > node.midBlue ? 1 : 0) << 2) | ((alpha
> node.midAlpha ? 1
+ : 0) << 3));
+ if (node.children[id] == null) {
+ node = new Node(node, id, level);
+ } else {
+ node = node.children[id];
+ }
+ node.numPixels++;
+ }
+
+ ++node.unique;
+ node.totalRed += red;
+ node.totalGreen += green;
+ node.totalBlue += blue;
+ node.totalAlpha += alpha;
+ } else if (!addTransparency) {
+ addTransparency = true;
+ numColors++;
+ firstColor = 1; // start at 1 as 0 will be the transparent
+ // color
+ }
+ }
+ }
+
+ /*
+ * reduction repeatedly prunes the tree until the number of nodes with
+ * unique > 0 is less than or equal to the maximum number of colors
+ * allowed in the output image.
+ *
+ * When a node to be pruned has offspring, the pruning procedure invokes
+ * itself recursively in order to prune the tree from the leaves upward.
+ * The statistics of the node being pruned are always added to the
+ * corresponding data in that node's parent. This retains the pruned
+ * node's color characteristics for later averaging.
+ */
+ void reduction() {
+ int threshold = 1;
+ while (numColors > maxColors) {
+ numColors = firstColor;
+ threshold = root.reduce(threshold, Integer.MAX_VALUE);
+ }
+ }
+
+ /**
+ * The result of a closest color search.
+ */
+ static class Search {
+ int distance;
+ int colorIndex;
+ }
+
+ /*
+ * Procedure assignment generates the output image from the pruned tree.
+ * The output image consists of two parts: (1) A color map, which is an
+ * array of color descriptions (RGB triples) for each color present in
+ * the output image; (2) A pixel array, which represents each pixel as
+ * an index into the color map array.
+ *
+ * First, the assignment phase makes one pass over the pruned color
+ * description tree to establish the image's color map. For each node
+ * with n2 > 0, it divides Sr, Sg, and Sb by n2. This produces the mean
+ * color of all pixels that classify no lower than this node. Each of
+ * these colors becomes an entry in the color map.
+ *
+ * Finally, the assignment phase reclassifies each pixel in the pruned
+ * tree to identify the deepest node containing the pixel's color. The
+ * pixel's value in the pixel array becomes the index of this node's
+ * mean color in the color map.
+ */
+ BufferedImage assignment() {
+ colorMap = new byte[4][numColors];
+
+ if (addTransparency) {
+ // if a transparency color is added, firstColor was set to 1,
+ // so color 0 can be used for this
+ colorMap[0][0] = 0;
+ colorMap[1][0] = 0;
+ colorMap[2][0] = 0;
+ colorMap[3][0] = 0;
+ }
+ numColors = firstColor;
+ root.mapColors();
+
+ // determine bit depth for palette
+ int depth;
+ for (depth = 1; depth <= 8; depth++)
+ if ((1 << depth) >= numColors)
+ break;
+
+ // create the right color model, depending on transparency settings:
+ IndexColorModel icm;
+ if (alphaToBitmask) {
+ if (addTransparency)
+ icm = new IndexColorModel(depth, numColors, colorMap[0],
+ colorMap[1], colorMap[2], 0);
+ else
+ icm = new IndexColorModel(depth, numColors, colorMap[0],
+ colorMap[1], colorMap[2]);
+ } else {
+ icm = new IndexColorModel(depth, numColors, colorMap[0],
+ colorMap[1], colorMap[2], colorMap[3]);
+ }
+ // create the indexed BufferedImage:
+ BufferedImage dest = new BufferedImage(source.getWidth(),
+ source.getHeight(), BufferedImage.TYPE_BYTE_INDEXED, icm);
+
+ boolean firstOut = true;
+ if (dither)
+ new DiffusionFilterOp().filter(source, dest);
+ else {
+ Search search = new Search();
+ // convert to indexed color
+ byte[] dst = ((DataBufferByte)
dest.getRaster().getDataBuffer()).getData();
+
+ for (int i = 0; i < pixels.length; i++) {
+ int pixel = pixels[i];
+ int red = (pixel >> 16) & 0xff;
+ int green = (pixel >> 8) & 0xff;
+ int blue = (pixel >> 0) & 0xff;
+ int alpha = (pixel >> 24) & 0xff;
+
+ if (alphaToBitmask)
+ alpha = alpha < 128 ? 0 : 0xff;
+
+ // this is super weird: on some systems, transparent pixels are
+ // not calculated correctly if the following block is taken out.
+ // the bug is very strange, isn't related to the code (compiler
error?)
+ // but doesn't allways happen. as soon as it does, though, it
doesn't
+ // seem to want to go away.
+ // This happened at various times on my two different debian systems
+ // and i never found out how to really fix it. the following line
seems to
+ // prevent it from happening, but i wonder wether there's a
better way
+ // to fix it.
+ // it looks as if the command forces alpha to take on correct
values.
+ // Until now I only knew of effects like that in quantum
mechanics...
+ if (i == 0) {
+ String fix = "" + alpha;
+ }
+
+ if (alpha == 0 && addTransparency) {
+ dst[i] = 0; // transparency color is at 0
+ } else {
+ // walk the tree to find the cube containing that color
+ Node node = root;
+ for (;;) {
+ int id = (((red > node.midRed ? 1 : 0) << 0)
+ | ((green > node.midGreen ? 1 : 0) << 1)
+ | ((blue > node.midBlue ? 1 : 0) << 2) | ((alpha
> node.midAlpha ? 1
+ : 0) << 3));
+ if (node.children[id] == null) {
+ break;
+ }
+ node = node.children[id];
+ }
+
+ if (QUICK) {
+ // if QUICK is set, just use that
+ // node. Strictly speaking, this isn't
+ // necessarily best match.
+ dst[i] = (byte) node.colorIndex;
+ } else {
+ // Find the closest color.
+ search.distance = Integer.MAX_VALUE;
+ node.parent.closestColor(red, green, blue, alpha,
+ search);
+ dst[i] = (byte) search.colorIndex;
+ }
+ }
+ }
+ }
+ return dest;
+ }
+
+ /**
+ * A single Node in the tree.
+ */
+ static class Node {
+ Cube cube;
+
+ // parent node
+ Node parent;
+
+ // children nodes
+ Node children[];
+ int numChildren;
+
+ // our index within our parent
+ int id;
+ // our level within the tree
+ int level;
+ // our color midpoint
+ int midRed;
+ int midGreen;
+ int midBlue;
+ int midAlpha;
+
+ // the pixel count for this node and all children
+ int numPixels;
+
+ // the pixel count for this node
+ int unique;
+ // the sum of all pixels contained in this node
+ int totalRed;
+ int totalGreen;
+ int totalBlue;
+ int totalAlpha;
+
+ // used to build the colorMap
+ int colorIndex;
+
+ Node(Cube cube) {
+ this.cube = cube;
+ this.parent = this;
+ this.children = new Node[MAX_CHILDREN];
+ this.id = 0;
+ this.level = 0;
+
+ this.numPixels = Integer.MAX_VALUE;
+
+ this.midRed = (MAX_RGB + 1) >> 1;
+ this.midGreen = (MAX_RGB + 1) >> 1;
+ this.midBlue = (MAX_RGB + 1) >> 1;
+ this.midAlpha = (MAX_RGB + 1) >> 1;
+ }
+
+ Node(Node parent, int id, int level) {
+ this.cube = parent.cube;
+ this.parent = parent;
+ this.children = new Node[MAX_CHILDREN];
+ this.id = id;
+ this.level = level;
+
+ // add to the cube
+ ++cube.numNodes;
+ if (level == cube.depth) {
+ ++cube.numColors;
+ }
+
+ // add to the parent
+ ++parent.numChildren;
+ parent.children[id] = this;
+
+ // figure out our midpoint
+ int bi = (1 << (MAX_TREE_DEPTH - level)) >> 1;
+ midRed = parent.midRed + ((id & 1) > 0 ? bi : -bi);
+ midGreen = parent.midGreen + ((id & 2) > 0 ? bi : -bi);
+ midBlue = parent.midBlue + ((id & 4) > 0 ? bi : -bi);
+ midAlpha = parent.midAlpha + ((id & 8) > 0 ? bi : -bi);
+ }
+
+ /**
+ * Remove this children node, and make sure our parent absorbs our
+ * pixel statistics.
+ */
+ void pruneChild() {
+ --parent.numChildren;
+ parent.unique += unique;
+ parent.totalRed += totalRed;
+ parent.totalGreen += totalGreen;
+ parent.totalBlue += totalBlue;
+ parent.totalAlpha += totalAlpha;
+ parent.children[id] = null;
+ --cube.numNodes;
+ cube = null;
+ parent = null;
+ }
+
+ /**
+ * Prune the lowest layer of the tree.
+ */
+ void pruneLevel() {
+ if (numChildren != 0) {
+ for (int id = 0; id < MAX_CHILDREN; id++) {
+ if (children[id] != null) {
+ children[id].pruneLevel();
+ }
+ }
+ }
+ if (level == cube.depth) {
+ pruneChild();
+ }
+ }
+
+ /**
+ * Remove any nodes that have fewer than threshold pixels. Also, as
+ * long as we're walking the tree: - figure out the color with the
+ * fewest pixels - recalculate the total number of colors in the
+ * tree
+ */
+ int reduce(int threshold, int nextThreshold) {
+ if (numChildren != 0) {
+ for (int id = 0; id < MAX_CHILDREN; id++) {
+ if (children[id] != null) {
+ nextThreshold = children[id].reduce(threshold,
+ nextThreshold);
+ }
+ }
+ }
+ if (numPixels <= threshold) {
+ pruneChild();
+ } else {
+ if (unique != 0) {
+ cube.numColors++;
+ }
+ if (numPixels < nextThreshold) {
+ nextThreshold = numPixels;
+ }
+ }
+ return nextThreshold;
+ }
+
+ /*
+ * mapColors traverses the color cube tree and notes each colorMap
+ * entry. A colorMap entry is any node in the color cube tree where
+ * the number of unique colors is not zero.
+ */
+ void mapColors() {
+ if (numChildren != 0) {
+ for (int id = 0; id < MAX_CHILDREN; id++) {
+ if (children[id] != null) {
+ children[id].mapColors();
+ }
+ }
+ }
+ if (unique != 0) {
+ int add = unique >> 1;
+ cube.colorMap[0][cube.numColors] = (byte) ((totalRed + add) /
unique);
+ cube.colorMap[1][cube.numColors] = (byte) ((totalGreen + add) /
unique);
+ cube.colorMap[2][cube.numColors] = (byte) ((totalBlue + add) /
unique);
+ cube.colorMap[3][cube.numColors] = (byte) ((totalAlpha + add) /
unique);
+ colorIndex = cube.numColors++;
+ }
+ }
+
+ /*
+ * ClosestColor traverses the color cube tree at a particular node
+ * and determines which colorMap entry best represents the input
+ * color.
+ */
+ void closestColor(int red, int green, int blue, int alpha,
+ Search search) {
+ if (numChildren != 0) {
+ for (int id = 0; id < MAX_CHILDREN; id++) {
+ if (children[id] != null) {
+ children[id].closestColor(red, green, blue, alpha,
+ search);
+ }
+ }
+ }
+
+ if (unique != 0) {
+ int distance = distance(
+ cube.colorMap[0][colorIndex] & 0xff,
+ cube.colorMap[1][colorIndex] & 0xff,
+ cube.colorMap[2][colorIndex] & 0xff,
+ cube.colorMap[3][colorIndex] & 0xff, red, green, blue,
+ alpha);
+ if (distance < search.distance) {
+ search.distance = distance;
+ search.colorIndex = colorIndex;
+ }
+ }
+ }
+
+ /**
+ * Figure out the distance between this node and som color.
+ */
+ final static int distance(int r1, int g1, int b1, int a1, int r2,
+ int g2, int b2, int a2) {
+ int da = a1 - a2;
+ int dr = r1 - r2;
+ int dg = g1 - g2;
+ int db = b1 - b2;
+
+ return da * da + dr * dr + dg * dg + db * db;
+// return (SQUARES[r1 - r2 + MAX_RGB] +
+// SQUARES[g1 - g2 + MAX_RGB] +
+// SQUARES[b1 - b2 + MAX_RGB] +
+// SQUARES[a1 - a2 + MAX_RGB]);
+ }
+
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+ if (parent == this) {
+ buf.append("root");
+ } else {
+ buf.append("node");
+ }
+ buf.append(' ');
+ buf.append(level);
+ buf.append(" [");
+ buf.append(midRed);
+ buf.append(',');
+ buf.append(midGreen);
+ buf.append(',');
+ buf.append(midBlue);
+ buf.append(',');
+ buf.append(midAlpha);
+ buf.append(']');
+ return new String(buf);
+ }
+ }
+ }
+}
\ No newline at end of file
Deleted:
trunk/framework/impl/src/main/resources/META-INF/services/javax.imageio.spi.ImageWriterSpi
===================================================================
---
trunk/framework/impl/src/main/resources/META-INF/services/javax.imageio.spi.ImageWriterSpi 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/framework/impl/src/main/resources/META-INF/services/javax.imageio.spi.ImageWriterSpi 2007-07-10
19:07:38 UTC (rev 1588)
@@ -1,2 +0,0 @@
-org.ajax4jsf.framework.util.image.imageio.gif.GIFImageWriterSpi
-
Modified:
trunk/framework/test/src/test/java/org/ajax4jsf/resource/CSSTemplateTestCase.java
===================================================================
---
trunk/framework/test/src/test/java/org/ajax4jsf/resource/CSSTemplateTestCase.java 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/framework/test/src/test/java/org/ajax4jsf/resource/CSSTemplateTestCase.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -26,11 +26,6 @@
import org.ajax4jsf.framework.util.config.WebXml;
import org.ajax4jsf.renderkit.compiler.TemplateContext;
-import org.ajax4jsf.resource.FacesResourceContext;
-import org.ajax4jsf.resource.InternetResource;
-import org.ajax4jsf.resource.InternetResourceBuilder;
-import org.ajax4jsf.resource.ResourceContext;
-import org.ajax4jsf.resource.TemplateCSSResource;
import org.ajax4jsf.tests.AbstractAjax4JsfTestCase;
import org.apache.shale.test.mock.MockPrintWriter;
Modified:
trunk/framework/test/src/test/java/org/ajax4jsf/resource/InternetResourceServiceTestCase.java
===================================================================
---
trunk/framework/test/src/test/java/org/ajax4jsf/resource/InternetResourceServiceTestCase.java 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/framework/test/src/test/java/org/ajax4jsf/resource/InternetResourceServiceTestCase.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -23,9 +23,6 @@
import java.io.IOException;
-import org.ajax4jsf.resource.InternetResource;
-import org.ajax4jsf.resource.InternetResourceBuilder;
-import org.ajax4jsf.resource.InternetResourceService;
import org.ajax4jsf.tests.AbstractAjax4JsfTestCase;
import org.apache.shale.test.mock.MockServletOutputStream;
Modified:
trunk/framework/test/src/test/java/org/ajax4jsf/resource/MockCacheableResource.java
===================================================================
---
trunk/framework/test/src/test/java/org/ajax4jsf/resource/MockCacheableResource.java 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/framework/test/src/test/java/org/ajax4jsf/resource/MockCacheableResource.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -24,10 +24,6 @@
import java.io.ByteArrayInputStream;
import java.io.InputStream;
-import org.ajax4jsf.resource.InternetResourceBase;
-import org.ajax4jsf.resource.LogfileRenderer;
-import org.ajax4jsf.resource.ResourceContext;
-
/**
* @author shura
*
Modified:
trunk/framework/test/src/test/java/org/ajax4jsf/resource/ParametersEncodingTestCase.java
===================================================================
---
trunk/framework/test/src/test/java/org/ajax4jsf/resource/ParametersEncodingTestCase.java 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/framework/test/src/test/java/org/ajax4jsf/resource/ParametersEncodingTestCase.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -2,7 +2,6 @@
import java.util.Arrays;
-import org.ajax4jsf.resource.ResourceBuilderImpl;
import org.ajax4jsf.tests.AbstractAjax4JsfTestCase;
public class ParametersEncodingTestCase extends AbstractAjax4JsfTestCase {
Modified:
trunk/framework/test/src/test/java/org/ajax4jsf/resource/ResourceServiceThreadsTestCase.java
===================================================================
---
trunk/framework/test/src/test/java/org/ajax4jsf/resource/ResourceServiceThreadsTestCase.java 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/framework/test/src/test/java/org/ajax4jsf/resource/ResourceServiceThreadsTestCase.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -23,9 +23,6 @@
import javax.faces.context.FacesContext;
-import org.ajax4jsf.resource.InternetResource;
-import org.ajax4jsf.resource.InternetResourceBuilder;
-import org.ajax4jsf.resource.InternetResourceService;
import org.ajax4jsf.tests.AbstractThreadedAjax4JsfTestCase;
import org.apache.shale.test.mock.MockHttpServletRequest;
import org.apache.shale.test.mock.MockHttpServletResponse;
Copied: trunk/framework/test/src/test/java/org/richfaces/skin (from rev 1585,
trunk/framework/test/src/test/java/org/ajax4jsf/framework/skin)
Deleted: trunk/framework/test/src/test/java/org/richfaces/skin/Bean.java
===================================================================
--- trunk/framework/test/src/test/java/org/ajax4jsf/framework/skin/Bean.java 2007-07-10
16:14:12 UTC (rev 1585)
+++ trunk/framework/test/src/test/java/org/richfaces/skin/Bean.java 2007-07-10 19:07:38
UTC (rev 1588)
@@ -1,27 +0,0 @@
-/**
- * License Agreement.
- *
- * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-package org.ajax4jsf.framework.skin;
-
-public class Bean {
- public String getName(){return "bindedtest";}
- public String getBean(){return "binded.string";}
-}
\ No newline at end of file
Copied: trunk/framework/test/src/test/java/org/richfaces/skin/Bean.java (from rev 1587,
trunk/framework/test/src/test/java/org/ajax4jsf/framework/skin/Bean.java)
===================================================================
--- trunk/framework/test/src/test/java/org/richfaces/skin/Bean.java
(rev 0)
+++ trunk/framework/test/src/test/java/org/richfaces/skin/Bean.java 2007-07-10 19:07:38
UTC (rev 1588)
@@ -0,0 +1,27 @@
+/**
+ * License Agreement.
+ *
+ * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
+ *
+ * Copyright (C) 2007 Exadel, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package org.richfaces.skin;
+
+public class Bean {
+ public String getName(){return "bindedtest";}
+ public String getBean(){return "binded.string";}
+}
\ No newline at end of file
Deleted: trunk/framework/test/src/test/java/org/richfaces/skin/SkinTestCase.java
===================================================================
---
trunk/framework/test/src/test/java/org/ajax4jsf/framework/skin/SkinTestCase.java 2007-07-10
16:14:12 UTC (rev 1585)
+++ trunk/framework/test/src/test/java/org/richfaces/skin/SkinTestCase.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -1,328 +0,0 @@
-/**
- * License Agreement.
- *
- * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-package org.ajax4jsf.framework.skin;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Properties;
-
-import javax.faces.FacesException;
-import javax.faces.FactoryFinder;
-import javax.faces.application.Application;
-import javax.faces.context.ExternalContext;
-import javax.faces.context.FacesContext;
-import javax.faces.el.ValueBinding;
-
-import junit.framework.TestCase;
-
-import org.easymock.MockControl;
-import org.easymock.classextension.MockClassControl;
-import org.richfaces.skin.Skin;
-import org.richfaces.skin.SkinFactory;
-
-/**
- * Test for Skin/skin factory methods.
- * @author asmirnov(a)exadel.com (latest modification by $Author: alexsmirnov $)
- * @version $Revision: 1.1.2.1 $ $Date: 2007/01/10 14:28:13 $
- *
- */
-public class SkinTestCase extends TestCase {
- private MockControl contextControl;
- private FacesContext mockContext;
-
- private MockControl externalContextControl;
- private ExternalContext mockExternalContext;
-
- private TestApplicationFactory appFactory;
-
- private MockControl bindingControl;
- private ValueBinding mockBinding;
- private MockControl bindingSkinControl;
- private ValueBinding mockSkinBinding;
-
- public SkinTestCase(String name) {
- super(name);
- }
-
- protected void setUp() throws Exception {
- contextControl = MockClassControl.createControl(FacesContext.class);
- mockContext = (FacesContext) contextControl.getMock();
- externalContextControl = MockClassControl.createControl(ExternalContext.class);
- mockExternalContext = (ExternalContext) externalContextControl.getMock();
- bindingControl = MockClassControl.createNiceControl(ValueBinding.class);
- mockBinding = (ValueBinding) bindingControl.getMock();
- bindingSkinControl = MockClassControl.createNiceControl(ValueBinding.class);
- mockSkinBinding = (ValueBinding) bindingSkinControl.getMock();
- FactoryFinder.releaseFactories();
- FactoryFinder.setFactory(FactoryFinder.APPLICATION_FACTORY,
TestApplicationFactory.class.getName());
- appFactory = (TestApplicationFactory)
FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY);
- super.setUp();
- }
-
- protected void tearDown() throws Exception {
- FactoryFinder.releaseFactories();
- SkinFactory.reset();
- super.tearDown();
- }
-
- /*
- * Test method for 'org.richfaces.skin.SkinFactory.getInstance()'
- */
- public void testGetInstance() {
- SkinFactory factory = SkinFactory.getInstance();
- SkinFactory factory1 = SkinFactory.getInstance();
- assertSame(factory,factory1);
- }
-
- /*
- * Test method for 'org.richfaces.skin.SkinFactory.getSkin(FacesContext)'
- */
- public void testGetSkin() {
- SkinFactory factory = SkinFactory.getInstance();
- // setup context mock
- mockContext.getExternalContext();
- contextControl.setReturnValue(mockExternalContext);
- contextControl.replay();
- // setup External context mock
- mockExternalContext.getInitParameter(SkinFactory.SKIN_PARAMETER);
- externalContextControl.setReturnValue("test");
- externalContextControl.replay();
- // setup Application mock
- Application app = appFactory.getApplication();
- app.createValueBinding("#{test.bean}");
- appFactory.getApplicationControl().setReturnValue(mockBinding);
- appFactory.getApplicationControl().replay();
- // setup Value binding mock.
- mockBinding.getValue(mockContext);
- bindingControl.setReturnValue("test.value");
- mockBinding.getValue(mockContext);
- bindingControl.setReturnValue("test.value1");
- bindingControl.setDefaultReturnValue("test.value");
- bindingControl.replay();
- // test call
- Skin skin = factory.getSkin(mockContext);
- // calls control
- contextControl.verify();
- externalContextControl.verify();
- appFactory.getApplicationControl().verify();
- assertNotNull("Null skin!",skin);
- // test properties
- assertEquals("string",skin.getParameter(mockContext,"string.property"));
- assertEquals("base.string",skin.getParameter(mockContext,"base.property"));
- assertEquals("test.value",skin.getParameter(mockContext,"bind.property"));
-// assertEquals("HTML_BASIC",skin.getRenderKitId(mockContext));
- }
-
- /*
- * Test method for 'org.richfaces.skin.SkinFactory.getSkin(FacesContext)'
- */
- public void testSkinReferences() {
- SkinFactory factory = SkinFactory.getInstance();
- // setup context mock
- mockContext.getExternalContext();
- contextControl.setReturnValue(mockExternalContext);
- contextControl.replay();
- // setup External context mock
- mockExternalContext.getInitParameter(SkinFactory.SKIN_PARAMETER);
- externalContextControl.setReturnValue("test");
- externalContextControl.replay();
- // setup Application mock
- Application app = appFactory.getApplication();
- app.createValueBinding("#{test.bean}");
- appFactory.getApplicationControl().setReturnValue(mockBinding);
- appFactory.getApplicationControl().replay();
- // setup Value binding mock.
- mockBinding.getValue(mockContext);
- bindingControl.setReturnValue("test.value");
- mockBinding.getValue(mockContext);
- bindingControl.setReturnValue("test.value1");
- bindingControl.setDefaultReturnValue("test.value");
- bindingControl.replay();
- // test call
- Skin skin = factory.getSkin(mockContext);
- // calls control
- contextControl.verify();
- externalContextControl.verify();
- appFactory.getApplicationControl().verify();
- assertNotNull("Null skin!",skin);
- assertEquals("default",skin.getParameter(mockContext,"c"));
- assertEquals("yyy",skin.getParameter(mockContext,"y"));
- }
-
- /*
- * Test method for 'org.richfaces.skin.SkinFactory.getSkin(FacesContext)'
- */
- public void testCyclicSkinReferences() {
- SkinFactory factory = SkinFactory.getInstance();
- // setup context mock
- mockContext.getExternalContext();
- contextControl.setReturnValue(mockExternalContext);
- contextControl.replay();
- // setup External context mock
- mockExternalContext.getInitParameter(SkinFactory.SKIN_PARAMETER);
- externalContextControl.setReturnValue("cyclic");
- externalContextControl.replay();
- // test call
- try {
- Skin skin = factory.getSkin(mockContext);
- } catch(FacesException e){
- return;
- }
- assertTrue(false);
- }
-
- /*
- * Test method for 'org.richfaces.skin.SkinFactory.getSkin(FacesContext)'
- */
- public void testBadSkinReferences() {
- SkinFactory factory = SkinFactory.getInstance();
- // setup context mock
- mockContext.getExternalContext();
- contextControl.setReturnValue(mockExternalContext);
- contextControl.replay();
- // setup External context mock
- mockExternalContext.getInitParameter(SkinFactory.SKIN_PARAMETER);
- externalContextControl.setReturnValue("noref");
- externalContextControl.replay();
- // test call
- try {
- Skin skin = factory.getSkin(mockContext);
- } catch(FacesException e){
- return;
- }
- assertTrue(false);
- }
- /*
- * Test method for 'org.richfaces.skin.SkinFactory.getSkin(FacesContext)'
- */
- public void testGetBindedSkin() {
- SkinFactory factory = SkinFactory.getInstance();
- // setup context mock
- mockContext.getExternalContext();
- contextControl.setReturnValue(mockExternalContext);
- mockContext.getApplication();
- contextControl.setReturnValue(appFactory.getApplication());
- contextControl.replay();
- // setup External context mock
- mockExternalContext.getInitParameter(SkinFactory.SKIN_PARAMETER);
- externalContextControl.setReturnValue("#{test.skin}");
- externalContextControl.replay();
- // setup Application mock
- Application app = appFactory.getApplication();
- app.createValueBinding("#{test.skin}");
- appFactory.getApplicationControl().setReturnValue(mockSkinBinding);
- app.createValueBinding("#{test.bean}");
- appFactory.getApplicationControl().setReturnValue(mockBinding);
- appFactory.getApplicationControl().replay();
- // setup Value binding mock.
- mockBinding.getValue(mockContext);
- bindingControl.setReturnValue("binded.test.value");
- bindingControl.replay();
- // skin EL binding.
- mockSkinBinding.getValue(mockContext);
- bindingSkinControl.setDefaultReturnValue("bindedtest");
- bindingSkinControl.replay();
- // test call
- Skin skin = factory.getSkin(mockContext);
- assertNotNull("Null skin!",skin);
- // test properties
- assertEquals("bindedstring",skin.getParameter(mockContext,"string.property"));
-// assertEquals("base.string",skin.getParameter(mockContext,"base.property"));
- assertEquals("binded.test.value",skin.getParameter(mockContext,"bind.property"));
- assertEquals("TEST",skin.getRenderKitId(mockContext));
-
-
- // calls control
-// contextControl.verify();
-// externalContextControl.verify();
-// appFactory.getApplicationControl().verify();
-// bindingControl.verify();
-// bindingSkinControl.verify();
-}
-
- public void testSkinHash() {
- SkinFactory factory = SkinFactory.getInstance();
- // setup context mock
- mockContext.getExternalContext();
- contextControl.setDefaultReturnValue(mockExternalContext);
- mockContext.getApplication();
- contextControl.setReturnValue(appFactory.getApplication());
- contextControl.replay();
- // setup External context mock
- mockExternalContext.getInitParameter(SkinFactory.SKIN_PARAMETER);
- externalContextControl.setReturnValue("#{test.skin}");
- Map params = new HashMap();
- mockExternalContext.getRequestMap();
- externalContextControl.setDefaultReturnValue(params);
- externalContextControl.replay();
- // setup Application mock
- Application app = appFactory.getApplication();
- app.createValueBinding("#{test.skin}");
- appFactory.getApplicationControl().setReturnValue(mockSkinBinding);
- app.createValueBinding("#{test.bean}");
- appFactory.getApplicationControl().setReturnValue(mockBinding);
- appFactory.getApplicationControl().replay();
- // setup Value binding mock.
- mockBinding.getValue(mockContext);
- bindingControl.setDefaultReturnValue("binded.test.value");
- bindingControl.replay();
- // skin EL binding.
- mockSkinBinding.getValue(mockContext);
- bindingSkinControl.setDefaultReturnValue("bindedtest");
- bindingSkinControl.replay();
- // test call
- Skin skin = factory.getSkin(mockContext);
- assertNotNull("Null skin!",skin);
- // test properties
- int hash = skin.hashCode(mockContext);
- assertTrue(params.containsKey(SkinImpl.REQUEST_HASH_CODE_PARAMETER));
- assertEquals(hash,skin.hashCode(mockContext));
- params.clear();
- assertEquals(hash,skin.hashCode(mockContext));
- // setup Value binding mock for different value - hash must differ.
- params.clear();
- bindingControl.reset();
- mockBinding.getValue(mockContext);
- bindingControl.setDefaultReturnValue("other.test.value");
- bindingControl.replay();
- assertFalse( hash==skin.hashCode(mockContext) );
-
- }
- /*
- * Test method for 'org.richfaces.skin.SkinFactory.getDefaultProperties()'
- */
- public void testGetDefaultProperties() {
- SkinFactoryImpl factory = (SkinFactoryImpl) SkinFactory.getInstance();
- Properties defaultProps = factory.getDefaultSkinProperties();
-// assertEquals("HTML_BASIC",defaultProps.getProperty("render.kit"));
- // Second default config
- assertEquals("default",defaultProps.getProperty("a"));
- }
-
- /*
- * Test method for 'org.richfaces.skin.SkinFactory.getSkinName(FacesContext)'
- */
- public void testGetSkinName() {
-
- }
-
-}
Copied: trunk/framework/test/src/test/java/org/richfaces/skin/SkinTestCase.java (from rev
1587, trunk/framework/test/src/test/java/org/ajax4jsf/framework/skin/SkinTestCase.java)
===================================================================
--- trunk/framework/test/src/test/java/org/richfaces/skin/SkinTestCase.java
(rev 0)
+++ trunk/framework/test/src/test/java/org/richfaces/skin/SkinTestCase.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -0,0 +1,330 @@
+/**
+ * License Agreement.
+ *
+ * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
+ *
+ * Copyright (C) 2007 Exadel, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package org.richfaces.skin;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.faces.FacesException;
+import javax.faces.FactoryFinder;
+import javax.faces.application.Application;
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+import javax.faces.el.ValueBinding;
+
+import junit.framework.TestCase;
+
+import org.easymock.MockControl;
+import org.easymock.classextension.MockClassControl;
+import org.richfaces.skin.Skin;
+import org.richfaces.skin.SkinFactory;
+import org.richfaces.skin.SkinFactoryImpl;
+import org.richfaces.skin.SkinImpl;
+
+/**
+ * Test for Skin/skin factory methods.
+ * @author asmirnov(a)exadel.com (latest modification by $Author: alexsmirnov $)
+ * @version $Revision: 1.1.2.1 $ $Date: 2007/01/10 14:28:13 $
+ *
+ */
+public class SkinTestCase extends TestCase {
+ private MockControl contextControl;
+ private FacesContext mockContext;
+
+ private MockControl externalContextControl;
+ private ExternalContext mockExternalContext;
+
+ private TestApplicationFactory appFactory;
+
+ private MockControl bindingControl;
+ private ValueBinding mockBinding;
+ private MockControl bindingSkinControl;
+ private ValueBinding mockSkinBinding;
+
+ public SkinTestCase(String name) {
+ super(name);
+ }
+
+ protected void setUp() throws Exception {
+ contextControl = MockClassControl.createControl(FacesContext.class);
+ mockContext = (FacesContext) contextControl.getMock();
+ externalContextControl = MockClassControl.createControl(ExternalContext.class);
+ mockExternalContext = (ExternalContext) externalContextControl.getMock();
+ bindingControl = MockClassControl.createNiceControl(ValueBinding.class);
+ mockBinding = (ValueBinding) bindingControl.getMock();
+ bindingSkinControl = MockClassControl.createNiceControl(ValueBinding.class);
+ mockSkinBinding = (ValueBinding) bindingSkinControl.getMock();
+ FactoryFinder.releaseFactories();
+ FactoryFinder.setFactory(FactoryFinder.APPLICATION_FACTORY,
TestApplicationFactory.class.getName());
+ appFactory = (TestApplicationFactory)
FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY);
+ super.setUp();
+ }
+
+ protected void tearDown() throws Exception {
+ FactoryFinder.releaseFactories();
+ SkinFactory.reset();
+ super.tearDown();
+ }
+
+ /*
+ * Test method for 'org.richfaces.skin.SkinFactory.getInstance()'
+ */
+ public void testGetInstance() {
+ SkinFactory factory = SkinFactory.getInstance();
+ SkinFactory factory1 = SkinFactory.getInstance();
+ assertSame(factory,factory1);
+ }
+
+ /*
+ * Test method for 'org.richfaces.skin.SkinFactory.getSkin(FacesContext)'
+ */
+ public void testGetSkin() {
+ SkinFactory factory = SkinFactory.getInstance();
+ // setup context mock
+ mockContext.getExternalContext();
+ contextControl.setReturnValue(mockExternalContext);
+ contextControl.replay();
+ // setup External context mock
+ mockExternalContext.getInitParameter(SkinFactory.SKIN_PARAMETER);
+ externalContextControl.setReturnValue("test");
+ externalContextControl.replay();
+ // setup Application mock
+ Application app = appFactory.getApplication();
+ app.createValueBinding("#{test.bean}");
+ appFactory.getApplicationControl().setReturnValue(mockBinding);
+ appFactory.getApplicationControl().replay();
+ // setup Value binding mock.
+ mockBinding.getValue(mockContext);
+ bindingControl.setReturnValue("test.value");
+ mockBinding.getValue(mockContext);
+ bindingControl.setReturnValue("test.value1");
+ bindingControl.setDefaultReturnValue("test.value");
+ bindingControl.replay();
+ // test call
+ Skin skin = factory.getSkin(mockContext);
+ // calls control
+ contextControl.verify();
+ externalContextControl.verify();
+ appFactory.getApplicationControl().verify();
+ assertNotNull("Null skin!",skin);
+ // test properties
+ assertEquals("string",skin.getParameter(mockContext,"string.property"));
+ assertEquals("base.string",skin.getParameter(mockContext,"base.property"));
+ assertEquals("test.value",skin.getParameter(mockContext,"bind.property"));
+// assertEquals("HTML_BASIC",skin.getRenderKitId(mockContext));
+ }
+
+ /*
+ * Test method for 'org.richfaces.skin.SkinFactory.getSkin(FacesContext)'
+ */
+ public void testSkinReferences() {
+ SkinFactory factory = SkinFactory.getInstance();
+ // setup context mock
+ mockContext.getExternalContext();
+ contextControl.setReturnValue(mockExternalContext);
+ contextControl.replay();
+ // setup External context mock
+ mockExternalContext.getInitParameter(SkinFactory.SKIN_PARAMETER);
+ externalContextControl.setReturnValue("test");
+ externalContextControl.replay();
+ // setup Application mock
+ Application app = appFactory.getApplication();
+ app.createValueBinding("#{test.bean}");
+ appFactory.getApplicationControl().setReturnValue(mockBinding);
+ appFactory.getApplicationControl().replay();
+ // setup Value binding mock.
+ mockBinding.getValue(mockContext);
+ bindingControl.setReturnValue("test.value");
+ mockBinding.getValue(mockContext);
+ bindingControl.setReturnValue("test.value1");
+ bindingControl.setDefaultReturnValue("test.value");
+ bindingControl.replay();
+ // test call
+ Skin skin = factory.getSkin(mockContext);
+ // calls control
+ contextControl.verify();
+ externalContextControl.verify();
+ appFactory.getApplicationControl().verify();
+ assertNotNull("Null skin!",skin);
+ assertEquals("default",skin.getParameter(mockContext,"c"));
+ assertEquals("yyy",skin.getParameter(mockContext,"y"));
+ }
+
+ /*
+ * Test method for 'org.richfaces.skin.SkinFactory.getSkin(FacesContext)'
+ */
+ public void testCyclicSkinReferences() {
+ SkinFactory factory = SkinFactory.getInstance();
+ // setup context mock
+ mockContext.getExternalContext();
+ contextControl.setReturnValue(mockExternalContext);
+ contextControl.replay();
+ // setup External context mock
+ mockExternalContext.getInitParameter(SkinFactory.SKIN_PARAMETER);
+ externalContextControl.setReturnValue("cyclic");
+ externalContextControl.replay();
+ // test call
+ try {
+ Skin skin = factory.getSkin(mockContext);
+ } catch(FacesException e){
+ return;
+ }
+ assertTrue(false);
+ }
+
+ /*
+ * Test method for 'org.richfaces.skin.SkinFactory.getSkin(FacesContext)'
+ */
+ public void testBadSkinReferences() {
+ SkinFactory factory = SkinFactory.getInstance();
+ // setup context mock
+ mockContext.getExternalContext();
+ contextControl.setReturnValue(mockExternalContext);
+ contextControl.replay();
+ // setup External context mock
+ mockExternalContext.getInitParameter(SkinFactory.SKIN_PARAMETER);
+ externalContextControl.setReturnValue("noref");
+ externalContextControl.replay();
+ // test call
+ try {
+ Skin skin = factory.getSkin(mockContext);
+ } catch(FacesException e){
+ return;
+ }
+ assertTrue(false);
+ }
+ /*
+ * Test method for 'org.richfaces.skin.SkinFactory.getSkin(FacesContext)'
+ */
+ public void testGetBindedSkin() {
+ SkinFactory factory = SkinFactory.getInstance();
+ // setup context mock
+ mockContext.getExternalContext();
+ contextControl.setReturnValue(mockExternalContext);
+ mockContext.getApplication();
+ contextControl.setReturnValue(appFactory.getApplication());
+ contextControl.replay();
+ // setup External context mock
+ mockExternalContext.getInitParameter(SkinFactory.SKIN_PARAMETER);
+ externalContextControl.setReturnValue("#{test.skin}");
+ externalContextControl.replay();
+ // setup Application mock
+ Application app = appFactory.getApplication();
+ app.createValueBinding("#{test.skin}");
+ appFactory.getApplicationControl().setReturnValue(mockSkinBinding);
+ app.createValueBinding("#{test.bean}");
+ appFactory.getApplicationControl().setReturnValue(mockBinding);
+ appFactory.getApplicationControl().replay();
+ // setup Value binding mock.
+ mockBinding.getValue(mockContext);
+ bindingControl.setReturnValue("binded.test.value");
+ bindingControl.replay();
+ // skin EL binding.
+ mockSkinBinding.getValue(mockContext);
+ bindingSkinControl.setDefaultReturnValue("bindedtest");
+ bindingSkinControl.replay();
+ // test call
+ Skin skin = factory.getSkin(mockContext);
+ assertNotNull("Null skin!",skin);
+ // test properties
+ assertEquals("bindedstring",skin.getParameter(mockContext,"string.property"));
+// assertEquals("base.string",skin.getParameter(mockContext,"base.property"));
+ assertEquals("binded.test.value",skin.getParameter(mockContext,"bind.property"));
+ assertEquals("TEST",skin.getRenderKitId(mockContext));
+
+
+ // calls control
+// contextControl.verify();
+// externalContextControl.verify();
+// appFactory.getApplicationControl().verify();
+// bindingControl.verify();
+// bindingSkinControl.verify();
+}
+
+ public void testSkinHash() {
+ SkinFactory factory = SkinFactory.getInstance();
+ // setup context mock
+ mockContext.getExternalContext();
+ contextControl.setDefaultReturnValue(mockExternalContext);
+ mockContext.getApplication();
+ contextControl.setReturnValue(appFactory.getApplication());
+ contextControl.replay();
+ // setup External context mock
+ mockExternalContext.getInitParameter(SkinFactory.SKIN_PARAMETER);
+ externalContextControl.setReturnValue("#{test.skin}");
+ Map params = new HashMap();
+ mockExternalContext.getRequestMap();
+ externalContextControl.setDefaultReturnValue(params);
+ externalContextControl.replay();
+ // setup Application mock
+ Application app = appFactory.getApplication();
+ app.createValueBinding("#{test.skin}");
+ appFactory.getApplicationControl().setReturnValue(mockSkinBinding);
+ app.createValueBinding("#{test.bean}");
+ appFactory.getApplicationControl().setReturnValue(mockBinding);
+ appFactory.getApplicationControl().replay();
+ // setup Value binding mock.
+ mockBinding.getValue(mockContext);
+ bindingControl.setDefaultReturnValue("binded.test.value");
+ bindingControl.replay();
+ // skin EL binding.
+ mockSkinBinding.getValue(mockContext);
+ bindingSkinControl.setDefaultReturnValue("bindedtest");
+ bindingSkinControl.replay();
+ // test call
+ Skin skin = factory.getSkin(mockContext);
+ assertNotNull("Null skin!",skin);
+ // test properties
+ int hash = skin.hashCode(mockContext);
+ assertTrue(params.containsKey(SkinImpl.REQUEST_HASH_CODE_PARAMETER));
+ assertEquals(hash,skin.hashCode(mockContext));
+ params.clear();
+ assertEquals(hash,skin.hashCode(mockContext));
+ // setup Value binding mock for different value - hash must differ.
+ params.clear();
+ bindingControl.reset();
+ mockBinding.getValue(mockContext);
+ bindingControl.setDefaultReturnValue("other.test.value");
+ bindingControl.replay();
+ assertFalse( hash==skin.hashCode(mockContext) );
+
+ }
+ /*
+ * Test method for 'org.richfaces.skin.SkinFactory.getDefaultProperties()'
+ */
+ public void testGetDefaultProperties() {
+ SkinFactoryImpl factory = (SkinFactoryImpl) SkinFactory.getInstance();
+ Properties defaultProps = factory.getDefaultSkinProperties();
+// assertEquals("HTML_BASIC",defaultProps.getProperty("render.kit"));
+ // Second default config
+ assertEquals("default",defaultProps.getProperty("a"));
+ }
+
+ /*
+ * Test method for 'org.richfaces.skin.SkinFactory.getSkinName(FacesContext)'
+ */
+ public void testGetSkinName() {
+
+ }
+
+}
Deleted: trunk/framework/test/src/test/java/org/richfaces/skin/SkinTests.java
===================================================================
---
trunk/framework/test/src/test/java/org/ajax4jsf/framework/skin/SkinTests.java 2007-07-10
16:14:12 UTC (rev 1585)
+++ trunk/framework/test/src/test/java/org/richfaces/skin/SkinTests.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -1,39 +0,0 @@
-/**
- * License Agreement.
- *
- * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-package org.ajax4jsf.framework.skin;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-public class SkinTests {
-
- public static Test suite() {
- TestSuite suite = new TestSuite(
- "Test for org.richfaces.skin");
- //$JUnit-BEGIN$
- suite.addTestSuite(SkinThreadsTestCase.class);
- suite.addTestSuite(SkinTestCase.class);
- //$JUnit-END$
- return suite;
- }
-
-}
Copied: trunk/framework/test/src/test/java/org/richfaces/skin/SkinTests.java (from rev
1587, trunk/framework/test/src/test/java/org/ajax4jsf/framework/skin/SkinTests.java)
===================================================================
--- trunk/framework/test/src/test/java/org/richfaces/skin/SkinTests.java
(rev 0)
+++ trunk/framework/test/src/test/java/org/richfaces/skin/SkinTests.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -0,0 +1,39 @@
+/**
+ * License Agreement.
+ *
+ * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
+ *
+ * Copyright (C) 2007 Exadel, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package org.richfaces.skin;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class SkinTests {
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(
+ "Test for org.richfaces.skin");
+ //$JUnit-BEGIN$
+ suite.addTestSuite(SkinThreadsTestCase.class);
+ suite.addTestSuite(SkinTestCase.class);
+ //$JUnit-END$
+ return suite;
+ }
+
+}
Deleted: trunk/framework/test/src/test/java/org/richfaces/skin/SkinThreadsTestCase.java
===================================================================
---
trunk/framework/test/src/test/java/org/ajax4jsf/framework/skin/SkinThreadsTestCase.java 2007-07-10
16:14:12 UTC (rev 1585)
+++
trunk/framework/test/src/test/java/org/richfaces/skin/SkinThreadsTestCase.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -1,112 +0,0 @@
-/**
- * License Agreement.
- *
- * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-package org.ajax4jsf.framework.skin;
-
-import javax.faces.context.FacesContext;
-
-import org.ajax4jsf.tests.AbstractThreadedAjax4JsfTestCase;
-import org.richfaces.skin.Skin;
-import org.richfaces.skin.SkinFactory;
-
-/**
- * @author asmirnov(a)exadel.com (latest modification by $Author: ishabalov $)
- * @version $Revision: 1.1.2.2 $ $Date: 2007/02/20 20:58:11 $
- *
- */
-public class SkinThreadsTestCase extends AbstractThreadedAjax4JsfTestCase {
-
- /**
- * @param s
- */
- public SkinThreadsTestCase(String s) {
- super(s);
- // TODO Auto-generated constructor stub
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.exadel.vcp.tests.VcpJsfTestCase#setUp()
- */
-public void setUp() throws Exception {
- // TODO Auto-generated method stub
- super.setUp();
- servletContext.setAttribute("skin", new Bean());
- }
- /*
- * (non-Javadoc)
- *
- * @see com.exadel.vcp.tests.VcpJsfTestCase#tearDown()
- */
- public void tearDown() throws Exception {
- // TODO Auto-generated method stub
- super.tearDown();
- }
-
-
- public class SkinTestRunnable extends TestCaseRunnable {
-
-
- /**
- *
- */
- public SkinTestRunnable() {
- // TODO Auto-generated constructor stub
- }
-
- /* (non-Javadoc)
- * @see
com.exadel.vcp.tests.ThreadedVcpJsfTestCase.TestCaseRunnable#runTestCase(javax.faces.context.FacesContext)
- */
- public void runTestCase(FacesContext context) throws Throwable {
- context.getExternalContext().getRequestMap().put("test", new Bean());
- Skin skin = SkinFactory.getInstance().getSkin(context);
- assertNotNull(skin);
- assertEquals("TEST", skin.getRenderKitId(context));
- assertEquals("binded.string", skin.getParameter(context,
"bind.property"));
- assertEquals("bindedstring", skin.getParameter(context,
"string.property"));
- assertEquals("10", skin.getParameter(context, "int.property"));
- assertNull(skin.getParameter(context, "notexist"));
- }
-
- }
-
- /**
- * Test skin factory for thread-safe.
- */
- public void testThreadsafe() {
- TestCaseRunnable[] runnables = new TestCaseRunnable[20];
- for (int i = 0; i < runnables.length; i++) {
- runnables[i] = new SkinTestRunnable();
-
- }
- this.runTestCaseRunnables(runnables);
- }
- /*
- * (non-Javadoc)
- *
- * @see com.exadel.vcp.tests.VcpJsfTestCase#getSkinName()
- */
- protected String getSkinName() {
- // TODO Auto-generated method stub
- return "#{skin.name}";
- }
-}
Copied: trunk/framework/test/src/test/java/org/richfaces/skin/SkinThreadsTestCase.java
(from rev 1587,
trunk/framework/test/src/test/java/org/ajax4jsf/framework/skin/SkinThreadsTestCase.java)
===================================================================
--- trunk/framework/test/src/test/java/org/richfaces/skin/SkinThreadsTestCase.java
(rev 0)
+++
trunk/framework/test/src/test/java/org/richfaces/skin/SkinThreadsTestCase.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -0,0 +1,112 @@
+/**
+ * License Agreement.
+ *
+ * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
+ *
+ * Copyright (C) 2007 Exadel, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package org.richfaces.skin;
+
+import javax.faces.context.FacesContext;
+
+import org.ajax4jsf.tests.AbstractThreadedAjax4JsfTestCase;
+import org.richfaces.skin.Skin;
+import org.richfaces.skin.SkinFactory;
+
+/**
+ * @author asmirnov(a)exadel.com (latest modification by $Author: ishabalov $)
+ * @version $Revision: 1.1.2.2 $ $Date: 2007/02/20 20:58:11 $
+ *
+ */
+public class SkinThreadsTestCase extends AbstractThreadedAjax4JsfTestCase {
+
+ /**
+ * @param s
+ */
+ public SkinThreadsTestCase(String s) {
+ super(s);
+ // TODO Auto-generated constructor stub
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.exadel.vcp.tests.VcpJsfTestCase#setUp()
+ */
+public void setUp() throws Exception {
+ // TODO Auto-generated method stub
+ super.setUp();
+ servletContext.setAttribute("skin", new Bean());
+ }
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.exadel.vcp.tests.VcpJsfTestCase#tearDown()
+ */
+ public void tearDown() throws Exception {
+ // TODO Auto-generated method stub
+ super.tearDown();
+ }
+
+
+ public class SkinTestRunnable extends TestCaseRunnable {
+
+
+ /**
+ *
+ */
+ public SkinTestRunnable() {
+ // TODO Auto-generated constructor stub
+ }
+
+ /* (non-Javadoc)
+ * @see
com.exadel.vcp.tests.ThreadedVcpJsfTestCase.TestCaseRunnable#runTestCase(javax.faces.context.FacesContext)
+ */
+ public void runTestCase(FacesContext context) throws Throwable {
+ context.getExternalContext().getRequestMap().put("test", new Bean());
+ Skin skin = SkinFactory.getInstance().getSkin(context);
+ assertNotNull(skin);
+ assertEquals("TEST", skin.getRenderKitId(context));
+ assertEquals("binded.string", skin.getParameter(context,
"bind.property"));
+ assertEquals("bindedstring", skin.getParameter(context,
"string.property"));
+ assertEquals("10", skin.getParameter(context, "int.property"));
+ assertNull(skin.getParameter(context, "notexist"));
+ }
+
+ }
+
+ /**
+ * Test skin factory for thread-safe.
+ */
+ public void testThreadsafe() {
+ TestCaseRunnable[] runnables = new TestCaseRunnable[20];
+ for (int i = 0; i < runnables.length; i++) {
+ runnables[i] = new SkinTestRunnable();
+
+ }
+ this.runTestCaseRunnables(runnables);
+ }
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.exadel.vcp.tests.VcpJsfTestCase#getSkinName()
+ */
+ protected String getSkinName() {
+ // TODO Auto-generated method stub
+ return "#{skin.name}";
+ }
+}
Deleted:
trunk/framework/test/src/test/java/org/richfaces/skin/TestApplicationFactory.java
===================================================================
---
trunk/framework/test/src/test/java/org/ajax4jsf/framework/skin/TestApplicationFactory.java 2007-07-10
16:14:12 UTC (rev 1585)
+++
trunk/framework/test/src/test/java/org/richfaces/skin/TestApplicationFactory.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -1,115 +0,0 @@
-/**
- * License Agreement.
- *
- * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-package org.ajax4jsf.framework.skin;
-
-
-
-import javax.faces.application.Application;
-
-import javax.faces.application.ApplicationFactory;
-
-
-
-import org.easymock.MockControl;
-
-import org.easymock.classextension.MockClassControl;
-
-
-
-/**
-
- * @author asmirnov(a)exadel.com (latest modification by $Author: ishabalov $)
-
- * @version $Revision: 1.1.2.2 $ $Date: 2007/02/20 20:58:11 $
-
- *
-
- */
-
-public class TestApplicationFactory extends ApplicationFactory {
-
-
-
- private MockControl applicationControl;
-
- private Application mockApplication;
-
-
-
- public TestApplicationFactory(){
-
- applicationControl = MockClassControl.createControl(Application.class);
-
- mockApplication = (Application) applicationControl.getMock();
-
- }
-
-
-
- /* (non-Javadoc)
-
- * @see javax.faces.application.ApplicationFactory#getApplication()
-
- */
-
- public Application getApplication() {
-
- // TODO Auto-generated method stub
-
- return mockApplication;
-
- }
-
-
-
- /* (non-Javadoc)
-
- * @see
javax.faces.application.ApplicationFactory#setApplication(javax.faces.application.Application)
-
- */
-
- public void setApplication(Application arg0) {
-
- // TODO Auto-generated method stub
-
-
-
- }
-
-
-
- /**
-
- * @return Returns the applicationControl.
-
- */
-
- public MockControl getApplicationControl() {
-
- return applicationControl;
-
- }
-
-
-
-}
-
Copied: trunk/framework/test/src/test/java/org/richfaces/skin/TestApplicationFactory.java
(from rev 1587,
trunk/framework/test/src/test/java/org/ajax4jsf/framework/skin/TestApplicationFactory.java)
===================================================================
--- trunk/framework/test/src/test/java/org/richfaces/skin/TestApplicationFactory.java
(rev 0)
+++
trunk/framework/test/src/test/java/org/richfaces/skin/TestApplicationFactory.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -0,0 +1,115 @@
+/**
+ * License Agreement.
+ *
+ * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
+ *
+ * Copyright (C) 2007 Exadel, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package org.richfaces.skin;
+
+
+
+import javax.faces.application.Application;
+
+import javax.faces.application.ApplicationFactory;
+
+
+
+import org.easymock.MockControl;
+
+import org.easymock.classextension.MockClassControl;
+
+
+
+/**
+
+ * @author asmirnov(a)exadel.com (latest modification by $Author: ishabalov $)
+
+ * @version $Revision: 1.1.2.2 $ $Date: 2007/02/20 20:58:11 $
+
+ *
+
+ */
+
+public class TestApplicationFactory extends ApplicationFactory {
+
+
+
+ private MockControl applicationControl;
+
+ private Application mockApplication;
+
+
+
+ public TestApplicationFactory(){
+
+ applicationControl = MockClassControl.createControl(Application.class);
+
+ mockApplication = (Application) applicationControl.getMock();
+
+ }
+
+
+
+ /* (non-Javadoc)
+
+ * @see javax.faces.application.ApplicationFactory#getApplication()
+
+ */
+
+ public Application getApplication() {
+
+ // TODO Auto-generated method stub
+
+ return mockApplication;
+
+ }
+
+
+
+ /* (non-Javadoc)
+
+ * @see
javax.faces.application.ApplicationFactory#setApplication(javax.faces.application.Application)
+
+ */
+
+ public void setApplication(Application arg0) {
+
+ // TODO Auto-generated method stub
+
+
+
+ }
+
+
+
+ /**
+
+ * @return Returns the applicationControl.
+
+ */
+
+ public MockControl getApplicationControl() {
+
+ return applicationControl;
+
+ }
+
+
+
+}
+
Modified: trunk/samples/useCases/src/main/java/control/test/ControlBackingBean.java
===================================================================
--- trunk/samples/useCases/src/main/java/control/test/ControlBackingBean.java 2007-07-10
18:39:35 UTC (rev 1587)
+++ trunk/samples/useCases/src/main/java/control/test/ControlBackingBean.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -13,9 +13,11 @@
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+
import javax.faces.event.ActionEvent;
-import org.ajax4jsf.ajax.html.HtmlAjaxRepeat;
+import org.ajax4jsf.component.html.HtmlAjaxRepeat;
+
/**
*
* @author Administrador
Modified: trunk/samples/useCases/src/test/java/org/ajax4jsf/BeanTest.java
===================================================================
--- trunk/samples/useCases/src/test/java/org/ajax4jsf/BeanTest.java 2007-07-10 18:39:35
UTC (rev 1587)
+++ trunk/samples/useCases/src/test/java/org/ajax4jsf/BeanTest.java 2007-07-10 19:07:38
UTC (rev 1588)
@@ -21,9 +21,7 @@
package org.ajax4jsf;
-import junit.framework.Test;
import junit.framework.TestCase;
-import junit.framework.TestSuite;
/**
*/
Modified:
trunk/ui/dataFilterSlider/src/main/java/org/richfaces/component/UIDataFltrSlider.java
===================================================================
---
trunk/ui/dataFilterSlider/src/main/java/org/richfaces/component/UIDataFltrSlider.java 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/ui/dataFilterSlider/src/main/java/org/richfaces/component/UIDataFltrSlider.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -21,23 +21,25 @@
package org.richfaces.component;
-import org.richfaces.event.DataFilterSliderEvent;
-import org.richfaces.event.DataFilterSliderListener;
-import org.richfaces.event.DataFilterSliderSource;
-import org.richfaces.event.DataFilterSliderAdapter;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
import javax.faces.component.UIComponent;
import javax.faces.component.UIComponentBase;
import javax.faces.component.UIData;
import javax.faces.context.FacesContext;
-import javax.faces.event.*;
+import javax.faces.el.MethodBinding;
+import javax.faces.event.AbortProcessingException;
+import javax.faces.event.FacesEvent;
import javax.faces.model.ListDataModel;
-import javax.faces.el.MethodBinding;
-import java.lang.reflect.InvocationTargetException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
+import org.richfaces.event.DataFilterSliderAdapter;
+import org.richfaces.event.DataFilterSliderEvent;
+import org.richfaces.event.DataFilterSliderListener;
+import org.richfaces.event.DataFilterSliderSource;
+
/**
* JSF component class
*/
Modified:
trunk/ui/dataFilterSlider/src/main/java/org/richfaces/taglib/DataFilterSliderListenerTagHandler.java
===================================================================
---
trunk/ui/dataFilterSlider/src/main/java/org/richfaces/taglib/DataFilterSliderListenerTagHandler.java 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/ui/dataFilterSlider/src/main/java/org/richfaces/taglib/DataFilterSliderListenerTagHandler.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -21,17 +21,21 @@
package org.richfaces.taglib;
-import com.sun.facelets.tag.jsf.ComponentConfig;
-import com.sun.facelets.tag.jsf.ComponentHandler;
-import com.sun.facelets.tag.*;
-import com.sun.facelets.FaceletContext;
-
+import javax.faces.component.UIComponent;
import javax.faces.el.MethodBinding;
-import javax.faces.component.UIComponent;
import org.richfaces.event.DataFilterSliderEvent;
+import com.sun.facelets.FaceletContext;
+import com.sun.facelets.tag.MetaRule;
+import com.sun.facelets.tag.MetaRuleset;
+import com.sun.facelets.tag.Metadata;
+import com.sun.facelets.tag.MetadataTarget;
+import com.sun.facelets.tag.TagAttribute;
+import com.sun.facelets.tag.jsf.ComponentConfig;
+import com.sun.facelets.tag.jsf.ComponentHandler;
+
public class DataFilterSliderListenerTagHandler extends ComponentHandler {
private final static String SLIDER_LISTENER = "sliderListener";
Modified:
trunk/ui/dataFilterSlider/src/test/java/org/richfaces/component/DataFilterSliderComponentTest.java
===================================================================
---
trunk/ui/dataFilterSlider/src/test/java/org/richfaces/component/DataFilterSliderComponentTest.java 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/ui/dataFilterSlider/src/test/java/org/richfaces/component/DataFilterSliderComponentTest.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -31,7 +31,6 @@
import javax.faces.component.UICommand;
import javax.faces.component.UIComponent;
import javax.faces.component.UIForm;
-import javax.faces.component.UIViewRoot;
import javax.faces.component.html.HtmlCommandLink;
import javax.faces.component.html.HtmlForm;
import javax.faces.context.FacesContext;
@@ -42,11 +41,11 @@
import javax.faces.el.ValueBinding;
import javax.servlet.http.HttpServletResponse;
-import org.ajax4jsf.framework.util.image.ImageInfo;
import org.ajax4jsf.resource.InternetResource;
import org.ajax4jsf.resource.InternetResourceBuilder;
import org.ajax4jsf.resource.Java2Dresource;
import org.ajax4jsf.resource.ResourceBuilderImpl;
+import org.ajax4jsf.resource.image.ImageInfo;
import org.ajax4jsf.tests.AbstractAjax4JsfTestCase;
import org.apache.commons.lang.StringUtils;
import org.richfaces.event.DataFilterSliderAdapter;
Modified:
trunk/ui/dropdown-menu/src/test/java/org/richfaces/component/DropDownMenuComponentTest.java
===================================================================
---
trunk/ui/dropdown-menu/src/test/java/org/richfaces/component/DropDownMenuComponentTest.java 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/ui/dropdown-menu/src/test/java/org/richfaces/component/DropDownMenuComponentTest.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -22,27 +22,27 @@
package org.richfaces.component;
-import com.gargoylesoftware.htmlunit.Page;
-import com.gargoylesoftware.htmlunit.html.HtmlElement;
-import com.gargoylesoftware.htmlunit.html.HtmlPage;
-import com.gargoylesoftware.htmlunit.html.HtmlScript;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
-import org.ajax4jsf.framework.util.image.ImageInfo;
+import javax.faces.component.UIForm;
+import javax.faces.component.html.HtmlForm;
+import javax.servlet.http.HttpServletResponse;
+
import org.ajax4jsf.resource.InternetResource;
import org.ajax4jsf.resource.InternetResourceBuilder;
import org.ajax4jsf.resource.ResourceBuilderImpl;
+import org.ajax4jsf.resource.image.ImageInfo;
import org.ajax4jsf.tests.AbstractAjax4JsfTestCase;
import org.apache.commons.lang.StringUtils;
-import javax.faces.component.UIForm;
-import javax.faces.component.html.HtmlForm;
-import javax.servlet.http.HttpServletResponse;
+import com.gargoylesoftware.htmlunit.Page;
+import com.gargoylesoftware.htmlunit.html.HtmlElement;
+import com.gargoylesoftware.htmlunit.html.HtmlPage;
+import com.gargoylesoftware.htmlunit.html.HtmlScript;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-
/**
* Unit test for Datascroller component.
*/
Modified:
trunk/ui/inputnumber-slider/src/test/java/org/richfaces/component/InputNumberSliderComponentTest.java
===================================================================
---
trunk/ui/inputnumber-slider/src/test/java/org/richfaces/component/InputNumberSliderComponentTest.java 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/ui/inputnumber-slider/src/test/java/org/richfaces/component/InputNumberSliderComponentTest.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -21,20 +21,11 @@
package org.richfaces.component;
-import com.gargoylesoftware.htmlunit.KeyValuePair;
-import com.gargoylesoftware.htmlunit.Page;
-import com.gargoylesoftware.htmlunit.html.*;
-import org.ajax4jsf.framework.util.image.ImageInfo;
-import org.ajax4jsf.resource.InternetResource;
-import org.ajax4jsf.resource.InternetResourceBuilder;
-import org.ajax4jsf.resource.Java2Dresource;
-import org.ajax4jsf.resource.ResourceBuilderImpl;
-import org.ajax4jsf.tests.AbstractAjax4JsfTestCase;
-import org.apache.commons.lang.StringUtils;
-import org.richfaces.renderkit.html.images.SliderArrowImage;
-import org.richfaces.renderkit.html.images.SliderArrowSelectedImage;
-import org.richfaces.renderkit.html.images.SliderFieldGradient;
-import org.richfaces.renderkit.html.images.SliderTrackGradient;
+import java.awt.Dimension;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
import javax.faces.component.UICommand;
import javax.faces.component.UIComponent;
@@ -46,12 +37,28 @@
import javax.faces.el.PropertyNotFoundException;
import javax.faces.el.ValueBinding;
import javax.servlet.http.HttpServletResponse;
-import java.awt.*;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
+import org.ajax4jsf.resource.InternetResource;
+import org.ajax4jsf.resource.InternetResourceBuilder;
+import org.ajax4jsf.resource.Java2Dresource;
+import org.ajax4jsf.resource.ResourceBuilderImpl;
+import org.ajax4jsf.resource.image.ImageInfo;
+import org.ajax4jsf.tests.AbstractAjax4JsfTestCase;
+import org.apache.commons.lang.StringUtils;
+import org.richfaces.renderkit.html.images.SliderArrowImage;
+import org.richfaces.renderkit.html.images.SliderArrowSelectedImage;
+import org.richfaces.renderkit.html.images.SliderFieldGradient;
+import org.richfaces.renderkit.html.images.SliderTrackGradient;
+
+import com.gargoylesoftware.htmlunit.KeyValuePair;
+import com.gargoylesoftware.htmlunit.Page;
+import com.gargoylesoftware.htmlunit.html.DomNode;
+import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
+import com.gargoylesoftware.htmlunit.html.HtmlElement;
+import com.gargoylesoftware.htmlunit.html.HtmlInput;
+import com.gargoylesoftware.htmlunit.html.HtmlPage;
+import com.gargoylesoftware.htmlunit.html.HtmlScript;
+
/** Unit test for simple Component. */
public class InputNumberSliderComponentTest extends AbstractAjax4JsfTestCase {
Modified:
trunk/ui/inputnumber-spinner/src/main/java/org/richfaces/renderkit/html/images/background/SpinnerButtonGradient.java
===================================================================
---
trunk/ui/inputnumber-spinner/src/main/java/org/richfaces/renderkit/html/images/background/SpinnerButtonGradient.java 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/ui/inputnumber-spinner/src/main/java/org/richfaces/renderkit/html/images/background/SpinnerButtonGradient.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -21,11 +21,6 @@
package org.richfaces.renderkit.html.images.background;
-import java.awt.Dimension;
-
-import javax.faces.context.FacesContext;
-
-import org.ajax4jsf.resource.ResourceContext;
import org.richfaces.renderkit.html.BaseGradient;
public class SpinnerButtonGradient extends BaseGradient {
Modified:
trunk/ui/inputnumber-spinner/src/main/java/org/richfaces/renderkit/html/images/background/SpinnerFieldGradient.java
===================================================================
---
trunk/ui/inputnumber-spinner/src/main/java/org/richfaces/renderkit/html/images/background/SpinnerFieldGradient.java 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/ui/inputnumber-spinner/src/main/java/org/richfaces/renderkit/html/images/background/SpinnerFieldGradient.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -21,11 +21,6 @@
package org.richfaces.renderkit.html.images.background;
-import java.awt.Dimension;
-
-import javax.faces.context.FacesContext;
-
-import org.ajax4jsf.resource.ResourceContext;
import org.richfaces.renderkit.html.BaseGradient;
public class SpinnerFieldGradient extends BaseGradient {
Modified:
trunk/ui/inputnumber-spinner/src/test/java/org/richfaces/component/InputNumberSpinnerComponentTest.java
===================================================================
---
trunk/ui/inputnumber-spinner/src/test/java/org/richfaces/component/InputNumberSpinnerComponentTest.java 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/ui/inputnumber-spinner/src/test/java/org/richfaces/component/InputNumberSpinnerComponentTest.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -21,20 +21,12 @@
package org.richfaces.component;
-import com.gargoylesoftware.htmlunit.KeyValuePair;
-import com.gargoylesoftware.htmlunit.Page;
-import com.gargoylesoftware.htmlunit.html.*;
-import org.ajax4jsf.framework.util.image.ImageInfo;
-import org.ajax4jsf.resource.InternetResource;
-import org.ajax4jsf.resource.InternetResourceBuilder;
-import org.ajax4jsf.resource.Java2Dresource;
-import org.ajax4jsf.resource.ResourceBuilderImpl;
-import org.ajax4jsf.tests.AbstractAjax4JsfTestCase;
-import org.apache.commons.lang.StringUtils;
-import org.richfaces.renderkit.html.images.background.SpinnerButtonGradient;
-import org.richfaces.renderkit.html.images.background.SpinnerFieldGradient;
-import org.richfaces.renderkit.html.images.buttons.SpinnerButtonDown;
-import org.richfaces.renderkit.html.images.buttons.SpinnerButtonUp;
+import java.awt.Dimension;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
import javax.faces.component.UICommand;
import javax.faces.component.UIComponent;
@@ -46,10 +38,27 @@
import javax.faces.el.PropertyNotFoundException;
import javax.faces.el.ValueBinding;
import javax.servlet.http.HttpServletResponse;
-import java.awt.*;
-import java.util.*;
-import java.util.List;
+import org.ajax4jsf.resource.InternetResource;
+import org.ajax4jsf.resource.InternetResourceBuilder;
+import org.ajax4jsf.resource.Java2Dresource;
+import org.ajax4jsf.resource.ResourceBuilderImpl;
+import org.ajax4jsf.resource.image.ImageInfo;
+import org.ajax4jsf.tests.AbstractAjax4JsfTestCase;
+import org.apache.commons.lang.StringUtils;
+import org.richfaces.renderkit.html.images.background.SpinnerButtonGradient;
+import org.richfaces.renderkit.html.images.background.SpinnerFieldGradient;
+import org.richfaces.renderkit.html.images.buttons.SpinnerButtonDown;
+import org.richfaces.renderkit.html.images.buttons.SpinnerButtonUp;
+
+import com.gargoylesoftware.htmlunit.KeyValuePair;
+import com.gargoylesoftware.htmlunit.Page;
+import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
+import com.gargoylesoftware.htmlunit.html.HtmlElement;
+import com.gargoylesoftware.htmlunit.html.HtmlInput;
+import com.gargoylesoftware.htmlunit.html.HtmlPage;
+import com.gargoylesoftware.htmlunit.html.HtmlScript;
+
/** Unit test for simple Component. */
public class InputNumberSpinnerComponentTest extends AbstractAjax4JsfTestCase {
Modified:
trunk/ui/menu-components/src/main/java/org/richfaces/renderkit/html/MenuGroupRendererBase.java
===================================================================
---
trunk/ui/menu-components/src/main/java/org/richfaces/renderkit/html/MenuGroupRendererBase.java 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/ui/menu-components/src/main/java/org/richfaces/renderkit/html/MenuGroupRendererBase.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -25,13 +25,10 @@
import javax.faces.context.FacesContext;
-import org.ajax4jsf.renderkit.AjaxRendererUtils;
import org.ajax4jsf.renderkit.ComponentVariables;
import org.ajax4jsf.renderkit.ComponentsVariableResolver;
import org.ajax4jsf.renderkit.HeaderResourcesRendererBase;
-import org.richfaces.component.MenuComponent;
import org.richfaces.component.UIMenuGroup;
-import org.richfaces.component.UIMenuItem;
import org.richfaces.component.util.ViewUtil;
Modified:
trunk/ui/menu-components/src/test/java/org/richfaces/component/MenuGroupComponentTest.java
===================================================================
---
trunk/ui/menu-components/src/test/java/org/richfaces/component/MenuGroupComponentTest.java 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/ui/menu-components/src/test/java/org/richfaces/component/MenuGroupComponentTest.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -32,22 +32,20 @@
import javax.faces.component.html.HtmlOutputText;
import javax.servlet.http.HttpServletResponse;
+import org.ajax4jsf.resource.InternetResource;
+import org.ajax4jsf.resource.InternetResourceBuilder;
+import org.ajax4jsf.resource.ResourceBuilderImpl;
+import org.ajax4jsf.resource.image.ImageInfo;
+import org.ajax4jsf.tests.AbstractAjax4JsfTestCase;
+import org.apache.commons.lang.StringUtils;
import org.richfaces.component.html.HtmlMenuGroup;
import org.richfaces.renderkit.html.images.MenuNodeImage;
import com.gargoylesoftware.htmlunit.Page;
-import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.html.HtmlElement;
+import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.html.HtmlScript;
-import org.ajax4jsf.framework.util.image.ImageInfo;
-import org.ajax4jsf.resource.InternetResource;
-import org.ajax4jsf.resource.InternetResourceBuilder;
-import org.ajax4jsf.resource.ResourceBuilderImpl;
-import org.ajax4jsf.tests.AbstractAjax4JsfTestCase;
-
-import org.apache.commons.lang.StringUtils;
-
/**
* Unit test for MenuGroup Component.
*/
Modified:
trunk/ui/menu-components/src/test/java/org/richfaces/component/MenuItemComponentTest.java
===================================================================
---
trunk/ui/menu-components/src/test/java/org/richfaces/component/MenuItemComponentTest.java 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/ui/menu-components/src/test/java/org/richfaces/component/MenuItemComponentTest.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -33,24 +33,22 @@
import javax.faces.event.PhaseId;
import javax.servlet.http.HttpServletResponse;
-import org.richfaces.component.html.HtmlMenuItem;
-import org.richfaces.renderkit.html.images.background.MenuItemBackground;
-
-import com.gargoylesoftware.htmlunit.Page;
-import com.gargoylesoftware.htmlunit.html.HtmlPage;
-import com.gargoylesoftware.htmlunit.html.HtmlElement;
-import com.gargoylesoftware.htmlunit.html.HtmlScript;
-
-import org.ajax4jsf.framework.util.image.ImageInfo;
import org.ajax4jsf.resource.InternetResource;
import org.ajax4jsf.resource.InternetResourceBuilder;
import org.ajax4jsf.resource.ResourceBuilderImpl;
+import org.ajax4jsf.resource.image.ImageInfo;
import org.ajax4jsf.tests.AbstractAjax4JsfTestCase;
import org.ajax4jsf.tests.MockViewRoot;
-
import org.apache.commons.collections.Buffer;
import org.apache.commons.lang.StringUtils;
+import org.richfaces.component.html.HtmlMenuItem;
+import org.richfaces.renderkit.html.images.background.MenuItemBackground;
+import com.gargoylesoftware.htmlunit.Page;
+import com.gargoylesoftware.htmlunit.html.HtmlElement;
+import com.gargoylesoftware.htmlunit.html.HtmlPage;
+import com.gargoylesoftware.htmlunit.html.HtmlScript;
+
/**
* Unit test for MenuItem Component.
*/
Modified:
trunk/ui/menu-components/src/test/java/org/richfaces/component/MenuSeparatorComponentTest.java
===================================================================
---
trunk/ui/menu-components/src/test/java/org/richfaces/component/MenuSeparatorComponentTest.java 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/ui/menu-components/src/test/java/org/richfaces/component/MenuSeparatorComponentTest.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -25,7 +25,6 @@
import javax.faces.component.html.HtmlForm;
import org.ajax4jsf.tests.AbstractAjax4JsfTestCase;
-import org.richfaces.component.html.HtmlMenuItem;
import org.richfaces.component.html.HtmlMenuSeparator;
import com.gargoylesoftware.htmlunit.html.HtmlElement;
Modified:
trunk/ui/separator/src/main/java/org/richfaces/renderkit/html/images/BevelSeparatorImage.java
===================================================================
---
trunk/ui/separator/src/main/java/org/richfaces/renderkit/html/images/BevelSeparatorImage.java 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/ui/separator/src/main/java/org/richfaces/renderkit/html/images/BevelSeparatorImage.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -21,6 +21,18 @@
package org.richfaces.renderkit.html.images;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.GradientPaint;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.Shape;
+import java.awt.geom.Rectangle2D;
+import java.io.Serializable;
+import java.util.Date;
+
+import javax.faces.context.FacesContext;
+
import org.ajax4jsf.framework.util.HtmlColor;
import org.ajax4jsf.framework.util.HtmlDimensions;
import org.ajax4jsf.resource.GifRenderer;
@@ -31,12 +43,6 @@
import org.richfaces.skin.Skin;
import org.richfaces.skin.SkinFactory;
-import javax.faces.context.FacesContext;
-import java.awt.*;
-import java.awt.geom.Rectangle2D;
-import java.io.Serializable;
-import java.util.Date;
-
/**
* @author Maksim Kaszynski, Filip Antonov
*/
Modified:
trunk/ui/separator/src/main/java/org/richfaces/renderkit/html/images/SimpleSeparatorImage.java
===================================================================
---
trunk/ui/separator/src/main/java/org/richfaces/renderkit/html/images/SimpleSeparatorImage.java 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/ui/separator/src/main/java/org/richfaces/renderkit/html/images/SimpleSeparatorImage.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -21,6 +21,16 @@
package org.richfaces.renderkit.html.images;
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import java.awt.image.RenderedImage;
+import java.io.Serializable;
+import java.util.Date;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+
import org.ajax4jsf.framework.util.HtmlColor;
import org.ajax4jsf.framework.util.HtmlDimensions;
import org.ajax4jsf.resource.GifRenderer;
@@ -31,14 +41,6 @@
import org.richfaces.skin.Skin;
import org.richfaces.skin.SkinFactory;
-import javax.faces.component.UIComponent;
-import javax.faces.context.FacesContext;
-import java.awt.*;
-import java.awt.image.BufferedImage;
-import java.awt.image.RenderedImage;
-import java.io.Serializable;
-import java.util.Date;
-
/**
* @author Konstantin Mishin, Filip Antonov
*/
Modified:
trunk/ui/separator/src/test/java/org/richfaces/component/SeparatorComponentTest.java
===================================================================
---
trunk/ui/separator/src/test/java/org/richfaces/component/SeparatorComponentTest.java 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/ui/separator/src/test/java/org/richfaces/component/SeparatorComponentTest.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -27,10 +27,10 @@
import javax.faces.component.html.HtmlOutputText;
import javax.servlet.http.HttpServletResponse;
-import org.ajax4jsf.framework.util.image.ImageInfo;
import org.ajax4jsf.resource.InternetResource;
import org.ajax4jsf.resource.InternetResourceBuilder;
import org.ajax4jsf.resource.ResourceBuilderImpl;
+import org.ajax4jsf.resource.image.ImageInfo;
import org.ajax4jsf.tests.AbstractAjax4JsfTestCase;
import com.gargoylesoftware.htmlunit.Page;
Modified:
trunk/ui/tabPanel/src/main/java/org/richfaces/renderkit/images/TabStripeImage.java
===================================================================
---
trunk/ui/tabPanel/src/main/java/org/richfaces/renderkit/images/TabStripeImage.java 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/ui/tabPanel/src/main/java/org/richfaces/renderkit/images/TabStripeImage.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -21,6 +21,15 @@
package org.richfaces.renderkit.images;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.geom.Rectangle2D;
+import java.util.Date;
+
+import javax.faces.context.FacesContext;
+
import org.ajax4jsf.framework.util.HtmlColor;
import org.ajax4jsf.resource.GifRenderer;
import org.ajax4jsf.resource.InternetResourceBuilder;
@@ -29,11 +38,6 @@
import org.richfaces.skin.Skin;
import org.richfaces.skin.SkinFactory;
-import javax.faces.context.FacesContext;
-import java.awt.*;
-import java.awt.geom.Rectangle2D;
-import java.util.Date;
-
/**
* @author Nick - mailto:nbelaevski@exadel.com
* created 02.02.2007
Modified:
trunk/ui/tabPanel/src/test/java/org/richfaces/component/TabPanelComponentTest.java
===================================================================
---
trunk/ui/tabPanel/src/test/java/org/richfaces/component/TabPanelComponentTest.java 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/ui/tabPanel/src/test/java/org/richfaces/component/TabPanelComponentTest.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -21,24 +21,26 @@
package org.richfaces.component;
-import com.gargoylesoftware.htmlunit.Page;
-import com.gargoylesoftware.htmlunit.html.HtmlElement;
-import com.gargoylesoftware.htmlunit.html.HtmlPage;
-import com.gargoylesoftware.htmlunit.html.HtmlScript;
-import org.ajax4jsf.framework.util.image.ImageInfo;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import javax.faces.component.UIForm;
+import javax.faces.component.html.HtmlForm;
+import javax.servlet.http.HttpServletResponse;
+
import org.ajax4jsf.resource.InternetResource;
import org.ajax4jsf.resource.InternetResourceBuilder;
import org.ajax4jsf.resource.ResourceBuilderImpl;
+import org.ajax4jsf.resource.image.ImageInfo;
import org.ajax4jsf.tests.AbstractAjax4JsfTestCase;
import org.apache.commons.lang.StringUtils;
-import javax.faces.component.UIForm;
-import javax.faces.component.html.HtmlForm;
-import javax.servlet.http.HttpServletResponse;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
+import com.gargoylesoftware.htmlunit.Page;
+import com.gargoylesoftware.htmlunit.html.HtmlElement;
+import com.gargoylesoftware.htmlunit.html.HtmlPage;
+import com.gargoylesoftware.htmlunit.html.HtmlScript;
/**
* Unit test for TabPanel component.
Modified:
trunk/ui/toolBar/src/test/java/org/richfaces/component/ToolBarComponentTest.java
===================================================================
---
trunk/ui/toolBar/src/test/java/org/richfaces/component/ToolBarComponentTest.java 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/ui/toolBar/src/test/java/org/richfaces/component/ToolBarComponentTest.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -21,23 +21,26 @@
package org.richfaces.component;
-import com.gargoylesoftware.htmlunit.Page;
-import com.gargoylesoftware.htmlunit.html.HtmlElement;
-import com.gargoylesoftware.htmlunit.html.HtmlPage;
-import junit.framework.Assert;
-import org.ajax4jsf.framework.util.image.ImageInfo;
-import org.ajax4jsf.resource.InternetResource;
-import org.ajax4jsf.resource.InternetResourceBuilder;
-import org.ajax4jsf.resource.ResourceBuilderImpl;
-import org.ajax4jsf.tests.AbstractAjax4JsfTestCase;
+import java.util.List;
import javax.faces.component.UICommand;
import javax.faces.component.UIForm;
import javax.faces.component.html.HtmlCommandButton;
import javax.faces.component.html.HtmlForm;
import javax.servlet.http.HttpServletResponse;
-import java.util.List;
+import junit.framework.Assert;
+
+import org.ajax4jsf.resource.InternetResource;
+import org.ajax4jsf.resource.InternetResourceBuilder;
+import org.ajax4jsf.resource.ResourceBuilderImpl;
+import org.ajax4jsf.resource.image.ImageInfo;
+import org.ajax4jsf.tests.AbstractAjax4JsfTestCase;
+
+import com.gargoylesoftware.htmlunit.Page;
+import com.gargoylesoftware.htmlunit.html.HtmlElement;
+import com.gargoylesoftware.htmlunit.html.HtmlPage;
+
/**
* Unit test for ToolBar component.
*/
Modified: trunk/ui/tree/src/test/java/org/richfaces/component/TreeComponentTest.java
===================================================================
--- trunk/ui/tree/src/test/java/org/richfaces/component/TreeComponentTest.java 2007-07-10
18:39:35 UTC (rev 1587)
+++ trunk/ui/tree/src/test/java/org/richfaces/component/TreeComponentTest.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -38,10 +38,10 @@
import javax.faces.event.PhaseId;
import javax.servlet.http.HttpServletResponse;
-import org.ajax4jsf.framework.util.image.ImageInfo;
import org.ajax4jsf.resource.InternetResource;
import org.ajax4jsf.resource.InternetResourceBuilder;
import org.ajax4jsf.resource.ResourceBuilderImpl;
+import org.ajax4jsf.resource.image.ImageInfo;
import org.ajax4jsf.tests.AbstractAjax4JsfTestCase;
import org.apache.commons.lang.StringUtils;
import org.richfaces.component.state.events.ExpandAllCommandEvent;
Modified:
trunk/ui/tree/src/test/java/org/richfaces/component/state/events/CollapseAllCommandEventTest.java
===================================================================
---
trunk/ui/tree/src/test/java/org/richfaces/component/state/events/CollapseAllCommandEventTest.java 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/ui/tree/src/test/java/org/richfaces/component/state/events/CollapseAllCommandEventTest.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -22,14 +22,11 @@
package org.richfaces.component.state.events;
import javax.faces.FacesException;
-import javax.faces.component.UIOutput;
import javax.faces.event.FacesListener;
import org.ajax4jsf.tests.AbstractAjax4JsfTestCase;
import org.richfaces.component.UITree;
-import junit.framework.TestCase;
-
/**
* @author Nick Belaevski - nbelaevski(a)exadel.com
* created 14.04.2007
Modified:
trunk/ui/tree/src/test/java/org/richfaces/component/state/events/CollapseNodeCommandEventTest.java
===================================================================
---
trunk/ui/tree/src/test/java/org/richfaces/component/state/events/CollapseNodeCommandEventTest.java 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/ui/tree/src/test/java/org/richfaces/component/state/events/CollapseNodeCommandEventTest.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -24,7 +24,6 @@
import java.util.ArrayList;
import javax.faces.FacesException;
-import javax.faces.component.UIOutput;
import javax.faces.event.FacesListener;
import org.ajax4jsf.tests.AbstractAjax4JsfTestCase;
@@ -32,8 +31,6 @@
import org.richfaces.model.ListRowKey;
import org.richfaces.model.TreeRowKey;
-import junit.framework.TestCase;
-
/**
* @author Nick Belaevski - nbelaevski(a)exadel.com
* created 14.04.2007
Modified:
trunk/ui/tree/src/test/java/org/richfaces/component/state/events/ExpandAllCommandEventTest.java
===================================================================
---
trunk/ui/tree/src/test/java/org/richfaces/component/state/events/ExpandAllCommandEventTest.java 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/ui/tree/src/test/java/org/richfaces/component/state/events/ExpandAllCommandEventTest.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -22,14 +22,11 @@
package org.richfaces.component.state.events;
import javax.faces.FacesException;
-import javax.faces.component.UIOutput;
import javax.faces.event.FacesListener;
import org.ajax4jsf.tests.AbstractAjax4JsfTestCase;
import org.richfaces.component.UITree;
-import junit.framework.TestCase;
-
/**
* @author Nick Belaevski - nbelaevski(a)exadel.com
* created 14.04.2007
Modified:
trunk/ui/tree/src/test/java/org/richfaces/component/state/events/ExpandNodeCommandEventTest.java
===================================================================
---
trunk/ui/tree/src/test/java/org/richfaces/component/state/events/ExpandNodeCommandEventTest.java 2007-07-10
18:39:35 UTC (rev 1587)
+++
trunk/ui/tree/src/test/java/org/richfaces/component/state/events/ExpandNodeCommandEventTest.java 2007-07-10
19:07:38 UTC (rev 1588)
@@ -24,7 +24,6 @@
import java.util.ArrayList;
import javax.faces.FacesException;
-import javax.faces.component.UIOutput;
import javax.faces.event.FacesListener;
import org.ajax4jsf.tests.AbstractAjax4JsfTestCase;
@@ -32,8 +31,6 @@
import org.richfaces.model.ListRowKey;
import org.richfaces.model.TreeRowKey;
-import junit.framework.TestCase;
-
/**
* @author Nick Belaevski - nbelaevski(a)exadel.com
* created 14.04.2007