This commit was manufactured by cvs2svn to create branch
'refactor_scripting_04_02'.
This commit is contained in:
parent
ca66d7ba90
commit
9ecef6e720
230 changed files with 0 additions and 43959 deletions
93
README.txt
93
README.txt
|
@ -1,93 +0,0 @@
|
|||
This is the README file for version 1.2 of Helma Object Publisher.
|
||||
|
||||
============================
|
||||
ABOUT HELMA OBJECT PUBLISHER
|
||||
============================
|
||||
|
||||
Helma Object Publisher is a web application server.
|
||||
|
||||
With Helma Object Publisher (sometimes simply refered to as Helma or
|
||||
Hop) you can define Objects and map them to a relational database
|
||||
table. These so-called HopObjects can be created, modified and deleted
|
||||
using a comfortable object/container model. Hence, no manual fiddling
|
||||
around with database code is necessary.
|
||||
|
||||
HopObjects are extended JavaScript objects which can be scripted using
|
||||
server-side JavaScript. Beyond the common JavaScript features, Helma
|
||||
provides special "skin" and template functionalities which facilitate
|
||||
the rendering of objects via a web interface.
|
||||
|
||||
Thanks to Helma's relational database mapping technology, HopObjects
|
||||
create a hierarchical structure, the Url space of a Helma site. The
|
||||
parts between slashes in a Helma Url represent HopObjects (similar to
|
||||
the document tree in static sites). The Helma Url space can be thought
|
||||
of as an analogy to the Document Object Model (Dom) in client-side
|
||||
JavaScript.
|
||||
|
||||
|
||||
===================
|
||||
SYSTEM REQUIREMENTS
|
||||
===================
|
||||
|
||||
Windows: 1) On Windows Helma won't run with Microsoft's version of
|
||||
Java (jview). You can get a compatible Java runtime from Sun or IBM:
|
||||
http://java.sun.com/j2se/1.3/jre/download-windows.html
|
||||
http://www.ibm.com/java/jdk/download/ 2) In the Windows start script
|
||||
I've hardcoded c:\java\lib\classes.zip in the CLASSPATH argument. Not
|
||||
good.
|
||||
|
||||
Macintosh: 1) If you are using the Mac version you should own a G3 CPU
|
||||
and/or have MRJ 2.2 (http://www.apple.com/java) installed. Other
|
||||
platforms have less frustration potential. The Mac OS version
|
||||
currently is not up-to-date (version 0.1).
|
||||
|
||||
Linux: The recomended virtual machine for running Helma on Linux is
|
||||
Blackdown's port of JDK 1.2.2 RC4
|
||||
(http://www.blackdown.org/java-linux/mirrors.html). JDK 1.1.7v3 will
|
||||
work, but much slower and show a lot of CPU activity even when the
|
||||
Helma is idle. IBM's version of JDK 1.1.8 also works well, but this
|
||||
JVM has some problems of its own with thread handling.
|
||||
|
||||
|
||||
============================
|
||||
INSTALLING AND RUNNING HELMA
|
||||
============================
|
||||
|
||||
Simply unzip the contents of the archive file into any place on your
|
||||
hard disk. Start Helma by opening the file hop.bat or hop.sh,
|
||||
respectively.
|
||||
|
||||
If you manage to get it running you should be able to connect your
|
||||
browser to http://127.0.0.1:8080/ (port 8080, that is).
|
||||
|
||||
This version is set up to use its own embedded Web server and a very
|
||||
basic embedded object database. For this reason it is able to run
|
||||
virtually without installation on any platform with a Java 1.1 virtual
|
||||
machine.
|
||||
|
||||
On the other hand, the embedded Web server and object db are meant for
|
||||
development work and not ready for prime time deployment. For that
|
||||
you'd probably use an external relational database, the Berkeley DB
|
||||
package and a full featured Web server like Apache.
|
||||
|
||||
|
||||
=====================================
|
||||
DOCUMENTATION AND FURTHER INFORMATION
|
||||
=====================================
|
||||
|
||||
Currently, a documentation-in-progress is available online only.
|
||||
Please refer to http://helma.org/docs/.
|
||||
|
||||
For further information http://helma.org generally is a good place.
|
||||
There is also a mailing-list about Helma-related stuff available at
|
||||
http://helma.org/lists/listinfo/hop.
|
||||
|
||||
For questions, comments or suggestions feel free to contact
|
||||
tobi@helma.at.
|
||||
|
||||
|
||||
|
||||
--
|
||||
|
||||
This document was last modified on Friday 22 June 2001 by
|
||||
tobi@helma.at
|
|
@ -1,9 +0,0 @@
|
|||
# List of apps to start.
|
||||
|
||||
base=self
|
||||
manage=self
|
||||
|
||||
bloggerapi
|
||||
himp
|
||||
lillebror
|
||||
hopblog
|
67
build/README
67
build/README
|
@ -1,67 +0,0 @@
|
|||
This is the README file for the Helma build files as part of the Helma Object Publisher. It is included in the current distribution (version 1.2pre as of 8 November 2001) downloadable at <http://helma.org/download>.
|
||||
|
||||
The build directory consists of the following files:
|
||||
|
||||
ant.jar
|
||||
build.bat
|
||||
build.sh
|
||||
build.xml
|
||||
crimson.jar
|
||||
jaxp.jar
|
||||
README
|
||||
|
||||
|
||||
PREREQUISITES
|
||||
=============
|
||||
|
||||
The Helma build script is using a software called Ant. Ant is a build system that was developed for the Jakarta Tomcat project. For more information about Ant, see <http://jakarta.apache.org/ant/>.
|
||||
|
||||
To run Ant, you also need JDK 1.3 or higher <http://java.sun.com/j2se/>.
|
||||
|
||||
For checking out the source files from Helma's CVS you also need a local installation of a CVS command-line client. More information about CVS at <http://www.cvshome.org/>.
|
||||
|
||||
|
||||
STARTING BUILD
|
||||
==============
|
||||
|
||||
The build system is started by invoking the shell script appropriate to your platform, ie. build.sh for *nix (Linux, NetBSD etc.) and build.bat for Windows systems.
|
||||
|
||||
The generic syntax is
|
||||
|
||||
./build target
|
||||
|
||||
The parameter "target" specifies one of the following build targets.
|
||||
|
||||
|
||||
BUILD TARGETS
|
||||
=============
|
||||
|
||||
checkout
|
||||
Fetches (or updates, resp.) the Helma source files from the CVS and copies them into the src/ directory (which will be created if necessary).
|
||||
|
||||
compile
|
||||
Compiles the source files contained in the src/ directory into the class/ directory (which will be created if necessary).
|
||||
|
||||
jar
|
||||
Stuffs the files in class/ together and saves them as .jar archive in the build directory. The file is named helma-yyyymmdd.jar.
|
||||
|
||||
javadoc
|
||||
Creates the Java API documentation for the Helma classes. The resulting files are saved into the docs/apidocs/ directory (which will be created if necessary).
|
||||
|
||||
package
|
||||
Builds all previous targets (checkout, compile, jar, javadoc) and saves the created files in the directory helma-1.x/ (with 1.x being the version number). All directories will be created if necessary.
|
||||
|
||||
package-zip
|
||||
Same as "package". Additionally, the files in the output directory will be compressed as .zip file.
|
||||
|
||||
package-tgz
|
||||
Same as "package". Additionall, the file in the output directory will be compressed as .tar.gz file.
|
||||
|
||||
package-all
|
||||
Builds all previous targets. The result is a complete and up-to-date (as in the CVS) installation of Helma, the API documentation, source and build files as well as compressed packages for *nix and Windows systems including all the files.
|
||||
|
||||
|
||||
--
|
||||
|
||||
This README was last updated on 8 November 2001 by tobi@helma.org.
|
||||
|
BIN
build/ant.jar
BIN
build/ant.jar
Binary file not shown.
|
@ -1,93 +0,0 @@
|
|||
This is the README file for version 1.2 of Helma Object Publisher.
|
||||
|
||||
============================
|
||||
ABOUT HELMA OBJECT PUBLISHER
|
||||
============================
|
||||
|
||||
Helma Object Publisher is a web application server.
|
||||
|
||||
With Helma Object Publisher (sometimes simply refered to as Helma or
|
||||
Hop) you can define Objects and map them to a relational database
|
||||
table. These so-called HopObjects can be created, modified and deleted
|
||||
using a comfortable object/container model. Hence, no manual fiddling
|
||||
around with database code is necessary.
|
||||
|
||||
HopObjects are extended JavaScript objects which can be scripted using
|
||||
server-side JavaScript. Beyond the common JavaScript features, Helma
|
||||
provides special "skin" and template functionalities which facilitate
|
||||
the rendering of objects via a web interface.
|
||||
|
||||
Thanks to Helma's relational database mapping technology, HopObjects
|
||||
create a hierarchical structure, the Url space of a Helma site. The
|
||||
parts between slashes in a Helma Url represent HopObjects (similar to
|
||||
the document tree in static sites). The Helma Url space can be thought
|
||||
of as an analogy to the Document Object Model (Dom) in client-side
|
||||
JavaScript.
|
||||
|
||||
|
||||
===================
|
||||
SYSTEM REQUIREMENTS
|
||||
===================
|
||||
|
||||
Windows: 1) On Windows Helma won't run with Microsoft's version of
|
||||
Java (jview). You can get a compatible Java runtime from Sun or IBM:
|
||||
http://java.sun.com/j2se/1.3/jre/download-windows.html
|
||||
http://www.ibm.com/java/jdk/download/ 2) In the Windows start script
|
||||
I've hardcoded c:\java\lib\classes.zip in the CLASSPATH argument. Not
|
||||
good.
|
||||
|
||||
Macintosh: 1) If you are using the Mac version you should own a G3 CPU
|
||||
and/or have MRJ 2.2 (http://www.apple.com/java) installed. Other
|
||||
platforms have less frustration potential. The Mac OS version
|
||||
currently is not up-to-date (version 0.1).
|
||||
|
||||
Linux: The recomended virtual machine for running Helma on Linux is
|
||||
Blackdown's port of JDK 1.2.2 RC4
|
||||
(http://www.blackdown.org/java-linux/mirrors.html). JDK 1.1.7v3 will
|
||||
work, but much slower and show a lot of CPU activity even when the
|
||||
Helma is idle. IBM's version of JDK 1.1.8 also works well, but this
|
||||
JVM has some problems of its own with thread handling.
|
||||
|
||||
|
||||
============================
|
||||
INSTALLING AND RUNNING HELMA
|
||||
============================
|
||||
|
||||
Simply unzip the contents of the archive file into any place on your
|
||||
hard disk. Start Helma by opening the file hop.bat or hop.sh,
|
||||
respectively.
|
||||
|
||||
If you manage to get it running you should be able to connect your
|
||||
browser to http://127.0.0.1:8080/ (port 8080, that is).
|
||||
|
||||
This version is set up to use its own embedded Web server and a very
|
||||
basic embedded object database. For this reason it is able to run
|
||||
virtually without installation on any platform with a Java 1.1 virtual
|
||||
machine.
|
||||
|
||||
On the other hand, the embedded Web server and object db are meant for
|
||||
development work and not ready for prime time deployment. For that
|
||||
you'd probably use an external relational database, the Berkeley DB
|
||||
package and a full featured Web server like Apache.
|
||||
|
||||
|
||||
=====================================
|
||||
DOCUMENTATION AND FURTHER INFORMATION
|
||||
=====================================
|
||||
|
||||
Currently, a documentation-in-progress is available online only.
|
||||
Please refer to http://helma.org/docs/.
|
||||
|
||||
For further information http://helma.org generally is a good place.
|
||||
There is also a mailing-list about Helma-related stuff available at
|
||||
http://helma.org/lists/listinfo/hop.
|
||||
|
||||
For questions, comments or suggestions feel free to contact
|
||||
tobi@helma.at.
|
||||
|
||||
|
||||
|
||||
--
|
||||
|
||||
This document was last modified on Friday 22 June 2001 by
|
||||
tobi@helma.at
|
|
@ -1,16 +0,0 @@
|
|||
# This is where you specify relational data sources to
|
||||
# map Helma types to relational databases.
|
||||
#
|
||||
# If you want to define a data source just for one
|
||||
# application, simply copy the db.properties file to
|
||||
# the application directory.
|
||||
#
|
||||
# The actual mapping of types is done in the
|
||||
# type.properties file in the prototype directories.
|
||||
#
|
||||
|
||||
# Properties of JDBC data sources
|
||||
myDataSource.url = jdbc:mysql://db.domain.com/space
|
||||
myDataSource.driver = org.gjt.mm.mysql.Driver
|
||||
myDataSource.user = username
|
||||
myDataSource.password = xyz
|
|
@ -1,50 +0,0 @@
|
|||
Copyright (c) 1999-2001 Helma Project. 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.
|
||||
|
||||
3. The end-user documentation included with the redistribution,
|
||||
if any, must include the following acknowledgment:
|
||||
"This product includes software developed by the Helma Project
|
||||
for use in the Helma Object Publisher (http://www.helma.org/)."
|
||||
Alternately, this acknowledgment may appear in the software itself,
|
||||
if and wherever such third-party acknowledgments normally appear.
|
||||
|
||||
4. The names "Helma" and "Hop" must not be used to endorse or
|
||||
promote products derived from this software without prior written
|
||||
permission. For written permission, please contact
|
||||
helma@helma.org.
|
||||
|
||||
5. Products derived from this software may not be called "Helma"
|
||||
or "Hop", nor may "Helma" or "Hop" appear in their name, without
|
||||
prior written permission of the Helma Project Group.
|
||||
|
||||
6. We ask you to give credit to the Helma Project for sites which build
|
||||
upon Helma. This would normally consist of a text or graphic link
|
||||
to http://helma.org/ with the line "Powered by Helma" somewhere on the
|
||||
site. While it is not a breach of this license to omit this, it's a
|
||||
great way for you to make help the Helma Project to continue
|
||||
to flourish and grow.
|
||||
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 HELMA PROJECT OR ITS
|
||||
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.
|
|
@ -1,33 +0,0 @@
|
|||
# The SMTP server to use for sending mails. Set and
|
||||
# uncomment this line before trying to send mails from
|
||||
# Helma applications.
|
||||
#
|
||||
# smtp=mail.yourdomain.com
|
||||
|
||||
|
||||
# Some examples for server-wide locale settings
|
||||
# (please refer to http://userpage.chemie.fu-berlin.de/diverse/doc/ISO_3166.html
|
||||
# for country codes, resp. http://www.ics.uci.edu/pub/ietf/http/related/iso639.txt
|
||||
# for language codes).
|
||||
#
|
||||
# country = AT
|
||||
# language = de
|
||||
#
|
||||
# country = UK
|
||||
# language = en
|
||||
#
|
||||
# country = FR
|
||||
# language = fr
|
||||
#
|
||||
# country = CZ
|
||||
# language = cs
|
||||
|
||||
# list ip addresses for admin-application here:
|
||||
allowAdmin=127.0.0.1, 192.168.0.1
|
||||
|
||||
# md5-encrypted username and password for admin-app
|
||||
# the default is test/test
|
||||
adminUsername=098f6bcd4621d373cade4e832627b4f6
|
||||
adminPassword=098f6bcd4621d373cade4e832627b4f6
|
||||
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
@echo off
|
||||
|
||||
|
||||
REM --------------------------------------------
|
||||
REM Defualt == jar
|
||||
REM "checkout" target gets sources from helma.org
|
||||
REM "compile" target compiles java sources
|
||||
REM "jar" target compiles and builds jar
|
||||
REM "javadoc" target builds the javadoc
|
||||
REM "package" target builds core + jar + javadoc + distribution
|
||||
REM --------------------------------------------
|
||||
set TARGET=%1%
|
||||
|
||||
|
||||
REM --------------------------------------------
|
||||
REM No need to edit anything past here
|
||||
REM --------------------------------------------
|
||||
set BUILDFILE=build.xml
|
||||
if "%TARGET%" == "" goto setdist
|
||||
goto final
|
||||
|
||||
:setdist
|
||||
set TARGET=jar
|
||||
goto final
|
||||
|
||||
:final
|
||||
|
||||
if "%JAVA_HOME%" == "" goto javahomeerror
|
||||
|
||||
set CP=%CLASSPATH%;ant.jar;jaxp.jar;crimson.jar
|
||||
if exist %JAVA_HOME%\lib\tools.jar set CP=%CP%;%JAVA_HOME%\lib\tools.jar
|
||||
|
||||
echo Classpath: %CP%
|
||||
echo JAVA_HOME: %JAVA_HOME%
|
||||
|
||||
%JAVA_HOME%\bin\java.exe -classpath "%CP%" org.apache.tools.ant.Main -buildfile %BUILDFILE% %TARGET%
|
||||
|
||||
goto end
|
||||
|
||||
|
||||
REM -----------ERROR-------------
|
||||
:javahomeerror
|
||||
echo "ERROR: JAVA_HOME not found in your environment."
|
||||
echo "Please, set the JAVA_HOME variable in your environment to match the"
|
||||
echo "location of the Java Virtual Machine you want to use."
|
||||
|
||||
:end
|
|
@ -1,49 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
# --------------------------------------------
|
||||
# Default == jar
|
||||
# "checkout" target gets sources from helma.org
|
||||
# "compile" target compiles java sources
|
||||
# "jar" target compiles and builds jar
|
||||
# "javadoc" target builds the javadoc
|
||||
# "package" target builds core + jar + javadoc + distribution
|
||||
# --------------------------------------------
|
||||
TARGET=${1}
|
||||
|
||||
# export JAVA_HOME=/usr/lib/java
|
||||
|
||||
export CVSHOME=:pserver:anonymous@coletta.helma.at:/opt/cvs
|
||||
|
||||
# comment this out to log in to CVS server
|
||||
# cvs -d :pserver:anonymous@coletta.helma.at:/opt/cvs login
|
||||
|
||||
#--------------------------------------------
|
||||
# No need to edit anything past here
|
||||
#--------------------------------------------
|
||||
if test -z "${JAVA_HOME}" ; then
|
||||
echo "ERROR: JAVA_HOME not found in your environment."
|
||||
echo "Please, set the JAVA_HOME variable in your environment to match the"
|
||||
echo "location of the Java Virtual Machine you want to use."
|
||||
exit
|
||||
fi
|
||||
|
||||
if test -z "${TARGET}" ; then
|
||||
TARGET=jar
|
||||
fi
|
||||
|
||||
if test -f ${JAVA_HOME}/lib/tools.jar ; then
|
||||
CLASSPATH=${CLASSPATH}:${JAVA_HOME}/lib/tools.jar
|
||||
fi
|
||||
|
||||
echo "Now building ${TARGET}..."
|
||||
|
||||
CP=${CLASSPATH}:ant.jar:jaxp.jar:crimson.jar:../lib/netcomponents.jar
|
||||
|
||||
echo "Classpath: ${CP}"
|
||||
echo "JAVA_HOME: ${JAVA_HOME}"
|
||||
|
||||
BUILDFILE=build.xml
|
||||
|
||||
${JAVA_HOME}/bin/java -classpath ${CP} org.apache.tools.ant.Main -buildfile ${BUILDFILE} ${TARGET}
|
||||
|
||||
|
264
build/build.xml
264
build/build.xml
|
@ -1,264 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<!-- Hop build file -->
|
||||
<!-- ======================================================================= -->
|
||||
<project name="Hop" default="main" basedir=".">
|
||||
|
||||
<!-- =================================================================== -->
|
||||
<!-- Initializes some variables -->
|
||||
<!-- =================================================================== -->
|
||||
<target name="init">
|
||||
<property name="Name" value="helma"/>
|
||||
<property name="year" value="1998-2002"/>
|
||||
<property name="version" value="1.2pre3"/>
|
||||
<property name="project" value="helma"/>
|
||||
<property name="build.compiler" value="classic"/>
|
||||
<property name="build.dir" value=".."/>
|
||||
<property name="build.src" value="${build.dir}/src"/>
|
||||
<property name="build.dest" value="${build.dir}/classes"/>
|
||||
<property name="build.work" value="${build.dir}/work"/>
|
||||
<property name="build.checkout" value="${build.work}/checkout"/>
|
||||
<property name="cvs.root" value=":pserver:anonymous@coletta.helma.at:/opt/cvs"/>
|
||||
<property name="javadoc.destdir" value="../docs/apidocs"/>
|
||||
<property name="jar.name" value="helma"/>
|
||||
<property name="final.name" value="${project}-${version}"/>
|
||||
<property name="final.dir" value="../${final.name}/"/>
|
||||
<property name="debug" value="off"/>
|
||||
<property name="optimize" value="on"/>
|
||||
<property name="deprecation" value="off"/>
|
||||
|
||||
<tstamp/>
|
||||
|
||||
<filter token="year" value="${year}"/>
|
||||
<filter token="version" value="${version}"/>
|
||||
<filter token="date" value="${TODAY}"/>
|
||||
|
||||
<!-- JDK1.1 collections support -->
|
||||
<property name="coll.import" value="com.sun.java.util.collections"/>
|
||||
<available classname="${coll.import}.Collection" property="coll.present"/>
|
||||
|
||||
</target>
|
||||
|
||||
|
||||
<!-- =================================================================== -->
|
||||
<!-- Copies the source code to the build directory and does filtering -->
|
||||
<!-- =================================================================== -->
|
||||
<target name="checkout" depends="init">
|
||||
|
||||
<!-- cvspass cvsroot="${cvs.root}" password=""/ -->
|
||||
|
||||
<mkdir dir="${build.src}"/>
|
||||
<mkdir dir="${build.checkout}"/>
|
||||
|
||||
<cvs cvsRoot="${cvs.root}" package="hop" dest="${build.checkout}"/>
|
||||
<copy todir="${build.src}">
|
||||
<fileset dir="${build.checkout}/hop"
|
||||
includes="helma/**/*.java,FESI/**/*.java,Acme/**/*.java"/>
|
||||
</copy>
|
||||
|
||||
<cvs cvsRoot="${cvs.root}" package="hopbuild/lib" dest="${build.checkout}"/>
|
||||
<copy todir="${build.dir}/lib">
|
||||
<fileset dir="${build.checkout}/hopbuild/lib"/>
|
||||
</copy>
|
||||
|
||||
<cvs cvsRoot="${cvs.root}" package="hopbuild/skeleton" dest="${build.checkout}"/>
|
||||
|
||||
<cvs cvsRoot="${cvs.root}" package="apps/base" dest="${build.checkout}"/>
|
||||
<cvs cvsRoot="${cvs.root}" package="apps/hopblog" dest="${build.checkout}"/>
|
||||
<cvs cvsRoot="${cvs.root}" package="apps/himp" dest="${build.checkout}"/>
|
||||
<cvs cvsRoot="${cvs.root}" package="apps/bloggerapi" dest="${build.checkout}"/>
|
||||
<cvs cvsRoot="${cvs.root}" package="apps/lillebror" dest="${build.checkout}"/>
|
||||
<cvs cvsRoot="${cvs.root}" package="apps/manage" dest="${build.checkout}"/>
|
||||
|
||||
</target>
|
||||
|
||||
|
||||
<!-- =================================================================== -->
|
||||
<!-- Does replacement on files for dealing with collections. -->
|
||||
<!-- XXX The efficiency could be improved here; all replacements should -->
|
||||
<!-- XXX happen during one read/write phase and only for files that have -->
|
||||
<!-- XXX changed. -->
|
||||
<!-- =================================================================== -->
|
||||
<target name="collections" if="coll.present" depends="init">
|
||||
<replace dir="${build.src}/helma" includes="**"
|
||||
token="java.util.Collection" value="${coll.import}.Collection"/>
|
||||
<replace dir="${build.src}/helma" includes="**"
|
||||
token="java.util.Map" value="${coll.import}.Map"/>
|
||||
<replace dir="${build.src}/helma" includes="**"
|
||||
token="java.util.HashMap" value="${coll.import}.HashMap"/>
|
||||
<replace dir="${build.src}/helma" includes="**"
|
||||
token="java.util.List" value="${coll.import}.List"/>
|
||||
<replace dir="${build.src}/helma" includes="**"
|
||||
token="java.util.LinkedList" value="${coll.import}.LinkedList"/>
|
||||
<replace dir="${build.src}/helma" includes="**"
|
||||
token="java.util.ArrayList" value="${coll.import}.ArrayList"/>
|
||||
<replace dir="${build.src}/helma" includes="**"
|
||||
token="java.util.Set" value="${coll.import}.Set"/>
|
||||
<replace dir="${build.src}/helma" includes="**"
|
||||
token="java.util.HashSet" value="${coll.import}.HashSet"/>
|
||||
<replace dir="${build.src}/helma" includes="**"
|
||||
token="java.util.Iterator" value="${coll.import}.Iterator"/>
|
||||
<!-- The following replace handles the "import java.util.*" case by -->
|
||||
<!-- adding an "import com.sun.java.util.collections.*" after it. -->
|
||||
<!-- BTW, \u000a is the Unicode escape for a new line. (jhunter) -->
|
||||
<replace dir="${build.src}/helma/framework/core" includes="**"
|
||||
token="java.util.*"
|
||||
value="java.util.*;\u000aimport ${coll.import}.*"/>
|
||||
<replace dir="${build.src}/helma/objectmodel" includes="**"
|
||||
token="java.util.*"
|
||||
value="java.util.*;\u000aimport ${coll.import}.*"/>
|
||||
</target>
|
||||
|
||||
|
||||
<!-- =================================================================== -->
|
||||
<!-- Compiles the source directory -->
|
||||
<!-- =================================================================== -->
|
||||
<target name="compile" depends="init">
|
||||
|
||||
<mkdir dir="${build.dest}"/>
|
||||
|
||||
<javac srcdir="${build.src}"
|
||||
destdir="${build.dest}"
|
||||
debug="${debug}"
|
||||
deprecation="${deprecation}"
|
||||
optimize="${optimize}">
|
||||
<classpath>
|
||||
<fileset dir="${build.dir}/lib">
|
||||
<exclude name="**/helma*.jar" />
|
||||
<include name="**/*.jar" />
|
||||
</fileset>
|
||||
<pathelement path="${classpath}" />
|
||||
</classpath>
|
||||
</javac>
|
||||
|
||||
<rmic classname="helma.framework.core.Application" base="${build.dest}"/>
|
||||
<rmic classname="helma.image.Server" base="${build.dest}"/>
|
||||
<rmic classname="helma.image.RemoteImage" base="${build.dest}"/>
|
||||
</target>
|
||||
|
||||
<!-- =================================================================== -->
|
||||
<!-- Creates a .jar file -->
|
||||
<!-- =================================================================== -->
|
||||
<target name="jar" depends="compile">
|
||||
<jar jarfile="${build.dir}/${jar.name}-${DSTAMP}.jar"
|
||||
basedir="${build.dest}"
|
||||
excludes="**/package.html"/>
|
||||
</target>
|
||||
|
||||
|
||||
<!-- =================================================================== -->
|
||||
<!-- Creates the API documentation -->
|
||||
<!-- =================================================================== -->
|
||||
<target name="javadocs" depends="init">
|
||||
<mkdir dir="${javadoc.destdir}"/>
|
||||
<javadoc packagenames="helma.*"
|
||||
sourcepath="${build.src}"
|
||||
destdir="${javadoc.destdir}"
|
||||
author="false"
|
||||
private="false"
|
||||
version="false"
|
||||
windowtitle="${Name} ${version} API"
|
||||
doctitle="${Name} ${version} API"
|
||||
bottom="Copyright © 1998-2001 Helma.org. All Rights Reserved."
|
||||
/>
|
||||
</target>
|
||||
|
||||
<!-- =================================================================== -->
|
||||
<!-- Package -->
|
||||
<!-- =================================================================== -->
|
||||
<target name="package" depends="checkout, jar, javadocs">
|
||||
|
||||
<mkdir dir="${final.dir}"/>
|
||||
|
||||
<!-- mkdir dir="${final.dir}/static"/ -->
|
||||
|
||||
<mkdir dir="${final.dir}/src"/>
|
||||
<!-- jar jarfile="${final.dir}/src/${Name}-src.jar"
|
||||
basedir="${build.src}"/ -->
|
||||
|
||||
<copy todir="${final.dir}/src">
|
||||
<fileset dir="${build.dir}/src" excludes="{Name}-src.jar"/>
|
||||
</copy>
|
||||
|
||||
<copy todir="${final.dir}/build">
|
||||
<fileset dir="${build.dir}/build"/>
|
||||
</copy>
|
||||
<chmod file="${final.dir}/build/build.sh" perm="755"/>
|
||||
|
||||
<copy todir="${final.dir}/docs">
|
||||
<fileset dir="../docs"/>
|
||||
</copy>
|
||||
|
||||
<copy todir="${final.dir}/lib">
|
||||
<fileset dir="${build.checkout}/hopbuild/lib"/>
|
||||
</copy>
|
||||
|
||||
<copy todir="${final.dir}">
|
||||
<fileset dir="${build.checkout}/hopbuild/skeleton" excludes="**/CVS"/>
|
||||
</copy>
|
||||
|
||||
<copy todir="${final.dir}/apps">
|
||||
<fileset dir="${build.checkout}/apps" excludes="**/CVS,manage/**"/>
|
||||
</copy>
|
||||
|
||||
<copy file="${build.dir}/${jar.name}-${DSTAMP}.jar" tofile="${final.dir}/lib/helma.jar"/>
|
||||
<chmod file="${final.dir}/hop.sh" perm="755"/>
|
||||
|
||||
<mkdir dir="${final.dir}/apps/manage"/>
|
||||
<zip zipfile="${final.dir}/apps/manage/manage.zip" basedir="${build.checkout}/apps/manage/" includes="**"/>
|
||||
|
||||
</target>
|
||||
|
||||
<!-- =================================================================== -->
|
||||
<!-- Packages the distribution with ZIP -->
|
||||
<!-- =================================================================== -->
|
||||
<target name="package-zip" depends="package">
|
||||
<zip zipfile="../${Name}-${version}.zip" basedir="../" includes="**/${final.name}/**"/>
|
||||
</target>
|
||||
|
||||
<!-- =================================================================== -->
|
||||
<!-- Packages the distribution with TAR-GZIP -->
|
||||
<!-- =================================================================== -->
|
||||
<target name="package-tgz" depends="package">
|
||||
<tar tarfile="../${Name}-${version}.tar" basedir=".." excludes="**">
|
||||
<tarfileset dir=".." mode="755">
|
||||
<include name="${final.name}/hop.sh"/>
|
||||
<include name="${final.name}/build/build.sh"/>
|
||||
</tarfileset>
|
||||
<tarfileset dir="..">
|
||||
<include name="${final.name}/**"/>
|
||||
<exclude name="${final.name}/hop.sh"/>
|
||||
<exclude name="${final.name}/build/build.sh"/>
|
||||
</tarfileset>
|
||||
</tar>
|
||||
<gzip zipfile="../${Name}-${version}.tar.gz" src="../${Name}-${version}.tar"/>
|
||||
</target>
|
||||
|
||||
<!-- =================================================================== -->
|
||||
<!-- Packages the distribution with ZIP and TAR-GZIP -->
|
||||
<!-- =================================================================== -->
|
||||
<target name="package-all" depends="package-zip, package-tgz">
|
||||
</target>
|
||||
|
||||
|
||||
<!-- =================================================================== -->
|
||||
<!-- These are just some tests -->
|
||||
<!-- =================================================================== -->
|
||||
<target name="ftp-test" depends="">
|
||||
<ftp server="piefke.helma.at"
|
||||
userid="anonymous"
|
||||
password="tobi@helma.at">
|
||||
<fileset dir="${build.dir}">
|
||||
<include name="${Name}-${version}.zip,${Name}-${version}.tar.gz"/>
|
||||
</fileset>
|
||||
</ftp>
|
||||
</target>
|
||||
|
||||
<target name="test1" depends="init">
|
||||
<mkdir dir="${build.checkout}"/>
|
||||
<cvs cvsRoot="${cvs.root}" package="apps/manage" dest="${build.checkout}"/>
|
||||
<zip zipfile="../manage.zip" basedir="${build.checkout}/apps/manage/" includes="**"/>
|
||||
</target>
|
||||
|
||||
</project>
|
Binary file not shown.
BIN
build/jaxp.jar
BIN
build/jaxp.jar
Binary file not shown.
|
@ -1,9 +0,0 @@
|
|||
# List of apps to start.
|
||||
|
||||
base=self
|
||||
manage=self
|
||||
|
||||
bloggerapi
|
||||
himp
|
||||
lillebror
|
||||
hopblog
|
|
@ -1,16 +0,0 @@
|
|||
# This is where you specify relational data sources to
|
||||
# map Helma types to relational databases.
|
||||
#
|
||||
# If you want to define a data source just for one
|
||||
# application, simply copy the db.properties file to
|
||||
# the application directory.
|
||||
#
|
||||
# The actual mapping of types is done in the
|
||||
# type.properties file in the prototype directories.
|
||||
#
|
||||
|
||||
# Properties of JDBC data sources
|
||||
myDataSource.url = jdbc:mysql://db.domain.com/space
|
||||
myDataSource.driver = org.gjt.mm.mysql.Driver
|
||||
myDataSource.user = username
|
||||
myDataSource.password = xyz
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,13 +0,0 @@
|
|||
@echo off
|
||||
|
||||
rem Batch file for starting Hop with a JDK-like virtual machine.
|
||||
|
||||
set JARS=lib\helma.jar;lib\berkeley.jar;lib\village.jar;lib\jsdk.jar;lib\openxml.jar
|
||||
set JARS=%JARS%;lib\sax.jar;lib\regexp.jar;lib\netcomponents.jar;lib\jimi.jar
|
||||
set JARS=%JARS%;lib\mail.jar;lib\activation.jar;lib\mysql.jar;lib\jdom.jar;lib\minml.jar
|
||||
|
||||
set HOP_PORT=8080
|
||||
|
||||
echo Starting Web server on port %HOP_PORT%
|
||||
|
||||
java -classpath c:\winnt\java\packages\rmi.zip;%JARS% helma.main.Server -w %HOP_PORT%
|
|
@ -1,11 +0,0 @@
|
|||
#!/bin/sh
|
||||
# Stupid shell script for starting Hop with a JDK-like virtual machine.
|
||||
# Presumes that you have your classpath set.
|
||||
|
||||
export HOP_PORT=8080
|
||||
|
||||
export JARS=lib/helma.jar:lib/berkeley.jar:lib/village.jar:lib/jsdk.jar:lib/openxml.jar
|
||||
export JARS=$JARS:lib/sax.jar:lib/regexp.jar:lib/netcomponents.jar:lib/jimi.jar
|
||||
export JARS=$JARS:lib/mail.jar:lib/activation.jar:lib/mysql.jar:lib/jdom.jar:lib/minml.jar
|
||||
|
||||
java -classpath $CLASSPATH:$JARS helma.main.Server -w $HOP_PORT
|
|
@ -1,50 +0,0 @@
|
|||
Copyright (c) 1999-2001 Helma Project. 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.
|
||||
|
||||
3. The end-user documentation included with the redistribution,
|
||||
if any, must include the following acknowledgment:
|
||||
"This product includes software developed by the Helma Project
|
||||
for use in the Helma Object Publisher (http://www.helma.org/)."
|
||||
Alternately, this acknowledgment may appear in the software itself,
|
||||
if and wherever such third-party acknowledgments normally appear.
|
||||
|
||||
4. The names "Helma" and "Hop" must not be used to endorse or
|
||||
promote products derived from this software without prior written
|
||||
permission. For written permission, please contact
|
||||
helma@helma.org.
|
||||
|
||||
5. Products derived from this software may not be called "Helma"
|
||||
or "Hop", nor may "Helma" or "Hop" appear in their name, without
|
||||
prior written permission of the Helma Project Group.
|
||||
|
||||
6. We ask you to give credit to the Helma Project for sites which build
|
||||
upon Helma. This would normally consist of a text or graphic link
|
||||
to http://helma.org/ with the line "Powered by Helma" somewhere on the
|
||||
site. While it is not a breach of this license to omit this, it's a
|
||||
great way for you to make help the Helma Project to continue
|
||||
to flourish and grow.
|
||||
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 HELMA PROJECT OR ITS
|
||||
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.
|
|
@ -1,33 +0,0 @@
|
|||
# The SMTP server to use for sending mails. Set and
|
||||
# uncomment this line before trying to send mails from
|
||||
# Helma applications.
|
||||
#
|
||||
# smtp=mail.yourdomain.com
|
||||
|
||||
|
||||
# Some examples for server-wide locale settings
|
||||
# (please refer to http://userpage.chemie.fu-berlin.de/diverse/doc/ISO_3166.html
|
||||
# for country codes, resp. http://www.ics.uci.edu/pub/ietf/http/related/iso639.txt
|
||||
# for language codes).
|
||||
#
|
||||
# country = AT
|
||||
# language = de
|
||||
#
|
||||
# country = UK
|
||||
# language = en
|
||||
#
|
||||
# country = FR
|
||||
# language = fr
|
||||
#
|
||||
# country = CZ
|
||||
# language = cs
|
||||
|
||||
# list ip addresses for admin-application here:
|
||||
allowAdmin=127.0.0.1, 192.168.0.1
|
||||
|
||||
# md5-encrypted username and password for admin-app
|
||||
# the default is test/test
|
||||
adminUsername=098f6bcd4621d373cade4e832627b4f6
|
||||
adminPassword=098f6bcd4621d373cade4e832627b4f6
|
||||
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 134 KiB |
|
@ -1,16 +0,0 @@
|
|||
# This is where you specify relational data sources to
|
||||
# map Helma types to relational databases.
|
||||
#
|
||||
# If you want to define a data source just for one
|
||||
# application, simply copy the db.properties file to
|
||||
# the application directory.
|
||||
#
|
||||
# The actual mapping of types is done in the
|
||||
# type.properties file in the prototype directories.
|
||||
#
|
||||
|
||||
# Properties of JDBC data sources
|
||||
myDataSource.url = jdbc:mysql://db.domain.com/space
|
||||
myDataSource.driver = org.gjt.mm.mysql.Driver
|
||||
myDataSource.user = username
|
||||
myDataSource.password = xyz
|
13
hop.bat
13
hop.bat
|
@ -1,13 +0,0 @@
|
|||
@echo off
|
||||
|
||||
rem Batch file for starting Hop with a JDK-like virtual machine.
|
||||
|
||||
set JARS=lib\helma.jar;lib\berkeley.jar;lib\village.jar;lib\jsdk.jar;lib\openxml.jar
|
||||
set JARS=%JARS%;lib\sax.jar;lib\regexp.jar;lib\netcomponents.jar;lib\jimi.jar
|
||||
set JARS=%JARS%;lib\mail.jar;lib\activation.jar;lib\mysql.jar;lib\jdom.jar;lib\minml.jar
|
||||
|
||||
set HOP_PORT=8080
|
||||
|
||||
echo Starting Web server on port %HOP_PORT%
|
||||
|
||||
java -classpath c:\winnt\java\packages\rmi.zip;%JARS% helma.main.Server -w %HOP_PORT%
|
11
hop.sh
11
hop.sh
|
@ -1,11 +0,0 @@
|
|||
#!/bin/sh
|
||||
# Stupid shell script for starting Hop with a JDK-like virtual machine.
|
||||
# Presumes that you have your classpath set.
|
||||
|
||||
export HOP_PORT=8080
|
||||
|
||||
export JARS=lib/helma.jar:lib/berkeley.jar:lib/village.jar:lib/jsdk.jar:lib/openxml.jar
|
||||
export JARS=$JARS:lib/sax.jar:lib/regexp.jar:lib/netcomponents.jar:lib/jimi.jar
|
||||
export JARS=$JARS:lib/mail.jar:lib/activation.jar:lib/mysql.jar:lib/jdom.jar:lib/minml.jar
|
||||
|
||||
java -classpath $CLASSPATH:$JARS helma.main.Server -w $HOP_PORT
|
Binary file not shown.
BIN
lib/berkeley.jar
BIN
lib/berkeley.jar
Binary file not shown.
Binary file not shown.
BIN
lib/jdom.jar
BIN
lib/jdom.jar
Binary file not shown.
BIN
lib/jimi.jar
BIN
lib/jimi.jar
Binary file not shown.
BIN
lib/jsdk.jar
BIN
lib/jsdk.jar
Binary file not shown.
BIN
lib/mail.jar
BIN
lib/mail.jar
Binary file not shown.
BIN
lib/minml.jar
BIN
lib/minml.jar
Binary file not shown.
BIN
lib/mysql.jar
BIN
lib/mysql.jar
Binary file not shown.
Binary file not shown.
BIN
lib/openxml.jar
BIN
lib/openxml.jar
Binary file not shown.
BIN
lib/regexp.jar
BIN
lib/regexp.jar
Binary file not shown.
BIN
lib/sax.jar
BIN
lib/sax.jar
Binary file not shown.
BIN
lib/village.jar
BIN
lib/village.jar
Binary file not shown.
50
license.txt
50
license.txt
|
@ -1,50 +0,0 @@
|
|||
Copyright (c) 1999-2001 Helma Project. 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.
|
||||
|
||||
3. The end-user documentation included with the redistribution,
|
||||
if any, must include the following acknowledgment:
|
||||
"This product includes software developed by the Helma Project
|
||||
for use in the Helma Object Publisher (http://www.helma.org/)."
|
||||
Alternately, this acknowledgment may appear in the software itself,
|
||||
if and wherever such third-party acknowledgments normally appear.
|
||||
|
||||
4. The names "Helma" and "Hop" must not be used to endorse or
|
||||
promote products derived from this software without prior written
|
||||
permission. For written permission, please contact
|
||||
helma@helma.org.
|
||||
|
||||
5. Products derived from this software may not be called "Helma"
|
||||
or "Hop", nor may "Helma" or "Hop" appear in their name, without
|
||||
prior written permission of the Helma Project Group.
|
||||
|
||||
6. We ask you to give credit to the Helma Project for sites which build
|
||||
upon Helma. This would normally consist of a text or graphic link
|
||||
to http://helma.org/ with the line "Powered by Helma" somewhere on the
|
||||
site. While it is not a breach of this license to omit this, it's a
|
||||
great way for you to make help the Helma Project to continue
|
||||
to flourish and grow.
|
||||
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 HELMA PROJECT OR ITS
|
||||
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.
|
|
@ -1,33 +0,0 @@
|
|||
# The SMTP server to use for sending mails. Set and
|
||||
# uncomment this line before trying to send mails from
|
||||
# Helma applications.
|
||||
#
|
||||
# smtp=mail.yourdomain.com
|
||||
|
||||
|
||||
# Some examples for server-wide locale settings
|
||||
# (please refer to http://userpage.chemie.fu-berlin.de/diverse/doc/ISO_3166.html
|
||||
# for country codes, resp. http://www.ics.uci.edu/pub/ietf/http/related/iso639.txt
|
||||
# for language codes).
|
||||
#
|
||||
# country = AT
|
||||
# language = de
|
||||
#
|
||||
# country = UK
|
||||
# language = en
|
||||
#
|
||||
# country = FR
|
||||
# language = fr
|
||||
#
|
||||
# country = CZ
|
||||
# language = cs
|
||||
|
||||
# list ip addresses for admin-application here:
|
||||
allowAdmin=127.0.0.1, 192.168.0.1
|
||||
|
||||
# md5-encrypted username and password for admin-app
|
||||
# the default is test/test
|
||||
adminUsername=098f6bcd4621d373cade4e832627b4f6
|
||||
adminPassword=098f6bcd4621d373cade4e832627b4f6
|
||||
|
||||
|
|
@ -1,613 +0,0 @@
|
|||
// Fmt - some simple single-arg sprintf-like routines
|
||||
//
|
||||
// Copyright (C) 1996 by Jef Poskanzer <jef@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/
|
||||
|
||||
package Acme;
|
||||
|
||||
/// Some simple single-arg sprintf-like routines.
|
||||
// <P>
|
||||
// It is apparently impossible to declare a Java method that accepts
|
||||
// variable numbers of any type of argument. You can declare it to take
|
||||
// Objects, but numeric variables and constants are not in fact Objects.
|
||||
// <P>
|
||||
// However, using the built-in string concatenation, it's almost as
|
||||
// convenient to make a series of single-argument formatting routines.
|
||||
// <P>
|
||||
// Fmt can format the following types:
|
||||
// <BLOCKQUOTE><CODE>
|
||||
// byte short int long float double char String Object
|
||||
// </CODE></BLOCKQUOTE>
|
||||
// For each type there is a set of overloaded methods, each returning
|
||||
// a formatted String. There's the plain formatting version:
|
||||
// <BLOCKQUOTE><PRE>
|
||||
// Fmt.fmt( x )
|
||||
// </PRE></BLOCKQUOTE>
|
||||
// There's a version specifying a minimum field width:
|
||||
// <BLOCKQUOTE><PRE>
|
||||
// Fmt.fmt( x, minWidth )
|
||||
// </PRE></BLOCKQUOTE>
|
||||
// And there's a version that takes flags:
|
||||
// <BLOCKQUOTE><PRE>
|
||||
// Fmt.fmt( x, minWidth, flags )
|
||||
// </PRE></BLOCKQUOTE>
|
||||
// Currently available flags are:
|
||||
// <BLOCKQUOTE><PRE>
|
||||
// Fmt.ZF - zero-fill
|
||||
// Fmt.LJ - left justify
|
||||
// Fmt.HX - hexadecimal
|
||||
// Fmt.OC - octal
|
||||
// </PRE></BLOCKQUOTE>
|
||||
// The HX and OC flags imply unsigned output.
|
||||
// <P>
|
||||
// For doubles and floats, there's a significant-figures parameter before
|
||||
// the flags:
|
||||
// <BLOCKQUOTE><PRE>
|
||||
// Fmt.fmt( d )
|
||||
// Fmt.fmt( d, minWidth )
|
||||
// Fmt.fmt( d, minWidth, sigFigs )
|
||||
// Fmt.fmt( d, minWidth, sigFigs, flags )
|
||||
// </PRE></BLOCKQUOTE>
|
||||
// <P>
|
||||
// <A HREF="/resources/classes/Acme/Fmt.java">Fetch the software.</A><BR>
|
||||
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
|
||||
// <HR>
|
||||
// Similar classes:
|
||||
// <UL>
|
||||
// <LI> Andrew Scherpbier's <A HREF="http://www.sdsu.edu/doc/java-SDSU/sdsu.FormatString.html">FormatString</A>
|
||||
// Tries to allow variable numbers of arguments by
|
||||
// supplying overloaded routines with different combinations of parameters,
|
||||
// but doesn't actually supply that many. The floating point conversion
|
||||
// is described as "very incomplete".
|
||||
// <LI> Core Java's <A HREF="http://www.apl.jhu.edu/~hall/java/CoreJava-Format.html">Format</A>.
|
||||
// The design seems a little weird. They want you to create an instance,
|
||||
// passing the format string to the constructor, and then call an instance
|
||||
// method with your data to do the actual formatting. The extra steps are
|
||||
// pointless; better to just use static methods.
|
||||
// </UL>
|
||||
|
||||
public class Fmt
|
||||
{
|
||||
|
||||
// Flags.
|
||||
/// Zero-fill.
|
||||
public static final int ZF = 1;
|
||||
/// Left justify.
|
||||
public static final int LJ = 2;
|
||||
/// Hexadecimal.
|
||||
public static final int HX = 4;
|
||||
/// Octal.
|
||||
public static final int OC = 8;
|
||||
// Was a number - internal use.
|
||||
private static final int WN = 16;
|
||||
|
||||
// byte
|
||||
public static String fmt( byte b )
|
||||
{
|
||||
return fmt( b, 0, 0 );
|
||||
}
|
||||
public static String fmt( byte b, int minWidth )
|
||||
{
|
||||
return fmt( b, minWidth, 0 );
|
||||
}
|
||||
public static String fmt( byte b, int minWidth, int flags )
|
||||
{
|
||||
boolean hexadecimal = ( ( flags & HX ) != 0 );
|
||||
boolean octal = ( ( flags & OC ) != 0 );
|
||||
if ( hexadecimal )
|
||||
return fmt( Integer.toString( b & 0xff, 16 ), minWidth, flags|WN );
|
||||
else if ( octal )
|
||||
return fmt( Integer.toString( b & 0xff, 8 ), minWidth, flags|WN );
|
||||
else
|
||||
return fmt( Integer.toString( b & 0xff ), minWidth, flags|WN );
|
||||
}
|
||||
|
||||
// short
|
||||
public static String fmt( short s )
|
||||
{
|
||||
return fmt( s, 0, 0 );
|
||||
}
|
||||
public static String fmt( short s, int minWidth )
|
||||
{
|
||||
return fmt( s, minWidth, 0 );
|
||||
}
|
||||
public static String fmt( short s, int minWidth, int flags )
|
||||
{
|
||||
boolean hexadecimal = ( ( flags & HX ) != 0 );
|
||||
boolean octal = ( ( flags & OC ) != 0 );
|
||||
if ( hexadecimal )
|
||||
return fmt(
|
||||
Integer.toString( s & 0xffff, 16 ), minWidth, flags|WN );
|
||||
else if ( octal )
|
||||
return fmt(
|
||||
Integer.toString( s & 0xffff, 8 ), minWidth, flags|WN );
|
||||
else
|
||||
return fmt( Integer.toString( s ), minWidth, flags|WN );
|
||||
}
|
||||
|
||||
// int
|
||||
public static String fmt( int i )
|
||||
{
|
||||
return fmt( i, 0, 0 );
|
||||
}
|
||||
public static String fmt( int i, int minWidth )
|
||||
{
|
||||
return fmt( i, minWidth, 0 );
|
||||
}
|
||||
public static String fmt( int i, int minWidth, int flags )
|
||||
{
|
||||
boolean hexadecimal = ( ( flags & HX ) != 0 );
|
||||
boolean octal = ( ( flags & OC ) != 0 );
|
||||
if ( hexadecimal )
|
||||
return fmt(
|
||||
Long.toString( i & 0xffffffffL, 16 ), minWidth, flags|WN );
|
||||
else if ( octal )
|
||||
return fmt(
|
||||
Long.toString( i & 0xffffffffL, 8 ), minWidth, flags|WN );
|
||||
else
|
||||
return fmt( Integer.toString( i ), minWidth, flags|WN );
|
||||
}
|
||||
|
||||
// long
|
||||
public static String fmt( long l )
|
||||
{
|
||||
return fmt( l, 0, 0 );
|
||||
}
|
||||
public static String fmt( long l, int minWidth )
|
||||
{
|
||||
return fmt( l, minWidth, 0 );
|
||||
}
|
||||
public static String fmt( long l, int minWidth, int flags )
|
||||
{
|
||||
boolean hexadecimal = ( ( flags & HX ) != 0 );
|
||||
boolean octal = ( ( flags & OC ) != 0 );
|
||||
if ( hexadecimal )
|
||||
{
|
||||
if ( ( l & 0xf000000000000000L ) != 0 )
|
||||
return fmt(
|
||||
Long.toString( l >>> 60, 16 ) +
|
||||
fmt( l & 0x0fffffffffffffffL, 15, HX|ZF ),
|
||||
minWidth, flags|WN );
|
||||
else
|
||||
return fmt( Long.toString( l, 16 ), minWidth, flags|WN );
|
||||
}
|
||||
else if ( octal )
|
||||
{
|
||||
if ( ( l & 0x8000000000000000L ) != 0 )
|
||||
return fmt(
|
||||
Long.toString( l >>> 63, 8 ) +
|
||||
fmt( l & 0x7fffffffffffffffL, 21, OC|ZF ),
|
||||
minWidth, flags|WN );
|
||||
else
|
||||
return fmt( Long.toString( l, 8 ), minWidth, flags|WN );
|
||||
}
|
||||
else
|
||||
return fmt( Long.toString( l ), minWidth, flags|WN );
|
||||
}
|
||||
|
||||
// float
|
||||
public static String fmt( float f )
|
||||
{
|
||||
return fmt( f, 0, 0, 0 );
|
||||
}
|
||||
public static String fmt( float f, int minWidth )
|
||||
{
|
||||
return fmt( f, minWidth, 0, 0 );
|
||||
}
|
||||
public static String fmt( float f, int minWidth, int sigFigs )
|
||||
{
|
||||
return fmt( f, minWidth, sigFigs, 0 );
|
||||
}
|
||||
public static String fmt( float f, int minWidth, int sigFigs, int flags )
|
||||
{
|
||||
if ( sigFigs != 0 )
|
||||
return fmt(
|
||||
sigFigFix( Float.toString( f ), sigFigs ), minWidth,
|
||||
flags|WN );
|
||||
else
|
||||
return fmt( Float.toString( f ), minWidth, flags|WN );
|
||||
}
|
||||
|
||||
// double
|
||||
public static String fmt( double d )
|
||||
{
|
||||
return fmt( d, 0, 0, 0 );
|
||||
}
|
||||
public static String fmt( double d, int minWidth )
|
||||
{
|
||||
return fmt( d, minWidth, 0, 0 );
|
||||
}
|
||||
public static String fmt( double d, int minWidth, int sigFigs )
|
||||
{
|
||||
return fmt( d, minWidth, sigFigs, 0 );
|
||||
}
|
||||
public static String fmt( double d, int minWidth, int sigFigs, int flags )
|
||||
{
|
||||
if ( sigFigs != 0 )
|
||||
return fmt(
|
||||
sigFigFix( doubleToString( d ), sigFigs ), minWidth,
|
||||
flags|WN );
|
||||
else
|
||||
return fmt( doubleToString( d ), minWidth, flags|WN );
|
||||
}
|
||||
|
||||
// char
|
||||
public static String fmt( char c )
|
||||
{
|
||||
return fmt( c, 0, 0 );
|
||||
}
|
||||
public static String fmt( char c, int minWidth )
|
||||
{
|
||||
return fmt( c, minWidth, 0 );
|
||||
}
|
||||
public static String fmt( char c, int minWidth, int flags )
|
||||
{
|
||||
// return fmt( Character.toString( c ), minWidth, flags );
|
||||
// Character currently lacks a static toString method. Workaround
|
||||
// is to make a temporary instance and use the instance toString.
|
||||
return fmt( new Character( c ).toString(), minWidth, flags );
|
||||
}
|
||||
|
||||
// Object
|
||||
public static String fmt( Object o )
|
||||
{
|
||||
return fmt( o, 0, 0 );
|
||||
}
|
||||
public static String fmt( Object o, int minWidth )
|
||||
{
|
||||
return fmt( o, minWidth, 0 );
|
||||
}
|
||||
public static String fmt( Object o, int minWidth, int flags )
|
||||
{
|
||||
return fmt( o.toString(), minWidth, flags );
|
||||
}
|
||||
|
||||
// String
|
||||
public static String fmt( String s )
|
||||
{
|
||||
return fmt( s, 0, 0 );
|
||||
}
|
||||
public static String fmt( String s, int minWidth )
|
||||
{
|
||||
return fmt( s, minWidth, 0 );
|
||||
}
|
||||
public static String fmt( String s, int minWidth, int flags )
|
||||
{
|
||||
int len = s.length();
|
||||
boolean zeroFill = ( ( flags & ZF ) != 0 );
|
||||
boolean leftJustify = ( ( flags & LJ ) != 0 );
|
||||
boolean hexadecimal = ( ( flags & HX ) != 0 );
|
||||
boolean octal = ( ( flags & OC ) != 0 );
|
||||
boolean wasNumber = ( ( flags & WN ) != 0 );
|
||||
if ( ( hexadecimal || octal || zeroFill ) && ! wasNumber )
|
||||
throw new InternalError( "Acme.Fmt: number flag on a non-number" );
|
||||
if ( zeroFill && leftJustify )
|
||||
throw new InternalError( "Acme.Fmt: zero-fill left-justify is silly" );
|
||||
if ( hexadecimal && octal )
|
||||
throw new InternalError( "Acme.Fmt: can't do both hex and octal" );
|
||||
if ( len >= minWidth )
|
||||
return s;
|
||||
int fillWidth = minWidth - len;
|
||||
StringBuffer fill = new StringBuffer( fillWidth );
|
||||
for ( int i = 0; i < fillWidth; ++i )
|
||||
if ( zeroFill )
|
||||
fill.append( '0' );
|
||||
else
|
||||
fill.append( ' ' );
|
||||
if ( leftJustify )
|
||||
return s + fill;
|
||||
else if ( zeroFill && s.startsWith( "-" ) )
|
||||
return "-" + fill + s.substring( 1 );
|
||||
else
|
||||
return fill + s;
|
||||
}
|
||||
|
||||
|
||||
// Internal routines.
|
||||
|
||||
private static String sigFigFix( String s, int sigFigs )
|
||||
{
|
||||
// First dissect the floating-point number string into sign,
|
||||
// integer part, fraction part, and exponent.
|
||||
String sign;
|
||||
String unsigned;
|
||||
if ( s.startsWith( "-" ) || s.startsWith( "+" ) )
|
||||
{
|
||||
sign = s.substring( 0, 1 );
|
||||
unsigned = s.substring( 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
sign = "";
|
||||
unsigned = s;
|
||||
}
|
||||
String mantissa;
|
||||
String exponent;
|
||||
int eInd = unsigned.indexOf( 'e' );
|
||||
if ( eInd == -1 ) // it may be 'e' or 'E'
|
||||
eInd = unsigned.indexOf( 'E' );
|
||||
if ( eInd == -1 )
|
||||
{
|
||||
mantissa = unsigned;
|
||||
exponent = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
mantissa = unsigned.substring( 0, eInd );
|
||||
exponent = unsigned.substring( eInd );
|
||||
}
|
||||
StringBuffer number, fraction;
|
||||
int dotInd = mantissa.indexOf( '.' );
|
||||
if ( dotInd == -1 )
|
||||
{
|
||||
number = new StringBuffer( mantissa );
|
||||
fraction = new StringBuffer( "" );
|
||||
}
|
||||
else
|
||||
{
|
||||
number = new StringBuffer( mantissa.substring( 0, dotInd ) );
|
||||
fraction = new StringBuffer( mantissa.substring( dotInd + 1 ) );
|
||||
}
|
||||
|
||||
int numFigs = number.length();
|
||||
int fracFigs = fraction.length();
|
||||
if ( ( numFigs == 0 || number.equals( "0" ) ) && fracFigs > 0 )
|
||||
{
|
||||
// Don't count leading zeros in the fraction.
|
||||
numFigs = 0;
|
||||
for ( int i = 0; i < fraction.length(); ++i )
|
||||
{
|
||||
if ( fraction.charAt( i ) != '0' )
|
||||
break;
|
||||
--fracFigs;
|
||||
}
|
||||
}
|
||||
int mantFigs = numFigs + fracFigs;
|
||||
if ( sigFigs > mantFigs )
|
||||
{
|
||||
// We want more figures; just append zeros to the fraction.
|
||||
for ( int i = mantFigs; i < sigFigs; ++i )
|
||||
fraction.append( '0' );
|
||||
}
|
||||
else if ( sigFigs < mantFigs && sigFigs >= numFigs )
|
||||
{
|
||||
// Want fewer figures in the fraction; chop.
|
||||
fraction.setLength(
|
||||
fraction.length() - ( fracFigs - ( sigFigs - numFigs ) ) );
|
||||
// Round?
|
||||
}
|
||||
else if ( sigFigs < numFigs )
|
||||
{
|
||||
// Want fewer figures in the number; turn them to zeros.
|
||||
fraction.setLength( 0 ); // should already be zero, but make sure
|
||||
for ( int i = sigFigs; i < numFigs; ++i )
|
||||
number.setCharAt( i, '0' );
|
||||
// Round?
|
||||
}
|
||||
// Else sigFigs == mantFigs, which is fine.
|
||||
|
||||
if ( fraction.length() == 0 )
|
||||
return sign + number + exponent;
|
||||
else
|
||||
return sign + number + "." + fraction + exponent;
|
||||
}
|
||||
|
||||
|
||||
/// Improved version of Double.toString(), returns more decimal places.
|
||||
// <P>
|
||||
// The JDK 1.0.2 version of Double.toString() returns only six decimal
|
||||
// places on some systems. In JDK 1.1 full precision is returned on
|
||||
// all platforms.
|
||||
// @deprecated
|
||||
// @see java.lang.Double#toString
|
||||
public static String doubleToString( double d )
|
||||
{
|
||||
// Handle special numbers first, to avoid complications.
|
||||
if ( Double.isNaN( d ) )
|
||||
return "NaN";
|
||||
if ( d == Double.NEGATIVE_INFINITY )
|
||||
return "-Inf";
|
||||
if ( d == Double.POSITIVE_INFINITY )
|
||||
return "Inf";
|
||||
|
||||
// Grab the sign, and then make the number positive for simplicity.
|
||||
boolean negative = false;
|
||||
if ( d < 0.0D )
|
||||
{
|
||||
negative = true;
|
||||
d = -d;
|
||||
}
|
||||
|
||||
// Get the native version of the unsigned value, as a template.
|
||||
String unsStr = Double.toString( d );
|
||||
|
||||
// Dissect out the exponent.
|
||||
String mantStr, expStr;
|
||||
int exp;
|
||||
int eInd = unsStr.indexOf( 'e' );
|
||||
if ( eInd == -1 ) // it may be 'e' or 'E'
|
||||
eInd = unsStr.indexOf( 'E' );
|
||||
if ( eInd == -1 )
|
||||
{
|
||||
mantStr = unsStr;
|
||||
expStr = "";
|
||||
exp = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
mantStr = unsStr.substring( 0, eInd );
|
||||
expStr = unsStr.substring( eInd + 1 );
|
||||
if ( expStr.startsWith( "+" ) )
|
||||
exp = Integer.parseInt( expStr.substring( 1 ) );
|
||||
else
|
||||
exp = Integer.parseInt( expStr );
|
||||
}
|
||||
|
||||
// Dissect out the number part.
|
||||
String numStr;
|
||||
int dotInd = mantStr.indexOf( '.' );
|
||||
if ( dotInd == -1 )
|
||||
numStr = mantStr;
|
||||
else
|
||||
numStr = mantStr.substring( 0, dotInd );
|
||||
long num;
|
||||
if ( numStr.length() == 0 )
|
||||
num = 0;
|
||||
else
|
||||
num = Integer.parseInt( numStr );
|
||||
|
||||
// Build the new mantissa.
|
||||
StringBuffer newMantBuf = new StringBuffer( numStr + "." );
|
||||
double p = Math.pow( 10, exp );
|
||||
double frac = d - num * p;
|
||||
String digits = "0123456789";
|
||||
int nDigits = 16 - numStr.length(); // about 16 digits in a double
|
||||
for ( int i = 0; i < nDigits; ++i )
|
||||
{
|
||||
p /= 10.0D;
|
||||
int dig = (int) ( frac / p );
|
||||
if ( dig < 0 ) dig = 0;
|
||||
if ( dig > 9 ) dig = 9;
|
||||
newMantBuf.append( digits.charAt( dig ) );
|
||||
frac -= dig * p;
|
||||
}
|
||||
|
||||
if ( (int) ( frac / p + 0.5D ) == 1 )
|
||||
{
|
||||
// Round up.
|
||||
boolean roundMore = true;
|
||||
for ( int i = newMantBuf.length() - 1; i >= 0; --i )
|
||||
{
|
||||
int dig = digits.indexOf( newMantBuf.charAt( i ) );
|
||||
if ( dig == -1 )
|
||||
continue;
|
||||
++dig;
|
||||
if ( dig == 10 )
|
||||
{
|
||||
newMantBuf.setCharAt( i, '0' );
|
||||
continue;
|
||||
}
|
||||
newMantBuf.setCharAt( i, digits.charAt( dig ) );
|
||||
roundMore = false;
|
||||
break;
|
||||
}
|
||||
if ( roundMore )
|
||||
{
|
||||
// If this happens, we need to prepend a 1. But I haven't
|
||||
// found a test case yet, so I'm leaving it out for now.
|
||||
// But if you get this message, please let me know!
|
||||
newMantBuf.append( "ROUNDMORE" );
|
||||
}
|
||||
}
|
||||
|
||||
// Chop any trailing zeros.
|
||||
int len = newMantBuf.length();
|
||||
while ( newMantBuf.charAt( len - 1 ) == '0' )
|
||||
newMantBuf.setLength( --len );
|
||||
// And chop a trailing dot, if any.
|
||||
if ( newMantBuf.charAt( len - 1 ) == '.' )
|
||||
newMantBuf.setLength( --len );
|
||||
|
||||
// Done.
|
||||
return ( negative ? "-" : "" ) +
|
||||
newMantBuf +
|
||||
( expStr.length() != 0 ? ( "e" + expStr ) : "" );
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
/// Test program.
|
||||
public static void main( String[] args )
|
||||
{
|
||||
System.out.println( "Starting tests." );
|
||||
show( Fmt.fmt( "Hello there." ) );
|
||||
show( Fmt.fmt( 123 ) );
|
||||
show( Fmt.fmt( 123, 10 ) );
|
||||
show( Fmt.fmt( 123, 10, Fmt.ZF ) );
|
||||
show( Fmt.fmt( 123, 10, Fmt.LJ ) );
|
||||
show( Fmt.fmt( -123 ) );
|
||||
show( Fmt.fmt( -123, 10 ) );
|
||||
show( Fmt.fmt( -123, 10, Fmt.ZF ) );
|
||||
show( Fmt.fmt( -123, 10, Fmt.LJ ) );
|
||||
show( Fmt.fmt( (byte) 0xbe, 22, Fmt.OC ) );
|
||||
show( Fmt.fmt( (short) 0xbabe, 22, Fmt.OC ) );
|
||||
show( Fmt.fmt( 0xcafebabe, 22, Fmt.OC ) );
|
||||
show( Fmt.fmt( 0xdeadbeefcafebabeL, 22, Fmt.OC ) );
|
||||
show( Fmt.fmt( 0x8000000000000000L, 22, Fmt.OC ) );
|
||||
show( Fmt.fmt( (byte) 0xbe, 16, Fmt.HX ) );
|
||||
show( Fmt.fmt( (short) 0xbabe, 16, Fmt.HX ) );
|
||||
show( Fmt.fmt( 0xcafebabe, 16, Fmt.HX ) );
|
||||
show( Fmt.fmt( 0xdeadbeefcafebabeL, 16, Fmt.HX ) );
|
||||
show( Fmt.fmt( 0x8000000000000000L, 16, Fmt.HX ) );
|
||||
show( Fmt.fmt( 'c' ) );
|
||||
show( Fmt.fmt( new java.util.Date() ) );
|
||||
show( Fmt.fmt( 123.456F ) );
|
||||
show( Fmt.fmt( 123456000000000000.0F ) );
|
||||
show( Fmt.fmt( 123.456F, 0, 8 ) );
|
||||
show( Fmt.fmt( 123.456F, 0, 7 ) );
|
||||
show( Fmt.fmt( 123.456F, 0, 6 ) );
|
||||
show( Fmt.fmt( 123.456F, 0, 5 ) );
|
||||
show( Fmt.fmt( 123.456F, 0, 4 ) );
|
||||
show( Fmt.fmt( 123.456F, 0, 3 ) );
|
||||
show( Fmt.fmt( 123.456F, 0, 2 ) );
|
||||
show( Fmt.fmt( 123.456F, 0, 1 ) );
|
||||
show( Fmt.fmt( 123456000000000000.0F, 0, 4 ) );
|
||||
show( Fmt.fmt( -123.456F, 0, 4 ) );
|
||||
show( Fmt.fmt( -123456000000000000.0F, 0, 4 ) );
|
||||
show( Fmt.fmt( 123.0F ) );
|
||||
show( Fmt.fmt( 123.0D ) );
|
||||
show( Fmt.fmt( 1.234567890123456789F ) );
|
||||
show( Fmt.fmt( 1.234567890123456789D ) );
|
||||
show( Fmt.fmt( 1234567890123456789F ) );
|
||||
show( Fmt.fmt( 1234567890123456789D ) );
|
||||
show( Fmt.fmt( 0.000000000000000000001234567890123456789F ) );
|
||||
show( Fmt.fmt( 0.000000000000000000001234567890123456789D ) );
|
||||
show( Fmt.fmt( 12300.0F ) );
|
||||
show( Fmt.fmt( 12300.0D ) );
|
||||
show( Fmt.fmt( 123000.0F ) );
|
||||
show( Fmt.fmt( 123000.0D ) );
|
||||
show( Fmt.fmt( 1230000.0F ) );
|
||||
show( Fmt.fmt( 1230000.0D ) );
|
||||
show( Fmt.fmt( 12300000.0F ) );
|
||||
show( Fmt.fmt( 12300000.0D ) );
|
||||
show( Fmt.fmt( Float.NaN ) );
|
||||
show( Fmt.fmt( Float.POSITIVE_INFINITY ) );
|
||||
show( Fmt.fmt( Float.NEGATIVE_INFINITY ) );
|
||||
show( Fmt.fmt( Double.NaN ) );
|
||||
show( Fmt.fmt( Double.POSITIVE_INFINITY ) );
|
||||
show( Fmt.fmt( Double.NEGATIVE_INFINITY ) );
|
||||
show( Fmt.fmt( 1.0F / 8.0F ) );
|
||||
show( Fmt.fmt( 1.0D / 8.0D ) );
|
||||
System.out.println( "Done with tests." );
|
||||
}
|
||||
|
||||
private static void show( String str )
|
||||
{
|
||||
System.out.println( "#" + str + "#" );
|
||||
}
|
||||
******************************************************************************/
|
||||
|
||||
}
|
|
@ -1,396 +0,0 @@
|
|||
// IntHashtable - a Hashtable that uses ints as the keys
|
||||
//
|
||||
// This is 90% based on JavaSoft's java.util.Hashtable.
|
||||
//
|
||||
// Visit the ACME Labs Java page for up-to-date versions of this and other
|
||||
// fine Java utilities: http://www.acme.com/java/
|
||||
|
||||
package Acme;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/// A Hashtable that uses ints as the keys.
|
||||
// <P>
|
||||
// Use just like java.util.Hashtable, except that the keys must be ints.
|
||||
// This is much faster than creating a new Integer for each access.
|
||||
// <P>
|
||||
// <A HREF="/resources/classes/Acme/IntHashtable.java">Fetch the software.</A><BR>
|
||||
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
|
||||
// <P>
|
||||
// @see java.util.Hashtable
|
||||
|
||||
public class IntHashtable extends Dictionary implements Cloneable
|
||||
{
|
||||
/// The hash table data.
|
||||
private IntHashtableEntry table[];
|
||||
|
||||
/// The total number of entries in the hash table.
|
||||
private int count;
|
||||
|
||||
/// Rehashes the table when count exceeds this threshold.
|
||||
private int threshold;
|
||||
|
||||
/// The load factor for the hashtable.
|
||||
private float loadFactor;
|
||||
|
||||
/// Constructs a new, empty hashtable with the specified initial
|
||||
// capacity and the specified load factor.
|
||||
// @param initialCapacity the initial number of buckets
|
||||
// @param loadFactor a number between 0.0 and 1.0, it defines
|
||||
// the threshold for rehashing the hashtable into
|
||||
// a bigger one.
|
||||
// @exception IllegalArgumentException If the initial capacity
|
||||
// is less than or equal to zero.
|
||||
// @exception IllegalArgumentException If the load factor is
|
||||
// less than or equal to zero.
|
||||
public IntHashtable( int initialCapacity, float loadFactor )
|
||||
{
|
||||
if ( initialCapacity <= 0 || loadFactor <= 0.0 )
|
||||
throw new IllegalArgumentException();
|
||||
this.loadFactor = loadFactor;
|
||||
table = new IntHashtableEntry[initialCapacity];
|
||||
threshold = (int) ( initialCapacity * loadFactor );
|
||||
}
|
||||
|
||||
/// Constructs a new, empty hashtable with the specified initial
|
||||
// capacity.
|
||||
// @param initialCapacity the initial number of buckets
|
||||
public IntHashtable( int initialCapacity )
|
||||
{
|
||||
this( initialCapacity, 0.75f );
|
||||
}
|
||||
|
||||
/// Constructs a new, empty hashtable. A default capacity and load factor
|
||||
// is used. Note that the hashtable will automatically grow when it gets
|
||||
// full.
|
||||
public IntHashtable()
|
||||
{
|
||||
this( 101, 0.75f );
|
||||
}
|
||||
|
||||
/// Returns the number of elements contained in the hashtable.
|
||||
public int size()
|
||||
{
|
||||
return count;
|
||||
}
|
||||
|
||||
/// Returns true if the hashtable contains no elements.
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return count == 0;
|
||||
}
|
||||
|
||||
/// Returns an enumeration of the hashtable's keys.
|
||||
// @see IntHashtable#elements
|
||||
public synchronized Enumeration keys()
|
||||
{
|
||||
return new IntHashtableEnumerator( table, true );
|
||||
}
|
||||
|
||||
/// Returns an enumeration of the elements. Use the Enumeration methods
|
||||
// on the returned object to fetch the elements sequentially.
|
||||
// @see IntHashtable#keys
|
||||
public synchronized Enumeration elements()
|
||||
{
|
||||
return new IntHashtableEnumerator( table, false );
|
||||
}
|
||||
|
||||
/// Returns true if the specified object is an element of the hashtable.
|
||||
// This operation is more expensive than the containsKey() method.
|
||||
// @param value the value that we are looking for
|
||||
// @exception NullPointerException If the value being searched
|
||||
// for is equal to null.
|
||||
// @see IntHashtable#containsKey
|
||||
public synchronized boolean contains( Object value )
|
||||
{
|
||||
if ( value == null )
|
||||
throw new NullPointerException();
|
||||
IntHashtableEntry tab[] = table;
|
||||
for ( int i = tab.length ; i-- > 0 ; )
|
||||
{
|
||||
for ( IntHashtableEntry e = tab[i] ; e != null ; e = e.next )
|
||||
{
|
||||
if ( e.value.equals( value ) )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Returns true if the collection contains an element for the key.
|
||||
// @param key the key that we are looking for
|
||||
// @see IntHashtable#contains
|
||||
public synchronized boolean containsKey( int key )
|
||||
{
|
||||
IntHashtableEntry tab[] = table;
|
||||
int hash = key;
|
||||
int index = ( hash & 0x7FFFFFFF ) % tab.length;
|
||||
for ( IntHashtableEntry e = tab[index] ; e != null ; e = e.next )
|
||||
{
|
||||
if ( e.hash == hash && e.key == key )
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Gets the object associated with the specified key in the
|
||||
// hashtable.
|
||||
// @param key the specified key
|
||||
// @returns the element for the key or null if the key
|
||||
// is not defined in the hash table.
|
||||
// @see IntHashtable#put
|
||||
public synchronized Object get( int key )
|
||||
{
|
||||
IntHashtableEntry tab[] = table;
|
||||
int hash = key;
|
||||
int index = ( hash & 0x7FFFFFFF ) % tab.length;
|
||||
for ( IntHashtableEntry e = tab[index] ; e != null ; e = e.next )
|
||||
{
|
||||
if ( e.hash == hash && e.key == key )
|
||||
return e.value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// A get method that takes an Object, for compatibility with
|
||||
// java.util.Dictionary. The Object must be an Integer.
|
||||
public Object get( Object okey )
|
||||
{
|
||||
if ( ! ( okey instanceof Integer ) )
|
||||
throw new InternalError( "key is not an Integer" );
|
||||
Integer ikey = (Integer) okey;
|
||||
int key = ikey.intValue();
|
||||
return get( key );
|
||||
}
|
||||
|
||||
/// Rehashes the content of the table into a bigger table.
|
||||
// This method is called automatically when the hashtable's
|
||||
// size exceeds the threshold.
|
||||
protected void rehash()
|
||||
{
|
||||
int oldCapacity = table.length;
|
||||
IntHashtableEntry oldTable[] = table;
|
||||
|
||||
int newCapacity = oldCapacity * 2 + 1;
|
||||
IntHashtableEntry newTable[] = new IntHashtableEntry[newCapacity];
|
||||
|
||||
threshold = (int) ( newCapacity * loadFactor );
|
||||
table = newTable;
|
||||
|
||||
for ( int i = oldCapacity ; i-- > 0 ; )
|
||||
{
|
||||
for ( IntHashtableEntry old = oldTable[i] ; old != null ; )
|
||||
{
|
||||
IntHashtableEntry e = old;
|
||||
old = old.next;
|
||||
|
||||
int index = ( e.hash & 0x7FFFFFFF ) % newCapacity;
|
||||
e.next = newTable[index];
|
||||
newTable[index] = e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Puts the specified element into the hashtable, using the specified
|
||||
// key. The element may be retrieved by doing a get() with the same key.
|
||||
// The key and the element cannot be null.
|
||||
// @param key the specified key in the hashtable
|
||||
// @param value the specified element
|
||||
// @exception NullPointerException If the value of the element
|
||||
// is equal to null.
|
||||
// @see IntHashtable#get
|
||||
// @return the old value of the key, or null if it did not have one.
|
||||
public synchronized Object put( int key, Object value )
|
||||
{
|
||||
// Make sure the value is not null.
|
||||
if ( value == null )
|
||||
throw new NullPointerException();
|
||||
|
||||
// Makes sure the key is not already in the hashtable.
|
||||
IntHashtableEntry tab[] = table;
|
||||
int hash = key;
|
||||
int index = ( hash & 0x7FFFFFFF ) % tab.length;
|
||||
for ( IntHashtableEntry e = tab[index] ; e != null ; e = e.next )
|
||||
{
|
||||
if ( e.hash == hash && e.key == key )
|
||||
{
|
||||
Object old = e.value;
|
||||
e.value = value;
|
||||
return old;
|
||||
}
|
||||
}
|
||||
|
||||
if ( count >= threshold )
|
||||
{
|
||||
// Rehash the table if the threshold is exceeded.
|
||||
rehash();
|
||||
return put( key, value );
|
||||
}
|
||||
|
||||
// Creates the new entry.
|
||||
IntHashtableEntry e = new IntHashtableEntry();
|
||||
e.hash = hash;
|
||||
e.key = key;
|
||||
e.value = value;
|
||||
e.next = tab[index];
|
||||
tab[index] = e;
|
||||
++count;
|
||||
return null;
|
||||
}
|
||||
|
||||
/// A put method that takes an Object, for compatibility with
|
||||
// java.util.Dictionary. The Object must be an Integer.
|
||||
public Object put( Object okey, Object value )
|
||||
{
|
||||
if ( ! ( okey instanceof Integer ) )
|
||||
throw new InternalError( "key is not an Integer" );
|
||||
Integer ikey = (Integer) okey;
|
||||
int key = ikey.intValue();
|
||||
return put( key, value );
|
||||
}
|
||||
|
||||
/// Removes the element corresponding to the key. Does nothing if the
|
||||
// key is not present.
|
||||
// @param key the key that needs to be removed
|
||||
// @return the value of key, or null if the key was not found.
|
||||
public synchronized Object remove( int key )
|
||||
{
|
||||
IntHashtableEntry tab[] = table;
|
||||
int hash = key;
|
||||
int index = ( hash & 0x7FFFFFFF ) % tab.length;
|
||||
for ( IntHashtableEntry e = tab[index], prev = null ; e != null ; prev = e, e = e.next )
|
||||
{
|
||||
if ( e.hash == hash && e.key == key )
|
||||
{
|
||||
if ( prev != null )
|
||||
prev.next = e.next;
|
||||
else
|
||||
tab[index] = e.next;
|
||||
--count;
|
||||
return e.value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// A remove method that takes an Object, for compatibility with
|
||||
// java.util.Dictionary. The Object must be an Integer.
|
||||
public Object remove( Object okey )
|
||||
{
|
||||
if ( ! ( okey instanceof Integer ) )
|
||||
throw new InternalError( "key is not an Integer" );
|
||||
Integer ikey = (Integer) okey;
|
||||
int key = ikey.intValue();
|
||||
return remove( key );
|
||||
}
|
||||
|
||||
/// Clears the hash table so that it has no more elements in it.
|
||||
public synchronized void clear()
|
||||
{
|
||||
IntHashtableEntry tab[] = table;
|
||||
for ( int index = tab.length; --index >= 0; )
|
||||
tab[index] = null;
|
||||
count = 0;
|
||||
}
|
||||
|
||||
/// Creates a clone of the hashtable. A shallow copy is made,
|
||||
// the keys and elements themselves are NOT cloned. This is a
|
||||
// relatively expensive operation.
|
||||
public synchronized Object clone()
|
||||
{
|
||||
try
|
||||
{
|
||||
IntHashtable t = (IntHashtable) super.clone();
|
||||
t.table = new IntHashtableEntry[table.length];
|
||||
for ( int i = table.length ; i-- > 0 ; )
|
||||
t.table[i] = ( table[i] != null ) ?
|
||||
(IntHashtableEntry) table[i].clone() : null;
|
||||
return t;
|
||||
}
|
||||
catch ( CloneNotSupportedException e)
|
||||
{
|
||||
// This shouldn't happen, since we are Cloneable.
|
||||
throw new InternalError();
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts to a rather lengthy String.
|
||||
public synchronized String toString()
|
||||
{
|
||||
int max = size() - 1;
|
||||
StringBuffer buf = new StringBuffer();
|
||||
Enumeration k = keys();
|
||||
Enumeration e = elements();
|
||||
buf.append( "{" );
|
||||
|
||||
for ( int i = 0; i <= max; ++i )
|
||||
{
|
||||
String s1 = k.nextElement().toString();
|
||||
String s2 = e.nextElement().toString();
|
||||
buf.append( s1 + "=" + s2 );
|
||||
if ( i < max )
|
||||
buf.append( ", " );
|
||||
}
|
||||
buf.append( "}" );
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class IntHashtableEntry
|
||||
{
|
||||
int hash;
|
||||
int key;
|
||||
Object value;
|
||||
IntHashtableEntry next;
|
||||
|
||||
protected Object clone()
|
||||
{
|
||||
IntHashtableEntry entry = new IntHashtableEntry();
|
||||
entry.hash = hash;
|
||||
entry.key = key;
|
||||
entry.value = value;
|
||||
entry.next = ( next != null ) ? (IntHashtableEntry) next.clone() : null;
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class IntHashtableEnumerator implements Enumeration
|
||||
{
|
||||
boolean keys;
|
||||
int index;
|
||||
IntHashtableEntry table[];
|
||||
IntHashtableEntry entry;
|
||||
|
||||
IntHashtableEnumerator( IntHashtableEntry table[], boolean keys )
|
||||
{
|
||||
this.table = table;
|
||||
this.keys = keys;
|
||||
this.index = table.length;
|
||||
}
|
||||
|
||||
public boolean hasMoreElements()
|
||||
{
|
||||
if ( entry != null )
|
||||
return true;
|
||||
while ( index-- > 0 )
|
||||
if ( ( entry = table[index] ) != null )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public Object nextElement()
|
||||
{
|
||||
if ( entry == null )
|
||||
while ( ( index-- > 0 ) && ( ( entry = table[index] ) == null ) )
|
||||
;
|
||||
if ( entry != null )
|
||||
{
|
||||
IntHashtableEntry e = entry;
|
||||
entry = e.next;
|
||||
return keys ? new Integer( e.key ) : e.value;
|
||||
}
|
||||
throw new NoSuchElementException( "IntHashtableEnumerator" );
|
||||
}
|
||||
}
|
|
@ -1,314 +0,0 @@
|
|||
// ImageDecoder - abstract class for reading in an image
|
||||
//
|
||||
// Copyright (C) 1996 by Jef Poskanzer <jef@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/
|
||||
|
||||
package Acme.JPM.Decoders;
|
||||
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
import java.awt.image.*;
|
||||
|
||||
/// Abstract class for reading in an image.
|
||||
// <P>
|
||||
// A framework for classes that read in and decode an image in
|
||||
// a particular file format.
|
||||
// <P>
|
||||
// This provides a very simplified rendition of the ImageProducer interface.
|
||||
// It requires the decoder to read the image a row at a time. It requires
|
||||
// use of the RGBdefault color model.
|
||||
// If you want more flexibility you can always implement ImageProducer
|
||||
// directly.
|
||||
// <P>
|
||||
// <A HREF="/resources/classes/Acme/JPM/Decoders/ImageDecoder.java">Fetch the software.</A><BR>
|
||||
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
|
||||
// <P>
|
||||
// @see PpmDecoder
|
||||
// @see Acme.JPM.Encoders.ImageEncoder
|
||||
|
||||
public abstract class ImageDecoder implements ImageProducer
|
||||
{
|
||||
|
||||
private InputStream in;
|
||||
private int width, height;
|
||||
private boolean[] rowsRead;
|
||||
private int[][] rgbPixels;
|
||||
private boolean startedRead = false;
|
||||
private boolean gotSize = false;
|
||||
private boolean err = false;
|
||||
private boolean producing = false;
|
||||
private Vector consumers = new Vector();
|
||||
private static final ColorModel model = ColorModel.getRGBdefault();
|
||||
|
||||
|
||||
/// Constructor.
|
||||
// @param in The stream to read the bytes from.
|
||||
public ImageDecoder( InputStream in )
|
||||
{
|
||||
this.in = in;
|
||||
}
|
||||
|
||||
|
||||
// Methods that subclasses implement.
|
||||
|
||||
/// Subclasses implement this to read in enough of the image stream
|
||||
// to figure out the width and height.
|
||||
abstract void readHeader( InputStream in ) throws IOException;
|
||||
|
||||
/// Subclasses implement this to return the width, or -1 if not known.
|
||||
abstract int getWidth();
|
||||
|
||||
/// Subclasses implement this to return the height, or -1 if not known.
|
||||
abstract int getHeight();
|
||||
|
||||
/// Subclasses implement this to read pixel data into the rgbRow
|
||||
// array, an int[width]. One int per pixel, no offsets or padding,
|
||||
// RGBdefault (AARRGGBB) color model.
|
||||
abstract void readRow( InputStream in, int row, int[] rgbRow ) throws IOException;
|
||||
|
||||
|
||||
// Our own methods.
|
||||
|
||||
void readImage()
|
||||
{
|
||||
try
|
||||
{
|
||||
readHeader( in );
|
||||
width = getWidth();
|
||||
height = getHeight();
|
||||
if ( width == -1 || height == -1 )
|
||||
err = true;
|
||||
else
|
||||
{
|
||||
rowsRead = new boolean[height];
|
||||
for ( int row = 0; row < height; ++row )
|
||||
rowsRead[row] = false;
|
||||
gotSize = true;
|
||||
notifyThem();
|
||||
rgbPixels = new int[height][width];
|
||||
for ( int row = 0; row < height; ++row )
|
||||
{
|
||||
readRow( in, row, rgbPixels[row] );
|
||||
rowsRead[row] = true;
|
||||
notifyThem();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( IOException e )
|
||||
{
|
||||
err = true;
|
||||
width = -1;
|
||||
height = -1;
|
||||
rowsRead = null;
|
||||
rgbPixels = null;
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void notifyThem()
|
||||
{
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
void sendImage()
|
||||
{
|
||||
// Grab the list of consumers, in case it changes while we're sending.
|
||||
ImageConsumer[] c = new ImageConsumer[consumers.size()];
|
||||
int i;
|
||||
for ( i = 0; i < c.length; ++i )
|
||||
c[i] = (ImageConsumer) consumers.elementAt( i );
|
||||
// Try to be as parallel as possible.
|
||||
waitForSize();
|
||||
for ( i = 0; i < c.length; ++i )
|
||||
sendHead( c[i] );
|
||||
for ( int row = 0; row < height; ++row )
|
||||
for ( i = 0; i < c.length; ++i )
|
||||
sendPixelRow( c[i], row );
|
||||
for ( i = 0; i < c.length; ++i )
|
||||
sendTail( c[i] );
|
||||
producing = false;
|
||||
}
|
||||
|
||||
private synchronized void waitForSize()
|
||||
{
|
||||
while ( ( ! err ) && ( ! gotSize ))
|
||||
{
|
||||
try
|
||||
{
|
||||
wait();
|
||||
}
|
||||
catch ( InterruptedException ignore ) {}
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void waitForRow( int row )
|
||||
{
|
||||
while ( ( ! err ) && ( ! rowsRead[row] ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
wait();
|
||||
}
|
||||
catch ( InterruptedException ignore ) {}
|
||||
}
|
||||
}
|
||||
|
||||
private void sendHead( ImageConsumer ic )
|
||||
{
|
||||
if ( err )
|
||||
return;
|
||||
ic.setDimensions( width, height );
|
||||
ic.setColorModel( model );
|
||||
ic.setHints(
|
||||
ImageConsumer.TOPDOWNLEFTRIGHT | ImageConsumer.COMPLETESCANLINES |
|
||||
ImageConsumer.SINGLEPASS | ImageConsumer.SINGLEFRAME );
|
||||
}
|
||||
|
||||
private void sendPixelRow( ImageConsumer ic, int row )
|
||||
{
|
||||
if ( err )
|
||||
return;
|
||||
waitForRow( row );
|
||||
if ( err )
|
||||
return;
|
||||
ic.setPixels( 0, row, width, 1, model, rgbPixels[row], 0, width );
|
||||
}
|
||||
|
||||
private void sendTail( ImageConsumer ic )
|
||||
{
|
||||
if ( err )
|
||||
ic.imageComplete( ImageConsumer.IMAGEERROR );
|
||||
else
|
||||
ic.imageComplete( ImageConsumer.STATICIMAGEDONE );
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Methods from ImageProducer.
|
||||
|
||||
/// This method is used to register an ImageConsumer with the
|
||||
// ImageProducer for access to the image data during a later
|
||||
// reconstruction of the Image. The ImageProducer may, at its
|
||||
// discretion, start delivering the image data to the consumer
|
||||
// using the ImageConsumer interface immediately, or when the
|
||||
// next available image reconstruction is triggered by a call
|
||||
// to the startProduction method.
|
||||
// @see #startProduction
|
||||
public void addConsumer( ImageConsumer ic )
|
||||
{
|
||||
if ( ic != null && ! isConsumer( ic ) )
|
||||
consumers.addElement( ic );
|
||||
}
|
||||
|
||||
/// This method determines if a given ImageConsumer object
|
||||
// is currently registered with this ImageProducer as one
|
||||
// of its consumers.
|
||||
public boolean isConsumer( ImageConsumer ic )
|
||||
{
|
||||
return consumers.contains( ic );
|
||||
}
|
||||
|
||||
/// This method removes the given ImageConsumer object
|
||||
// from the list of consumers currently registered to
|
||||
// receive image data. It is not considered an error
|
||||
// to remove a consumer that is not currently registered.
|
||||
// The ImageProducer should stop sending data to this
|
||||
// consumer as soon as is feasible.
|
||||
public void removeConsumer( ImageConsumer ic )
|
||||
{
|
||||
consumers.removeElement( ic );
|
||||
}
|
||||
|
||||
/// This method both registers the given ImageConsumer object
|
||||
// as a consumer and starts an immediate reconstruction of
|
||||
// the image data which will then be delivered to this
|
||||
// consumer and any other consumer which may have already
|
||||
// been registered with the producer. This method differs
|
||||
// from the addConsumer method in that a reproduction of
|
||||
// the image data should be triggered as soon as possible.
|
||||
// @see #addConsumer
|
||||
public void startProduction( ImageConsumer ic )
|
||||
{
|
||||
addConsumer( ic );
|
||||
if ( ! startedRead )
|
||||
{
|
||||
startedRead = true;
|
||||
new ImageDecoderRead( this );
|
||||
}
|
||||
if ( ! producing )
|
||||
{
|
||||
producing = true;
|
||||
sendImage();
|
||||
}
|
||||
}
|
||||
|
||||
/// This method is used by an ImageConsumer to request that
|
||||
// the ImageProducer attempt to resend the image data one
|
||||
// more time in TOPDOWNLEFTRIGHT order so that higher
|
||||
// quality conversion algorithms which depend on receiving
|
||||
// pixels in order can be used to produce a better output
|
||||
// version of the image. The ImageProducer is free to
|
||||
// ignore this call if it cannot resend the data in that
|
||||
// order. If the data can be resent, then the ImageProducer
|
||||
// should respond by executing the following minimum set of
|
||||
// ImageConsumer method calls:
|
||||
// <PRE>
|
||||
// ic.setHints( TOPDOWNLEFTRIGHT | [otherhints] );
|
||||
// ic.setPixels( [...] ); // as many times as needed
|
||||
// ic.imageComplete( [status] );
|
||||
// </PRE>
|
||||
// @see ImageConsumer#setHints
|
||||
public void requestTopDownLeftRightResend( ImageConsumer ic )
|
||||
{
|
||||
addConsumer( ic );
|
||||
waitForSize();
|
||||
sendHead( ic );
|
||||
for ( int row = 0; row < height; ++row )
|
||||
sendPixelRow( ic, row );
|
||||
sendTail( ic );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class ImageDecoderRead extends Thread
|
||||
{
|
||||
|
||||
private ImageDecoder parent;
|
||||
|
||||
public ImageDecoderRead( ImageDecoder parent )
|
||||
{
|
||||
this.parent = parent;
|
||||
start();
|
||||
}
|
||||
|
||||
// Methods from Runnable.
|
||||
|
||||
public void run()
|
||||
{
|
||||
parent.readImage();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,267 +0,0 @@
|
|||
// PpmDecoder - read in a PPM image
|
||||
//
|
||||
// Copyright (C) 1996 by Jef Poskanzer <jef@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/
|
||||
|
||||
package Acme.JPM.Decoders;
|
||||
|
||||
import java.io.*;
|
||||
import java.awt.image.*;
|
||||
|
||||
/// Read in a PPM image.
|
||||
// <P>
|
||||
// <A HREF="/resources/classes/Acme/JPM/Decoders/PpmDecoder.java">Fetch the software.</A><BR>
|
||||
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
|
||||
// <P>
|
||||
// @see Acme.JPM.Encoders.PpmEncoder
|
||||
|
||||
public class PpmDecoder extends ImageDecoder
|
||||
{
|
||||
|
||||
/// Constructor.
|
||||
// @param in The stream to read the bytes from.
|
||||
public PpmDecoder( InputStream in )
|
||||
{
|
||||
super( in );
|
||||
}
|
||||
|
||||
|
||||
private int type;
|
||||
private static final int PBM_ASCII = 1;
|
||||
private static final int PGM_ASCII = 2;
|
||||
private static final int PPM_ASCII = 3;
|
||||
private static final int PBM_RAW = 4;
|
||||
private static final int PGM_RAW = 5;
|
||||
private static final int PPM_RAW = 6;
|
||||
|
||||
private int width = -1, height = -1;
|
||||
private int maxval;
|
||||
|
||||
/// Subclasses implement this to read in enough of the image stream
|
||||
// to figure out the width and height.
|
||||
void readHeader( InputStream in ) throws IOException
|
||||
{
|
||||
char c1, c2;
|
||||
|
||||
c1 = (char) readByte( in );
|
||||
c2 = (char) readByte( in );
|
||||
|
||||
if ( c1 != 'P' )
|
||||
throw new IOException( "not a PBM/PGM/PPM file" );
|
||||
switch ( c2 )
|
||||
{
|
||||
case '1':
|
||||
type = PBM_ASCII;
|
||||
break;
|
||||
case '2':
|
||||
type = PGM_ASCII;
|
||||
break;
|
||||
case '3':
|
||||
type = PPM_ASCII;
|
||||
break;
|
||||
case '4':
|
||||
type = PBM_RAW;
|
||||
break;
|
||||
case '5':
|
||||
type = PGM_RAW;
|
||||
break;
|
||||
case '6':
|
||||
type = PPM_RAW;
|
||||
break;
|
||||
default:
|
||||
throw new IOException( "not a standard PBM/PGM/PPM file" );
|
||||
}
|
||||
width = readInt( in );
|
||||
height = readInt( in );
|
||||
if ( type != PBM_ASCII && type != PBM_RAW )
|
||||
maxval = readInt( in );
|
||||
}
|
||||
|
||||
/// Subclasses implement this to return the width, or -1 if not known.
|
||||
int getWidth()
|
||||
{
|
||||
return width;
|
||||
}
|
||||
|
||||
/// Subclasses implement this to return the height, or -1 if not known.
|
||||
int getHeight()
|
||||
{
|
||||
return height;
|
||||
}
|
||||
|
||||
/// Subclasses implement this to read pixel data into the rgbRow
|
||||
// array, an int[width]. One int per pixel, no offsets or padding,
|
||||
// RGBdefault (AARRGGBB) color model
|
||||
void readRow( InputStream in, int row, int[] rgbRow ) throws IOException
|
||||
{
|
||||
int col, r, g, b;
|
||||
int rgb = 0;
|
||||
char c;
|
||||
|
||||
for ( col = 0; col < width; ++col )
|
||||
{
|
||||
switch ( type )
|
||||
{
|
||||
case PBM_ASCII:
|
||||
c = readChar( in );
|
||||
if ( c == '1' )
|
||||
rgb = 0xff000000;
|
||||
else if ( c == '0' )
|
||||
rgb = 0xffffffff;
|
||||
else
|
||||
throw new IOException( "illegal PBM bit" );
|
||||
break;
|
||||
case PGM_ASCII:
|
||||
g = readInt( in );
|
||||
rgb = makeRgb( g, g, g );
|
||||
break;
|
||||
case PPM_ASCII:
|
||||
r = readInt( in );
|
||||
g = readInt( in );
|
||||
b = readInt( in );
|
||||
rgb = makeRgb( r, g, b );
|
||||
break;
|
||||
case PBM_RAW:
|
||||
if ( readBit( in ) )
|
||||
rgb = 0xff000000;
|
||||
else
|
||||
rgb = 0xffffffff;
|
||||
break;
|
||||
case PGM_RAW:
|
||||
g = readByte( in );
|
||||
if ( maxval != 255 )
|
||||
g = fixDepth( g );
|
||||
rgb = makeRgb( g, g, g );
|
||||
break;
|
||||
case PPM_RAW:
|
||||
r = readByte( in );
|
||||
g = readByte( in );
|
||||
b = readByte( in );
|
||||
if ( maxval != 255 )
|
||||
{
|
||||
r = fixDepth( r );
|
||||
g = fixDepth( g );
|
||||
b = fixDepth( b );
|
||||
}
|
||||
rgb = makeRgb( r, g, b );
|
||||
break;
|
||||
}
|
||||
rgbRow[col] = rgb;
|
||||
}
|
||||
}
|
||||
|
||||
/// Utility routine to read a byte. Instead of returning -1 on
|
||||
// EOF, it throws an exception.
|
||||
private static int readByte( InputStream in ) throws IOException
|
||||
{
|
||||
int b = in.read();
|
||||
if ( b == -1 )
|
||||
throw new EOFException();
|
||||
return b;
|
||||
}
|
||||
|
||||
private int bitshift = -1;
|
||||
private int bits;
|
||||
|
||||
/// Utility routine to read a bit, packed eight to a byte, big-endian.
|
||||
private boolean readBit( InputStream in ) throws IOException
|
||||
{
|
||||
if ( bitshift == -1 )
|
||||
{
|
||||
bits = readByte( in );
|
||||
bitshift = 7;
|
||||
}
|
||||
boolean bit = ( ( ( bits >> bitshift ) & 1 ) != 0 );
|
||||
--bitshift;
|
||||
return bit;
|
||||
}
|
||||
|
||||
/// Utility routine to read a character, ignoring comments.
|
||||
private static char readChar( InputStream in ) throws IOException
|
||||
{
|
||||
char c;
|
||||
|
||||
c = (char) readByte( in );
|
||||
if ( c == '#' )
|
||||
{
|
||||
do
|
||||
{
|
||||
c = (char) readByte( in );
|
||||
}
|
||||
while ( c != '\n' && c != '\r' );
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/// Utility routine to read the first non-whitespace character.
|
||||
private static char readNonwhiteChar( InputStream in ) throws IOException
|
||||
{
|
||||
char c;
|
||||
|
||||
do
|
||||
{
|
||||
c = readChar( in );
|
||||
}
|
||||
while ( c == ' ' || c == '\t' || c == '\n' || c == '\r' );
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/// Utility routine to read an ASCII integer, ignoring comments.
|
||||
private static int readInt( InputStream in ) throws IOException
|
||||
{
|
||||
char c;
|
||||
int i;
|
||||
|
||||
c = readNonwhiteChar( in );
|
||||
if ( c < '0' || c > '9' )
|
||||
throw new IOException( "junk in file where integer should be" );
|
||||
|
||||
i = 0;
|
||||
do
|
||||
{
|
||||
i = i * 10 + c - '0';
|
||||
c = readChar( in );
|
||||
}
|
||||
while ( c >= '0' && c <= '9' );
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/// Utility routine to rescale a pixel value from a non-eight-bit maxval.
|
||||
private int fixDepth( int p )
|
||||
{
|
||||
return ( p * 255 + maxval / 2 ) / maxval;
|
||||
}
|
||||
|
||||
/// Utility routine make an RGBdefault pixel from three color values.
|
||||
private static int makeRgb( int r, int g, int b )
|
||||
{
|
||||
return 0xff000000 | ( r << 16 ) | ( g << 8 ) | b;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,691 +0,0 @@
|
|||
// GifEncoder - write out an image as a GIF
|
||||
//
|
||||
// Transparency handling and variable bit size courtesy of Jack Palevich.
|
||||
//
|
||||
// Copyright (C)1996,1998 by Jef Poskanzer <jef@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/
|
||||
|
||||
package Acme.JPM.Encoders;
|
||||
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
import java.awt.Image;
|
||||
import java.awt.image.*;
|
||||
|
||||
/// Write out an image as a GIF.
|
||||
// <P>
|
||||
// <A HREF="/resources/classes/Acme/JPM/Encoders/GifEncoder.java">Fetch the software.</A><BR>
|
||||
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
|
||||
// <P>
|
||||
// @see ToGif
|
||||
|
||||
public class GifEncoder extends ImageEncoder
|
||||
{
|
||||
|
||||
private boolean interlace = false;
|
||||
|
||||
/// Constructor from Image.
|
||||
// @param img The image to encode.
|
||||
// @param out The stream to write the GIF to.
|
||||
public GifEncoder( Image img, OutputStream out ) throws IOException
|
||||
{
|
||||
super( img, out );
|
||||
}
|
||||
|
||||
/// Constructor from Image with interlace setting.
|
||||
// @param img The image to encode.
|
||||
// @param out The stream to write the GIF to.
|
||||
// @param interlace Whether to interlace.
|
||||
public GifEncoder( Image img, OutputStream out, boolean interlace ) throws IOException
|
||||
{
|
||||
super( img, out );
|
||||
this.interlace = interlace;
|
||||
}
|
||||
|
||||
/// Constructor from ImageProducer.
|
||||
// @param prod The ImageProducer to encode.
|
||||
// @param out The stream to write the GIF to.
|
||||
public GifEncoder( ImageProducer prod, OutputStream out ) throws IOException
|
||||
{
|
||||
super( prod, out );
|
||||
}
|
||||
|
||||
/// Constructor from ImageProducer with interlace setting.
|
||||
// @param prod The ImageProducer to encode.
|
||||
// @param out The stream to write the GIF to.
|
||||
public GifEncoder( ImageProducer prod, OutputStream out, boolean interlace ) throws IOException
|
||||
{
|
||||
super( prod, out );
|
||||
this.interlace = interlace;
|
||||
}
|
||||
|
||||
|
||||
int width, height;
|
||||
int[][] rgbPixels;
|
||||
|
||||
void encodeStart( int width, int height ) throws IOException
|
||||
{
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
rgbPixels = new int[height][width];
|
||||
}
|
||||
|
||||
void encodePixels(
|
||||
int x, int y, int w, int h, int[] rgbPixels, int off, int scansize )
|
||||
throws IOException
|
||||
{
|
||||
// Save the pixels.
|
||||
for ( int row = 0; row < h; ++row )
|
||||
System.arraycopy(
|
||||
rgbPixels, row * scansize + off,
|
||||
this.rgbPixels[y + row], x, w );
|
||||
|
||||
}
|
||||
|
||||
Acme.IntHashtable colorHash;
|
||||
|
||||
void encodeDone() throws IOException
|
||||
{
|
||||
int transparentIndex = -1;
|
||||
int transparentRgb = -1;
|
||||
// Put all the pixels into a hash table.
|
||||
colorHash = new Acme.IntHashtable();
|
||||
int index = 0;
|
||||
for ( int row = 0; row < height; ++row )
|
||||
{
|
||||
int rowOffset = row * width;
|
||||
for ( int col = 0; col < width; ++col )
|
||||
{
|
||||
int rgb = rgbPixels[row][col];
|
||||
boolean isTransparent = ( ( rgb >>> 24 ) < 0x80 );
|
||||
if ( isTransparent )
|
||||
{
|
||||
if ( transparentIndex < 0 )
|
||||
{
|
||||
// First transparent color; remember it.
|
||||
transparentIndex = index;
|
||||
transparentRgb = rgb;
|
||||
}
|
||||
else if ( rgb != transparentRgb )
|
||||
{
|
||||
// A second transparent color; replace it with
|
||||
// the first one.
|
||||
rgbPixels[row][col] = rgb = transparentRgb;
|
||||
}
|
||||
}
|
||||
GifEncoderHashitem item =
|
||||
(GifEncoderHashitem) colorHash.get( rgb );
|
||||
if ( item == null )
|
||||
{
|
||||
if ( index >= 256 )
|
||||
throw new IOException( "too many colors for a GIF" );
|
||||
item = new GifEncoderHashitem(
|
||||
rgb, 1, index, isTransparent );
|
||||
++index;
|
||||
colorHash.put( rgb, item );
|
||||
}
|
||||
else
|
||||
++item.count;
|
||||
}
|
||||
}
|
||||
|
||||
// Figure out how many bits to use.
|
||||
int logColors;
|
||||
if ( index <= 2 )
|
||||
logColors = 1;
|
||||
else if ( index <= 4 )
|
||||
logColors = 2;
|
||||
else if ( index <= 16 )
|
||||
logColors = 4;
|
||||
else
|
||||
logColors = 8;
|
||||
|
||||
// Turn colors into colormap entries.
|
||||
int mapSize = 1 << logColors;
|
||||
byte[] reds = new byte[mapSize];
|
||||
byte[] grns = new byte[mapSize];
|
||||
byte[] blus = new byte[mapSize];
|
||||
for ( Enumeration e = colorHash.elements(); e.hasMoreElements(); )
|
||||
{
|
||||
GifEncoderHashitem item = (GifEncoderHashitem) e.nextElement();
|
||||
reds[item.index] = (byte) ( ( item.rgb >> 16 ) & 0xff );
|
||||
grns[item.index] = (byte) ( ( item.rgb >> 8 ) & 0xff );
|
||||
blus[item.index] = (byte) ( item.rgb & 0xff );
|
||||
}
|
||||
|
||||
GIFEncode(
|
||||
out, width, height, interlace, (byte) 0, transparentIndex,
|
||||
logColors, reds, grns, blus );
|
||||
}
|
||||
|
||||
byte GetPixel( int x, int y ) throws IOException
|
||||
{
|
||||
GifEncoderHashitem item =
|
||||
(GifEncoderHashitem) colorHash.get( rgbPixels[y][x] );
|
||||
if ( item == null )
|
||||
throw new IOException( "color not found" );
|
||||
return (byte) item.index;
|
||||
}
|
||||
|
||||
static void writeString( OutputStream out, String str ) throws IOException
|
||||
{
|
||||
byte[] buf = str.getBytes();
|
||||
out.write( buf );
|
||||
}
|
||||
|
||||
// Adapted from ppmtogif, which is based on GIFENCOD by David
|
||||
// Rowley <mgardi@watdscu.waterloo.edu>. Lempel-Zim compression
|
||||
// based on "compress".
|
||||
|
||||
int Width, Height;
|
||||
boolean Interlace;
|
||||
int curx, cury;
|
||||
int CountDown;
|
||||
int Pass = 0;
|
||||
|
||||
void GIFEncode(
|
||||
OutputStream outs, int Width, int Height, boolean Interlace, byte Background, int Transparent, int BitsPerPixel, byte[] Red, byte[] Green, byte[] Blue )
|
||||
throws IOException
|
||||
{
|
||||
byte B;
|
||||
int LeftOfs, TopOfs;
|
||||
int ColorMapSize;
|
||||
int InitCodeSize;
|
||||
int i;
|
||||
|
||||
this.Width = Width;
|
||||
this.Height = Height;
|
||||
this.Interlace = Interlace;
|
||||
ColorMapSize = 1 << BitsPerPixel;
|
||||
LeftOfs = TopOfs = 0;
|
||||
|
||||
// Calculate number of bits we are expecting
|
||||
CountDown = Width * Height;
|
||||
|
||||
// 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;
|
||||
|
||||
// Write the Magic header
|
||||
writeString( outs, "GIF89a" );
|
||||
|
||||
// Write out the screen width and height
|
||||
Putword( Width, outs );
|
||||
Putword( Height, outs );
|
||||
|
||||
// Indicate that there is a global colour map
|
||||
B = (byte) 0x80; // Yes, there is a color map
|
||||
// OR in the resolution
|
||||
B |= (byte) ( ( 8 - 1 ) << 4 );
|
||||
// Not sorted
|
||||
// OR in the Bits per Pixel
|
||||
B |= (byte) ( ( BitsPerPixel - 1 ) );
|
||||
|
||||
// Write it out
|
||||
Putbyte( B, outs );
|
||||
|
||||
// Write out the Background colour
|
||||
Putbyte( Background, outs );
|
||||
|
||||
// Pixel aspect ratio - 1:1.
|
||||
//Putbyte( (byte) 49, outs );
|
||||
// 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.
|
||||
Putbyte( (byte) 0, outs );
|
||||
|
||||
// Write out the Global Colour Map
|
||||
for ( i = 0; i < ColorMapSize; ++i )
|
||||
{
|
||||
Putbyte( Red[i], outs );
|
||||
Putbyte( Green[i], outs );
|
||||
Putbyte( Blue[i], outs );
|
||||
}
|
||||
|
||||
// Write out extension for transparent colour index, if necessary.
|
||||
if ( Transparent != -1 )
|
||||
{
|
||||
Putbyte( (byte) '!', outs );
|
||||
Putbyte( (byte) 0xf9, outs );
|
||||
Putbyte( (byte) 4, outs );
|
||||
Putbyte( (byte) 1, outs );
|
||||
Putbyte( (byte) 0, outs );
|
||||
Putbyte( (byte) 0, outs );
|
||||
Putbyte( (byte) Transparent, outs );
|
||||
Putbyte( (byte) 0, outs );
|
||||
}
|
||||
|
||||
// Write an Image separator
|
||||
Putbyte( (byte) ',', outs );
|
||||
|
||||
// Write the Image header
|
||||
Putword( LeftOfs, outs );
|
||||
Putword( TopOfs, outs );
|
||||
Putword( Width, outs );
|
||||
Putword( Height, outs );
|
||||
|
||||
// Write out whether or not the image is interlaced
|
||||
if ( Interlace )
|
||||
Putbyte( (byte) 0x40, outs );
|
||||
else
|
||||
Putbyte( (byte) 0x00, outs );
|
||||
|
||||
// Write out the initial code size
|
||||
Putbyte( (byte) InitCodeSize, outs );
|
||||
|
||||
// Go and actually compress the data
|
||||
compress( InitCodeSize+1, outs );
|
||||
|
||||
// Write out a Zero-length packet (to end the series)
|
||||
Putbyte( (byte) 0, outs );
|
||||
|
||||
// Write the GIF file terminator
|
||||
Putbyte( (byte) ';', outs );
|
||||
}
|
||||
|
||||
// Bump the 'curx' and 'cury' to point to the next pixel
|
||||
void BumpPixel()
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static final int EOF = -1;
|
||||
|
||||
// Return the next pixel from the image
|
||||
int GIFNextPixel() throws IOException
|
||||
{
|
||||
byte r;
|
||||
|
||||
if ( CountDown == 0 )
|
||||
return EOF;
|
||||
|
||||
--CountDown;
|
||||
|
||||
r = GetPixel( curx, cury );
|
||||
|
||||
BumpPixel();
|
||||
|
||||
return r & 0xff;
|
||||
}
|
||||
|
||||
// Write out a word to the GIF file
|
||||
void Putword( int w, OutputStream outs ) throws IOException
|
||||
{
|
||||
Putbyte( (byte) ( w & 0xff ), outs );
|
||||
Putbyte( (byte) ( ( w >> 8 ) & 0xff ), outs );
|
||||
}
|
||||
|
||||
// Write out a byte to the GIF file
|
||||
void Putbyte( byte b, OutputStream outs ) throws IOException
|
||||
{
|
||||
outs.write( b );
|
||||
}
|
||||
|
||||
|
||||
// GIFCOMPR.C - GIF Image compression routines
|
||||
//
|
||||
// Lempel-Ziv compression based on 'compress'. GIF modifications by
|
||||
// David Rowley (mgardi@watdcsu.waterloo.edu)
|
||||
|
||||
// General DEFINEs
|
||||
|
||||
static final int BITS = 12;
|
||||
|
||||
static final int HSIZE = 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)
|
||||
|
||||
int n_bits; // number of bits/code
|
||||
int maxbits = BITS; // user settable max # bits/code
|
||||
int maxcode; // maximum code, given n_bits
|
||||
int maxmaxcode = 1 << BITS; // should NEVER generate this code
|
||||
|
||||
final int MAXCODE( int n_bits )
|
||||
{
|
||||
return ( 1 << n_bits ) - 1;
|
||||
}
|
||||
|
||||
int[] htab = new int[HSIZE];
|
||||
int[] codetab = new int[HSIZE];
|
||||
|
||||
int hsize = HSIZE; // for dynamic table sizing
|
||||
|
||||
int free_ent = 0; // first unused entry
|
||||
|
||||
// block compression parameters -- after all codes are used up,
|
||||
// and compression rate changes, start over.
|
||||
boolean clear_flg = 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.
|
||||
|
||||
int g_init_bits;
|
||||
|
||||
int ClearCode;
|
||||
int EOFCode;
|
||||
|
||||
void compress( int init_bits, OutputStream outs ) throws IOException
|
||||
{
|
||||
int fcode;
|
||||
int i /* = 0 */;
|
||||
int c;
|
||||
int ent;
|
||||
int disp;
|
||||
int hsize_reg;
|
||||
int hshift;
|
||||
|
||||
// Set up the globals: g_init_bits - initial number of bits
|
||||
g_init_bits = init_bits;
|
||||
|
||||
// Set up the necessary values
|
||||
clear_flg = false;
|
||||
n_bits = g_init_bits;
|
||||
maxcode = MAXCODE( n_bits );
|
||||
|
||||
ClearCode = 1 << ( init_bits - 1 );
|
||||
EOFCode = ClearCode + 1;
|
||||
free_ent = ClearCode + 2;
|
||||
|
||||
char_init();
|
||||
|
||||
ent = GIFNextPixel();
|
||||
|
||||
hshift = 0;
|
||||
for ( fcode = hsize; fcode < 65536; fcode *= 2 )
|
||||
++hshift;
|
||||
hshift = 8 - hshift; // set hash code range bound
|
||||
|
||||
hsize_reg = hsize;
|
||||
cl_hash( hsize_reg ); // clear hash table
|
||||
|
||||
output( ClearCode, outs );
|
||||
|
||||
outer_loop:
|
||||
while ( (c = GIFNextPixel()) != EOF )
|
||||
{
|
||||
fcode = ( c << maxbits ) + ent;
|
||||
i = ( c << hshift ) ^ ent; // xor hashing
|
||||
|
||||
if ( htab[i] == fcode )
|
||||
{
|
||||
ent = codetab[i];
|
||||
continue;
|
||||
}
|
||||
else if ( htab[i] >= 0 ) // non-empty slot
|
||||
{
|
||||
disp = hsize_reg - i; // secondary hash (after G. Knott)
|
||||
if ( i == 0 )
|
||||
disp = 1;
|
||||
do
|
||||
{
|
||||
if ( (i -= disp) < 0 )
|
||||
i += hsize_reg;
|
||||
|
||||
if ( htab[i] == fcode )
|
||||
{
|
||||
ent = codetab[i];
|
||||
continue outer_loop;
|
||||
}
|
||||
}
|
||||
while ( htab[i] >= 0 );
|
||||
}
|
||||
output( ent, outs );
|
||||
ent = c;
|
||||
if ( free_ent < maxmaxcode )
|
||||
{
|
||||
codetab[i] = free_ent++; // code -> hashtable
|
||||
htab[i] = fcode;
|
||||
}
|
||||
else
|
||||
cl_block( outs );
|
||||
}
|
||||
// Put out the final code.
|
||||
output( ent, outs );
|
||||
output( EOFCode, outs );
|
||||
}
|
||||
|
||||
// output
|
||||
//
|
||||
// Output the given code.
|
||||
// Inputs:
|
||||
// code: A n_bits-bit integer. If == -1, then EOF. This assumes
|
||||
// that n_bits =< 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 cur_accum = 0;
|
||||
int cur_bits = 0;
|
||||
|
||||
int masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
|
||||
0x001F, 0x003F, 0x007F, 0x00FF,
|
||||
0x01FF, 0x03FF, 0x07FF, 0x0FFF,
|
||||
0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
|
||||
|
||||
void output( int code, OutputStream outs ) throws IOException
|
||||
{
|
||||
cur_accum &= masks[cur_bits];
|
||||
|
||||
if ( cur_bits > 0 )
|
||||
cur_accum |= ( code << cur_bits );
|
||||
else
|
||||
cur_accum = code;
|
||||
|
||||
cur_bits += n_bits;
|
||||
|
||||
while ( cur_bits >= 8 )
|
||||
{
|
||||
char_out( (byte) ( cur_accum & 0xff ), outs );
|
||||
cur_accum >>= 8;
|
||||
cur_bits -= 8;
|
||||
}
|
||||
|
||||
// If the next entry is going to be too big for the code size,
|
||||
// then increase it, if possible.
|
||||
if ( free_ent > maxcode || clear_flg )
|
||||
{
|
||||
if ( clear_flg )
|
||||
{
|
||||
maxcode = MAXCODE(n_bits = g_init_bits);
|
||||
clear_flg = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
++n_bits;
|
||||
if ( n_bits == maxbits )
|
||||
maxcode = maxmaxcode;
|
||||
else
|
||||
maxcode = MAXCODE(n_bits);
|
||||
}
|
||||
}
|
||||
|
||||
if ( code == EOFCode )
|
||||
{
|
||||
// At EOF, write the rest of the buffer.
|
||||
while ( cur_bits > 0 )
|
||||
{
|
||||
char_out( (byte) ( cur_accum & 0xff ), outs );
|
||||
cur_accum >>= 8;
|
||||
cur_bits -= 8;
|
||||
}
|
||||
|
||||
flush_char( outs );
|
||||
}
|
||||
}
|
||||
|
||||
// Clear out the hash table
|
||||
|
||||
// table clear for block compress
|
||||
void cl_block( OutputStream outs ) throws IOException
|
||||
{
|
||||
cl_hash( hsize );
|
||||
free_ent = ClearCode + 2;
|
||||
clear_flg = true;
|
||||
|
||||
output( ClearCode, outs );
|
||||
}
|
||||
|
||||
// reset code table
|
||||
void cl_hash( int hsize )
|
||||
{
|
||||
for ( int i = 0; i < hsize; ++i )
|
||||
htab[i] = -1;
|
||||
}
|
||||
|
||||
// GIF Specific routines
|
||||
|
||||
// Number of characters so far in this 'packet'
|
||||
int a_count;
|
||||
|
||||
// Set up the 'byte output' routine
|
||||
void char_init()
|
||||
{
|
||||
a_count = 0;
|
||||
}
|
||||
|
||||
// Define the storage for the packet accumulator
|
||||
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 char_out( byte c, OutputStream outs ) throws IOException
|
||||
{
|
||||
accum[a_count++] = c;
|
||||
if ( a_count >= 254 )
|
||||
flush_char( outs );
|
||||
}
|
||||
|
||||
// Flush the packet to disk, and reset the accumulator
|
||||
void flush_char( OutputStream outs ) throws IOException
|
||||
{
|
||||
if ( a_count > 0 )
|
||||
{
|
||||
outs.write( a_count );
|
||||
outs.write( accum, 0, a_count );
|
||||
a_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class GifEncoderHashitem
|
||||
{
|
||||
|
||||
public int rgb;
|
||||
public int count;
|
||||
public int index;
|
||||
public boolean isTransparent;
|
||||
|
||||
public GifEncoderHashitem( int rgb, int count, int index, boolean isTransparent )
|
||||
{
|
||||
this.rgb = rgb;
|
||||
this.count = count;
|
||||
this.index = index;
|
||||
this.isTransparent = isTransparent;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,271 +0,0 @@
|
|||
// ImageEncoder - abstract class for writing out an image
|
||||
//
|
||||
// Copyright (C) 1996 by Jef Poskanzer <jef@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/
|
||||
|
||||
package Acme.JPM.Encoders;
|
||||
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
import java.awt.Image;
|
||||
import java.awt.image.*;
|
||||
|
||||
/// Abstract class for writing out an image.
|
||||
// <P>
|
||||
// A framework for classes that encode and write out an image in
|
||||
// a particular file format.
|
||||
// <P>
|
||||
// This provides a simplified rendition of the ImageConsumer interface.
|
||||
// It always delivers the pixels as ints in the RGBdefault color model.
|
||||
// It always provides them in top-down left-right order.
|
||||
// If you want more flexibility you can always implement ImageConsumer
|
||||
// directly.
|
||||
// <P>
|
||||
// <A HREF="/resources/classes/Acme/JPM/Encoders/ImageEncoder.java">Fetch the software.</A><BR>
|
||||
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
|
||||
// <P>
|
||||
// @see GifEncoder
|
||||
// @see PpmEncoder
|
||||
// @see Acme.JPM.Decoders.ImageDecoder
|
||||
|
||||
public abstract class ImageEncoder implements ImageConsumer
|
||||
{
|
||||
|
||||
protected OutputStream out;
|
||||
|
||||
private ImageProducer producer;
|
||||
private int width = -1;
|
||||
private int height = -1;
|
||||
private int hintflags = 0;
|
||||
private boolean started = false;
|
||||
private boolean encoding;
|
||||
private IOException iox;
|
||||
private static final ColorModel rgbModel = ColorModel.getRGBdefault();
|
||||
private Hashtable props = null;
|
||||
|
||||
/// Constructor.
|
||||
// @param img The image to encode.
|
||||
// @param out The stream to write the bytes to.
|
||||
public ImageEncoder( Image img, OutputStream out ) throws IOException
|
||||
{
|
||||
this( img.getSource(), out );
|
||||
}
|
||||
|
||||
/// Constructor.
|
||||
// @param producer The ImageProducer to encode.
|
||||
// @param out The stream to write the bytes to.
|
||||
public ImageEncoder( ImageProducer producer, OutputStream out ) throws IOException
|
||||
{
|
||||
this.producer = producer;
|
||||
this.out = out;
|
||||
}
|
||||
|
||||
|
||||
// Methods that subclasses implement.
|
||||
|
||||
/// Subclasses implement this to initialize an encoding.
|
||||
abstract void encodeStart( int w, int h ) throws IOException;
|
||||
|
||||
/// Subclasses implement this to actually write out some bits. They
|
||||
// are guaranteed to be delivered in top-down-left-right order.
|
||||
// One int per pixel, index is row * scansize + off + col,
|
||||
// RGBdefault (AARRGGBB) color model.
|
||||
abstract void encodePixels(
|
||||
int x, int y, int w, int h, int[] rgbPixels, int off, int scansize )
|
||||
throws IOException;
|
||||
|
||||
/// Subclasses implement this to finish an encoding.
|
||||
abstract void encodeDone() throws IOException;
|
||||
|
||||
|
||||
// Our own methods.
|
||||
|
||||
/// Call this after initialization to get things going.
|
||||
public synchronized void encode() throws IOException
|
||||
{
|
||||
encoding = true;
|
||||
iox = null;
|
||||
producer.startProduction( this );
|
||||
while ( encoding )
|
||||
try
|
||||
{
|
||||
wait();
|
||||
}
|
||||
catch ( InterruptedException e ) {}
|
||||
if ( iox != null )
|
||||
throw iox;
|
||||
}
|
||||
|
||||
private boolean accumulate = false;
|
||||
private int[] accumulator;
|
||||
|
||||
private void encodePixelsWrapper(
|
||||
int x, int y, int w, int h, int[] rgbPixels, int off, int scansize )
|
||||
throws IOException
|
||||
{
|
||||
if ( ! started )
|
||||
{
|
||||
started = true;
|
||||
encodeStart( width, height );
|
||||
if ( ( hintflags & TOPDOWNLEFTRIGHT ) == 0 )
|
||||
{
|
||||
accumulate = true;
|
||||
accumulator = new int[width * height];
|
||||
}
|
||||
}
|
||||
if ( accumulate )
|
||||
for ( int row = 0; row < h; ++row )
|
||||
System.arraycopy(
|
||||
rgbPixels, row * scansize + off,
|
||||
accumulator, ( y + row ) * width + x,
|
||||
w );
|
||||
else
|
||||
encodePixels( x, y, w, h, rgbPixels, off, scansize );
|
||||
}
|
||||
|
||||
private void encodeFinish() throws IOException
|
||||
{
|
||||
if ( accumulate )
|
||||
{
|
||||
encodePixels( 0, 0, width, height, accumulator, 0, width );
|
||||
accumulator = null;
|
||||
accumulate = false;
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void stop()
|
||||
{
|
||||
encoding = false;
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
|
||||
// Methods from ImageConsumer.
|
||||
|
||||
public void setDimensions( int width, int height )
|
||||
{
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
public void setProperties( Hashtable props )
|
||||
{
|
||||
this.props = props;
|
||||
}
|
||||
|
||||
public void setColorModel( ColorModel model )
|
||||
{
|
||||
// Ignore.
|
||||
}
|
||||
|
||||
public void setHints( int hintflags )
|
||||
{
|
||||
this.hintflags = hintflags;
|
||||
}
|
||||
|
||||
public void setPixels(
|
||||
int x, int y, int w, int h, ColorModel model, byte[] pixels,
|
||||
int off, int scansize )
|
||||
{
|
||||
int[] rgbPixels = new int[w];
|
||||
for ( int row = 0; row < h; ++row )
|
||||
{
|
||||
int rowOff = off + row * scansize;
|
||||
for ( int col = 0; col < w; ++col )
|
||||
rgbPixels[col] = model.getRGB( pixels[rowOff + col] & 0xff );
|
||||
try
|
||||
{
|
||||
encodePixelsWrapper( x, y + row, w, 1, rgbPixels, 0, w );
|
||||
}
|
||||
catch ( IOException e )
|
||||
{
|
||||
iox = e;
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setPixels(
|
||||
int x, int y, int w, int h, ColorModel model, int[] pixels,
|
||||
int off, int scansize )
|
||||
{
|
||||
if ( model == rgbModel )
|
||||
{
|
||||
try
|
||||
{
|
||||
encodePixelsWrapper( x, y, w, h, pixels, off, scansize );
|
||||
}
|
||||
catch ( IOException e )
|
||||
{
|
||||
iox = e;
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int[] rgbPixels = new int[w];
|
||||
for ( int row = 0; row < h; ++row )
|
||||
{
|
||||
int rowOff = off + row * scansize;
|
||||
for ( int col = 0; col < w; ++col )
|
||||
rgbPixels[col] = model.getRGB( pixels[rowOff + col] );
|
||||
try
|
||||
{
|
||||
encodePixelsWrapper( x, y + row, w, 1, rgbPixels, 0, w );
|
||||
}
|
||||
catch ( IOException e )
|
||||
{
|
||||
iox = e;
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void imageComplete( int status )
|
||||
{
|
||||
producer.removeConsumer( this );
|
||||
if ( status == ImageConsumer.IMAGEABORTED )
|
||||
iox = new IOException( "image aborted" );
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
encodeFinish();
|
||||
encodeDone();
|
||||
}
|
||||
catch ( IOException e )
|
||||
{
|
||||
iox = e;
|
||||
}
|
||||
}
|
||||
stop();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,448 +0,0 @@
|
|||
// JpegEncoder - write out an image as a JPEG
|
||||
//
|
||||
// Copyright (C) 1996 by Jef Poskanzer <jef@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/
|
||||
|
||||
package Acme.JPM.Encoders;
|
||||
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
import java.awt.Image;
|
||||
import java.awt.image.*;
|
||||
|
||||
/// Write out an image as a JPEG.
|
||||
// DOESN'T WORK YET.
|
||||
// <P>
|
||||
// <A HREF="/resources/classes/Acme/JPM/Encoders/JpegEncoder.java">Fetch the software.</A><BR>
|
||||
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
|
||||
// <P>
|
||||
// @see ToJpeg
|
||||
|
||||
public class JpegEncoder extends ImageEncoder
|
||||
{
|
||||
|
||||
/// Constructor.
|
||||
// @param img The image to encode.
|
||||
// @param out The stream to write the JPEG to.
|
||||
public JpegEncoder( Image img, OutputStream out ) throws IOException
|
||||
{
|
||||
super( img, out );
|
||||
}
|
||||
|
||||
/// Constructor.
|
||||
// @param prod The ImageProducer to encode.
|
||||
// @param out The stream to write the JPEG to.
|
||||
public JpegEncoder( ImageProducer prod, OutputStream out ) throws IOException
|
||||
{
|
||||
super( prod, out );
|
||||
}
|
||||
|
||||
int qfactor = 100;
|
||||
|
||||
/// Set the Q-factor.
|
||||
public void setQfactor( int qfactor )
|
||||
{
|
||||
this.qfactor = qfactor;
|
||||
}
|
||||
|
||||
int width, height;
|
||||
int[][] rgbPixels;
|
||||
|
||||
void encodeStart( int width, int height ) throws IOException
|
||||
{
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
rgbPixels = new int[height][width];
|
||||
}
|
||||
|
||||
void encodePixels(
|
||||
int x, int y, int w, int h, int[] rgbPixels, int off, int scansize )
|
||||
throws IOException
|
||||
{
|
||||
// Save the pixels.
|
||||
for ( int row = 0; row < h; ++row )
|
||||
System.arraycopy(
|
||||
rgbPixels, row * scansize + off,
|
||||
this.rgbPixels[y + row], x, w );
|
||||
|
||||
}
|
||||
|
||||
void encodeDone() throws IOException
|
||||
{
|
||||
writeJfifHuffHeader();
|
||||
// !!!
|
||||
}
|
||||
|
||||
|
||||
// Some of the following code is derived from the Berkeley Continuous
|
||||
// Media Toolkit (http://bmrc.berkeley.edu/projects/cmt/), which is
|
||||
// Copyright (c) 1996 The Regents of the University of California.
|
||||
// All rights reserved.
|
||||
//
|
||||
// IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
|
||||
// DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
|
||||
// OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE
|
||||
// UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
// DAMAGE.
|
||||
//
|
||||
// THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
// ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION
|
||||
// TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
|
||||
|
||||
// This array represents the default JFIF header for quality = 100 and
|
||||
// size = 640x480, with Huffman tables. The values are adjusted when a
|
||||
// file is generated.
|
||||
private static byte[] jfifHuff100Header = {
|
||||
// SOI
|
||||
(byte) 0xFF, (byte) 0xD8,
|
||||
|
||||
// JFIF header
|
||||
(byte) 0xFF, (byte) 0xE0, // Marker
|
||||
(byte) 0x00, (byte) 0x10, // Length = 16 bytes
|
||||
(byte) 0x4A, (byte) 0x46, (byte) 0x49, (byte) 0x46, // "JFIF"
|
||||
(byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x00,
|
||||
(byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00,
|
||||
|
||||
// Start of frame (section B.2.2)
|
||||
(byte) 0xFF, (byte) 0xC0, // Baseline DCT
|
||||
(byte) 0x00, (byte) 0x11, // Length = 17 bytes
|
||||
(byte) 0x08, // Sample precision
|
||||
(byte) 0x01, (byte) 0xE0, // Height
|
||||
(byte) 0x02, (byte) 0x80, // Width
|
||||
(byte) 0x03, // Number of components = 3
|
||||
// Scan 1: 2:1 horiz, (byte) 1:1 vertical, (byte) use QT 0
|
||||
(byte) 0x01, (byte) 0x21, (byte) 0x00,
|
||||
// Scan 2: 1:1 horiz, (byte) 1:1 vertical, (byte) use QT 1
|
||||
(byte) 0x02, (byte) 0x11, (byte) 0x01,
|
||||
// Scan 3: 1:1 horiz, (byte) 1:1 vertical, (byte) use QT 1
|
||||
(byte) 0x03, (byte) 0x11, (byte) 0x01,
|
||||
|
||||
// Define Quant table (section B.2.4.1)
|
||||
(byte) 0xFF, (byte) 0xDB, // Marker
|
||||
(byte) 0x00, (byte) 0x84, // Length (both tables)
|
||||
(byte) 0x00, // 8 bit values, (byte) table 0
|
||||
(byte) 0x10, (byte) 0x0B, (byte) 0x0C, (byte) 0x0E, (byte) 0x0C,
|
||||
(byte) 0x0A, (byte) 0x10, (byte) 0x0E, (byte) 0x0D, (byte) 0x0E,
|
||||
(byte) 0x12, (byte) 0x11, (byte) 0x10, (byte) 0x13, (byte) 0x18,
|
||||
(byte) 0x28, (byte) 0x1A, (byte) 0x18, (byte) 0x16, (byte) 0x16,
|
||||
(byte) 0x18, (byte) 0x31, (byte) 0x23, (byte) 0x25, (byte) 0x1D,
|
||||
(byte) 0x28, (byte) 0x3A, (byte) 0x33, (byte) 0x3D, (byte) 0x3C,
|
||||
(byte) 0x39, (byte) 0x33, (byte) 0x38, (byte) 0x37, (byte) 0x40,
|
||||
(byte) 0x48, (byte) 0x5C, (byte) 0x4E, (byte) 0x40, (byte) 0x44,
|
||||
(byte) 0x57, (byte) 0x45, (byte) 0x37, (byte) 0x38, (byte) 0x50,
|
||||
(byte) 0x6D, (byte) 0x51, (byte) 0x57, (byte) 0x5F, (byte) 0x62,
|
||||
(byte) 0x67, (byte) 0x68, (byte) 0x67, (byte) 0x3E, (byte) 0x4D,
|
||||
(byte) 0x71, (byte) 0x79, (byte) 0x70, (byte) 0x64, (byte) 0x78,
|
||||
(byte) 0x5C, (byte) 0x65, (byte) 0x67, (byte) 0x63,
|
||||
|
||||
(byte) 0x01, // 8 bit values, (byte) table 1
|
||||
(byte) 0x11, (byte) 0x12, (byte) 0x12, (byte) 0x18, (byte) 0x15,
|
||||
(byte) 0x18, (byte) 0x2F, (byte) 0x1A, (byte) 0x1A, (byte) 0x2F,
|
||||
(byte) 0x63, (byte) 0x42, (byte) 0x38, (byte) 0x42, (byte) 0x63,
|
||||
(byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
|
||||
(byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
|
||||
(byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
|
||||
(byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
|
||||
(byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
|
||||
(byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
|
||||
(byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
|
||||
(byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
|
||||
(byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
|
||||
(byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
|
||||
|
||||
// Define huffman table (section B.2.4.1)
|
||||
(byte) 0xFF, (byte) 0xC4, // Marker
|
||||
(byte) 0x00, (byte) 0x1F, // Length (31 bytes)
|
||||
(byte) 0x00, // DC, (byte) table 0
|
||||
(byte) 0x00, (byte) 0x01, (byte) 0x05, (byte) 0x01, (byte) 0x01,
|
||||
(byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x00,
|
||||
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||
(byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x03,
|
||||
(byte) 0x04, (byte) 0x05, (byte) 0x06, (byte) 0x07, (byte) 0x08,
|
||||
(byte) 0x09, (byte) 0x0A, (byte) 0x0B,
|
||||
|
||||
// Define huffman table (section B.2.4.1)
|
||||
(byte) 0xFF, (byte) 0xC4, // Marker
|
||||
(byte) 0x00, (byte) 0xB5, // Length (181 bytes)
|
||||
(byte) 0x10, // AC, (byte) table 0
|
||||
(byte) 0x00, (byte) 0x02, (byte) 0x01, (byte) 0x03, (byte) 0x03,
|
||||
(byte) 0x02, (byte) 0x04, (byte) 0x03, (byte) 0x05, (byte) 0x05,
|
||||
(byte) 0x04, (byte) 0x04, (byte) 0x00, (byte) 0x00, (byte) 0x01,
|
||||
(byte) 0x7D, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x00,
|
||||
(byte) 0x04, (byte) 0x11, (byte) 0x05, (byte) 0x12, (byte) 0x21,
|
||||
(byte) 0x31, (byte) 0x41, (byte) 0x06, (byte) 0x13, (byte) 0x51,
|
||||
(byte) 0x61, (byte) 0x07, (byte) 0x22, (byte) 0x71, (byte) 0x14,
|
||||
(byte) 0x32, (byte) 0x81, (byte) 0x91, (byte) 0xA1, (byte) 0x08,
|
||||
(byte) 0x23, (byte) 0x42, (byte) 0xB1, (byte) 0xC1, (byte) 0x15,
|
||||
(byte) 0x52, (byte) 0xD1, (byte) 0xF0, (byte) 0x24, (byte) 0x33,
|
||||
(byte) 0x62, (byte) 0x72, (byte) 0x82, (byte) 0x09, (byte) 0x0A,
|
||||
(byte) 0x16, (byte) 0x17, (byte) 0x18, (byte) 0x19, (byte) 0x1A,
|
||||
(byte) 0x25, (byte) 0x26, (byte) 0x27, (byte) 0x28, (byte) 0x29,
|
||||
(byte) 0x2A, (byte) 0x34, (byte) 0x35, (byte) 0x36, (byte) 0x37,
|
||||
(byte) 0x38, (byte) 0x39, (byte) 0x3A, (byte) 0x43, (byte) 0x44,
|
||||
(byte) 0x45, (byte) 0x46, (byte) 0x47, (byte) 0x48, (byte) 0x49,
|
||||
(byte) 0x4A, (byte) 0x53, (byte) 0x54, (byte) 0x55, (byte) 0x56,
|
||||
(byte) 0x57, (byte) 0x58, (byte) 0x59, (byte) 0x5A, (byte) 0x63,
|
||||
(byte) 0x64, (byte) 0x65, (byte) 0x66, (byte) 0x67, (byte) 0x68,
|
||||
(byte) 0x69, (byte) 0x6A, (byte) 0x73, (byte) 0x74, (byte) 0x75,
|
||||
(byte) 0x76, (byte) 0x77, (byte) 0x78, (byte) 0x79, (byte) 0x7A,
|
||||
(byte) 0x83, (byte) 0x84, (byte) 0x85, (byte) 0x86, (byte) 0x87,
|
||||
(byte) 0x88, (byte) 0x89, (byte) 0x8A, (byte) 0x92, (byte) 0x93,
|
||||
(byte) 0x94, (byte) 0x95, (byte) 0x96, (byte) 0x97, (byte) 0x98,
|
||||
(byte) 0x99, (byte) 0x9A, (byte) 0xA2, (byte) 0xA3, (byte) 0xA4,
|
||||
(byte) 0xA5, (byte) 0xA6, (byte) 0xA7, (byte) 0xA8, (byte) 0xA9,
|
||||
(byte) 0xAA, (byte) 0xB2, (byte) 0xB3, (byte) 0xB4, (byte) 0xB5,
|
||||
(byte) 0xB6, (byte) 0xB7, (byte) 0xB8, (byte) 0xB9, (byte) 0xBA,
|
||||
(byte) 0xC2, (byte) 0xC3, (byte) 0xC4, (byte) 0xC5, (byte) 0xC6,
|
||||
(byte) 0xC7, (byte) 0xC8, (byte) 0xC9, (byte) 0xCA, (byte) 0xD2,
|
||||
(byte) 0xD3, (byte) 0xD4, (byte) 0xD5, (byte) 0xD6, (byte) 0xD7,
|
||||
(byte) 0xD8, (byte) 0xD9, (byte) 0xDA, (byte) 0xE1, (byte) 0xE2,
|
||||
(byte) 0xE3, (byte) 0xE4, (byte) 0xE5, (byte) 0xE6, (byte) 0xE7,
|
||||
(byte) 0xE8, (byte) 0xE9, (byte) 0xEA, (byte) 0xF1, (byte) 0xF2,
|
||||
(byte) 0xF3, (byte) 0xF4, (byte) 0xF5, (byte) 0xF6, (byte) 0xF7,
|
||||
(byte) 0xF8, (byte) 0xF9, (byte) 0xFA,
|
||||
|
||||
// Define huffman table (section B.2.4.1)
|
||||
(byte) 0xFF, (byte) 0xC4, // Marker
|
||||
(byte) 0x00, (byte) 0x1F, // Length (31 bytes)
|
||||
(byte) 0x01, // DC, (byte) table 1
|
||||
(byte) 0x00, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x01,
|
||||
(byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x01,
|
||||
(byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||
(byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x03,
|
||||
(byte) 0x04, (byte) 0x05, (byte) 0x06, (byte) 0x07, (byte) 0x08,
|
||||
(byte) 0x09, (byte) 0x0A, (byte) 0x0B,
|
||||
|
||||
// Define huffman table (section B.2.4.1)
|
||||
(byte) 0xFF, (byte) 0xC4, // Marker
|
||||
(byte) 0x00, (byte) 0xB5, // Length (181 bytes)
|
||||
(byte) 0x11, // AC, (byte) table 1
|
||||
(byte) 0x00, (byte) 0x02, (byte) 0x01, (byte) 0x02, (byte) 0x04,
|
||||
(byte) 0x04, (byte) 0x03, (byte) 0x04, (byte) 0x07, (byte) 0x05,
|
||||
(byte) 0x04, (byte) 0x04, (byte) 0x00, (byte) 0x01, (byte) 0x02,
|
||||
(byte) 0x77, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x03,
|
||||
(byte) 0x11, (byte) 0x04, (byte) 0x05, (byte) 0x21, (byte) 0x31,
|
||||
(byte) 0x06, (byte) 0x12, (byte) 0x41, (byte) 0x51, (byte) 0x07,
|
||||
(byte) 0x61, (byte) 0x71, (byte) 0x13, (byte) 0x22, (byte) 0x32,
|
||||
(byte) 0x81, (byte) 0x08, (byte) 0x14, (byte) 0x42, (byte) 0x91,
|
||||
(byte) 0xA1, (byte) 0xB1, (byte) 0xC1, (byte) 0x09, (byte) 0x23,
|
||||
(byte) 0x33, (byte) 0x52, (byte) 0xF0, (byte) 0x15, (byte) 0x62,
|
||||
(byte) 0x72, (byte) 0xD1, (byte) 0x0A, (byte) 0x16, (byte) 0x24,
|
||||
(byte) 0x34, (byte) 0xE1, (byte) 0x25, (byte) 0xF1, (byte) 0x17,
|
||||
(byte) 0x18, (byte) 0x19, (byte) 0x1A, (byte) 0x26, (byte) 0x27,
|
||||
(byte) 0x28, (byte) 0x29, (byte) 0x2A, (byte) 0x35, (byte) 0x36,
|
||||
(byte) 0x37, (byte) 0x38, (byte) 0x39, (byte) 0x3A, (byte) 0x43,
|
||||
(byte) 0x44, (byte) 0x45, (byte) 0x46, (byte) 0x47, (byte) 0x48,
|
||||
(byte) 0x49, (byte) 0x4A, (byte) 0x53, (byte) 0x54, (byte) 0x55,
|
||||
(byte) 0x56, (byte) 0x57, (byte) 0x58, (byte) 0x59, (byte) 0x5A,
|
||||
(byte) 0x63, (byte) 0x64, (byte) 0x65, (byte) 0x66, (byte) 0x67,
|
||||
(byte) 0x68, (byte) 0x69, (byte) 0x6A, (byte) 0x73, (byte) 0x74,
|
||||
(byte) 0x75, (byte) 0x76, (byte) 0x77, (byte) 0x78, (byte) 0x79,
|
||||
(byte) 0x7A, (byte) 0x82, (byte) 0x83, (byte) 0x84, (byte) 0x85,
|
||||
(byte) 0x86, (byte) 0x87, (byte) 0x88, (byte) 0x89, (byte) 0x8A,
|
||||
(byte) 0x92, (byte) 0x93, (byte) 0x94, (byte) 0x95, (byte) 0x96,
|
||||
(byte) 0x97, (byte) 0x98, (byte) 0x99, (byte) 0x9A, (byte) 0xA2,
|
||||
(byte) 0xA3, (byte) 0xA4, (byte) 0xA5, (byte) 0xA6, (byte) 0xA7,
|
||||
(byte) 0xA8, (byte) 0xA9, (byte) 0xAA, (byte) 0xB2, (byte) 0xB3,
|
||||
(byte) 0xB4, (byte) 0xB5, (byte) 0xB6, (byte) 0xB7, (byte) 0xB8,
|
||||
(byte) 0xB9, (byte) 0xBA, (byte) 0xC2, (byte) 0xC3, (byte) 0xC4,
|
||||
(byte) 0xC5, (byte) 0xC6, (byte) 0xC7, (byte) 0xC8, (byte) 0xC9,
|
||||
(byte) 0xCA, (byte) 0xD2, (byte) 0xD3, (byte) 0xD4, (byte) 0xD5,
|
||||
(byte) 0xD6, (byte) 0xD7, (byte) 0xD8, (byte) 0xD9, (byte) 0xDA,
|
||||
(byte) 0xE2, (byte) 0xE3, (byte) 0xE4, (byte) 0xE5, (byte) 0xE6,
|
||||
(byte) 0xE7, (byte) 0xE8, (byte) 0xE9, (byte) 0xEA, (byte) 0xF2,
|
||||
(byte) 0xF3, (byte) 0xF4, (byte) 0xF5, (byte) 0xF6, (byte) 0xF7,
|
||||
(byte) 0xF8, (byte) 0xF9, (byte) 0xFA,
|
||||
|
||||
// Start of Scan (section B.2.3)
|
||||
(byte) 0xFF, (byte) 0xDA, // Marker
|
||||
(byte) 0x00, (byte) 0x0C, // Length of header
|
||||
(byte) 0x03, // Number of image components
|
||||
// Scan 1: use DC/AC huff tables 0/0
|
||||
(byte) 0x01, (byte) 0x00,
|
||||
// Scan 2: use DC/AC huff tables 1/1
|
||||
(byte) 0x02, (byte) 0x11,
|
||||
// Scan 3: use DC/AC huff tables 1/1
|
||||
(byte) 0x03, (byte) 0x11,
|
||||
(byte) 0x00, (byte) 0x3F, (byte) 0x00 // Not used
|
||||
};
|
||||
|
||||
// This array represents the default JFIF header for quality = 100 and
|
||||
// size = 640x480, without Huffman tables. The values are adjusted when a
|
||||
// file is generated.
|
||||
private static byte[] jfifNoHuff100Header = {
|
||||
// SOI
|
||||
(byte) 0xFF, (byte) 0xD8,
|
||||
|
||||
// JFIF header
|
||||
(byte) 0xFF, (byte) 0xE0, // Marker
|
||||
(byte) 0x00, (byte) 0x10, // Length = 16 bytes
|
||||
(byte) 0x4A, (byte) 0x46, (byte) 0x49, (byte) 0x46, // "JFIF"
|
||||
(byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x00,
|
||||
(byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00,
|
||||
|
||||
// Start of frame (section B.2.2)
|
||||
(byte) 0xFF, (byte) 0xC0, // Baseline DCT
|
||||
(byte) 0x00, (byte) 0x11, // Length = 17 bytes
|
||||
(byte) 0x08, // Sample precision
|
||||
(byte) 0x01, (byte) 0xE0, // Height
|
||||
(byte) 0x02, (byte) 0x80, // Width
|
||||
(byte) 0x03, // Number of components = 3
|
||||
// Scan 1: 2:1 horiz, (byte) 1:1 vertical, (byte) use QT 0
|
||||
(byte) 0x01, (byte) 0x21, (byte) 0x00,
|
||||
// Scan 2: 1:1 horiz, (byte) 1:1 vertical, (byte) use QT 1
|
||||
(byte) 0x02, (byte) 0x11, (byte) 0x01,
|
||||
// Scan 3: 1:1 horiz, (byte) 1:1 vertical, (byte) use QT 1
|
||||
(byte) 0x03, (byte) 0x11, (byte) 0x01,
|
||||
|
||||
// Define Quant table (section B.2.4.1)
|
||||
(byte) 0xFF, (byte) 0xDB, // Marker
|
||||
(byte) 0x00, (byte) 0x84, // Length (both tables)
|
||||
(byte) 0x00, // 8 bit values, (byte) table 0
|
||||
(byte) 0x10, (byte) 0x0B, (byte) 0x0C, (byte) 0x0E, (byte) 0x0C,
|
||||
(byte) 0x0A, (byte) 0x10, (byte) 0x0E, (byte) 0x0D, (byte) 0x0E,
|
||||
(byte) 0x12, (byte) 0x11, (byte) 0x10, (byte) 0x13, (byte) 0x18,
|
||||
(byte) 0x28, (byte) 0x1A, (byte) 0x18, (byte) 0x16, (byte) 0x16,
|
||||
(byte) 0x18, (byte) 0x31, (byte) 0x23, (byte) 0x25, (byte) 0x1D,
|
||||
(byte) 0x28, (byte) 0x3A, (byte) 0x33, (byte) 0x3D, (byte) 0x3C,
|
||||
(byte) 0x39, (byte) 0x33, (byte) 0x38, (byte) 0x37, (byte) 0x40,
|
||||
(byte) 0x48, (byte) 0x5C, (byte) 0x4E, (byte) 0x40, (byte) 0x44,
|
||||
(byte) 0x57, (byte) 0x45, (byte) 0x37, (byte) 0x38, (byte) 0x50,
|
||||
(byte) 0x6D, (byte) 0x51, (byte) 0x57, (byte) 0x5F, (byte) 0x62,
|
||||
(byte) 0x67, (byte) 0x68, (byte) 0x67, (byte) 0x3E, (byte) 0x4D,
|
||||
(byte) 0x71, (byte) 0x79, (byte) 0x70, (byte) 0x64, (byte) 0x78,
|
||||
(byte) 0x5C, (byte) 0x65, (byte) 0x67, (byte) 0x63,
|
||||
|
||||
(byte) 0x01, // 8 bit values, (byte) table 1
|
||||
(byte) 0x11, (byte) 0x12, (byte) 0x12, (byte) 0x18, (byte) 0x15,
|
||||
(byte) 0x18, (byte) 0x2F, (byte) 0x1A, (byte) 0x1A, (byte) 0x2F,
|
||||
(byte) 0x63, (byte) 0x42, (byte) 0x38, (byte) 0x42, (byte) 0x63,
|
||||
(byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
|
||||
(byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
|
||||
(byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
|
||||
(byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
|
||||
(byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
|
||||
(byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
|
||||
(byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
|
||||
(byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
|
||||
(byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
|
||||
(byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63,
|
||||
|
||||
// Start of Scan (section B.2.3)
|
||||
(byte) 0xFF, (byte) 0xDA, // Marker
|
||||
(byte) 0x00, (byte) 0x0C, // Length of header
|
||||
(byte) 0x03, // Number of image components
|
||||
// Scan 1: use DC/AC huff tables 0/0
|
||||
(byte) 0x01, (byte) 0x00,
|
||||
// Scan 2: use DC/AC huff tables 1/1
|
||||
(byte) 0x02, (byte) 0x11,
|
||||
// Scan 3: use DC/AC huff tables 1/1
|
||||
(byte) 0x03, (byte) 0x11,
|
||||
(byte) 0x00, (byte) 0x3F, (byte) 0x00 // Not used
|
||||
};
|
||||
|
||||
private void writeJfifHuffHeader() throws IOException
|
||||
{
|
||||
byte[] newHeader = new byte[jfifHuff100Header.length];
|
||||
|
||||
System.arraycopy(
|
||||
jfifHuff100Header, 0, newHeader, 0, jfifHuff100Header.length );
|
||||
|
||||
// Set image width in JFIF header.
|
||||
newHeader[27] = (byte) ( ( width >>> 8 ) & 0xff );
|
||||
newHeader[28] = (byte) ( width & 0xff );
|
||||
|
||||
// Set image height in JFIF header.
|
||||
newHeader[25] = (byte) ( ( height >>> 8 ) & 0xff );
|
||||
newHeader[26] = (byte) ( height & 0xff );
|
||||
|
||||
// Adjust the quality factor.
|
||||
//
|
||||
// The default quality factor is 100, therefore if
|
||||
// our quality factor does not equal 100 we must
|
||||
// scale the quantization matrices in the JFIF header.
|
||||
// Note that values are clipped to a max of 255.
|
||||
if ( qfactor != 100 )
|
||||
{
|
||||
for ( int i = 44; i < 108; ++i )
|
||||
{
|
||||
int t = ( newHeader[i] * qfactor ) / 100;
|
||||
newHeader[i] = (byte) Math.max( t, 0xff );
|
||||
}
|
||||
for ( int i = 109; i < 173; ++i )
|
||||
{
|
||||
int t = ( newHeader[i] * qfactor ) / 100;
|
||||
newHeader[i] = (byte) Math.max( t, 0xff );
|
||||
}
|
||||
}
|
||||
|
||||
// Write out buffer.
|
||||
out.write( newHeader );
|
||||
}
|
||||
|
||||
private void writeJfifNoHuffHeader() throws IOException
|
||||
{
|
||||
byte[] newHeader = new byte[jfifNoHuff100Header.length];
|
||||
|
||||
System.arraycopy(
|
||||
jfifNoHuff100Header, 0, newHeader, 0, jfifNoHuff100Header.length );
|
||||
|
||||
// Set image width in JFIF header.
|
||||
newHeader[27] = (byte) ( ( width >>> 8 ) & 0xff );
|
||||
newHeader[28] = (byte) ( width & 0xff );
|
||||
|
||||
// Set image height in JFIF header.
|
||||
newHeader[25] = (byte) ( ( height >>> 8 ) & 0xff );
|
||||
newHeader[26] = (byte) ( height & 0xff );
|
||||
|
||||
// Adjust the quality factor.
|
||||
//
|
||||
// The default quality factor is 100, therefore if
|
||||
// our quality factor does not equal 100 we must
|
||||
// scale the quantization matrices in the JFIF header.
|
||||
// Note that values are clipped to a max of 255.
|
||||
if ( qfactor != 100 )
|
||||
{
|
||||
for ( int i = 44; i < 108; ++i )
|
||||
{
|
||||
int t = ( newHeader[i] * qfactor ) / 100;
|
||||
newHeader[i] = (byte) Math.max( t, 0xff );
|
||||
}
|
||||
for ( int i = 109; i < 173; ++i )
|
||||
{
|
||||
int t = ( newHeader[i] * qfactor ) / 100;
|
||||
newHeader[i] = (byte) Math.max( t, 0xff );
|
||||
}
|
||||
}
|
||||
|
||||
// Write out buffer.
|
||||
out.write( newHeader );
|
||||
}
|
||||
|
||||
}
|
|
@ -1,103 +0,0 @@
|
|||
// PpmEncoder - write out an image as a PPM
|
||||
//
|
||||
// Copyright (C)1996,1998 by Jef Poskanzer <jef@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/
|
||||
|
||||
package Acme.JPM.Encoders;
|
||||
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
import java.awt.Image;
|
||||
import java.awt.image.*;
|
||||
|
||||
/// Write out an image as a PPM.
|
||||
// <P>
|
||||
// Writes an image onto a specified OutputStream in the PPM file format.
|
||||
// <P>
|
||||
// <A HREF="/resources/classes/Acme/JPM/Encoders/PpmEncoder.java">Fetch the software.</A><BR>
|
||||
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
|
||||
// <P>
|
||||
// @see ToPpm
|
||||
|
||||
public class PpmEncoder extends ImageEncoder
|
||||
{
|
||||
|
||||
/// Constructor.
|
||||
// @param img The image to encode.
|
||||
// @param out The stream to write the PPM to.
|
||||
public PpmEncoder( Image img, OutputStream out ) throws IOException
|
||||
{
|
||||
super( img, out );
|
||||
}
|
||||
|
||||
/// Constructor.
|
||||
// @param prod The ImageProducer to encode.
|
||||
// @param out The stream to write the PPM to.
|
||||
public PpmEncoder( ImageProducer prod, OutputStream out ) throws IOException
|
||||
{
|
||||
super( prod, out );
|
||||
}
|
||||
|
||||
|
||||
void encodeStart( int width, int height ) throws IOException
|
||||
{
|
||||
writeString( out, "P6\n" );
|
||||
writeString( out, width + " " + height + "\n" );
|
||||
writeString( out, "255\n" );
|
||||
}
|
||||
|
||||
static void writeString( OutputStream out, String str ) throws IOException
|
||||
{
|
||||
byte[] buf = str.getBytes();
|
||||
out.write( buf );
|
||||
}
|
||||
|
||||
void encodePixels(
|
||||
int x, int y, int w, int h, int[] rgbPixels, int off, int scansize )
|
||||
throws IOException
|
||||
{
|
||||
byte[] ppmPixels = new byte[w * 3];
|
||||
for ( int row = 0; row < h; ++row )
|
||||
{
|
||||
int rowOff = off + row * scansize;
|
||||
for ( int col = 0; col < w; ++col )
|
||||
{
|
||||
int i = rowOff + col;
|
||||
int j = col * 3;
|
||||
ppmPixels[j ] = (byte) ( ( rgbPixels[i] & 0xff0000 ) >> 16 );
|
||||
ppmPixels[j + 1] = (byte) ( ( rgbPixels[i] & 0x00ff00 ) >> 8 );
|
||||
ppmPixels[j + 2] = (byte) ( rgbPixels[i] & 0x0000ff );
|
||||
}
|
||||
out.write( ppmPixels );
|
||||
}
|
||||
}
|
||||
|
||||
void encodeDone() throws IOException
|
||||
{
|
||||
// Nothing.
|
||||
}
|
||||
|
||||
}
|
|
@ -1,106 +0,0 @@
|
|||
// CompositeFilter - compose two filters into one
|
||||
//
|
||||
// Copyright (C) 1997 by Jef Poskanzer <jef@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/
|
||||
|
||||
package Acme.JPM.Filters;
|
||||
|
||||
import java.awt.image.*;
|
||||
import java.util.*;
|
||||
|
||||
/// Compose two filters into one.
|
||||
// <P>
|
||||
// <A HREF="/resources/classes/Acme/JPM/Filters/CompositeFilter.java">Fetch the software.</A><BR>
|
||||
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
|
||||
|
||||
public class CompositeFilter extends ImageFilterPlus
|
||||
{
|
||||
|
||||
private ImageFilterPlus filterOne, filterTwo;
|
||||
private ImageFilter instanceOne, instanceTwo;
|
||||
|
||||
/// Constructor. Builds a filter chain with a FilteredImageSource as
|
||||
// the glue.
|
||||
public CompositeFilter( ImageProducer producer, ImageFilterPlus filterOne, ImageFilterPlus filterTwo )
|
||||
{
|
||||
super( producer );
|
||||
this.filterOne = filterOne;
|
||||
this.filterTwo = filterTwo;
|
||||
|
||||
filterOne.setSource( producer );
|
||||
ImageProducer producerOne =
|
||||
new FilteredImageSource( producer, filterOne );
|
||||
filterTwo.setSource( producerOne );
|
||||
}
|
||||
|
||||
public ImageFilter getFilterInstance( ImageConsumer consumer )
|
||||
{
|
||||
CompositeFilter instance = (CompositeFilter) clone();
|
||||
instance.instanceTwo = filterTwo.getFilterInstance( consumer );
|
||||
instance.instanceOne = filterOne.getFilterInstance( instanceTwo );
|
||||
return (ImageFilter) instance;
|
||||
}
|
||||
|
||||
|
||||
// The rest of the methods just delegate to instanceOne.
|
||||
|
||||
public void setColorModel( ColorModel model )
|
||||
{
|
||||
instanceOne.setColorModel( model );
|
||||
}
|
||||
|
||||
public void setDimensions( int width, int height )
|
||||
{
|
||||
instanceOne.setDimensions( width, height );
|
||||
}
|
||||
|
||||
public void setHints( int hintflags )
|
||||
{
|
||||
instanceOne.setHints( hintflags );
|
||||
}
|
||||
|
||||
public void setProperties( Hashtable props )
|
||||
{
|
||||
instanceOne.setProperties( props );
|
||||
}
|
||||
|
||||
public void setPixels( int x, int y, int w, int h, ColorModel model, byte[] pixels, int off, int scansize )
|
||||
{
|
||||
instanceOne.setPixels( x, y, w, h, model, pixels, off, scansize );
|
||||
}
|
||||
|
||||
public void setPixels( int x, int y, int w, int h, ColorModel model, int[] pixels, int off, int scansize )
|
||||
{
|
||||
instanceOne.setPixels( x, y, w, h, model, pixels, off, scansize );
|
||||
}
|
||||
|
||||
public void imageComplete( int status )
|
||||
{
|
||||
//super.imageComplete( status );
|
||||
instanceOne.imageComplete( status );
|
||||
}
|
||||
|
||||
}
|
|
@ -1,169 +0,0 @@
|
|||
// EdgeDetect - edge-detection filter
|
||||
//
|
||||
// Copyright (C) 1996 by Jef Poskanzer <jef@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/
|
||||
|
||||
package Acme.JPM.Filters;
|
||||
|
||||
import java.io.*;
|
||||
import java.awt.image.*;
|
||||
import Acme.JPM.Decoders.*;
|
||||
import Acme.JPM.Encoders.*;
|
||||
|
||||
/// Edge-detection filter.
|
||||
// <IMG ALIGN=RIGHT WIDTH=202 HEIGHT=200 SRC="Earth-EdgeDetect.jpg">
|
||||
// <IMG ALIGN=RIGHT WIDTH=202 HEIGHT=200 SRC="Earth.jpg">
|
||||
// <P>
|
||||
// Outlines the edges of an image.
|
||||
// The edge detection technique used is to take the Pythagorean sum of
|
||||
// two Sobel gradient operators at 90 degrees to each other, separately
|
||||
// for each color component.
|
||||
// For more details see "Digital Image Processing" by Gonzalez and Wintz,
|
||||
// chapter 7.
|
||||
// <P>
|
||||
// This filter is slow.
|
||||
// <P>
|
||||
// <A HREF="/resources/classes/Acme/JPM/Filters/EdgeDetect.java">Fetch the software.</A><BR>
|
||||
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
|
||||
|
||||
public class EdgeDetect extends RGBAllFilter
|
||||
{
|
||||
|
||||
// Constructor.
|
||||
public EdgeDetect( ImageProducer producer )
|
||||
{
|
||||
super( producer );
|
||||
}
|
||||
|
||||
|
||||
private static final double SCALE = 1.8D;
|
||||
|
||||
public void filterRGBAll( int width, int height, int[][] rgbPixels )
|
||||
{
|
||||
int[][] newPixels = new int[height][width];
|
||||
long sum1, sum2;
|
||||
double sum;
|
||||
int r, g, b;
|
||||
|
||||
// First and last rows are black.
|
||||
for ( int col = 0; col < width; ++col )
|
||||
{
|
||||
newPixels[0][col] = 0xff000000;
|
||||
newPixels[height - 1][col] = 0xff000000;
|
||||
}
|
||||
for ( int row = 1; row < height - 1; ++row )
|
||||
{
|
||||
// First and last columns are black too.
|
||||
newPixels[row][0] = 0xff000000;
|
||||
newPixels[row][width - 1] = 0xff000000;
|
||||
// The real pixels.
|
||||
for ( int col = 1; col < width - 1; ++col )
|
||||
{
|
||||
sum1 =
|
||||
rgbModel.getRed( rgbPixels[row - 1][col + 1] ) -
|
||||
rgbModel.getRed( rgbPixels[row - 1][col - 1] ) +
|
||||
2 * (
|
||||
rgbModel.getRed( rgbPixels[row][col + 1] ) -
|
||||
rgbModel.getRed( rgbPixels[row][col - 1] ) ) +
|
||||
rgbModel.getRed( rgbPixels[row + 1][col + 1] ) -
|
||||
rgbModel.getRed( rgbPixels[row + 1][col - 1] );
|
||||
sum2 = (
|
||||
rgbModel.getRed( rgbPixels[row + 1][col - 1] ) +
|
||||
2 * rgbModel.getRed( rgbPixels[row + 1][col] ) +
|
||||
rgbModel.getRed( rgbPixels[row + 1][col + 1] )
|
||||
) - (
|
||||
rgbModel.getRed( rgbPixels[row - 1][col - 1] ) +
|
||||
2 * rgbModel.getRed( rgbPixels[row - 1][col] ) +
|
||||
rgbModel.getRed( rgbPixels[row - 1][col + 1] )
|
||||
);
|
||||
sum = Math.sqrt( (double) ( sum1*sum1 + sum2*sum2 ) ) / SCALE;
|
||||
r = Math.min( (int) sum, 255 );
|
||||
|
||||
sum1 =
|
||||
rgbModel.getGreen( rgbPixels[row - 1][col + 1] ) -
|
||||
rgbModel.getGreen( rgbPixels[row - 1][col - 1] ) +
|
||||
2 * (
|
||||
rgbModel.getGreen( rgbPixels[row][col + 1] ) -
|
||||
rgbModel.getGreen( rgbPixels[row][col - 1] ) ) +
|
||||
rgbModel.getGreen( rgbPixels[row + 1][col + 1] ) -
|
||||
rgbModel.getGreen( rgbPixels[row + 1][col - 1] );
|
||||
sum2 = (
|
||||
rgbModel.getGreen( rgbPixels[row + 1][col - 1] ) +
|
||||
2 * rgbModel.getGreen( rgbPixels[row + 1][col] ) +
|
||||
rgbModel.getGreen( rgbPixels[row + 1][col + 1] )
|
||||
) - (
|
||||
rgbModel.getGreen( rgbPixels[row - 1][col - 1] ) +
|
||||
2 * rgbModel.getGreen( rgbPixels[row - 1][col] ) +
|
||||
rgbModel.getGreen( rgbPixels[row - 1][col + 1] )
|
||||
);
|
||||
sum = Math.sqrt( (double) ( sum1*sum1 + sum2*sum2 ) ) / SCALE;
|
||||
g = Math.min( (int) sum, 255 );
|
||||
|
||||
sum1 =
|
||||
rgbModel.getBlue( rgbPixels[row - 1][col + 1] ) -
|
||||
rgbModel.getBlue( rgbPixels[row - 1][col - 1] ) +
|
||||
2 * (
|
||||
rgbModel.getBlue( rgbPixels[row][col + 1] ) -
|
||||
rgbModel.getBlue( rgbPixels[row][col - 1] ) ) +
|
||||
rgbModel.getBlue( rgbPixels[row + 1][col + 1] ) -
|
||||
rgbModel.getBlue( rgbPixels[row + 1][col - 1] );
|
||||
sum2 = (
|
||||
rgbModel.getBlue( rgbPixels[row + 1][col - 1] ) +
|
||||
2 * rgbModel.getBlue( rgbPixels[row + 1][col] ) +
|
||||
rgbModel.getBlue( rgbPixels[row + 1][col + 1] )
|
||||
) - (
|
||||
rgbModel.getBlue( rgbPixels[row - 1][col - 1] ) +
|
||||
2 * rgbModel.getBlue( rgbPixels[row - 1][col] ) +
|
||||
rgbModel.getBlue( rgbPixels[row - 1][col + 1] )
|
||||
);
|
||||
sum = Math.sqrt( (double) ( sum1*sum1 + sum2*sum2 ) ) / SCALE;
|
||||
b = Math.min( (int) sum, 255 );
|
||||
|
||||
newPixels[row][col] =
|
||||
0xff000000 | ( r << 16 ) | ( g << 8 ) | b;
|
||||
}
|
||||
}
|
||||
setPixels( width, height, newPixels );
|
||||
}
|
||||
|
||||
|
||||
// Main routine for command-line interface.
|
||||
public static void main( String[] args )
|
||||
{
|
||||
if ( args.length != 0 )
|
||||
usage();
|
||||
ImageFilterPlus filter = new EdgeDetect( null );
|
||||
System.exit(
|
||||
ImageFilterPlus.filterStream( System.in, System.out, filter ) );
|
||||
}
|
||||
|
||||
private static void usage()
|
||||
{
|
||||
System.err.println( "usage: EdgeDetect" );
|
||||
System.exit( 1 );
|
||||
}
|
||||
|
||||
}
|
|
@ -1,140 +0,0 @@
|
|||
// Enlarge - an ImageFilter that enlarges by pixel replication
|
||||
//
|
||||
// Copyright (C) 1996 by Jef Poskanzer <jef@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/
|
||||
|
||||
package Acme.JPM.Filters;
|
||||
|
||||
import java.awt.image.*;
|
||||
|
||||
/// An ImageFilter that enlarges by pixel replication.
|
||||
// <P>
|
||||
// Enlarges an image an integral factor by replicating pixels.
|
||||
// The output uses the same color model as the input.
|
||||
// This filter is very fast.
|
||||
// <P>
|
||||
// <A HREF="/resources/classes/Acme/JPM/Filters/Enlarge.java">Fetch the software.</A><BR>
|
||||
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
|
||||
// <P>
|
||||
// @see Shrink
|
||||
// @see ScaleCopy
|
||||
|
||||
public class Enlarge extends ImageFilterPlus
|
||||
{
|
||||
|
||||
private int multiplier;
|
||||
private int newWidth, newHeight;
|
||||
|
||||
/// Constructor.
|
||||
public Enlarge( ImageProducer producer, int multiplier )
|
||||
{
|
||||
super( producer );
|
||||
this.multiplier = multiplier;
|
||||
}
|
||||
|
||||
|
||||
public void setDimensions( int width, int height )
|
||||
{
|
||||
newWidth = width * multiplier;
|
||||
newHeight = height * multiplier;
|
||||
consumer.setDimensions( newWidth, newHeight );
|
||||
}
|
||||
|
||||
public void setPixels( int x, int y, int w, int h, ColorModel model, byte[] pixels, int off, int scansize )
|
||||
{
|
||||
int newX = Math.min( x * multiplier, newWidth - 1 );
|
||||
int newY = Math.min( y * multiplier, newHeight - 1 );
|
||||
int newW = w * multiplier;
|
||||
if ( newX + newW > newWidth )
|
||||
newW = newWidth - newX;
|
||||
int newH = h * multiplier;
|
||||
if ( newY + newH > newHeight )
|
||||
newH = newHeight - newY;
|
||||
byte[] newPixels = new byte[newW * newH];
|
||||
for ( int row = 0; row < h; ++row )
|
||||
{
|
||||
for ( int col = 0; col < w; ++col )
|
||||
{
|
||||
byte pixel = pixels[row * scansize + off + col];
|
||||
for ( int i = 0; i < multiplier; ++i )
|
||||
for ( int j = 0; j < multiplier; ++j )
|
||||
{
|
||||
int newRow = row * multiplier + i;
|
||||
int newCol = col * multiplier + j;
|
||||
newPixels[newRow * newW + newCol] = pixel;
|
||||
}
|
||||
}
|
||||
}
|
||||
consumer.setPixels( newX, newY, newW, newH, model, newPixels, 0, newW );
|
||||
}
|
||||
|
||||
public void setPixels( int x, int y, int w, int h, ColorModel model, int[] pixels, int off, int scansize )
|
||||
{
|
||||
int newX = Math.min( x * multiplier, newWidth - 1 );
|
||||
int newY = Math.min( y * multiplier, newHeight - 1 );
|
||||
int newW = w * multiplier;
|
||||
if ( newX + newW > newWidth )
|
||||
newW = newWidth - newX;
|
||||
int newH = h * multiplier;
|
||||
if ( newY + newH > newHeight )
|
||||
newH = newHeight - newY;
|
||||
int[] newPixels = new int[newW * newH];
|
||||
for ( int row = 0; row < h; ++row )
|
||||
{
|
||||
for ( int col = 0; col < w; ++col )
|
||||
{
|
||||
int pixel = pixels[row * scansize + off + col];
|
||||
for ( int i = 0; i < multiplier; ++i )
|
||||
for ( int j = 0; j < multiplier; ++j )
|
||||
{
|
||||
int newRow = row * multiplier + i;
|
||||
int newCol = col * multiplier + j;
|
||||
newPixels[newRow * newW + newCol] = pixel;
|
||||
}
|
||||
}
|
||||
}
|
||||
consumer.setPixels( newX, newY, newW, newH, model, newPixels, 0, newW );
|
||||
}
|
||||
|
||||
|
||||
// Main routine for command-line interface.
|
||||
public static void main( String[] args )
|
||||
{
|
||||
if ( args.length != 1 )
|
||||
usage();
|
||||
ImageFilterPlus filter =
|
||||
new Enlarge( null, Integer.parseInt( args[0] ) );
|
||||
System.exit(
|
||||
ImageFilterPlus.filterStream( System.in, System.out, filter ) );
|
||||
}
|
||||
|
||||
private static void usage()
|
||||
{
|
||||
System.err.println( "usage: Enlarge <multiplier>" );
|
||||
System.exit( 1 );
|
||||
}
|
||||
|
||||
}
|
|
@ -1,295 +0,0 @@
|
|||
// Flip - an ImageFilter that flips or rotates the image
|
||||
//
|
||||
// Copyright (C) 1997 by Jef Poskanzer <jef@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/
|
||||
|
||||
package Acme.JPM.Filters;
|
||||
|
||||
import java.awt.image.*;
|
||||
|
||||
/// An ImageFilter that flips or rotates the image.
|
||||
// <P>
|
||||
// Flips the image left-right, top-bottom, rotates clockwise or
|
||||
// counter-clockwise, or otherwise munges the image as specified.
|
||||
// This filter is fast.
|
||||
// <P>
|
||||
// <A HREF="/resources/classes/Acme/JPM/Filters/Flip.java">Fetch the software.</A><BR>
|
||||
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
|
||||
|
||||
public class Flip extends ImageFilterPlus
|
||||
{
|
||||
|
||||
/// The null transformation.
|
||||
public static final int FLIP_NULL = 0;
|
||||
|
||||
/// Flip left to right.
|
||||
public static final int FLIP_LR = 1;
|
||||
|
||||
/// Flip top to bottom.
|
||||
public static final int FLIP_TB = 2;
|
||||
|
||||
/// Transpose X and Y - reflection along a diagonal.
|
||||
public static final int FLIP_XY = 3;
|
||||
|
||||
/// Rotate clockwise 90 degrees.
|
||||
public static final int FLIP_CW = 4;
|
||||
|
||||
/// Rotate counter-clockwise 90 degrees.
|
||||
public static final int FLIP_CCW = 5;
|
||||
|
||||
/// Rotate 180 degrees.
|
||||
public static final int FLIP_R180 = 6;
|
||||
|
||||
private int flipType;
|
||||
private int width, height;
|
||||
private int newWidth, newHeight;
|
||||
|
||||
/// Constructor.
|
||||
public Flip( ImageProducer producer, int flipType )
|
||||
{
|
||||
super( producer, true );
|
||||
this.flipType = flipType;
|
||||
}
|
||||
|
||||
|
||||
public void setDimensions( int width, int height )
|
||||
{
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
switch ( flipType )
|
||||
{
|
||||
case FLIP_NULL:
|
||||
case FLIP_LR:
|
||||
case FLIP_TB:
|
||||
case FLIP_R180:
|
||||
newWidth = width;
|
||||
newHeight = height;
|
||||
break;
|
||||
case FLIP_XY:
|
||||
case FLIP_CW:
|
||||
case FLIP_CCW:
|
||||
newWidth = height;
|
||||
newHeight = width;
|
||||
break;
|
||||
}
|
||||
consumer.setDimensions( newWidth, newHeight );
|
||||
}
|
||||
|
||||
public void setPixels( int x, int y, int w, int h, ColorModel model, byte[] pixels, int off, int scansize )
|
||||
{
|
||||
int newX = x;
|
||||
int newY = y;
|
||||
int newW = w;
|
||||
int newH = h;
|
||||
switch ( flipType )
|
||||
{
|
||||
case FLIP_NULL:
|
||||
break;
|
||||
case FLIP_LR:
|
||||
newX = width - ( x + w );
|
||||
break;
|
||||
case FLIP_TB:
|
||||
newY = height - ( y + h );
|
||||
break;
|
||||
case FLIP_XY:
|
||||
newW = h;
|
||||
newH = w;
|
||||
newX = y;
|
||||
newY = x;
|
||||
break;
|
||||
case FLIP_CW:
|
||||
newW = h;
|
||||
newH = w;
|
||||
newX = height - ( y + h );
|
||||
newY = x;
|
||||
break;
|
||||
case FLIP_CCW:
|
||||
newW = h;
|
||||
newH = w;
|
||||
newX = y;
|
||||
newY = width - ( x + w );
|
||||
break;
|
||||
case FLIP_R180:
|
||||
newX = width - ( x + w );
|
||||
newY = height - ( y + h );
|
||||
break;
|
||||
}
|
||||
byte[] newPixels = new byte[newW * newH];
|
||||
for ( int row = 0; row < h; ++row )
|
||||
{
|
||||
for ( int col = 0; col < w; ++col )
|
||||
{
|
||||
int index = row * scansize + off + col;
|
||||
int newRow = row;
|
||||
int newCol = col;
|
||||
switch ( flipType )
|
||||
{
|
||||
case FLIP_NULL:
|
||||
break;
|
||||
case FLIP_LR:
|
||||
newCol = w - col - 1;
|
||||
break;
|
||||
case FLIP_TB:
|
||||
newRow = h - row - 1;
|
||||
break;
|
||||
case FLIP_XY:
|
||||
newRow = col;
|
||||
newCol = row;
|
||||
break;
|
||||
case FLIP_CW:
|
||||
newRow = col;
|
||||
newCol = h - row - 1;;
|
||||
break;
|
||||
case FLIP_CCW:
|
||||
newRow = w - col - 1;
|
||||
newCol = row;
|
||||
break;
|
||||
case FLIP_R180:
|
||||
newRow = h - row - 1;
|
||||
newCol = w - col - 1;
|
||||
break;
|
||||
}
|
||||
int newIndex = newRow * newW + newCol;
|
||||
newPixels[newIndex] = pixels[index];
|
||||
}
|
||||
}
|
||||
consumer.setPixels( newX, newY, newW, newH, model, newPixels, 0, newW );
|
||||
}
|
||||
|
||||
public void setPixels( int x, int y, int w, int h, ColorModel model, int[] pixels, int off, int scansize )
|
||||
{
|
||||
int newX = x;
|
||||
int newY = y;
|
||||
int newW = w;
|
||||
int newH = h;
|
||||
switch ( flipType )
|
||||
{
|
||||
case FLIP_NULL:
|
||||
break;
|
||||
case FLIP_LR:
|
||||
newX = width - ( x + w );
|
||||
break;
|
||||
case FLIP_TB:
|
||||
newY = height - ( y + h );
|
||||
break;
|
||||
case FLIP_XY:
|
||||
newW = h;
|
||||
newH = w;
|
||||
newX = y;
|
||||
newY = x;
|
||||
break;
|
||||
case FLIP_CW:
|
||||
newW = h;
|
||||
newH = w;
|
||||
newX = height - ( y + h );
|
||||
newY = x;
|
||||
break;
|
||||
case FLIP_CCW:
|
||||
newW = h;
|
||||
newH = w;
|
||||
newX = y;
|
||||
newY = width - ( x + w );
|
||||
break;
|
||||
case FLIP_R180:
|
||||
newX = width - ( x + w );
|
||||
newY = height - ( y + h );
|
||||
break;
|
||||
}
|
||||
int[] newPixels = new int[newW * newH];
|
||||
for ( int row = 0; row < h; ++row )
|
||||
{
|
||||
for ( int col = 0; col < w; ++col )
|
||||
{
|
||||
int index = row * scansize + off + col;
|
||||
int newRow = row;
|
||||
int newCol = col;
|
||||
switch ( flipType )
|
||||
{
|
||||
case FLIP_NULL:
|
||||
break;
|
||||
case FLIP_LR:
|
||||
newCol = w - col - 1;
|
||||
break;
|
||||
case FLIP_TB:
|
||||
newRow = h - row - 1;
|
||||
break;
|
||||
case FLIP_XY:
|
||||
newRow = col;
|
||||
newCol = row;
|
||||
break;
|
||||
case FLIP_CW:
|
||||
newRow = col;
|
||||
newCol = h - row - 1;;
|
||||
break;
|
||||
case FLIP_CCW:
|
||||
newRow = w - col - 1;
|
||||
newCol = row;
|
||||
break;
|
||||
case FLIP_R180:
|
||||
newRow = h - row - 1;
|
||||
newCol = w - col - 1;
|
||||
break;
|
||||
}
|
||||
int newIndex = newRow * newW + newCol;
|
||||
newPixels[newIndex] = pixels[index];
|
||||
}
|
||||
}
|
||||
consumer.setPixels( newX, newY, newW, newH, model, newPixels, 0, newW );
|
||||
}
|
||||
|
||||
|
||||
// Main routine for command-line interface.
|
||||
public static void main( String[] args )
|
||||
{
|
||||
if ( args.length != 1 )
|
||||
usage();
|
||||
int flipType = FLIP_NULL;
|
||||
if ( args[0].equalsIgnoreCase( "-lr" ) )
|
||||
flipType = FLIP_LR;
|
||||
else if ( args[0].equalsIgnoreCase( "-tb" ) )
|
||||
flipType = FLIP_TB;
|
||||
else if ( args[0].equalsIgnoreCase( "-xy" ) )
|
||||
flipType = FLIP_XY;
|
||||
else if ( args[0].equalsIgnoreCase( "-cw" ) )
|
||||
flipType = FLIP_CW;
|
||||
else if ( args[0].equalsIgnoreCase( "-ccw" ) )
|
||||
flipType = FLIP_CCW;
|
||||
else if ( args[0].equalsIgnoreCase( "-r180" ) )
|
||||
flipType = FLIP_R180;
|
||||
else
|
||||
usage();
|
||||
ImageFilterPlus filter = new Flip( null, flipType );
|
||||
System.exit(
|
||||
ImageFilterPlus.filterStream( System.in, System.out, filter ) );
|
||||
}
|
||||
|
||||
private static void usage()
|
||||
{
|
||||
System.err.println( "usage: Flip -lr|-tb|-xy|-cw|-ccw|-r180" );
|
||||
System.exit( 1 );
|
||||
}
|
||||
|
||||
}
|
|
@ -1,148 +0,0 @@
|
|||
// Gamma - gamma-correction filter
|
||||
//
|
||||
// Copyright (C) 1996 by Jef Poskanzer <jef@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/
|
||||
|
||||
package Acme.JPM.Filters;
|
||||
|
||||
import java.awt.image.*;
|
||||
|
||||
/// Gamma-correction filter.
|
||||
// <P>
|
||||
// Gamma correction fixes a form of color distortion common to many monitors.
|
||||
// Values less than 1.0 darken the image, and greater than 1.0 lighten it.
|
||||
// <P>
|
||||
// <A HREF="/resources/classes/Acme/JPM/Filters/Gamma.java">Fetch the software.</A><BR>
|
||||
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
|
||||
|
||||
public class Gamma extends RGBBlockFilter
|
||||
{
|
||||
|
||||
private double rValue, gValue, bValue;
|
||||
|
||||
/// Constructor, single exponent.
|
||||
public Gamma( ImageProducer producer, double value )
|
||||
{
|
||||
this( producer, value, value, value );
|
||||
}
|
||||
|
||||
/// Constructor, different exponents for R G and B.
|
||||
public Gamma( ImageProducer producer, double rValue, double gValue, double bValue )
|
||||
{
|
||||
super( producer );
|
||||
this.rValue = rValue;
|
||||
this.gValue = gValue;
|
||||
this.bValue = bValue;
|
||||
}
|
||||
|
||||
|
||||
private int[] rTable, gTable, bTable;
|
||||
|
||||
public int[][] filterRGBBlock( int x, int y, int width, int height, int[][] rgbPixels )
|
||||
{
|
||||
initialize();
|
||||
for ( int row = 0; row < height; ++row )
|
||||
for ( int col = 0; col < width; ++col )
|
||||
{
|
||||
int rgb = rgbPixels[row][col];
|
||||
int a = ( rgb >> 24 ) & 0xff;
|
||||
int r = ( rgb >> 16 ) & 0xff;
|
||||
int g = ( rgb >> 8 ) & 0xff;
|
||||
int b = rgb & 0xff;
|
||||
r = rTable[r];
|
||||
g = gTable[g];
|
||||
b = bTable[b];
|
||||
rgbPixels[row][col] =
|
||||
( a << 24 ) | ( r << 16 ) | ( g << 8 ) | b;
|
||||
}
|
||||
return rgbPixels;
|
||||
}
|
||||
|
||||
|
||||
private boolean initialized = false;
|
||||
|
||||
private void initialize()
|
||||
{
|
||||
if ( initialized )
|
||||
return;
|
||||
initialized = true;
|
||||
|
||||
rTable = buildTable( rValue );
|
||||
|
||||
if ( gValue == rValue )
|
||||
gTable = rTable;
|
||||
else
|
||||
gTable = buildTable( gValue );
|
||||
|
||||
if ( bValue == rValue )
|
||||
bTable = rTable;
|
||||
else if ( bValue == gValue )
|
||||
bTable = gTable;
|
||||
else
|
||||
bTable = buildTable( bValue );
|
||||
}
|
||||
|
||||
private int[] buildTable( double gamma )
|
||||
{
|
||||
int[] table = new int[256];
|
||||
double oneOverGamma = 1.0D / gamma;
|
||||
for ( int i = 0; i < 256; ++i )
|
||||
{
|
||||
int v = (int) (
|
||||
( 255.0D * Math.pow( i / 255.0D, oneOverGamma ) ) + 0.5D );
|
||||
if ( v > 255 )
|
||||
v = 255;
|
||||
table[i] = v;
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
|
||||
// Main routine for command-line interface.
|
||||
public static void main( String[] args )
|
||||
{
|
||||
ImageFilterPlus filter = null;
|
||||
if ( args.length == 1 )
|
||||
filter = new Gamma( null, Double.valueOf( args[0] ).doubleValue() );
|
||||
else if ( args.length == 3 )
|
||||
filter = new Gamma( null,
|
||||
Double.valueOf( args[0] ).doubleValue(),
|
||||
Double.valueOf( args[1] ).doubleValue(),
|
||||
Double.valueOf( args[2] ).doubleValue() );
|
||||
else
|
||||
usage();
|
||||
System.exit(
|
||||
ImageFilterPlus.filterStream( System.in, System.out, filter ) );
|
||||
}
|
||||
|
||||
private static void usage()
|
||||
{
|
||||
System.err.println( "usage: Gamma <value>" );
|
||||
System.err.println( "or: Gamma <rValue> <gValue> <bValue>" );
|
||||
System.exit( 1 );
|
||||
}
|
||||
|
||||
}
|
|
@ -1,160 +0,0 @@
|
|||
// ImageFilterPlus - an ImageFilter with some extra features and bug fixes
|
||||
//
|
||||
// Copyright (C) 1996 by Jef Poskanzer <jef@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/
|
||||
|
||||
package Acme.JPM.Filters;
|
||||
|
||||
import java.awt.image.*;
|
||||
import java.io.*;
|
||||
import Acme.JPM.Decoders.*;
|
||||
import Acme.JPM.Encoders.*;
|
||||
|
||||
/// An ImageFilter with some extra features and bug fixes.
|
||||
// <P>
|
||||
// You can use an image filter to turn one Image into another via
|
||||
// a FilteredImageSource, e.g.:
|
||||
// <BLOCKQUOTE><CODE><PRE>
|
||||
// Image newImage = comp.createImage( new FilteredImageSource(
|
||||
// oldImage.getSource(), new SomeFilter( oldImage.getSource() ) ) );
|
||||
// </PRE></CODE></BLOCKQUOTE>
|
||||
// Or use the convenient utility JPMUtils.filterImage():
|
||||
// <BLOCKQUOTE><CODE><PRE>
|
||||
// Image newImage = JPMUtils.filterImage(
|
||||
// comp, SomeFilter( oldImage.getSource() ) );
|
||||
// </PRE></CODE></BLOCKQUOTE>
|
||||
// <P>
|
||||
// You can also use image filters from the command line, reading PPM
|
||||
// from stdin and writing PPM to stdout, if you add code like the following
|
||||
// to each filter:
|
||||
// <BLOCKQUOTE><CODE><PRE>
|
||||
// System.exit(
|
||||
// ImageFilterPlus.filterStream(
|
||||
// System.in, System.out,
|
||||
// new SomeFilter( null ) ) );
|
||||
// </PRE></CODE></BLOCKQUOTE>
|
||||
// <P>
|
||||
// <A HREF="/resources/classes/Acme/JPM/Filters/ImageFilterPlus.java">Fetch the software.</A><BR>
|
||||
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
|
||||
|
||||
public class ImageFilterPlus extends ImageFilter
|
||||
{
|
||||
|
||||
private ImageProducer producer;
|
||||
private boolean pixelOrderChanges;
|
||||
|
||||
/// Constructor.
|
||||
// @param producer The ImageProducer is required, so that we can
|
||||
// remove ourself from its consumers list when we're done.
|
||||
// However, if you don't have the producer available when you want
|
||||
// to create the filter, you can pass in null and set it later
|
||||
// via setSource().
|
||||
public ImageFilterPlus( ImageProducer producer )
|
||||
{
|
||||
this( producer, false );
|
||||
}
|
||||
|
||||
/// Constructor, with pixel order change.
|
||||
// @param producer The ImageProducer is required, so that we can
|
||||
// remove ourself from its consumers list when we're done.
|
||||
// However, if you don't have the producer available when you want
|
||||
// to create the filter, you can pass in null and set it later
|
||||
// via setSource().
|
||||
// @param pixelOrderChanges If the filter may output pixels in a different
|
||||
// order from the one they were delivered in, this flag must be set.
|
||||
public ImageFilterPlus( ImageProducer producer, boolean pixelOrderChanges )
|
||||
{
|
||||
setSource( producer );
|
||||
this.pixelOrderChanges = pixelOrderChanges;
|
||||
}
|
||||
|
||||
|
||||
/// The default color model - useful for comparisons.
|
||||
public static final ColorModel rgbModel = ColorModel.getRGBdefault();
|
||||
|
||||
|
||||
/// Return the ImageProducer for this filter.
|
||||
public ImageProducer getSource()
|
||||
{
|
||||
return producer;
|
||||
}
|
||||
|
||||
/// Set the ImageProducer for this filter, if it wasn't set by the
|
||||
// constructor.
|
||||
public void setSource( ImageProducer producer )
|
||||
{
|
||||
this.producer = producer;
|
||||
}
|
||||
|
||||
|
||||
/// Set the hint flags. If the pixel order may change, we have to
|
||||
// turn off the TOPDOWNLEFTRIGHT flag; otherwise the flags are passed
|
||||
// through unmodified.
|
||||
public void setHints( int hintflags )
|
||||
{
|
||||
if ( pixelOrderChanges )
|
||||
hintflags &= ~TOPDOWNLEFTRIGHT;
|
||||
consumer.setHints( hintflags );
|
||||
}
|
||||
|
||||
|
||||
/// This routine fixes a bug in java.awt.image.ImageFilter. All
|
||||
// ImageConsumers are required remove themselves from the producer's
|
||||
// list when they're done reading. If they don't do this then some
|
||||
// producers will generate an error. The standard ImageFilter class
|
||||
// fails to do this, but this one does it.
|
||||
public void imageComplete( int status )
|
||||
{
|
||||
if ( status != ImageConsumer.SINGLEFRAMEDONE )
|
||||
producer.removeConsumer( this );
|
||||
super.imageComplete( status );
|
||||
}
|
||||
|
||||
|
||||
/// Filter a PPM InputStream to a PPM OutputStream.
|
||||
// <P>
|
||||
// Create the filter with a null producer, and this routine will
|
||||
// fill it in for you.
|
||||
// @return a status code suitable for use with System.exit().
|
||||
public static int filterStream( InputStream in, OutputStream out, ImageFilterPlus filter )
|
||||
{
|
||||
ImageDecoder producer = new PpmDecoder( in );
|
||||
filter.setSource( producer );
|
||||
try
|
||||
{
|
||||
ImageEncoder consumer = new PpmEncoder(
|
||||
new FilteredImageSource( producer, filter ), out );
|
||||
consumer.encode();
|
||||
}
|
||||
catch ( IOException e )
|
||||
{
|
||||
System.err.println( e.toString() );
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
// Invert - color-inversion filter
|
||||
//
|
||||
// Copyright (C) 1997 by Jef Poskanzer <jef@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/
|
||||
|
||||
package Acme.JPM.Filters;
|
||||
|
||||
import java.awt.image.*;
|
||||
|
||||
/// Color-inversion filter.
|
||||
// <P>
|
||||
// Switches black for white, and all the other colors too.
|
||||
// This filter is very fast.
|
||||
// <P>
|
||||
// <A HREF="/resources/classes/Acme/JPM/Filters/Invert.java">Fetch the software.</A><BR>
|
||||
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
|
||||
|
||||
public class Invert extends RGBBlockFilter
|
||||
{
|
||||
|
||||
/// Constructor.
|
||||
public Invert( ImageProducer producer )
|
||||
{
|
||||
super( producer );
|
||||
}
|
||||
|
||||
|
||||
public int[][] filterRGBBlock( int x, int y, int width, int height, int[][] rgbPixels )
|
||||
{
|
||||
for ( int row = 0; row < height; ++row )
|
||||
for ( int col = 0; col < width; ++col )
|
||||
{
|
||||
int rgb = rgbPixels[row][col];
|
||||
int alpha = rgb & 0xff000000;
|
||||
int rest = ( ~ rgb ) & 0x00ffffff;
|
||||
rgbPixels[row][col] = alpha | rest;
|
||||
}
|
||||
return rgbPixels;
|
||||
}
|
||||
|
||||
|
||||
// Main routine for command-line interface.
|
||||
public static void main( String[] args )
|
||||
{
|
||||
ImageFilterPlus filter = null;
|
||||
if ( args.length == 0 )
|
||||
filter = new Invert( null );
|
||||
else
|
||||
usage();
|
||||
System.exit(
|
||||
ImageFilterPlus.filterStream( System.in, System.out, filter ) );
|
||||
}
|
||||
|
||||
private static void usage()
|
||||
{
|
||||
System.err.println( "usage: Invert" );
|
||||
System.exit( 1 );
|
||||
}
|
||||
|
||||
}
|
|
@ -1,133 +0,0 @@
|
|||
// Margin - an ImageFilter that adds a margin to an image
|
||||
//
|
||||
// Copyright (C) 1997 by Jef Poskanzer <jef@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/
|
||||
|
||||
package Acme.JPM.Filters;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.*;
|
||||
|
||||
/// An ImageFilter that adds a margin to an image.
|
||||
// <P>
|
||||
// Adds a margin of a specified color and width around an image.
|
||||
// The output uses the same color model as the input.
|
||||
// This filter is very fast.
|
||||
// <P>
|
||||
// <A HREF="/resources/classes/Acme/JPM/Filters/Margin.java">Fetch the software.</A><BR>
|
||||
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
|
||||
|
||||
public class Margin extends ImageFilterPlus
|
||||
{
|
||||
|
||||
private Color color;
|
||||
private int size;
|
||||
private int width, height;
|
||||
private int newWidth;
|
||||
|
||||
/// Constructor.
|
||||
public Margin( ImageProducer producer, Color color, int size )
|
||||
{
|
||||
super( producer, true );
|
||||
this.color = color;
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
|
||||
public void setDimensions( int width, int height )
|
||||
{
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
newWidth = width + size * 2;
|
||||
consumer.setDimensions( newWidth, height + size * 2 );
|
||||
}
|
||||
|
||||
private boolean started = false;
|
||||
|
||||
private void start()
|
||||
{
|
||||
started = true;
|
||||
int rgb = color.getRGB();
|
||||
|
||||
int[] fullRow = new int[newWidth];
|
||||
for ( int col = 0; col < newWidth; ++col )
|
||||
fullRow[col] = rgb;
|
||||
for ( int row = 0; row < size; ++row )
|
||||
{
|
||||
consumer.setPixels(
|
||||
0, row, newWidth, 1, rgbModel, fullRow, 0, newWidth );
|
||||
consumer.setPixels(
|
||||
0, size + height + row, newWidth, 1, rgbModel, fullRow, 0,
|
||||
newWidth );
|
||||
}
|
||||
|
||||
int[] sideRow = new int[size];
|
||||
for ( int col = 0; col < size; ++col )
|
||||
sideRow[col] = rgb;
|
||||
for ( int row = 0; row < height; ++row )
|
||||
{
|
||||
consumer.setPixels(
|
||||
0, size + row, size, 1, rgbModel, sideRow, 0, size );
|
||||
consumer.setPixels(
|
||||
size + width, size + row, size, 1, rgbModel, sideRow, 0, size );
|
||||
}
|
||||
}
|
||||
|
||||
public void setPixels( int x, int y, int w, int h, ColorModel model, byte[] pixels, int off, int scansize )
|
||||
{
|
||||
if ( ! started )
|
||||
start();
|
||||
consumer.setPixels(
|
||||
x + size, y + size, w, h, model, pixels, off, scansize );
|
||||
}
|
||||
|
||||
public void setPixels( int x, int y, int w, int h, ColorModel model, int[] pixels, int off, int scansize )
|
||||
{
|
||||
if ( ! started )
|
||||
start();
|
||||
consumer.setPixels(
|
||||
x + size, y + size, w, h, model, pixels, off, scansize );
|
||||
}
|
||||
|
||||
|
||||
// Main routine for command-line interface.
|
||||
public static void main( String[] args )
|
||||
{
|
||||
if ( args.length != 1 )
|
||||
usage();
|
||||
ImageFilterPlus filter =
|
||||
new Margin( null, Color.black, Integer.parseInt( args[0] ) );
|
||||
System.exit(
|
||||
ImageFilterPlus.filterStream( System.in, System.out, filter ) );
|
||||
}
|
||||
|
||||
private static void usage()
|
||||
{
|
||||
System.err.println( "usage: Margin <size>" );
|
||||
System.exit( 1 );
|
||||
}
|
||||
|
||||
}
|
|
@ -1,141 +0,0 @@
|
|||
// Oil - oil-transfer filter
|
||||
//
|
||||
// Copyright (C) 1996 by Jef Poskanzer <jef@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/
|
||||
|
||||
package Acme.JPM.Filters;
|
||||
|
||||
import java.awt.image.*;
|
||||
|
||||
/// Oil-transfer filter.
|
||||
// <IMG ALIGN=RIGHT WIDTH=202 HEIGHT=200 SRC="Earth-Oil.jpg">
|
||||
// <IMG ALIGN=RIGHT WIDTH=202 HEIGHT=200 SRC="Earth.jpg">
|
||||
// <P>
|
||||
// The oil transfer is described in "Beyond Photography" by Holzmann,
|
||||
// chapter 4, photo 7.
|
||||
// It's a sort of localized smearing.
|
||||
// The parameter controls the size of the smeared area, with a default of 3.
|
||||
// <P>
|
||||
// This filter is very slow.
|
||||
// <P>
|
||||
// <A HREF="/resources/classes/Acme/JPM/Filters/Oil.java">Fetch the software.</A><BR>
|
||||
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
|
||||
|
||||
public class Oil extends RGBAllFilter
|
||||
{
|
||||
|
||||
private int n;
|
||||
|
||||
/// Constructor.
|
||||
public Oil( ImageProducer producer, int n )
|
||||
{
|
||||
super( producer );
|
||||
this.n = n;
|
||||
}
|
||||
|
||||
/// Constructor, default value.
|
||||
public Oil( ImageProducer producer )
|
||||
{
|
||||
this( producer, 3 );
|
||||
}
|
||||
|
||||
|
||||
public void filterRGBAll( int width, int height, int[][] rgbPixels )
|
||||
{
|
||||
int[][] newPixels = new int[height][width];
|
||||
int[] rHist = new int[256];
|
||||
int[] gHist = new int[256];
|
||||
int[] bHist = new int[256];
|
||||
|
||||
for ( int row = 0; row < height; ++row )
|
||||
{
|
||||
for ( int col = 0; col < width; ++col )
|
||||
{
|
||||
for ( int i = 0; i < 256; ++i )
|
||||
rHist[i] = gHist[i] = bHist[i] =0;
|
||||
for ( int drow = row - n; drow <= row + n; ++drow )
|
||||
if ( drow >= 0 && drow < height )
|
||||
for ( int dcol = col - n; dcol <= col + n; ++dcol )
|
||||
if ( dcol >= 0 && dcol < width )
|
||||
{
|
||||
int rgb = rgbPixels[drow][dcol];
|
||||
rHist[( rgb >> 16 ) & 0xff]++;
|
||||
gHist[( rgb >> 8 ) & 0xff]++;
|
||||
bHist[rgb & 0xff]++;
|
||||
}
|
||||
int r = 0, g = 0, b = 0;
|
||||
for ( int i = 1; i < 256; ++i )
|
||||
{
|
||||
if ( rHist[i] > rHist[r] )
|
||||
r = i;
|
||||
if ( gHist[i] > gHist[g] )
|
||||
g = i;
|
||||
if ( bHist[i] > bHist[b] )
|
||||
b = i;
|
||||
}
|
||||
newPixels[row][col] =
|
||||
0xff000000 | ( r << 16 ) | ( g << 8 ) | b;
|
||||
}
|
||||
}
|
||||
setPixels( width, height, newPixels );
|
||||
}
|
||||
|
||||
|
||||
// Main routine for command-line interface.
|
||||
public static void main( String[] args )
|
||||
{
|
||||
int n = -1;
|
||||
int argc = args.length;
|
||||
int argn;
|
||||
for ( argn = 0; argn < argc && args[argn].charAt( 0 ) == '-'; ++argn )
|
||||
{
|
||||
if ( args[argn].equals( "-n" ) && argn + 1 < argc )
|
||||
{
|
||||
++argn;
|
||||
n = Integer.parseInt( args[argn] );
|
||||
}
|
||||
else
|
||||
usage();
|
||||
}
|
||||
if ( argn != argc )
|
||||
usage();
|
||||
|
||||
ImageFilterPlus filter;
|
||||
if ( n == -1 )
|
||||
filter = new Oil( null );
|
||||
else
|
||||
filter = new Oil( null, n );
|
||||
System.exit(
|
||||
ImageFilterPlus.filterStream( System.in, System.out, filter ) );
|
||||
}
|
||||
|
||||
private static void usage()
|
||||
{
|
||||
System.err.println( "usage: Oil [-n N]" );
|
||||
System.exit( 1 );
|
||||
}
|
||||
|
||||
}
|
|
@ -1,170 +0,0 @@
|
|||
// RGBAllFilter - an ImageFilter that grabs the whole image
|
||||
//
|
||||
// Copyright (C) 1996 by Jef Poskanzer <jef@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/
|
||||
|
||||
package Acme.JPM.Filters;
|
||||
|
||||
import java.awt.image.*;
|
||||
|
||||
/// An ImageFilter that grabs the whole image.
|
||||
// <P>
|
||||
// Many image filters need to work on the whole image at once.
|
||||
// This class collects up the image and hands it to a single
|
||||
// routine for processing.
|
||||
// <P>
|
||||
// Also, because Java's image classes allow each setPixels() call to
|
||||
// use a different color model, we have to convert all pixels into
|
||||
// the default RGB model.
|
||||
// <P>
|
||||
// Here's a sample RGBAllFilter that smooths an image by averaging
|
||||
// nine adjacent pixels.
|
||||
// <BLOCKQUOTE><CODE><PRE>
|
||||
// class SmoothFilter extends RGBAllFilter
|
||||
// {
|
||||
// public void filterRGBAll( int width, int height, int[][] rgbPixels )
|
||||
// {
|
||||
// int[][] newPixels = new int[height][width];
|
||||
// for ( int row = 0; row < height; ++row )
|
||||
// for ( int col = 0; col < width; ++col )
|
||||
// {
|
||||
// int a = 0, r = 0, g = 0, b = 0, c = 0;
|
||||
// for ( int subrow = row - 1; subrow <= row + 1; ++subrow )
|
||||
// if ( subrow >= 0 && subrow < height )
|
||||
// for ( int subcol = col - 1; subcol <= col + 1; ++subcol )
|
||||
// if ( subcol >= 0 && subcol < width )
|
||||
// {
|
||||
// int pixel = rgbPixels[subrow][subcol];
|
||||
// a += rgbModel.getAlpha( pixel );
|
||||
// r += rgbModel.getRed( pixel );
|
||||
// g += rgbModel.getGreen( pixel );
|
||||
// b += rgbModel.getBlue( pixel );
|
||||
// ++c;
|
||||
// }
|
||||
// a /= c;
|
||||
// r /= c;
|
||||
// g /= c;
|
||||
// b /= c;
|
||||
// newPixels[row][col] =
|
||||
// ( a << 24 ) | ( r << 16 ) | ( g << 8 ) | b;
|
||||
// }
|
||||
// setPixels( width, height, newPixels );
|
||||
// }
|
||||
// }
|
||||
// </PRE></CODE></BLOCKQUOTE>
|
||||
// <P>
|
||||
// <A HREF="/resources/classes/Acme/JPM/Filters/RGBAllFilter.java">Fetch the software.</A><BR>
|
||||
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
|
||||
|
||||
public abstract class RGBAllFilter extends ImageFilterPlus
|
||||
{
|
||||
|
||||
private int width = -1, height = -1;
|
||||
private int[][] rgbPixels = null;
|
||||
|
||||
public RGBAllFilter( ImageProducer producer )
|
||||
{
|
||||
super( producer );
|
||||
}
|
||||
|
||||
|
||||
/// This is the routine that subclasses must implement.
|
||||
// It gets the entire image as an int[height][width] in the default
|
||||
// RGB color model. It should call setPixels() with a filtered array,
|
||||
// same color model.
|
||||
public abstract void filterRGBAll( int width, int height, int[][] rgbPixels );
|
||||
|
||||
|
||||
/// The version of setPixels() that gets called by the subclass.
|
||||
public void setPixels( int newWidth, int newHeight, int[][] newPixels )
|
||||
{
|
||||
// Send it on to the consumer.
|
||||
consumer.setDimensions( newWidth, newHeight );
|
||||
for ( int row = 0; row < newHeight; ++row )
|
||||
consumer.setPixels(
|
||||
0, row, newWidth, 1, rgbModel, newPixels[row], 0, newWidth );
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void setColorModel( ColorModel model )
|
||||
{
|
||||
consumer.setColorModel( rgbModel );
|
||||
}
|
||||
|
||||
public void setDimensions( int width, int height )
|
||||
{
|
||||
if ( width == this.width && height == this.height )
|
||||
return;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
rgbPixels = new int[height][width];
|
||||
}
|
||||
|
||||
public void setPixels( int x, int y, int w, int h, ColorModel model, byte[] pixels, int off, int scansize )
|
||||
{
|
||||
for ( int row = 0; row < h; ++row )
|
||||
{
|
||||
int rowOffsetIn = row * scansize + off;
|
||||
for ( int col = 0; col < w; ++col )
|
||||
rgbPixels[y + row][x + col] =
|
||||
model.getRGB( pixels[rowOffsetIn + col] & 0xff );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setPixels( int x, int y, int w, int h, ColorModel model, int[] pixels, int off, int scansize )
|
||||
{
|
||||
for ( int row = 0; row < h; ++row )
|
||||
{
|
||||
int rowOffsetIn = row * scansize + off;
|
||||
if ( model == rgbModel )
|
||||
System.arraycopy(
|
||||
pixels, rowOffsetIn, rgbPixels[y + row], x, w );
|
||||
else
|
||||
for ( int col = 0; col < w; ++col )
|
||||
rgbPixels[y + row][x + col] =
|
||||
model.getRGB( pixels[rowOffsetIn + col] );
|
||||
}
|
||||
}
|
||||
|
||||
public void imageComplete( int status )
|
||||
{
|
||||
if ( status == ImageConsumer.IMAGEERROR ||
|
||||
status == ImageConsumer.IMAGEABORTED )
|
||||
{
|
||||
super.imageComplete( status );
|
||||
return;
|
||||
}
|
||||
|
||||
// Do the actual work.
|
||||
filterRGBAll( width, height, rgbPixels );
|
||||
|
||||
// And we're done.
|
||||
super.imageComplete( status );
|
||||
}
|
||||
|
||||
}
|
|
@ -1,135 +0,0 @@
|
|||
// RGBBlockFilter - more efficient RGB ImageFilter
|
||||
//
|
||||
// Copyright (C) 1996 by Jef Poskanzer <jef@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/
|
||||
|
||||
package Acme.JPM.Filters;
|
||||
|
||||
import java.awt.image.*;
|
||||
|
||||
/// More efficient RGB ImageFilter.
|
||||
// <P>
|
||||
// Similar in concept to java.awt.image.RGBImageFilter, but designed
|
||||
// to run more efficiently when filtering large images.
|
||||
// <P>
|
||||
// As with RGBImageFilter, you only have to implement a single routine
|
||||
// to use the filter. However, RGBImageFilter's routine filters a single
|
||||
// pixel at a time. This means a lot of routine-calling overhead.
|
||||
// RGBBlockFilter filters a block at a time.
|
||||
// <P>
|
||||
// Here's a sample RGBBlockFilter that makes an image translucent
|
||||
// by setting all the alpha values to 0x80:
|
||||
// <BLOCKQUOTE><CODE><PRE>
|
||||
// class TranslucentFilter extends RGBBlockFilter
|
||||
// {
|
||||
// public int[] filterRGBBlock(
|
||||
// int x, int y, int width, int height, int[][] rgbPixels )
|
||||
// {
|
||||
// for ( int row = 0; row < height; ++row )
|
||||
// for ( int col = 0; col < width; ++col )
|
||||
// rgbPixels[row][col] =
|
||||
// ( rgbPixels[row][col] & 0x00ffffff ) | 0x80000000;
|
||||
// return rgbPixels;
|
||||
// }
|
||||
// }
|
||||
// </PRE></CODE></BLOCKQUOTE>
|
||||
// <P>
|
||||
// <A HREF="/resources/classes/Acme/JPM/Filters/RGBBlockFilter.java">Fetch the software.</A><BR>
|
||||
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
|
||||
|
||||
public abstract class RGBBlockFilter extends ImageFilterPlus
|
||||
{
|
||||
|
||||
public RGBBlockFilter( ImageProducer producer )
|
||||
{
|
||||
super( producer );
|
||||
}
|
||||
|
||||
|
||||
/// This is the routine that subclasses must implement.
|
||||
// It gets a block of the image as an int[height][width] in the default
|
||||
// RGB color model. It should return a filtered array, same size
|
||||
// and same model.
|
||||
public abstract int[][] filterRGBBlock(
|
||||
int x, int y, int width, int height, int[][] rgbPixels );
|
||||
|
||||
|
||||
public void setColorModel( ColorModel model )
|
||||
{
|
||||
consumer.setColorModel( rgbModel );
|
||||
}
|
||||
|
||||
/// Byte version of setPixels reformats the pixels to RGB and the
|
||||
// array to 2 dimensions.
|
||||
public void setPixels(
|
||||
int x, int y, int width, int height, ColorModel model,
|
||||
byte[] pixels, int offset, int scansize )
|
||||
{
|
||||
int[][] rgbPixels = new int[height][width];
|
||||
for ( int row = 0; row < height; ++row )
|
||||
{
|
||||
int rowOffsetIn = offset + row * scansize;
|
||||
for ( int col = 0; col < width; ++col )
|
||||
rgbPixels[row][col] =
|
||||
model.getRGB( pixels[rowOffsetIn + col] & 0xff );
|
||||
}
|
||||
setPixels( x, y, width, height, rgbPixels );
|
||||
}
|
||||
|
||||
/// Int version of setPixels reformats the array to 2 dimensions.
|
||||
public void setPixels(
|
||||
int x, int y, int width, int height, ColorModel model,
|
||||
int[] pixels, int offset, int scansize )
|
||||
{
|
||||
int[][] rgbPixels = new int[height][width];
|
||||
for ( int row = 0; row < height; ++row )
|
||||
{
|
||||
int rowOffsetIn = offset + row * scansize;
|
||||
int rowOffsetOut = row * width;
|
||||
// Convert color models if necessary.
|
||||
if ( model == rgbModel )
|
||||
System.arraycopy(
|
||||
pixels, rowOffsetIn, rgbPixels[row], 0, width );
|
||||
else
|
||||
for ( int col = 0; col < width; ++col )
|
||||
rgbPixels[row][col] =
|
||||
model.getRGB( pixels[rowOffsetIn + col] );
|
||||
}
|
||||
setPixels( x, y, width, height, rgbPixels );
|
||||
}
|
||||
|
||||
/// Call the filter routine, and send the results to the consumer.
|
||||
private void setPixels( int x, int y, int width, int height, int[][] rgbPixels )
|
||||
{
|
||||
int[][] newPixels = filterRGBBlock( x, y, width, height, rgbPixels );
|
||||
|
||||
// And send it on to the consumer.
|
||||
for ( int row = 0; row < height; ++row )
|
||||
consumer.setPixels(
|
||||
x, y + row, width, 1, rgbModel, newPixels[row], 0, width );
|
||||
}
|
||||
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
// Rotate - rotate an image by some angle
|
||||
//
|
||||
// Copyright (C) 1997 by Jef Poskanzer <jef@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/
|
||||
|
||||
package Acme.JPM.Filters;
|
||||
|
||||
import java.awt.image.*;
|
||||
|
||||
/// Rotate an image by some angle.
|
||||
// <P>
|
||||
// Rotates an image by the specified angle.
|
||||
// The angle is in degrees measured counter-clockwise.
|
||||
// It can be negative, but it should be between -90 and 90
|
||||
// or the resulting image will be unreasonably large.
|
||||
// Staying between -45 and 45 is best.
|
||||
// <P>
|
||||
// The rotation algorithm is Alan Paeth's three-shear method, described
|
||||
// in "A Fast Algorithm for General Raster Rotation", Graphics Interface
|
||||
// '86, pp. 77-81.
|
||||
// <P>
|
||||
// This filter is slow.
|
||||
// <P>
|
||||
// <A HREF="/resources/classes/Acme/JPM/Filters/Rotate.java">Fetch the software.</A><BR>
|
||||
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
|
||||
|
||||
public class Rotate extends CompositeFilter
|
||||
{
|
||||
|
||||
private double angle;
|
||||
|
||||
/// Constructor.
|
||||
public Rotate( ImageProducer producer, double angle )
|
||||
{
|
||||
super( producer, new Shear( null, angle ), new Flip( null, Flip.FLIP_XY ) );
|
||||
this.angle = angle * Math.PI / 180.0;
|
||||
double xshearfac = Math.tan( angle / 2.0 );
|
||||
double yshearfac = Math.sin( angle );
|
||||
}
|
||||
|
||||
|
||||
// Main routine for command-line interface.
|
||||
public static void main( String[] args )
|
||||
{
|
||||
if ( args.length != 1 )
|
||||
usage();
|
||||
ImageFilterPlus filter = new Rotate( null, Integer.parseInt( args[0] ) );
|
||||
System.exit(
|
||||
ImageFilterPlus.filterStream( System.in, System.out, filter ) );
|
||||
}
|
||||
|
||||
private static void usage()
|
||||
{
|
||||
System.err.println( "usage: Rotate <angle>" );
|
||||
System.exit( 1 );
|
||||
}
|
||||
|
||||
}
|
|
@ -1,159 +0,0 @@
|
|||
// ScaleCopy - an ImageFilter that scales by pixel copying
|
||||
//
|
||||
// Copyright (C) 1996 by Jef Poskanzer <jef@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/
|
||||
|
||||
package Acme.JPM.Filters;
|
||||
|
||||
import java.awt.image.*;
|
||||
|
||||
/// An ImageFilter that scales by pixel copying.
|
||||
// <P>
|
||||
// Scales an image by copying pixels.
|
||||
// If the image is being enlarged, pixels get replicated;
|
||||
// if the image is being shrunk, pixels get dropped.
|
||||
// The output uses the same color model as the input.
|
||||
// For enlarging, this filter is slightly slower than Enlarge due
|
||||
// to the floating-point arithmetic;
|
||||
// for shrinking, it's much faster than Shrink, but
|
||||
// the results aren't as nice.
|
||||
// <P>
|
||||
// <A HREF="/resources/classes/Acme/JPM/Filters/ScaleCopy.java">Fetch the software.</A><BR>
|
||||
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
|
||||
// <P>
|
||||
// @see Enlarge
|
||||
// @see Shrink
|
||||
|
||||
public class ScaleCopy extends ImageFilterPlus
|
||||
{
|
||||
|
||||
private double xScale, yScale;
|
||||
private int newWidth, newHeight;
|
||||
|
||||
/// Constructor, same X and Y scale factor.
|
||||
public ScaleCopy( ImageProducer producer, double scale )
|
||||
{
|
||||
this( producer, scale, scale );
|
||||
}
|
||||
|
||||
/// Constructor, different X and Y scale factors.
|
||||
public ScaleCopy( ImageProducer producer, double xScale, double yScale )
|
||||
{
|
||||
super( producer );
|
||||
this.xScale = xScale;
|
||||
this.yScale = yScale;
|
||||
}
|
||||
|
||||
|
||||
public void setDimensions( int width, int height )
|
||||
{
|
||||
newWidth = (int) ( width * xScale );
|
||||
newHeight = (int) ( height * yScale );
|
||||
consumer.setDimensions( newWidth, newHeight );
|
||||
}
|
||||
|
||||
public void setPixels( int x, int y, int w, int h, ColorModel model, byte[] pixels, int off, int scansize )
|
||||
{
|
||||
int newX = Math.min( (int) ( x * xScale ), newWidth - 1 );
|
||||
int newY = Math.min( (int) ( y * yScale ), newHeight - 1 );
|
||||
int newW = Math.max( (int) ( w * xScale ), 1 );
|
||||
if ( newX + newW > newWidth )
|
||||
newW = newWidth - newX;
|
||||
int newH = Math.max( (int) ( h * yScale ), 1 );
|
||||
if ( newY + newH > newHeight )
|
||||
newH = newHeight - newY;
|
||||
byte[] newPixels = new byte[newW * newH];
|
||||
for ( int newRow = 0; newRow < newH; ++newRow )
|
||||
{
|
||||
int row = (int) ( newRow / yScale );
|
||||
if ( row >= h )
|
||||
continue;
|
||||
for ( int newCol = 0; newCol < newW; ++newCol )
|
||||
{
|
||||
int col = (int) ( newCol / xScale );
|
||||
if ( col >= w )
|
||||
continue;
|
||||
newPixels[newRow * newW + newCol] =
|
||||
pixels[row * scansize + off + col];
|
||||
}
|
||||
}
|
||||
consumer.setPixels( newX, newY, newW, newH, model, newPixels, 0, newW );
|
||||
}
|
||||
|
||||
public void setPixels( int x, int y, int w, int h, ColorModel model, int[] pixels, int off, int scansize )
|
||||
{
|
||||
int newX = Math.min( (int) ( x * xScale ), newWidth - 1 );
|
||||
int newY = Math.min( (int) ( y * yScale ), newHeight - 1 );
|
||||
int newW = Math.max( (int) ( w * xScale ), 1 );
|
||||
if ( newX + newW > newWidth )
|
||||
newW = newWidth - newX;
|
||||
int newH = Math.max( (int) ( h * yScale ), 1 );
|
||||
if ( newY + newH > newHeight )
|
||||
newH = newHeight - newY;
|
||||
int[] newPixels = new int[newW * newH];
|
||||
for ( int newRow = 0; newRow < newH; ++newRow )
|
||||
{
|
||||
int row = (int) ( newRow / yScale );
|
||||
if ( row >= h )
|
||||
continue;
|
||||
for ( int newCol = 0; newCol < newW; ++newCol )
|
||||
{
|
||||
int col = (int) ( newCol / xScale );
|
||||
if ( col >= w )
|
||||
continue;
|
||||
newPixels[newRow * newW + newCol] =
|
||||
pixels[row * scansize + off + col];
|
||||
}
|
||||
}
|
||||
consumer.setPixels( newX, newY, newW, newH, model, newPixels, 0, newW );
|
||||
}
|
||||
|
||||
|
||||
// Main routine for command-line interface.
|
||||
public static void main( String[] args )
|
||||
{
|
||||
ImageFilterPlus filter = null;
|
||||
if ( args.length == 1 )
|
||||
filter = new ScaleCopy( null,
|
||||
Double.valueOf( args[0] ).doubleValue() );
|
||||
else if ( args.length == 2 )
|
||||
filter = new ScaleCopy( null,
|
||||
Double.valueOf( args[0] ).doubleValue(),
|
||||
Double.valueOf( args[1] ).doubleValue() );
|
||||
else
|
||||
usage();
|
||||
System.exit(
|
||||
ImageFilterPlus.filterStream( System.in, System.out, filter ) );
|
||||
}
|
||||
|
||||
private static void usage()
|
||||
{
|
||||
System.err.println( "usage: ScaleCopy scale" );
|
||||
System.err.println( "or: ScaleCopy xScale yScale" );
|
||||
System.exit( 1 );
|
||||
}
|
||||
|
||||
}
|
|
@ -1,144 +0,0 @@
|
|||
// Shear - shear an image by some angle
|
||||
//
|
||||
// Copyright (C) 1997 by Jef Poskanzer <jef@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/
|
||||
|
||||
package Acme.JPM.Filters;
|
||||
|
||||
import java.awt.image.*;
|
||||
|
||||
/// Shear an image by some angle.
|
||||
// <P>
|
||||
// Shears an image by the specified angle.
|
||||
// The angle is in degrees (floating point), and measures this:
|
||||
// <BLOCKQUOTE><PRE><CODE>
|
||||
// +-------+ +-------+
|
||||
// | | |\ \
|
||||
// | OLD | | \ NEW \
|
||||
// | | |an\ \
|
||||
// +-------+ |gle+-------+
|
||||
// </CODE></PRE></BLOCKQUOTE>
|
||||
// If the angle is negative, it shears the other way:
|
||||
// <BLOCKQUOTE><PRE><CODE>
|
||||
// +-------+ |-an+-------+
|
||||
// | | |gl/ /
|
||||
// | OLD | |e/ NEW /
|
||||
// | | |/ /
|
||||
// +-------+ +-------+
|
||||
// </CODE></PRE></BLOCKQUOTE>
|
||||
// The angle should not get too close to 90 or -90, or the resulting
|
||||
// image will be unreasonably wide. Staying between -45 and 45 is best.
|
||||
// <P>
|
||||
// The shearing is implemented by looping over the source pixels and
|
||||
// distributing fractions to each of the destination pixels.
|
||||
// This has an "anti-aliasing" effect - it avoids jagged edges and similar
|
||||
// artifacts.
|
||||
// <P>
|
||||
// This filter is fast.
|
||||
// <P>
|
||||
// <A HREF="/resources/classes/Acme/JPM/Filters/Shear.java">Fetch the software.</A><BR>
|
||||
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
|
||||
|
||||
public class Shear extends RGBAllFilter
|
||||
{
|
||||
|
||||
private double angle;
|
||||
|
||||
/// Constructor.
|
||||
public Shear( ImageProducer producer, double angle )
|
||||
{
|
||||
super( producer );
|
||||
this.angle = angle * Math.PI / 180.0;
|
||||
}
|
||||
|
||||
|
||||
public void filterRGBAll( int width, int height, int[][] rgbPixels )
|
||||
{
|
||||
double shearfac = Math.tan( angle );
|
||||
if ( shearfac < 0.0 )
|
||||
shearfac = -shearfac;
|
||||
int newWidth = (int) ( height * shearfac + width + 0.999999 );
|
||||
int[][] newPixels = new int[height][newWidth];
|
||||
for ( int row = 0; row < height; ++row )
|
||||
{
|
||||
double new0;
|
||||
if ( angle > 0.0 )
|
||||
new0 = row * shearfac;
|
||||
else
|
||||
new0 = ( height - row ) * shearfac;
|
||||
int intnew0 = (int) new0;
|
||||
double fracnew0 = new0 - intnew0;
|
||||
double omfracnew0 = 1.0 - fracnew0;
|
||||
|
||||
for ( int col = 0; col < newWidth; ++col )
|
||||
newPixels[row][col] = 0x00000000;
|
||||
|
||||
int preva = 0;
|
||||
int prevr = ( rgbPixels[row][0] >> 16 ) & 0xff;
|
||||
int prevg = ( rgbPixels[row][0] >> 8 ) & 0xff;
|
||||
int prevb = rgbPixels[row][0] & 0xff;
|
||||
for ( int col = 0; col < width; ++col )
|
||||
{
|
||||
int rgb = rgbPixels[row][col];
|
||||
int a = ( rgb >> 24 ) & 0xff;
|
||||
int r = ( rgb >> 16 ) & 0xff;
|
||||
int g = ( rgb >> 8 ) & 0xff;
|
||||
int b = rgb & 0xff;
|
||||
newPixels[row][intnew0 + col] =
|
||||
( (int) ( fracnew0 * preva + omfracnew0 * a ) << 24 ) |
|
||||
( (int) ( fracnew0 * prevr + omfracnew0 * r ) << 16 ) |
|
||||
( (int) ( fracnew0 * prevg + omfracnew0 * g ) << 8 ) |
|
||||
( (int) ( fracnew0 * prevb + omfracnew0 * b ) );
|
||||
preva = a;
|
||||
prevr = r;
|
||||
prevg = g;
|
||||
prevb = b;
|
||||
}
|
||||
newPixels[row][intnew0 + width] =
|
||||
( (int) ( fracnew0 * preva ) << 24 ) |
|
||||
( prevr << 16 ) | ( prevg << 8 ) | prevb;
|
||||
}
|
||||
setPixels( newWidth, height, newPixels );
|
||||
}
|
||||
|
||||
|
||||
// Main routine for command-line interface.
|
||||
public static void main( String[] args )
|
||||
{
|
||||
if ( args.length != 1 )
|
||||
usage();
|
||||
ImageFilterPlus filter = new Shear( null, Integer.parseInt( args[0] ) );
|
||||
System.exit(
|
||||
ImageFilterPlus.filterStream( System.in, System.out, filter ) );
|
||||
}
|
||||
|
||||
private static void usage()
|
||||
{
|
||||
System.err.println( "usage: Shear <angle>" );
|
||||
System.exit( 1 );
|
||||
}
|
||||
|
||||
}
|
|
@ -1,116 +0,0 @@
|
|||
// Shrink - an ImageFilter that shrinks by pixel averaging
|
||||
//
|
||||
// Copyright (C) 1996 by Jef Poskanzer <jef@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/
|
||||
|
||||
package Acme.JPM.Filters;
|
||||
|
||||
import java.awt.image.*;
|
||||
|
||||
/// An ImageFilter that shrinks by pixel averaging.
|
||||
// <P>
|
||||
// Shrinks an image an integral factor by averaging pixels.
|
||||
// Because the resulting pixels might not fit into the input's
|
||||
// color model, the output is always in the default RGB color model.
|
||||
// This filter is somewhat slow.
|
||||
// <P>
|
||||
// <A HREF="/resources/classes/Acme/JPM/Filters/Shrink.java">Fetch the software.</A><BR>
|
||||
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
|
||||
// <P>
|
||||
// @see Enlarge
|
||||
// @see ScaleCopy
|
||||
|
||||
public class Shrink extends RGBAllFilter
|
||||
{
|
||||
|
||||
private int divisor;
|
||||
|
||||
/// Constructor.
|
||||
public Shrink( ImageProducer producer, int divisor )
|
||||
{
|
||||
super( producer );
|
||||
this.divisor = divisor;
|
||||
}
|
||||
|
||||
|
||||
public void filterRGBAll( int width, int height, int[][] rgbPixels )
|
||||
{
|
||||
int divisor2 = divisor * divisor;
|
||||
int newWidth = Math.max( width / divisor, 1 );
|
||||
int newHeight = Math.max( height / divisor, 1 );
|
||||
int[][] newPixels = new int[newHeight][newWidth];
|
||||
for ( int newRow = 0; newRow < newHeight; ++newRow )
|
||||
{
|
||||
for ( int newCol = 0; newCol < newWidth; ++newCol )
|
||||
{
|
||||
int a = 0, r = 0, g = 0, b = 0;
|
||||
for ( int i = 0; i < divisor; ++i )
|
||||
{
|
||||
int row = newRow * divisor + i;
|
||||
if ( row >= height )
|
||||
continue;
|
||||
for ( int j = 0; j < divisor; ++j )
|
||||
{
|
||||
int col = newCol * divisor + j;
|
||||
if ( col >= width )
|
||||
continue;
|
||||
int rgb = rgbPixels[row][col];
|
||||
a += ( rgb >> 24 ) & 0xff;
|
||||
r += ( rgb >> 16 ) & 0xff;
|
||||
g += ( rgb >> 8 ) & 0xff;
|
||||
b += rgb & 0xff;
|
||||
}
|
||||
}
|
||||
a /= divisor2;
|
||||
r /= divisor2;
|
||||
g /= divisor2;
|
||||
b /= divisor2;
|
||||
newPixels[newRow][newCol] =
|
||||
( a << 24 ) | ( r << 16 ) | ( g << 8 ) | b;
|
||||
}
|
||||
}
|
||||
setPixels( newWidth, newHeight, newPixels );
|
||||
}
|
||||
|
||||
|
||||
// Main routine for command-line interface.
|
||||
public static void main( String[] args )
|
||||
{
|
||||
if ( args.length != 1 )
|
||||
usage();
|
||||
ImageFilterPlus filter = new Enlarge(
|
||||
null, Integer.parseInt( args[0] ) );
|
||||
System.exit(
|
||||
ImageFilterPlus.filterStream( System.in, System.out, filter ) );
|
||||
}
|
||||
|
||||
private static void usage()
|
||||
{
|
||||
System.err.println( "usage: Shrink <divisor>" );
|
||||
System.exit( 1 );
|
||||
}
|
||||
|
||||
}
|
|
@ -1,123 +0,0 @@
|
|||
// Smooth - smoothing filter
|
||||
//
|
||||
// Copyright (C) 1996 by Jef Poskanzer <jef@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/
|
||||
|
||||
package Acme.JPM.Filters;
|
||||
|
||||
import java.awt.image.*;
|
||||
|
||||
/// Smoothing filter.
|
||||
// <P>
|
||||
// Smooths an image by averaging adjacent pixels.
|
||||
// <P>
|
||||
// <A HREF="/resources/classes/Acme/JPM/Filters/Smooth.java">Fetch the software.</A><BR>
|
||||
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
|
||||
|
||||
public class Smooth extends RGBAllFilter
|
||||
{
|
||||
|
||||
private int n;
|
||||
|
||||
/// Constructor.
|
||||
public Smooth( ImageProducer producer, int n )
|
||||
{
|
||||
super( producer );
|
||||
this.n = n;
|
||||
}
|
||||
|
||||
/// Constructor, default value.
|
||||
public Smooth( ImageProducer producer )
|
||||
{
|
||||
this( producer, 1 );
|
||||
}
|
||||
|
||||
|
||||
public void filterRGBAll( int width, int height, int[][] rgbPixels )
|
||||
{
|
||||
int[][] newPixels = new int[height][width];
|
||||
for ( int row = 0; row < height; ++row )
|
||||
for ( int col = 0; col < width; ++col )
|
||||
{
|
||||
int a = 0, r = 0, g = 0, b = 0, c = 0;
|
||||
for ( int subrow = row - n; subrow <= row + n; ++subrow )
|
||||
if ( subrow >= 0 && subrow < height )
|
||||
for ( int subcol = col - n; subcol <= col + n; ++subcol )
|
||||
if ( subcol >= 0 && subcol < width )
|
||||
{
|
||||
int rgb = rgbPixels[subrow][subcol];
|
||||
a += ( rgb >> 24 ) & 0xff;
|
||||
r += ( rgb >> 16 ) & 0xff;
|
||||
g += ( rgb >> 8 ) & 0xff;
|
||||
b += rgb & 0xff;
|
||||
++c;
|
||||
}
|
||||
a /= c;
|
||||
r /= c;
|
||||
g /= c;
|
||||
b /= c;
|
||||
newPixels[row][col] =
|
||||
( a << 24 ) | ( r << 16 ) | ( g << 8 ) | b;
|
||||
}
|
||||
setPixels( width, height, newPixels );
|
||||
}
|
||||
|
||||
|
||||
// Main routine for command-line interface.
|
||||
public static void main( String[] args )
|
||||
{
|
||||
int n = -1;
|
||||
int argc = args.length;
|
||||
int argn;
|
||||
for ( argn = 0; argn < argc && args[argn].charAt( 0 ) == '-'; ++argn )
|
||||
{
|
||||
if ( args[argn].equals( "-n" ) && argn + 1 < argc )
|
||||
{
|
||||
++argn;
|
||||
n = Integer.parseInt( args[argn] );
|
||||
}
|
||||
else
|
||||
usage();
|
||||
}
|
||||
if ( argn != argc )
|
||||
usage();
|
||||
|
||||
ImageFilterPlus filter;
|
||||
if ( n == -1 )
|
||||
filter = new Smooth( null );
|
||||
else
|
||||
filter = new Smooth( null, n );
|
||||
System.exit(
|
||||
ImageFilterPlus.filterStream( System.in, System.out, filter ) );
|
||||
}
|
||||
|
||||
private static void usage()
|
||||
{
|
||||
System.err.println( "usage: Smooth [-n N]" );
|
||||
System.exit( 1 );
|
||||
}
|
||||
|
||||
}
|
|
@ -1,126 +0,0 @@
|
|||
// Tile - an ImageFilter that replicates an image in a tiled pattern
|
||||
//
|
||||
// Copyright (C) 1996 by Jef Poskanzer <jef@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/
|
||||
|
||||
package Acme.JPM.Filters;
|
||||
|
||||
import java.awt.image.*;
|
||||
|
||||
/// An ImageFilter that replicates an image in a tiled pattern.
|
||||
// <P>
|
||||
// Tiles the image onto an output image of a specified size.
|
||||
// The output uses the same color model as the input.
|
||||
// This filter is very fast.
|
||||
// <P>
|
||||
// <A HREF="/resources/classes/Acme/JPM/Filters/Tile.java">Fetch the software.</A><BR>
|
||||
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
|
||||
|
||||
public class Tile extends ImageFilterPlus
|
||||
{
|
||||
|
||||
private int width, height;
|
||||
private int newWidth, newHeight;
|
||||
private int nWide, nHigh;
|
||||
|
||||
/// Constructor.
|
||||
public Tile( ImageProducer producer, int newWidth, int newHeight )
|
||||
{
|
||||
super( producer, true );
|
||||
this.newWidth = newWidth;
|
||||
this.newHeight = newHeight;
|
||||
}
|
||||
|
||||
|
||||
public void setDimensions( int width, int height )
|
||||
{
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
consumer.setDimensions( newWidth, newHeight );
|
||||
nWide = ( newWidth + width - 1 ) / width;
|
||||
nHigh = ( newHeight + height - 1 ) / height;
|
||||
}
|
||||
|
||||
public void setPixels( int x, int y, int w, int h, ColorModel model, byte[] pixels, int off, int scansize )
|
||||
{
|
||||
for ( int r = 0; r < nHigh; ++r )
|
||||
{
|
||||
int ty = r * height + y;
|
||||
int th = h;
|
||||
if ( ty + th > newHeight )
|
||||
th = newHeight - ty;
|
||||
for ( int c = 0; c < nWide; ++c )
|
||||
{
|
||||
int tx = c * width + x;
|
||||
int tw = w;
|
||||
if ( tx + tw > newWidth )
|
||||
tw = newWidth - tx;
|
||||
consumer.setPixels(
|
||||
tx, ty, tw, th, model, pixels, off, scansize );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setPixels( int x, int y, int w, int h, ColorModel model, int[] pixels, int off, int scansize )
|
||||
{
|
||||
for ( int r = 0; r < nHigh; ++r )
|
||||
{
|
||||
int ty = r * height + y;
|
||||
int th = h;
|
||||
if ( ty + th > newHeight )
|
||||
th = newHeight - ty;
|
||||
for ( int c = 0; c < nWide; ++c )
|
||||
{
|
||||
int tx = c * width + x;
|
||||
int tw = w;
|
||||
if ( tx + tw > newWidth )
|
||||
tw = newWidth - tx;
|
||||
consumer.setPixels(
|
||||
tx, ty, tw, th, model, pixels, off, scansize );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Main routine for command-line interface.
|
||||
public static void main( String[] args )
|
||||
{
|
||||
if ( args.length != 2 )
|
||||
usage();
|
||||
ImageFilterPlus filter =
|
||||
new Tile( null,
|
||||
Integer.parseInt( args[0] ), Integer.parseInt( args[1] ) );
|
||||
System.exit(
|
||||
ImageFilterPlus.filterStream( System.in, System.out, filter ) );
|
||||
}
|
||||
|
||||
private static void usage()
|
||||
{
|
||||
System.err.println( "usage: Tile <width> <height>" );
|
||||
System.exit( 1 );
|
||||
}
|
||||
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
// JPMUtils - static utility routines for the JPM packages
|
||||
//
|
||||
// Copyright (C) 1996 by Jef Poskanzer <jef@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/
|
||||
|
||||
package Acme.JPM;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.*;
|
||||
import Acme.JPM.Filters.*;
|
||||
|
||||
/// Static utility routines for the JPM packages.
|
||||
// <P>
|
||||
// <A HREF="/resources/classes/Acme/JPM/JPMUtils.java">Fetch the software.</A><BR>
|
||||
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
|
||||
|
||||
public class JPMUtils
|
||||
{
|
||||
|
||||
/// Filter one image into another.
|
||||
public static Image filterImage( Component comp, ImageFilterPlus filter )
|
||||
{
|
||||
return comp.createImage(
|
||||
new FilteredImageSource( filter.getSource(), filter ) );
|
||||
}
|
||||
|
||||
}
|
|
@ -1,303 +0,0 @@
|
|||
// LruHashtable - a Hashtable that expires least-recently-used objects
|
||||
//
|
||||
// Copyright (C) 1996 by Jef Poskanzer <jef@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/
|
||||
|
||||
package Acme;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/// A Hashtable that expires least-recently-used objects.
|
||||
// <P>
|
||||
// Use just like java.util.Hashtable, except that the initial-capacity
|
||||
// parameter is required. Instead of growing bigger than that size,
|
||||
// it will throw out objects that haven't been looked at in a while.
|
||||
// <P>
|
||||
// <A HREF="/resources/classes/Acme/LruHashtable.java">Fetch the software.</A><BR>
|
||||
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
|
||||
// <P>
|
||||
// @see java.util.Hashtable
|
||||
|
||||
public class LruHashtable extends Hashtable
|
||||
{
|
||||
|
||||
// Number of buckets.
|
||||
private static final int nBuckets = 2;
|
||||
|
||||
// Load factor.
|
||||
private float loadFactor;
|
||||
|
||||
// When count exceeds this threshold, expires the old table.
|
||||
private int threshold;
|
||||
|
||||
// Capacity of each bucket.
|
||||
private int eachCapacity;
|
||||
|
||||
// The tables.
|
||||
private Hashtable oldTable;
|
||||
private Hashtable newTable;
|
||||
|
||||
/// Constructs a new, empty hashtable with the specified initial
|
||||
// capacity and the specified load factor.
|
||||
// Unlike a plain Hashtable, an LruHashtable will never grow or
|
||||
// shrink from this initial capacity.
|
||||
// @param initialCapacity the initial number of buckets
|
||||
// @param loadFactor a number between 0.0 and 1.0, it defines
|
||||
// the threshold for expiring old entries
|
||||
// @exception IllegalArgumentException If the initial capacity
|
||||
// is less than or equal to zero.
|
||||
// @exception IllegalArgumentException If the load factor is
|
||||
// less than or equal to zero.
|
||||
public LruHashtable( int initialCapacity, float loadFactor )
|
||||
{
|
||||
// We have to call a superclass constructor, but we're not actually
|
||||
// going to use it at all. The only reason we want to extend Hashtable
|
||||
// is for type conformance. So, make a parent hash table of minimum
|
||||
// size and then ignore it.
|
||||
super( 1 );
|
||||
|
||||
if ( initialCapacity <= 0 || loadFactor <= 0.0 )
|
||||
throw new IllegalArgumentException();
|
||||
this.loadFactor = loadFactor;
|
||||
threshold = (int) ( initialCapacity * loadFactor ) - 1;
|
||||
eachCapacity = initialCapacity / nBuckets + 1;
|
||||
oldTable = new Hashtable( eachCapacity, loadFactor );
|
||||
newTable = new Hashtable( eachCapacity, loadFactor );
|
||||
}
|
||||
|
||||
/// Constructs a new, empty hashtable with the specified initial
|
||||
// capacity.
|
||||
// Unlike a plain Hashtable, an LruHashtable will never grow or
|
||||
// shrink from this initial capacity.
|
||||
// @param initialCapacity the initial number of buckets
|
||||
public LruHashtable( int initialCapacity )
|
||||
{
|
||||
this( initialCapacity, 0.75F );
|
||||
}
|
||||
|
||||
/// Returns the number of elements contained in the hashtable.
|
||||
public int size()
|
||||
{
|
||||
return newTable.size() + oldTable.size();
|
||||
}
|
||||
|
||||
/// Returns true if the hashtable contains no elements.
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
/// Returns an enumeration of the hashtable's keys.
|
||||
// @see LruHashtable#elements
|
||||
// @see Enumeration
|
||||
public synchronized Enumeration keys()
|
||||
{
|
||||
return new LruHashtableEnumerator( oldTable, newTable, true );
|
||||
}
|
||||
|
||||
/// Returns an enumeration of the elements. Use the Enumeration methods
|
||||
// on the returned object to fetch the elements sequentially.
|
||||
// @see LruHashtable#keys
|
||||
// @see Enumeration
|
||||
public synchronized Enumeration elements()
|
||||
{
|
||||
return new LruHashtableEnumerator( oldTable, newTable, false );
|
||||
}
|
||||
|
||||
/// Returns true if the specified object is an element of the hashtable.
|
||||
// This operation is more expensive than the containsKey() method.
|
||||
// @param value the value that we are looking for
|
||||
// @exception NullPointerException If the value being searched
|
||||
// for is equal to null.
|
||||
// @see LruHashtable#containsKey
|
||||
public synchronized boolean contains( Object value )
|
||||
{
|
||||
if ( newTable.contains( value ) )
|
||||
return true;
|
||||
if ( oldTable.contains( value ) )
|
||||
{
|
||||
// We would like to move the object from the old table to the
|
||||
// new table. However, we need keys to re-add the objects, and
|
||||
// there's no good way to find all the keys for the given object.
|
||||
// We'd have to enumerate through all the keys and check each
|
||||
// one. Yuck. For now we just punt. Anyway, contains() is
|
||||
// probably not a commonly-used operation.
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Returns true if the collection contains an element for the key.
|
||||
// @param key the key that we are looking for
|
||||
// @see LruHashtable#contains
|
||||
public synchronized boolean containsKey( Object key )
|
||||
{
|
||||
if ( newTable.containsKey( key ) )
|
||||
return true;
|
||||
if ( oldTable.containsKey( key ) )
|
||||
{
|
||||
// Move object from old table to new table.
|
||||
Object value = oldTable.get( key );
|
||||
newTable.put( key, value );
|
||||
oldTable.remove( key );
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Gets the object associated with the specified key in the
|
||||
// hashtable.
|
||||
// @param key the specified key
|
||||
// @returns the element for the key or null if the key
|
||||
// is not defined in the hash table.
|
||||
// @see LruHashtable#put
|
||||
public synchronized Object get( Object key )
|
||||
{
|
||||
Object value;
|
||||
value = newTable.get( key );
|
||||
if ( value != null )
|
||||
return value;
|
||||
value = oldTable.get( key );
|
||||
if ( value != null )
|
||||
{
|
||||
// Move object from old table to new table.
|
||||
newTable.put( key, value );
|
||||
oldTable.remove( key );
|
||||
return value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Puts the specified element into the hashtable, using the specified
|
||||
// key. The element may be retrieved by doing a get() with the same key.
|
||||
// The key and the element cannot be null.
|
||||
// @param key the specified key in the hashtable
|
||||
// @param value the specified element
|
||||
// @exception NullPointerException If the value of the element
|
||||
// is equal to null.
|
||||
// @see LruHashtable#get
|
||||
// @return the old value of the key, or null if it did not have one.
|
||||
public synchronized Object put( Object key, Object value )
|
||||
{
|
||||
Object oldValue = newTable.put( key, value );
|
||||
if ( oldValue != null )
|
||||
return oldValue;
|
||||
oldValue = oldTable.get( key );
|
||||
if ( oldValue != null )
|
||||
oldTable.remove( key );
|
||||
else
|
||||
{
|
||||
if ( size() >= threshold )
|
||||
{
|
||||
// Rotate the tables.
|
||||
oldTable = newTable;
|
||||
newTable = new Hashtable( eachCapacity, loadFactor );
|
||||
}
|
||||
}
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
/// Removes the element corresponding to the key. Does nothing if the
|
||||
// key is not present.
|
||||
// @param key the key that needs to be removed
|
||||
// @return the value of key, or null if the key was not found.
|
||||
public synchronized Object remove( Object key )
|
||||
{
|
||||
Object oldValue = newTable.remove( key );
|
||||
if ( oldValue == null )
|
||||
oldValue = oldTable.remove( key );
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
/// Clears the hash table so that it has no more elements in it.
|
||||
public synchronized void clear()
|
||||
{
|
||||
newTable.clear();
|
||||
oldTable.clear();
|
||||
}
|
||||
|
||||
/// Creates a clone of the hashtable. A shallow copy is made,
|
||||
// the keys and elements themselves are NOT cloned. This is a
|
||||
// relatively expensive operation.
|
||||
public synchronized Object clone()
|
||||
{
|
||||
LruHashtable n = (LruHashtable) super.clone();
|
||||
n.newTable = (Hashtable) n.newTable.clone();
|
||||
n.oldTable = (Hashtable) n.oldTable.clone();
|
||||
return n;
|
||||
}
|
||||
|
||||
// toString() can be inherited.
|
||||
|
||||
}
|
||||
|
||||
|
||||
class LruHashtableEnumerator implements Enumeration
|
||||
{
|
||||
Enumeration oldEnum;
|
||||
Enumeration newEnum;
|
||||
boolean old;
|
||||
|
||||
LruHashtableEnumerator( Hashtable oldTable, Hashtable newTable, boolean keys )
|
||||
{
|
||||
if ( keys )
|
||||
{
|
||||
oldEnum = oldTable.keys();
|
||||
newEnum = newTable.keys();
|
||||
}
|
||||
else
|
||||
{
|
||||
oldEnum = oldTable.elements();
|
||||
newEnum = newTable.elements();
|
||||
}
|
||||
old = true;
|
||||
}
|
||||
|
||||
public boolean hasMoreElements()
|
||||
{
|
||||
boolean r;
|
||||
if ( old )
|
||||
{
|
||||
r = oldEnum.hasMoreElements();
|
||||
if ( ! r )
|
||||
{
|
||||
old = false;
|
||||
r = newEnum.hasMoreElements();
|
||||
}
|
||||
}
|
||||
else
|
||||
r = newEnum.hasMoreElements();
|
||||
return r;
|
||||
}
|
||||
|
||||
public Object nextElement()
|
||||
{
|
||||
if ( old )
|
||||
return oldEnum.nextElement();
|
||||
return newEnum.nextElement();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,313 +0,0 @@
|
|||
// CgiServlet - runs CGI programs
|
||||
//
|
||||
// Copyright (C)1996,1998 by Jef Poskanzer <jef@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/
|
||||
|
||||
package Acme.Serve;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.*;
|
||||
|
||||
/// Runs CGI programs.
|
||||
// <P>
|
||||
// Note: although many implementations of CGI set the working directory of
|
||||
// the subprocess to be the directory containing the executable file, the
|
||||
// CGI spec actually says nothing about the working directory. Since
|
||||
// Java has no method for setting the working directory, this implementation
|
||||
// does not set it.
|
||||
// <P>
|
||||
// <A HREF="/resources/classes/Acme/Serve/CgiServlet.java">Fetch the software.</A><BR>
|
||||
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
|
||||
// <P>
|
||||
// @see Acme.Serve.Serve
|
||||
|
||||
public class CgiServlet extends HttpServlet
|
||||
{
|
||||
|
||||
/// Returns a string containing information about the author, version, and
|
||||
// copyright of the servlet.
|
||||
public String getServletInfo()
|
||||
{
|
||||
return "runs CGI programs";
|
||||
}
|
||||
|
||||
/// Services a single request from the client.
|
||||
// @param req the servlet request
|
||||
// @param req the servlet response
|
||||
// @exception ServletException when an exception has occurred
|
||||
public void service( HttpServletRequest req, HttpServletResponse res ) throws ServletException, IOException
|
||||
{
|
||||
if ( ! ( req.getMethod().equalsIgnoreCase( "get" ) ||
|
||||
req.getMethod().equalsIgnoreCase( "post" ) ) )
|
||||
{
|
||||
res.sendError( HttpServletResponse.SC_NOT_IMPLEMENTED );
|
||||
return;
|
||||
}
|
||||
|
||||
String path = req.getServletPath();
|
||||
if ( path == null || path.charAt( 0 ) != '/' )
|
||||
{
|
||||
res.sendError( HttpServletResponse.SC_BAD_REQUEST );
|
||||
return;
|
||||
}
|
||||
if ( path.indexOf( "/../" ) != -1 || path.endsWith( "/.." ) )
|
||||
{
|
||||
res.sendError( HttpServletResponse.SC_FORBIDDEN );
|
||||
return;
|
||||
}
|
||||
|
||||
// Make a version without the leading /.
|
||||
String pathname = path.substring( 1 );
|
||||
if ( pathname.length() == 0 )
|
||||
pathname = "./";
|
||||
|
||||
dispatchPathname( req, res, path, pathname );
|
||||
}
|
||||
|
||||
|
||||
private void dispatchPathname( HttpServletRequest req, HttpServletResponse res, String path, String pathname ) throws IOException
|
||||
{
|
||||
String filename = pathname.replace( '/', File.separatorChar );
|
||||
if ( filename.charAt( filename.length() - 1 ) == File.separatorChar )
|
||||
filename = filename.substring( 0, filename.length() - 1 );
|
||||
filename = getServletContext().getRealPath( filename );
|
||||
File file = new File( filename );
|
||||
if ( file.exists() )
|
||||
serveFile( req, res, path, filename, file );
|
||||
else
|
||||
res.sendError( HttpServletResponse.SC_NOT_FOUND );
|
||||
}
|
||||
|
||||
|
||||
private void serveFile( HttpServletRequest req, HttpServletResponse res, String path, String filename, File file ) throws IOException
|
||||
{
|
||||
String queryString = req.getQueryString();
|
||||
int contentLength = req.getContentLength();
|
||||
int c;
|
||||
|
||||
log( "running " + path );
|
||||
|
||||
// Make argument list.
|
||||
Vector argVec = new Vector();
|
||||
argVec.addElement( filename );
|
||||
if ( queryString != null && queryString.indexOf( "=" ) == -1 )
|
||||
{
|
||||
Enumeration enum = new StringTokenizer( queryString, "+" );
|
||||
while ( enum.hasMoreElements() )
|
||||
argVec.addElement( (String) enum.nextElement() );
|
||||
}
|
||||
String argList[] = makeList( argVec );
|
||||
|
||||
// Make environment list.
|
||||
Vector envVec = new Vector();
|
||||
envVec.addElement( makeEnv(
|
||||
"PATH", "/usr/local/bin:/usr/ucb:/bin:/usr/bin" ) );
|
||||
envVec.addElement( makeEnv( "GATEWAY_INTERFACE", "CGI/1.1" ) );
|
||||
envVec.addElement( makeEnv(
|
||||
"SERVER_SOFTWARE", getServletContext().getServerInfo() ) );
|
||||
envVec.addElement( makeEnv( "SERVER_NAME", req.getServerName() ) );
|
||||
envVec.addElement( makeEnv(
|
||||
"SERVER_PORT", Integer.toString( req.getServerPort() ) ) );
|
||||
envVec.addElement( makeEnv( "REMOTE_ADDR", req.getRemoteAddr() ) );
|
||||
envVec.addElement( makeEnv( "REMOTE_HOST", req.getRemoteHost() ) );
|
||||
envVec.addElement( makeEnv( "REQUEST_METHOD", req.getMethod() ) );
|
||||
if ( contentLength != -1 )
|
||||
envVec.addElement( makeEnv(
|
||||
"CONTENT_LENGTH", Integer.toString( contentLength ) ) );
|
||||
if ( req.getContentType() != null )
|
||||
envVec.addElement( makeEnv(
|
||||
"CONTENT_TYPE", req.getContentType() ) );
|
||||
envVec.addElement( makeEnv( "SCRIPT_NAME", req.getServletPath() ) );
|
||||
if ( req.getPathInfo() != null )
|
||||
envVec.addElement( makeEnv( "PATH_INFO", req.getPathInfo() ) );
|
||||
if ( req.getPathTranslated() != null )
|
||||
envVec.addElement( makeEnv(
|
||||
"PATH_TRANSLATED", req.getPathTranslated() ) );
|
||||
if ( queryString != null )
|
||||
envVec.addElement( makeEnv( "QUERY_STRING", queryString ) );
|
||||
envVec.addElement( makeEnv( "SERVER_PROTOCOL", req.getProtocol() ) );
|
||||
if ( req.getRemoteUser() != null )
|
||||
envVec.addElement( makeEnv( "REMOTE_USER", req.getRemoteUser() ) );
|
||||
if ( req.getAuthType() != null )
|
||||
envVec.addElement( makeEnv( "AUTH_TYPE", req.getAuthType() ) );
|
||||
Enumeration enum = req.getHeaderNames();
|
||||
while ( enum.hasMoreElements() )
|
||||
{
|
||||
String name = (String) enum.nextElement();
|
||||
String value = req.getHeader( name );
|
||||
if ( value == null )
|
||||
value = "";
|
||||
envVec.addElement( makeEnv(
|
||||
"HTTP_" + name.toUpperCase().replace( '-', '_' ), value ) );
|
||||
}
|
||||
String envList[] = makeList( envVec );
|
||||
|
||||
// Start the command.
|
||||
Process proc = Runtime.getRuntime().exec( argList, envList );
|
||||
|
||||
try
|
||||
{
|
||||
// If it's a POST, copy the request data to the process.
|
||||
if ( req.getMethod().equalsIgnoreCase( "post" ) )
|
||||
{
|
||||
InputStream reqIn = req.getInputStream();
|
||||
OutputStream procOut = proc.getOutputStream();
|
||||
for ( int i = 0; i < contentLength; ++i )
|
||||
{
|
||||
c = reqIn.read();
|
||||
if ( c == -1 )
|
||||
break;
|
||||
procOut.write( c );
|
||||
}
|
||||
procOut.close();
|
||||
}
|
||||
|
||||
// Now read the response from the process.
|
||||
BufferedReader procIn = new BufferedReader( new InputStreamReader(
|
||||
proc.getInputStream() ) );
|
||||
OutputStream resOut = res.getOutputStream();
|
||||
// Some of the headers have to be intercepted and handled.
|
||||
boolean firstLine = true;
|
||||
while ( true )
|
||||
{
|
||||
String line = procIn.readLine();
|
||||
if ( line == null )
|
||||
break;
|
||||
line = line.trim();
|
||||
if ( line.equals( "" ) )
|
||||
break;
|
||||
int colon = line.indexOf( ":" );
|
||||
if ( colon == -1 )
|
||||
{
|
||||
// No colon. If it's the first line, parse it for status.
|
||||
if ( firstLine )
|
||||
{
|
||||
StringTokenizer tok = new StringTokenizer( line, " " );
|
||||
try
|
||||
{
|
||||
switch( tok.countTokens() )
|
||||
{
|
||||
case 2:
|
||||
tok.nextToken();
|
||||
res.setStatus(
|
||||
Integer.parseInt( tok.nextToken() ) );
|
||||
break;
|
||||
case 3:
|
||||
tok.nextToken();
|
||||
res.setStatus(
|
||||
Integer.parseInt( tok.nextToken() ),
|
||||
tok.nextToken() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch ( NumberFormatException ignore ) {}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No colon and it's not the first line? Ignore.
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// There's a colon. Check for certain special headers.
|
||||
String name = line.substring( 0, colon );
|
||||
String value = line.substring( colon + 1 ).trim();
|
||||
if ( name.equalsIgnoreCase( "Status" ) )
|
||||
{
|
||||
StringTokenizer tok = new StringTokenizer( value, " " );
|
||||
try
|
||||
{
|
||||
switch( tok.countTokens() )
|
||||
{
|
||||
case 1:
|
||||
res.setStatus(
|
||||
Integer.parseInt( tok.nextToken() ) );
|
||||
break;
|
||||
case 2:
|
||||
res.setStatus(
|
||||
Integer.parseInt( tok.nextToken() ),
|
||||
tok.nextToken() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch ( NumberFormatException ignore ) {}
|
||||
}
|
||||
else if ( name.equalsIgnoreCase( "Content-type" ) )
|
||||
{
|
||||
res.setContentType( value );
|
||||
}
|
||||
else if ( name.equalsIgnoreCase( "Content-length" ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
res.setContentLength( Integer.parseInt( value ) );
|
||||
}
|
||||
catch ( NumberFormatException ignore ) {}
|
||||
}
|
||||
else if ( name.equalsIgnoreCase( "Location" ) )
|
||||
{
|
||||
res.setStatus(
|
||||
HttpServletResponse.SC_MOVED_TEMPORARILY );
|
||||
res.setHeader( name, value );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not a special header. Just set it.
|
||||
res.setHeader( name, value );
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copy the rest of the data uninterpreted.
|
||||
Acme.Utils.copyStream( procIn, resOut );
|
||||
procIn.close();
|
||||
resOut.close();
|
||||
}
|
||||
catch ( IOException e )
|
||||
{
|
||||
//res.sendError( HttpServletResponse.SC_INTERNAL_SERVER_ERROR );
|
||||
// There's some weird bug in Java, when reading from a Process
|
||||
// you get a spurious IOException. We have to ignore it.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static String makeEnv( String name, String value )
|
||||
{
|
||||
return name + "=" + value;
|
||||
}
|
||||
|
||||
|
||||
private static String[] makeList( Vector vec )
|
||||
{
|
||||
String list[] = new String[vec.size()];
|
||||
for ( int i = 0; i < vec.size(); ++i )
|
||||
list[i] = (String) vec.elementAt( i );
|
||||
return list;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,316 +0,0 @@
|
|||
// FileServlet - servlet similar to a standard httpd
|
||||
//
|
||||
// Copyright (C)1996,1998 by Jef Poskanzer <jef@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/
|
||||
|
||||
package Acme.Serve;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.text.*;
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.*;
|
||||
|
||||
/// Servlet similar to a standard httpd.
|
||||
// <P>
|
||||
// Implements the "GET" and "HEAD" methods for files and directories.
|
||||
// Handles index.html.
|
||||
// Redirects directory URLs that lack a trailing /.
|
||||
// Handles If-Modified-Since and Range.
|
||||
// <P>
|
||||
// <A HREF="/resources/classes/Acme/Serve/FileServlet.java">Fetch the software.</A><BR>
|
||||
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
|
||||
// <P>
|
||||
// @see Acme.Serve.Serve
|
||||
|
||||
public class FileServlet extends HttpServlet
|
||||
{
|
||||
|
||||
// We keep a single throttle table for all instances of the servlet.
|
||||
// Normally there is only one instance; the exception is subclasses.
|
||||
static Acme.WildcardDictionary throttleTab = null;
|
||||
|
||||
/// Constructor.
|
||||
public FileServlet()
|
||||
{
|
||||
}
|
||||
|
||||
/// Constructor with throttling.
|
||||
// @param throttles filename containing throttle settings
|
||||
// @see ThrottledOutputStream
|
||||
public FileServlet( String throttles ) throws IOException
|
||||
{
|
||||
this();
|
||||
readThrottles( throttles );
|
||||
}
|
||||
|
||||
private void readThrottles( String throttles ) throws IOException
|
||||
{
|
||||
Acme.WildcardDictionary newThrottleTab =
|
||||
ThrottledOutputStream.parseThrottleFile( throttles );
|
||||
if ( throttleTab == null )
|
||||
throttleTab = newThrottleTab;
|
||||
else
|
||||
{
|
||||
// Merge the new one into the old one.
|
||||
Enumeration keys = newThrottleTab.keys();
|
||||
Enumeration elements = newThrottleTab.elements();
|
||||
while ( keys.hasMoreElements() )
|
||||
{
|
||||
Object key = keys.nextElement();
|
||||
Object element = elements.nextElement();
|
||||
throttleTab.put( key, element );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a string containing information about the author, version, and
|
||||
// copyright of the servlet.
|
||||
public String getServletInfo()
|
||||
{
|
||||
return "servlet similar to a standard httpd";
|
||||
}
|
||||
|
||||
|
||||
/// Services a single request from the client.
|
||||
// @param req the servlet request
|
||||
// @param req the servlet response
|
||||
// @exception ServletException when an exception has occurred
|
||||
public void service( HttpServletRequest req, HttpServletResponse res ) throws ServletException, IOException
|
||||
{
|
||||
boolean headOnly;
|
||||
if ( req.getMethod().equalsIgnoreCase( "get" ) )
|
||||
headOnly = false;
|
||||
else if ( ! req.getMethod().equalsIgnoreCase( "head" ) )
|
||||
headOnly = true;
|
||||
else
|
||||
{
|
||||
res.sendError( HttpServletResponse.SC_NOT_IMPLEMENTED );
|
||||
return;
|
||||
}
|
||||
|
||||
String path = req.getServletPath();
|
||||
if ( path == null || path.charAt( 0 ) != '/' )
|
||||
{
|
||||
res.sendError( HttpServletResponse.SC_BAD_REQUEST );
|
||||
return;
|
||||
}
|
||||
if ( path.indexOf( "/../" ) != -1 || path.endsWith( "/.." ) )
|
||||
{
|
||||
res.sendError( HttpServletResponse.SC_FORBIDDEN );
|
||||
return;
|
||||
}
|
||||
|
||||
// Make a version without the leading /.
|
||||
String pathname = path.substring( 1 );
|
||||
if ( pathname.length() == 0 )
|
||||
pathname = "./";
|
||||
|
||||
dispatchPathname( req, res, headOnly, path, pathname );
|
||||
}
|
||||
|
||||
|
||||
private void dispatchPathname( HttpServletRequest req, HttpServletResponse res, boolean headOnly, String path, String pathname ) throws IOException
|
||||
{
|
||||
String filename = pathname.replace( '/', File.separatorChar );
|
||||
if ( filename.charAt( filename.length() - 1 ) == File.separatorChar )
|
||||
filename = filename.substring( 0, filename.length() - 1 );
|
||||
filename = getServletContext().getRealPath( filename );
|
||||
File file = new File( filename );
|
||||
if ( file.exists() )
|
||||
{
|
||||
if ( ! file.isDirectory() )
|
||||
serveFile( req, res, headOnly, path, filename, file );
|
||||
else
|
||||
{
|
||||
if ( pathname.charAt( pathname.length() - 1 ) != '/' )
|
||||
redirectDirectory( req, res, path, file );
|
||||
else
|
||||
{
|
||||
String indexFilename =
|
||||
filename + File.separatorChar + "index.html";
|
||||
File indexFile = new File( indexFilename );
|
||||
if ( indexFile.exists() )
|
||||
serveFile(
|
||||
req, res, headOnly, path, indexFilename,
|
||||
indexFile );
|
||||
else
|
||||
serveDirectory(
|
||||
req, res, headOnly, path, filename, file );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( pathname.endsWith( "/index.html" ) )
|
||||
dispatchPathname(
|
||||
req, res, headOnly, path,
|
||||
pathname.substring( 0, pathname.length() - 10 ) );
|
||||
else if ( pathname.equals( "index.html" ) )
|
||||
dispatchPathname( req, res, headOnly, path, "./" );
|
||||
else
|
||||
res.sendError( HttpServletResponse.SC_NOT_FOUND );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void serveFile( HttpServletRequest req, HttpServletResponse res, boolean headOnly, String path, String filename, File file ) throws IOException
|
||||
{
|
||||
// log( "getting " + path );
|
||||
if ( ! file.canRead() )
|
||||
{
|
||||
res.sendError( HttpServletResponse.SC_FORBIDDEN );
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle If-Modified-Since.
|
||||
res.setStatus( HttpServletResponse.SC_OK );
|
||||
long lastMod = file.lastModified();
|
||||
String ifModSinceStr = req.getHeader( "If-Modified-Since" );
|
||||
long ifModSince = -1;
|
||||
if ( ifModSinceStr != null )
|
||||
{
|
||||
int semi = ifModSinceStr.indexOf( ';' );
|
||||
if ( semi != -1 )
|
||||
ifModSinceStr = ifModSinceStr.substring( 0, semi );
|
||||
try
|
||||
{
|
||||
ifModSince =
|
||||
DateFormat.getDateInstance().parse( ifModSinceStr ).getTime();
|
||||
}
|
||||
catch ( Exception ignore ) {}
|
||||
}
|
||||
if ( ifModSince != -1 && ifModSince >= lastMod )
|
||||
{
|
||||
res.setStatus( HttpServletResponse.SC_NOT_MODIFIED );
|
||||
headOnly = true;
|
||||
}
|
||||
|
||||
String rangeStr = req.getHeader( "Range" );
|
||||
if ( rangeStr != null )
|
||||
{
|
||||
//!!!
|
||||
}
|
||||
|
||||
res.setContentType( getServletContext().getMimeType( filename ) );
|
||||
res.setContentLength( (int) file.length() );
|
||||
res.setDateHeader( "Last-modified", lastMod );
|
||||
OutputStream out = res.getOutputStream();
|
||||
if ( ! headOnly )
|
||||
{
|
||||
// Check throttle.
|
||||
if ( throttleTab != null )
|
||||
{
|
||||
ThrottleItem throttleItem =
|
||||
(ThrottleItem) throttleTab.get( path );
|
||||
if ( throttleItem != null )
|
||||
{
|
||||
// !!! Need to account for multiple simultaneous fetches.
|
||||
out = new ThrottledOutputStream(
|
||||
out, throttleItem.getMaxBps() );
|
||||
}
|
||||
}
|
||||
|
||||
InputStream in = new FileInputStream( file );
|
||||
copyStream( in, out );
|
||||
in.close();
|
||||
}
|
||||
out.close();
|
||||
}
|
||||
|
||||
/// Copy a file from in to out.
|
||||
// Sub-classes can override this in order to do filtering of some sort.
|
||||
public void copyStream( InputStream in, OutputStream out ) throws IOException
|
||||
{
|
||||
Acme.Utils.copyStream( in, out );
|
||||
}
|
||||
|
||||
|
||||
private void serveDirectory( HttpServletRequest req, HttpServletResponse res, boolean headOnly, String path, String filename, File file ) throws IOException
|
||||
{
|
||||
log( "indexing " + path );
|
||||
if ( ! file.canRead() )
|
||||
{
|
||||
res.sendError( HttpServletResponse.SC_FORBIDDEN );
|
||||
return;
|
||||
}
|
||||
res.setStatus( HttpServletResponse.SC_OK );
|
||||
res.setContentType( "text/html" );
|
||||
OutputStream out = res.getOutputStream();
|
||||
if ( ! headOnly )
|
||||
{
|
||||
PrintStream p = new PrintStream( new BufferedOutputStream( out ) );
|
||||
p.println( "<HTML><HEAD>" );
|
||||
p.println( "<TITLE>Index of " + path + "</TITLE>" );
|
||||
p.println( "</HEAD><BODY BGCOLOR=\"#ffffff\">" );
|
||||
p.println( "<H2>Index of " + path + "</H2>" );
|
||||
p.println( "<PRE>" );
|
||||
p.println( "mode bytes last-changed name" );
|
||||
p.println( "<HR>" );
|
||||
String[] names = file.list();
|
||||
Acme.Utils.sortStrings( names );
|
||||
for ( int i = 0; i < names.length; ++i )
|
||||
{
|
||||
String aFilename = filename + File.separatorChar + names[i];
|
||||
File aFile = new File( aFilename );
|
||||
String aFileType;
|
||||
if ( aFile.isDirectory() )
|
||||
aFileType = "d";
|
||||
else if ( aFile.isFile() )
|
||||
aFileType = "-";
|
||||
else
|
||||
aFileType = "?";
|
||||
String aFileRead = ( aFile.canRead() ? "r" : "-" );
|
||||
String aFileWrite = ( aFile.canWrite() ? "w" : "-" );
|
||||
String aFileExe = "-";
|
||||
String aFileSize = Acme.Fmt.fmt( aFile.length(), 8 );
|
||||
String aFileDate =
|
||||
Acme.Utils.lsDateStr( new Date( aFile.lastModified() ) );
|
||||
String aFileDirsuf = ( aFile.isDirectory() ? "/" : "" );
|
||||
String aFileSuf = ( aFile.isDirectory() ? "/" : "" );
|
||||
p.println(
|
||||
aFileType + aFileRead + aFileWrite + aFileExe +
|
||||
" " + aFileSize + " " + aFileDate + " " +
|
||||
"<A HREF=\"" + names[i] + aFileDirsuf + "\">" +
|
||||
names[i] + aFileSuf + "</A>" );
|
||||
}
|
||||
p.println( "</PRE>" );
|
||||
p.println( "<HR>" );
|
||||
ServeUtils.writeAddress( p );
|
||||
p.println( "</BODY></HTML>" );
|
||||
p.flush();
|
||||
}
|
||||
out.close();
|
||||
}
|
||||
|
||||
|
||||
protected void redirectDirectory( HttpServletRequest req, HttpServletResponse res, String path, File file ) throws IOException
|
||||
{
|
||||
log( "redirecting " + path );
|
||||
res.sendRedirect( path + "/" );
|
||||
}
|
||||
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
// SampleServlet - trivial servlet
|
||||
//
|
||||
// Copyright (C) 1996 by Jef Poskanzer <jef@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/
|
||||
|
||||
package Acme.Serve;
|
||||
|
||||
import java.io.*;
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.*;
|
||||
|
||||
/// Trivial servlet.
|
||||
// <P>
|
||||
// <A HREF="/resources/classes/Acme/Serve/SampleServlet.java">Fetch the software.</A><BR>
|
||||
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
|
||||
|
||||
public class SampleServlet extends HttpServlet
|
||||
{
|
||||
|
||||
/// Returns a string containing information about the author, version, and
|
||||
// copyright of the servlet.
|
||||
public String getServletInfo()
|
||||
{
|
||||
return "trivial servlet";
|
||||
}
|
||||
|
||||
/// Services a single request from the client.
|
||||
// @param req the servlet request
|
||||
// @param req the servlet response
|
||||
// @exception ServletException when an exception has occurred
|
||||
public void service( HttpServletRequest req, HttpServletResponse res ) throws ServletException, IOException
|
||||
{
|
||||
log( "called" );
|
||||
res.setStatus( HttpServletResponse.SC_OK );
|
||||
res.setContentType( "text/html" );
|
||||
ServletOutputStream p = res.getOutputStream();
|
||||
p.println( "<HTML><HEAD>" );
|
||||
p.println( "<TITLE>Sample Servlet Output</TITLE>" );
|
||||
p.println( "</HEAD><BODY>" );
|
||||
p.println( "<H2>Sample Servlet Output</H2>" );
|
||||
p.println( "<P>Output from a sample servlet." );
|
||||
p.println( "</BODY></HTML>" );
|
||||
p.flush();
|
||||
p.close();
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,95 +0,0 @@
|
|||
// ServeUtils - static utilities for minimal Java HTTP server
|
||||
//
|
||||
// Copyright (C) 1996 by Jef Poskanzer <jef@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/
|
||||
|
||||
package Acme.Serve;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.*;
|
||||
|
||||
/// Static utilities for minimal Java HTTP server.
|
||||
// <P>
|
||||
// <A HREF="/resources/classes/Acme/Serve/ServeUtils.java">Fetch the software.</A><BR>
|
||||
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
|
||||
|
||||
public class ServeUtils
|
||||
{
|
||||
|
||||
// Server identification.
|
||||
public static final String serverName = "Helma";
|
||||
// we're using the server version from helma.main.Server class.
|
||||
// public static final String serverVersion = "1.2 p1";
|
||||
public static final String serverUrl = "http://helma.org/";
|
||||
|
||||
/// Write a standard-format HTML address for this server.
|
||||
public static void writeAddress( OutputStream o ) throws IOException
|
||||
{
|
||||
PrintStream p = new PrintStream( o );
|
||||
p.println(
|
||||
"<ADDRESS><A HREF=\"" + serverUrl + "\">" +
|
||||
serverName + " " + helma.main.Server.version + "</A></ADDRESS>" );
|
||||
}
|
||||
|
||||
|
||||
/// Get a cookie of a given name.
|
||||
public static String getCookie( HttpServletRequest req, String name )
|
||||
{
|
||||
String h = req.getHeader( "Cookie" );
|
||||
if ( h == null )
|
||||
return null;
|
||||
StringTokenizer st = new StringTokenizer( h, "; " );
|
||||
while ( st.hasMoreTokens() )
|
||||
{
|
||||
String tk = st.nextToken();
|
||||
int eq = tk.indexOf( '=' );
|
||||
String n, v;
|
||||
if ( eq == -1 )
|
||||
{
|
||||
n = tk;
|
||||
v = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
n = tk.substring( 0, eq );
|
||||
v = tk.substring( eq + 1 );
|
||||
}
|
||||
if ( name.equals( n ) )
|
||||
return v;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Set a cookie.
|
||||
public static void setCookie( HttpServletResponse res, String name, String value )
|
||||
{
|
||||
res.setHeader( "Set-Cookie", name + "=" + value );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,132 +0,0 @@
|
|||
// TestServlet - simple servlet that tests the Servlet API
|
||||
//
|
||||
// Copyright (C) 1996,1998 by Jef Poskanzer <jef@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/
|
||||
|
||||
package Acme.Serve;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.*;
|
||||
|
||||
/// Simple servlet that tests the Servlet API.
|
||||
// Sample output:
|
||||
// <PRE>
|
||||
// getContentLength(): -1
|
||||
// getContentType(): null
|
||||
// getProtocol(): HTTP/1.0
|
||||
// getScheme(): http
|
||||
// getServerName(): www.acme.com
|
||||
// getServerPort(): 1234
|
||||
// getRemoteAddr(): 192.100.66.1
|
||||
// getRemoteHost(): acme.com
|
||||
// getMethod(): GET
|
||||
// getRequestURI(): http://www.acme.com:1234/TestServlet?foo=bar
|
||||
// getServletPath(): /TestServlet
|
||||
// getPathInfo(): null
|
||||
// getPathTranslated(): null
|
||||
// getQueryString(): foo=bar
|
||||
// getRemoteUser(): null
|
||||
// getAuthType(): null
|
||||
//
|
||||
// Parameters:
|
||||
// foo = bar
|
||||
//
|
||||
// Header:
|
||||
// accept: text/html, image/gif, image/jpeg, *; q=.2
|
||||
// user-agent: Java1.0.2
|
||||
// </PRE>
|
||||
// <A HREF="/resources/classes/Acme/Serve/TestServlet.java">Fetch the software.</A><BR>
|
||||
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
|
||||
|
||||
public class TestServlet extends HttpServlet
|
||||
{
|
||||
|
||||
/// Returns a string containing information about the author, version, and
|
||||
// copyright of the servlet.
|
||||
public String getServletInfo()
|
||||
{
|
||||
return "simple servlet that tests the Servlet API";
|
||||
}
|
||||
|
||||
/// Services a single request from the client.
|
||||
// @param req the servlet request
|
||||
// @param req the servlet response
|
||||
// @exception ServletException when an exception has occurred
|
||||
public void service( HttpServletRequest req, HttpServletResponse res ) throws ServletException, IOException
|
||||
{
|
||||
Enumeration en;
|
||||
log( "called" );
|
||||
res.setStatus( HttpServletResponse.SC_OK );
|
||||
res.setContentType( "text/html" );
|
||||
ServletOutputStream p = res.getOutputStream();
|
||||
p.println( "<HTML><HEAD>" );
|
||||
p.println( "<TITLE>Test Servlet Output</TITLE>" );
|
||||
p.println( "</HEAD><BODY>" );
|
||||
p.println( "<H2>Test Servlet Output</H2>" );
|
||||
p.println( "<HR>" );
|
||||
p.println( "<PRE>" );
|
||||
p.println( "getContentLength(): " + req.getContentLength() );
|
||||
p.println( "getContentType(): " + req.getContentType() );
|
||||
p.println( "getProtocol(): " + req.getProtocol() );
|
||||
p.println( "getScheme(): " + req.getScheme() );
|
||||
p.println( "getServerName(): " + req.getServerName() );
|
||||
p.println( "getServerPort(): " + req.getServerPort() );
|
||||
p.println( "getRemoteAddr(): " + req.getRemoteAddr() );
|
||||
p.println( "getRemoteHost(): " + req.getRemoteHost() );
|
||||
p.println( "getMethod(): " + req.getMethod() );
|
||||
p.println( "getRequestURI(): " + req.getRequestURI() );
|
||||
p.println( "getServletPath(): " + req.getServletPath() );
|
||||
p.println( "getPathInfo(): " + req.getPathInfo() );
|
||||
p.println( "getPathTranslated(): " + req.getPathTranslated() );
|
||||
p.println( "getQueryString(): " + req.getQueryString() );
|
||||
p.println( "getRemoteUser(): " + req.getRemoteUser() );
|
||||
p.println( "getAuthType(): " + req.getAuthType() );
|
||||
p.println( "" );
|
||||
p.println( "Parameters:" );
|
||||
en = req.getParameterNames();
|
||||
while ( en.hasMoreElements() )
|
||||
{
|
||||
String name = (String) en.nextElement();
|
||||
p.println( " " + name + " = " + req.getParameter( name ) );
|
||||
}
|
||||
p.println( "" );
|
||||
p.println( "Headers:" );
|
||||
en = req.getHeaderNames();
|
||||
while ( en.hasMoreElements() )
|
||||
{
|
||||
String name = (String) en.nextElement();
|
||||
p.println( " " + name + ": " + req.getHeader( name ) );
|
||||
}
|
||||
p.println( "</PRE>" );
|
||||
p.println( "<HR>" );
|
||||
p.println( "</BODY></HTML>" );
|
||||
p.flush();
|
||||
p.close();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
// ThrottleItem - data item for ThrottledOutputStream
|
||||
//
|
||||
// Copyright (C) 1996 by Jef Poskanzer <jef@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/
|
||||
|
||||
package Acme.Serve;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
/// Data item for ThrottledOutputStream.
|
||||
// <P>
|
||||
// <A HREF="/resources/classes/Acme/Serve/ThrottleItem.java">Fetch the software.</A><BR>
|
||||
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
|
||||
|
||||
public class ThrottleItem
|
||||
{
|
||||
|
||||
private long maxBps;
|
||||
|
||||
/// Constructor.
|
||||
public ThrottleItem( long maxBps )
|
||||
{
|
||||
this.maxBps = maxBps;
|
||||
}
|
||||
|
||||
public long getMaxBps()
|
||||
{
|
||||
return maxBps;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,156 +0,0 @@
|
|||
// ThrottledOutputStream - output stream with throttling
|
||||
//
|
||||
// Copyright (C)1996,1998 by Jef Poskanzer <jef@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/
|
||||
|
||||
package Acme.Serve;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
/// Output stream with throttling.
|
||||
// <P>
|
||||
// Restricts output to a specified rate. Also includes a static utility
|
||||
// routine for parsing a file of throttle settings.
|
||||
// <P>
|
||||
// <A HREF="/resources/classes/Acme/Serve/ThrottledOutputStream.java">Fetch the software.</A><BR>
|
||||
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
|
||||
|
||||
public class ThrottledOutputStream extends FilterOutputStream
|
||||
{
|
||||
|
||||
/// Parses a standard throttle file.
|
||||
// <P>
|
||||
// A throttle file lets you set maximum byte rates on filename patterns.
|
||||
// The format of the throttle file is very simple. A # starts a
|
||||
// comment, and the rest of the line is ignored. Blank lines are ignored.
|
||||
// The rest of the lines should consist of a pattern, whitespace, and a
|
||||
// number. The pattern is a simple shell-style filename pattern, using
|
||||
// ? and *, or multiple such patterns separated by |.
|
||||
// <P>
|
||||
// The numbers in the file are byte rates, specified in units of bytes
|
||||
// per second. For comparison, a v.32b/v.42b modem gives about
|
||||
// 1500/2000 B/s depending on compression, a double-B-channel ISDN line
|
||||
// about 12800 B/s, and a T1 line is about 150000 B/s.
|
||||
// <P>
|
||||
// Example:
|
||||
// <BLOCKQUOTE><PRE>
|
||||
// # throttle file for www.acme.com
|
||||
// * 100000 # limit total web usage to 2/3 of our T1
|
||||
// *.jpg|*.gif 50000 # limit images to 1/3 of our T1
|
||||
// *.mpg 20000 # and movies to even less
|
||||
// jef/* 20000 # jef's pages are too popular
|
||||
// </PRE></BLOCKQUOTE>
|
||||
// <P>
|
||||
// The routine returns a WildcardDictionary. Do a lookup in this
|
||||
// dictionary using a filename, and you'll get back a ThrottleItem
|
||||
// containing the corresponding byte rate.
|
||||
public static Acme.WildcardDictionary parseThrottleFile( String filename ) throws IOException
|
||||
{
|
||||
Acme.WildcardDictionary wcd = new Acme.WildcardDictionary();
|
||||
BufferedReader br = new BufferedReader( new FileReader( filename ) );
|
||||
while ( true )
|
||||
{
|
||||
String line = br.readLine();
|
||||
if ( line == null )
|
||||
break;
|
||||
int i = line.indexOf( '#' );
|
||||
if ( i != -1 )
|
||||
line = line.substring( 0, i );
|
||||
line = line.trim();
|
||||
if ( line.length() == 0 )
|
||||
continue;
|
||||
String[] words = Acme.Utils.splitStr( line );
|
||||
if ( words.length != 2 )
|
||||
throw new IOException( "malformed throttle line: " + line );
|
||||
try
|
||||
{
|
||||
wcd.put(
|
||||
words[0], new ThrottleItem( Long.parseLong( words[1] ) ) );
|
||||
}
|
||||
catch ( NumberFormatException e )
|
||||
{
|
||||
throw new IOException(
|
||||
"malformed number in throttle line: " + line );
|
||||
}
|
||||
}
|
||||
br.close();
|
||||
return wcd;
|
||||
}
|
||||
|
||||
|
||||
private long maxBps;
|
||||
private long bytes;
|
||||
private long start;
|
||||
|
||||
/// Constructor.
|
||||
public ThrottledOutputStream( OutputStream out, long maxBps )
|
||||
{
|
||||
super( out );
|
||||
this.maxBps = maxBps;
|
||||
bytes = 0;
|
||||
start = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
private byte[] oneByte = new byte[1];
|
||||
|
||||
/// Writes a byte. This method will block until the byte is actually
|
||||
// written.
|
||||
// @param b the byte to be written
|
||||
// @exception IOException if an I/O error has occurred
|
||||
public void write( int b ) throws IOException
|
||||
{
|
||||
oneByte[0] = (byte) b;
|
||||
write( oneByte, 0, 1 );
|
||||
}
|
||||
|
||||
/// Writes a subarray of bytes.
|
||||
// @param b the data to be written
|
||||
// @param off the start offset in the data
|
||||
// @param len the number of bytes that are written
|
||||
// @exception IOException if an I/O error has occurred
|
||||
public void write( byte b[], int off, int len ) throws IOException
|
||||
{
|
||||
// Check the throttle.
|
||||
bytes += len;
|
||||
long elapsed = System.currentTimeMillis() - start;
|
||||
long bps = bytes * 1000L / elapsed;
|
||||
if ( bps > maxBps )
|
||||
{
|
||||
// Oops, sending too fast.
|
||||
long wakeElapsed = bytes * 1000L / maxBps;
|
||||
try
|
||||
{
|
||||
Thread.sleep( wakeElapsed - elapsed );
|
||||
}
|
||||
catch ( InterruptedException ignore ) {}
|
||||
}
|
||||
|
||||
// Write the bytes.
|
||||
out.write( b, off, len );
|
||||
}
|
||||
|
||||
}
|
1053
src/Acme/Utils.java
1053
src/Acme/Utils.java
File diff suppressed because it is too large
Load diff
|
@ -1,147 +0,0 @@
|
|||
// WildcardDictionary - a dictionary with wildcard lookups
|
||||
//
|
||||
// Copyright (C) 1996 by Jef Poskanzer <jef@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/
|
||||
|
||||
package Acme;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/// A dictionary with wildcard lookups.
|
||||
// <P>
|
||||
// The keys in this dictionary are wildcard patterns. When you do a get(),
|
||||
// the string you pass in is matched against all the patterns, and the
|
||||
// first match is returned.
|
||||
// <P>
|
||||
// The wildcard matcher is fairly simple, it implements * meaning any
|
||||
// string, ? meaning any single character, and | separating multiple
|
||||
// patterns. All other characters must match literally.
|
||||
// <P>
|
||||
// <A HREF="/resources/classes/Acme/WildcardDictionary.java">Fetch the software.</A><BR>
|
||||
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
|
||||
// <P>
|
||||
// @see Acme.Utils#match
|
||||
|
||||
public class WildcardDictionary extends Dictionary
|
||||
{
|
||||
|
||||
private Vector keys;
|
||||
private Vector elements;
|
||||
|
||||
/// Constructor.
|
||||
public WildcardDictionary()
|
||||
{
|
||||
keys = new Vector();
|
||||
elements = new Vector();
|
||||
}
|
||||
|
||||
/// Returns the number of elements contained within the dictionary.
|
||||
public int size()
|
||||
{
|
||||
return elements.size();
|
||||
}
|
||||
|
||||
/// Returns true if the dictionary contains no elements.
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
/// Returns an enumeration of the dictionary's keys.
|
||||
public Enumeration keys()
|
||||
{
|
||||
return keys.elements();
|
||||
}
|
||||
|
||||
/// Returns an enumeration of the elements. Use the Enumeration methods
|
||||
// on the returned object to fetch the elements sequentially.
|
||||
public Enumeration elements()
|
||||
{
|
||||
return elements.elements();
|
||||
}
|
||||
|
||||
/// Gets the object associated with the specified key in the dictionary.
|
||||
// The key is assumed to be a String, which is matched against
|
||||
// the wildcard-pattern keys in the dictionary.
|
||||
// @param key the string to match
|
||||
// @returns the element for the key, or null if there's no match
|
||||
// @see Acme.Utils#match
|
||||
public synchronized Object get( Object key )
|
||||
{
|
||||
String sKey = (String) key;
|
||||
for ( int i = 0; i < keys.size(); ++i )
|
||||
{
|
||||
String thisKey = (String) keys.elementAt( i );
|
||||
if ( Acme.Utils.match( thisKey, sKey ) )
|
||||
return elements.elementAt( i );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Puts the specified element into the Dictionary, using the specified
|
||||
// key. The element may be retrieved by doing a get() with the same
|
||||
// key. The key and the element cannot be null.
|
||||
// @param key the specified wildcard-pattern key
|
||||
// @param value the specified element
|
||||
// @return the old value of the key, or null if it did not have one.
|
||||
// @exception NullPointerException If the value of the specified
|
||||
// element is null.
|
||||
public synchronized Object put( Object key, Object element )
|
||||
{
|
||||
int i = keys.indexOf( key );
|
||||
if ( i != -1 )
|
||||
{
|
||||
Object oldElement = elements.elementAt( i );
|
||||
elements.setElementAt( element, i );
|
||||
return oldElement;
|
||||
}
|
||||
else
|
||||
{
|
||||
keys.addElement( key );
|
||||
elements.addElement( element );
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes the element corresponding to the key. Does nothing if the
|
||||
// key is not present.
|
||||
// @param key the key that needs to be removed
|
||||
// @return the value of key, or null if the key was not found.
|
||||
public synchronized Object remove( Object key )
|
||||
{
|
||||
int i = keys.indexOf( key );
|
||||
if ( i != -1 )
|
||||
{
|
||||
Object oldElement = elements.elementAt( i );
|
||||
keys.removeElementAt( i );
|
||||
elements.removeElementAt( i );
|
||||
return oldElement;
|
||||
}
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
/* Generated By:JJTree: Do not edit this line. ASTAllocationExpression.java */
|
||||
|
||||
package FESI.AST;
|
||||
|
||||
import FESI.Parser.*;
|
||||
|
||||
public class ASTAllocationExpression extends SimpleNode {
|
||||
public ASTAllocationExpression(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public ASTAllocationExpression(EcmaScript p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(int id) {
|
||||
return new ASTAllocationExpression(id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(EcmaScript p, int id) {
|
||||
return new ASTAllocationExpression(p, id);
|
||||
}
|
||||
|
||||
/** Accept the visitor. **/
|
||||
public Object jjtAccept(EcmaScriptVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
/* Generated By:JJTree: Do not edit this line. ASTAndExpressionSequence.java */
|
||||
|
||||
package FESI.AST;
|
||||
|
||||
import FESI.Parser.*;
|
||||
|
||||
public class ASTAndExpressionSequence extends SimpleNode {
|
||||
public ASTAndExpressionSequence(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public ASTAndExpressionSequence(EcmaScript p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(int id) {
|
||||
return new ASTAndExpressionSequence(id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(EcmaScript p, int id) {
|
||||
return new ASTAndExpressionSequence(p, id);
|
||||
}
|
||||
|
||||
/** Accept the visitor. **/
|
||||
public Object jjtAccept(EcmaScriptVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
/* Generated By:JJTree: Do not edit this line. ASTAssignmentExpression.java */
|
||||
|
||||
package FESI.AST;
|
||||
|
||||
import FESI.Parser.*;
|
||||
|
||||
public class ASTAssignmentExpression extends SimpleNode {
|
||||
public ASTAssignmentExpression(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public ASTAssignmentExpression(EcmaScript p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(int id) {
|
||||
return new ASTAssignmentExpression(id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(EcmaScript p, int id) {
|
||||
return new ASTAssignmentExpression(p, id);
|
||||
}
|
||||
|
||||
/** Accept the visitor. **/
|
||||
public Object jjtAccept(EcmaScriptVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
/* Generated By:JJTree: Do not edit this line. ASTBinaryExpressionSequence.java */
|
||||
|
||||
package FESI.AST;
|
||||
|
||||
import FESI.Parser.*;
|
||||
|
||||
public class ASTBinaryExpressionSequence extends SimpleNode {
|
||||
public ASTBinaryExpressionSequence(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public ASTBinaryExpressionSequence(EcmaScript p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(int id) {
|
||||
return new ASTBinaryExpressionSequence(id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(EcmaScript p, int id) {
|
||||
return new ASTBinaryExpressionSequence(p, id);
|
||||
}
|
||||
|
||||
/** Accept the visitor. **/
|
||||
public Object jjtAccept(EcmaScriptVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
/* Generated By:JJTree: Do not edit this line. ASTBreakStatement.java */
|
||||
|
||||
package FESI.AST;
|
||||
|
||||
import FESI.Parser.*;
|
||||
|
||||
public class ASTBreakStatement extends SimpleNode {
|
||||
public ASTBreakStatement(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public ASTBreakStatement(EcmaScript p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(int id) {
|
||||
return new ASTBreakStatement(id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(EcmaScript p, int id) {
|
||||
return new ASTBreakStatement(p, id);
|
||||
}
|
||||
|
||||
/** Accept the visitor. **/
|
||||
public Object jjtAccept(EcmaScriptVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
/* Generated By:JJTree: Do not edit this line. ASTCompositeReference.java */
|
||||
|
||||
package FESI.AST;
|
||||
|
||||
import FESI.Parser.*;
|
||||
|
||||
public class ASTCompositeReference extends SimpleNode {
|
||||
public ASTCompositeReference(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public ASTCompositeReference(EcmaScript p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(int id) {
|
||||
return new ASTCompositeReference(id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(EcmaScript p, int id) {
|
||||
return new ASTCompositeReference(p, id);
|
||||
}
|
||||
|
||||
/** Accept the visitor. **/
|
||||
public Object jjtAccept(EcmaScriptVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
/* Generated By:JJTree: Do not edit this line. ASTConditionalExpression.java */
|
||||
|
||||
package FESI.AST;
|
||||
|
||||
import FESI.Parser.*;
|
||||
|
||||
public class ASTConditionalExpression extends SimpleNode {
|
||||
public ASTConditionalExpression(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public ASTConditionalExpression(EcmaScript p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(int id) {
|
||||
return new ASTConditionalExpression(id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(EcmaScript p, int id) {
|
||||
return new ASTConditionalExpression(p, id);
|
||||
}
|
||||
|
||||
/** Accept the visitor. **/
|
||||
public Object jjtAccept(EcmaScriptVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
/* Generated By:JJTree: Do not edit this line. ASTContinueStatement.java */
|
||||
|
||||
package FESI.AST;
|
||||
|
||||
import FESI.Parser.*;
|
||||
|
||||
public class ASTContinueStatement extends SimpleNode {
|
||||
public ASTContinueStatement(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public ASTContinueStatement(EcmaScript p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(int id) {
|
||||
return new ASTContinueStatement(id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(EcmaScript p, int id) {
|
||||
return new ASTContinueStatement(p, id);
|
||||
}
|
||||
|
||||
/** Accept the visitor. **/
|
||||
public Object jjtAccept(EcmaScriptVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
/* Generated By:JJTree: Do not edit this line. ASTEmptyExpression.java */
|
||||
|
||||
package FESI.AST;
|
||||
|
||||
import FESI.Parser.*;
|
||||
|
||||
public class ASTEmptyExpression extends SimpleNode {
|
||||
public ASTEmptyExpression(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public ASTEmptyExpression(EcmaScript p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(int id) {
|
||||
return new ASTEmptyExpression(id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(EcmaScript p, int id) {
|
||||
return new ASTEmptyExpression(p, id);
|
||||
}
|
||||
|
||||
/** Accept the visitor. **/
|
||||
public Object jjtAccept(EcmaScriptVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
/* Generated By:JJTree: Do not edit this line. ASTExpressionList.java */
|
||||
|
||||
package FESI.AST;
|
||||
|
||||
import FESI.Parser.*;
|
||||
|
||||
public class ASTExpressionList extends SimpleNode {
|
||||
public ASTExpressionList(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public ASTExpressionList(EcmaScript p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(int id) {
|
||||
return new ASTExpressionList(id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(EcmaScript p, int id) {
|
||||
return new ASTExpressionList(p, id);
|
||||
}
|
||||
|
||||
/** Accept the visitor. **/
|
||||
public Object jjtAccept(EcmaScriptVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
/* Generated By:JJTree: Do not edit this line. ASTForInStatement.java */
|
||||
|
||||
package FESI.AST;
|
||||
|
||||
import FESI.Parser.*;
|
||||
|
||||
public class ASTForInStatement extends SimpleNode {
|
||||
public ASTForInStatement(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public ASTForInStatement(EcmaScript p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(int id) {
|
||||
return new ASTForInStatement(id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(EcmaScript p, int id) {
|
||||
return new ASTForInStatement(p, id);
|
||||
}
|
||||
|
||||
/** Accept the visitor. **/
|
||||
public Object jjtAccept(EcmaScriptVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
/* Generated By:JJTree: Do not edit this line. ASTForStatement.java */
|
||||
|
||||
package FESI.AST;
|
||||
|
||||
import FESI.Parser.*;
|
||||
|
||||
public class ASTForStatement extends SimpleNode {
|
||||
public ASTForStatement(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public ASTForStatement(EcmaScript p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(int id) {
|
||||
return new ASTForStatement(id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(EcmaScript p, int id) {
|
||||
return new ASTForStatement(p, id);
|
||||
}
|
||||
|
||||
/** Accept the visitor. **/
|
||||
public Object jjtAccept(EcmaScriptVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
/* Generated By:JJTree: Do not edit this line. ASTForVarInStatement.java */
|
||||
|
||||
package FESI.AST;
|
||||
|
||||
import FESI.Parser.*;
|
||||
|
||||
public class ASTForVarInStatement extends SimpleNode {
|
||||
public ASTForVarInStatement(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public ASTForVarInStatement(EcmaScript p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(int id) {
|
||||
return new ASTForVarInStatement(id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(EcmaScript p, int id) {
|
||||
return new ASTForVarInStatement(p, id);
|
||||
}
|
||||
|
||||
/** Accept the visitor. **/
|
||||
public Object jjtAccept(EcmaScriptVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
/* Generated By:JJTree: Do not edit this line. ASTForVarStatement.java */
|
||||
|
||||
package FESI.AST;
|
||||
|
||||
import FESI.Parser.*;
|
||||
|
||||
public class ASTForVarStatement extends SimpleNode {
|
||||
public ASTForVarStatement(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public ASTForVarStatement(EcmaScript p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(int id) {
|
||||
return new ASTForVarStatement(id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(EcmaScript p, int id) {
|
||||
return new ASTForVarStatement(p, id);
|
||||
}
|
||||
|
||||
/** Accept the visitor. **/
|
||||
public Object jjtAccept(EcmaScriptVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
/* Generated By:JJTree: Do not edit this line. ASTFormalParameterList.java */
|
||||
|
||||
package FESI.AST;
|
||||
|
||||
import FESI.Parser.*;
|
||||
|
||||
public class ASTFormalParameterList extends SimpleNode {
|
||||
public ASTFormalParameterList(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public ASTFormalParameterList(EcmaScript p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(int id) {
|
||||
return new ASTFormalParameterList(id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(EcmaScript p, int id) {
|
||||
return new ASTFormalParameterList(p, id);
|
||||
}
|
||||
|
||||
/** Accept the visitor. **/
|
||||
public Object jjtAccept(EcmaScriptVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
|
||||
// JMCL
|
||||
public String [] getArguments() {
|
||||
int n = jjtGetNumChildren();
|
||||
String [] args = new String[n];
|
||||
for (int i=0; i<n; i++) {
|
||||
ASTIdentifier idNode = (ASTIdentifier) (jjtGetChild(i));
|
||||
args[i]=idNode.getName();
|
||||
}
|
||||
return args;
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
/* Generated By:JJTree: Do not edit this line. ASTFunctionCallParameters.java */
|
||||
|
||||
package FESI.AST;
|
||||
|
||||
import FESI.Parser.*;
|
||||
|
||||
public class ASTFunctionCallParameters extends SimpleNode {
|
||||
public ASTFunctionCallParameters(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public ASTFunctionCallParameters(EcmaScript p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(int id) {
|
||||
return new ASTFunctionCallParameters(id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(EcmaScript p, int id) {
|
||||
return new ASTFunctionCallParameters(p, id);
|
||||
}
|
||||
|
||||
/** Accept the visitor. **/
|
||||
public Object jjtAccept(EcmaScriptVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
/* Generated By:JJTree: Do not edit this line. ASTFunctionDeclaration.java */
|
||||
|
||||
package FESI.AST;
|
||||
|
||||
import FESI.Parser.*;
|
||||
|
||||
public class ASTFunctionDeclaration extends SimpleNode {
|
||||
|
||||
private String sourceString = null;
|
||||
|
||||
public ASTFunctionDeclaration(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public ASTFunctionDeclaration(EcmaScript p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(int id) {
|
||||
return new ASTFunctionDeclaration(id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(EcmaScript p, int id) {
|
||||
return new ASTFunctionDeclaration(p, id);
|
||||
}
|
||||
|
||||
/** Accept the visitor. **/
|
||||
public Object jjtAccept(EcmaScriptVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
|
||||
public void setSourceString(String sourceString) {
|
||||
this.sourceString = sourceString;
|
||||
}
|
||||
public String getSourceString() {
|
||||
return sourceString;
|
||||
}
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
/* Generated By:JJTree: Do not edit this line. ASTIdentifier.java */
|
||||
|
||||
package FESI.AST;
|
||||
|
||||
import FESI.Parser.*;
|
||||
|
||||
public class ASTIdentifier extends SimpleNode {
|
||||
|
||||
private String identifierName = null;
|
||||
private int hash = 0;
|
||||
|
||||
public ASTIdentifier(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public ASTIdentifier(EcmaScript p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(int id) {
|
||||
return new ASTIdentifier(id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(EcmaScript p, int id) {
|
||||
return new ASTIdentifier(p, id);
|
||||
}
|
||||
|
||||
/** Accept the visitor. **/
|
||||
public Object jjtAccept(EcmaScriptVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
|
||||
// JMCL
|
||||
public void setName(String identifierName) {
|
||||
this.identifierName = identifierName.intern(); // to lower number of strings
|
||||
this.hash = identifierName.hashCode();
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return hash;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return identifierName;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "<" + identifierName + ">";
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue