Advanced image processing in java

zhaozj2021-02-11  222

BBS Shuimu Tsinghua Station: Essence

Sender: Midi (Midi), News District: Java

Title: Advanced Image Processing in Java

Japanese issue: sat Sep 7 16:09:51 1996

Chapter Project

Class Organization

How it works

Fractals and the Mandelbrot Set

Using the applets

The Mandelbrot Class

CalculateFilterNotify Interface

CalculatorProducer Interface

The CalculatorFilter Class

The CalculatorImage Class

The Mandelapp Class

The MandelzoomApp Class

The Bmpimage Class

Automatic Documentation with javadoc

Summary

Advanced Image Processing

THIS Chapter's Project, One That Views The Mandelbrot Set, Gives You

Examples of some of the more advanced conceces you have been introducesd to.

The Mandelbrot Set Is The Most Specular Example of Fractals, Which

REPRESENTS One of the Hot Scientific Topics of Recent Years. with the

Applets in this chapter, you can view or generate an Original Mandelbrot

Image and zoom in and out of it to produce new portions of the set.

Since the Mandelbrot Set Can take a while to generate 梤 Equiring millions of

Calculations 梚 T Gives You a chance to Combine Threads and Image Filters SO

You can view the set as it's being generated. You might alsowant to save

The Mandelbrot Image. The BmpClass, Introduces, That Converts

A Bmp Formatted File Into A Java Image, IS Enhanced So you can save the

Mandelbrot Data as a bmp file. You can the view or modify it with any Tool

That Can Handle The Bmp FineL, The Chapter Concludes by Showing

How you can auto-docuument the source of a java class Into a html file. this

Can Be Viewed by a Browser and Has Links to Other Classes.

Since You Have Already Been Introduces to Most Aspects of Java, this

Chapter Will Jump Straight Into the Project. Topics Will Be Introduces.

Chapter Project

There Are Actually Two Applets in this chapter. The first applet,

Mandelapp, IS Used to Generate A Full Mandelbrot Set. The Tools and BMP

File product by this applet area input inten the second applet, called

MandelzoomApp. This applet displays a masterbrot set, the allows you to

Zoom (Magnify) Portions of the set so you can inspect ITS Fractal

Qualities. You can also return to previous images and zoom INTO Another

Area.

If you want to use the file-saving capabilities of this program, you need

To Run IT from Something That Does Not Prevent File Saving, Such as The

AppletViewer Program. You Can Run The Program in a Browser Like Netscape,

IT WILL BE ABLE to Do Everything Except Save The Images as Files.

Class ORGANIZATION

Table 14.1 lists the classes Used in this chapter's applets. Most of The CHE

Classes Are New, So Their Names Are Set in Boldface Type. EXISTING CLASSES

That were modified harve their names italicized.

Table 14.1. Mandelbrot Project Classes and interfaces.

Class / Interface Description

Bmpimage for Bmp-Image Conversion.

Calculatorfilter ImageFilter That Products Updates of Images AS AS UPDATES OF IMAGES As

Are generated.

CalculatorfilterNotifyInterface That Defines Ways An ImageFilter CAN

Receive data updates.

CalculatorImage Used to Tie a Calculation Object, An Image, And A

Calculatorfilter together.

CalculatorProducer Interface That Defines a Mechanism for Establishing

How an imagefilter can update a calculation class.

Mandelapp An Applet That Produces A Full Mandelbrot Image and

Lets you save it to a file.

Mandelentry Accessor Class for Keeping Information About A

Mandelbrot Image.a Thread That Produces Mandelbrot Data for THE

Specified parameters. IT IMPLEMENTS

Mandelbrot Calculator-Producter to Get Started by A Filter. IT

Uses CalculatorFilterNotify to Update A Filter with

New Data.

Mandelzoomapp An Applet That Displays The Full Mandelbrot Set and

You to zoom in and out of the set.

HOW it works

Because The Mandelbrot Set Can Take Quite a While To Generate, IT WAS

Designed by Combining a Calculation Thread with an iMage Filter So you can

See the results as the it is generated. However, Understanding How The

Classes Intergend Is A Little Tricky. Figure 14.1 shows the workflow

Involved in producing a masterbrot image. Understanding this flow is the

Key to understanding this project.

Figure 14.1. Workflow of Producting a Mandelbrot Image.

The Process Begins When An Applet Displaying Mandelbrot Sets Constructs A

Mandelbrot Object. (In this Project, The Two Applet Classes Are ManDelapp)

And MandelzoomApp.) The Mandelbrot Object, In Turn, Creates An Instance of

THE CALCULATORIMAGE CLASS. The Mandelbrot Set Passs Itself as a part of

The CalculatorImage Constructor. It is reference as a CalculatorProducer

Object, An Interface That The Mandelbrot Class Implements. This Interface

Implementation will be used to communicate with the image filter.

In the next step, the applet requests a masterbrot image. This is initiated

By Calling the getImage () Method of the Mandelbrot Object, Which in Turn

Leads to a call to a like-named method of the calculatorimage object. at

This Point, The CalculatorImage Object First Creates A Color Palette B

Using an instance of the ImagecolorModel Class, Then Creates A

MemoryImagesource Object. This Object, Which Implements ImageProducer, Produces An Image Initialized to All Zeros (Black); It's Combined with an AN

Instance of the Calculatorfilter Class to Produce A FilteredImagesource.

When the memoryImagesource Object Produces ITS Empty Image, IT IS Passed To

The CalculatorFilter, Which Takes The Opportunity To Produce The Calculate

IT Does this by kicking off the thread of the image to be

Calculated. The CalculatorFilter Doesn't Know That It Is The Mandelbrot Set

That's Calculated 梚 T Just Knows That Some Calculation Needs To Occur in The

CalculatorProducer Object In Which It Has A Reference.

Once the Mandelbrot Thread Is Started, It Begins The Long Calculation To

Product a Mandelbrot Set. WHENEVER IT FINISHES A Section of the Set, IT

Notifier the filter with new data through the calculatorfilternotify

Interface. The Filter, In Turn, Lets The Viewing Applet Know That It HAS

New Data to Display by Updating The Corresponding ImageConsumer, Which

Causes the applet's imageupdate () Method to Be Called. This Causes A

Repaint, and the new image data to be displayed. this process refeats unsteil

The full is understand.

As you have probably observed, this is a completed process. Although the the

Mechanics of Image Processing Were Introduces, IT Doesn't hurt

To have another example. The Calculator Classes Here Are ManT to Provide a

Generic Approach Toward Manipulating Images That Need Long Calculation.

You Can Replace The Mandelbrot Class with Some Other Calculation Thread

That Implements CalculatorProducer, And Everything Should Work. A Good

Exercise Would Be To Replace Mandelbrot with Another Fractal Calculation OR

(i Found That ReplacingMandelbrot with a julia fractal class calculation WAS VERY EASY).

Fractals and the masterbrot set

Before going intels of the classes That make Up this Project,

IT's Worth Spending a Couple of Moments To Understand What's Behind The

Images produced by the masterelbrot class.

In the 1970s, Benoit Mandelbrot At IBM WAS Using Computers To Study Curves

Generated by Items of Complex Formulas. He Found That these Curves Had

Unusual Characteristics, One of Which IS Called Self-Similarity. The Curves

Have a series of patterns That Repeat Themsels atpected More

Closely.

One of the characteristics of the curves mandelbrot studied Was That They

Could Be Described As Having a CERTAIN DIMENSIONAL Quality That Mandelbrot

TERMED "Fractal." One of the Fractals That Mandelbrot Was Investigating IS

Called julia sets. by mapping the set in a certin way, mandelbrot calme

Across A Set That Turned Out To include All the julia sets 梐 Kind of A

Master Set That Was Deemed The Mandelbrot Set. This Set Has Several

Spectacular Features, All of Them Beautiful. The Most Striking of these IS

ITS Self-Similarity and a extraordinary sensitivity to initial conditions.

As you cost the masterelbrot set, you will be amazed by Both ITS Seeming

Chaos and Exquisite Order.

Figure 14.2 Shows The Famous Mandelbrot Set, Produced by this Chapter's

Mandelapp applet. Figure show the Kind of Chapter Shows the Kind of CHAPTER

Images That Appear When You Zoom Into Various Places in this set. The

Mandelbrot Set Is Based On a Seeding, Shown in ITERATED FUNCTION

Formula 14.1.

Figure 14.2. The full mandelbrot set image.

Formula 14.1. Formula for Calculating The Mandelbrot Set.zn 1 = Zn2 C

In Formula 14.1, Z and C Are Complex Numbers. The Mandelbrot Set IS

Concerned with what happens when z0 is zero and c is set over a range of

Values. The real part of c is set to the x-axis, and the complex portion

Corresponds to the y-axis. a color is mapped to each point based on how

Quickly the corresponding value of c causes the ity to reach

Infinity. The Process of "Zooming" in And out of the masterelbrot set is

Equivalent to Defining What Ranges of C Are Going to Be Explored. IT IS

Amazing That Something So Simple Can Yield Patterns so Sophistated!

-------------------------------------------------- -------------------------

[Image] Note: if you are more interested in chaos and fractals, There Are A

Lot of Places to Turn. Chaos by James Gleick (Penguin, 1987) Is A Layman's

Introduction to the ideas and discoveries That Gave Rise to Chaos THEORY

And The Study of Fractals. Mandelbrot's The Fractal Geometry of Nature

(W.H. Freeman, 1983) Lays Out His Ideas On Fractals and Nature. For A

Rigorous Mathematical Treatment of Fractals, See The Beautiful BOOK

Fractals Everywhere (Academic Press, 1988), Written by one of the foremost

Figures in Fractals, Michael Barnsley. Among Other Things, Barnsley Is A

Major Innovator on Now Use Fractal Geometrics to Achieve High Rates of

Data compression.

For A NO-Nonsense Approach To Writing Programs That Display Fractals, See

Fractal Programming In C by Roger T. Stevens (M & T Books, 1989). The

Algorithms for the Mandelbrot Set Were Developed from this book. The c

Programs in this book map Very Easily to java 梕 xcept for the underlying

Graphics Tools, Which Were Developed for MS-DOS. HOWEVER, The ImageCalculation Classes Created in this Chapter Aim To Fill this Gap. with

Stevens's book and these classes, you shouth becomle to move his c cot

Right over to java and begin exploring the amazing world of fractals!

-------------------------------------------------- -------------------------

USING THE Applets

There are two applets in this chapter. The first applet, Mandelapp,

GENERATES The Full Mandelbrot Set. This Will Take a little while, depending

ON Your Computer; for Example, ON A 486DX2-50 PC, IT Takes a Couple of

MINUTES. WHEN The Image Is Complete, Indicated by a Message on The

Browser's Status Bar, You CAN Save The Image To a bmp formatted file by

Clicking Anywhere On The Applet's Display Area. The File Will Be Called

Mandel.bmp. Remember to Run this applet from a program, Such as

AppletViewer, That Lets Applets Write to Disk.

The Other Applet, Mandelappzoom, Is More Full-Featured. It Begins by

Loading the mandelbrot bitmap specified by an HTML Applet Parameter Tag.

The Default Mandel1 Corresponds To a Bmp File and a data file That

Specifies X-Y Parameter Values ​​梚 NCluded On this Book's CD-ROM.

ONCE The Image IS Up, You Can Pick Regions To Zoom in By Clicking ON A

Point in the image, damning the mouse to the endpoint of the region

You want to display. Enterz or z on the keyboard, and the applet create

The image representing the new region of the masterelbrot set. The key to

This applet is patience! The Calculation CAN Take a Little While To Set Up

And Run. The applet tries to help your bar by Updating the status bar

To indeicate what is going on. Furthermore, The Image Filter Displays Each

Column of the set as the calculation advance.you might select a region That Doesn't Appear to have newything

TO Show when Zoom on It. You CAN Stop A Calculation In The Middle By

Entering a or a on the keyboard. The applet will take a moment to wrap up,

But the you can proked .hen you are having problem

Interesting Region to Look At, Try Increasing The size of the highlight

Area. this Will Yield a bigger area there is generated, giving you a better

Feel for what stay be inSpected. You get the best results by working with

Medium-sized highlighted region, rather tour or small one.

Figure 14.3 to 14.6 show what thing of the zoomed-in regions of there

Mandelbrot Set Look Like. Figure 14.3 Is A Large Area Picked Above THE

Black "Circles" of The Full Mandelbrot Set; Figure 14.5 Explores An Area

Between Two of The Black Areas. The Richest Displays See Seem to Occur At The

Boundaries of the Black Areas. The Black Color INDICES That That

Particular Value Takes a long time to reach infinity. Consequently, There

Are Also The Regions Take The Longest To Calculate. You get What you

Pay for!

Figure 14.3. Zoom in over black regions of phase 14.2.

Figure 14.4. Zoom in.

Figure 14.5. Zoom in Between Black Regions of Figure 14.2.

Figure 14.6. Zoom in y 14.5.

The zoom applet maintains a cache of processed images So you can way

And forth among the processed images. Table 14.2 Lists the text cots for

Using the zoom applet.

Table 14.2. Codes for Controlling The Mandelbrot Applet.

Characters Action

A OR A Abort Current Mandelbrot Calculation.

B or B Go to Previous Image.

F or f go to next image.

C or C Remove All But Full Image from Memory.N or N Go To Next Image.

P or P Go to Previous Image.

S or s save the current image to a bmp file prefixed by TempMandel.

Z or z zoom in on currently highlighted region.

The Mandelbrot Class

The Mandelbrot Class, Shown in Listing 14.1, Calculates The Mandelbrot Set.

IT Implements The Runnable Interface, So It Can Run as a Thread, And Also

Implements the CalculatorProducer Interface, SO IT CAN Update An Image

FILTER OF Progress Made in Its Calculation.

There Are Two Constructors for the Mandelbrot Class. The Default

Constructor Produces The Full Mandelbrot Set and Takes The Dimensions of

The Image to Calculate. The Real and Imagine Variables in the constructors in THE Constructors

And the run () Method Are used to map the x-y axis to the real and imaginary

Portions of c in formula 14.1. The Other constructor is buy to zoom in on ON

A user-defined mapping.

A Couple of the Other Variables Are Worth Noting. The Variable

Maxiterations represents when to stop calculating a number. if this number,

Set to 512, IS Reached, THE Starting Value of C Takes a long time to

Head Toward Infinity. The Variable MaxSize Is A Simpleer Indicator of How HOW

Quickly The Current Value Grows. How The Current Calculation IS Related To

THESE VARIABLES IS MAPPED TO A Specific Color; The Higher The Number, The

SLOWER The Growth. if You Have A Fast Computer, You Can Adjust these

Variables to get a richer or duller expression of the masterbrot set.

Once the thread is start (by The CalculatorFilter Object Through The Calculator

START () Method, The Run () Method Calculates The Mandelbrot Values ​​and

Stores a Color Corresponding to The Growth Rate of The Current Complex

Number Into a Pixel Array. When a Column IS Complete, IT Uses ThecalculatefilterNotify To Let The Related Filter Know That New Data Has Been

Producesd. it also checks to seehe a 百 百 al al a a.

Note How it synchronizes the stopcalc boolean Object in the run () and

Stop () Methods.

The Calculation Can take A While to Complete. Still, IT Takes Only a Couple

Of minutes on a 486-based pc. this Performance is quite a testament to

Java! With Other Interpreted, Portable Languages ​​you Would Probably Be

Tempted to use the reset button BECAUSE The Calculation Would Take SO

Long. with java you get fast vict visual feedback on how the set unfolds.

A good excercise is to save any partially development Mandelbrot Set; you can

Use the savebmp () Method here. You Also Need Some Kind of Data File To

Indicate Where The Calculation WAS Stopped.

Listing 14.1. The Mandelbrot Class.

Import java.awt.image. *;

Import Java.awt.Image;

Import java.lang. *;

// Class for Producing a Mandelbrot Set Image ...

Public Class Mandelbrot Implements Runnable, CalculatorProducer {

Int width; // The Dimensions of the Image ...

INT height;

CalculatefilterNotify Filter; // Keeps TRACK OF Image Production ...

Int Pix []; // Pixels Used to Construction ...

CalculatorImage img;

// General Mandelbrot Parameters ...

INT NUMCOLORS = 256;

INT MaxItems = 512;

INT maxSize = 4;

Double Realmax, Imaginemax, Realmin, Imaginemin; // Define Sizes To Build ...

Private Boolean Stopcalc = New Boolean (false); // Stop Calculation ...

// Create Standard Mandelbrot Set

Public Mandelbrot (int width, int hotht) {

THIS.WIDTH = Width;

THISHEIGHT = HEIGHT;

Realmax = 1.20; // Default Starting Sizes ...

Realmin = -2.0; imaginemax = 1.20;

Imaginemin = -1.20;

}

// Create Zoom of Mandelbrot Set

Public Mandelbrot (int Width, Int Height, Double Realmax, Double Realmin,

Double Imaginemax, Double Imaginemin) {

THIS.WIDTH = Width;

THISHEIGHT = HEIGHT;

this.realmax = realmax; // default starting sizes ...

THIALMIN = Realmin;

this.imaginemax = imaginemax;

THIS.IMAGINEMIN = Imaginemin;

}

// Start Product Producing The Mandelbrot Set ...

Public image getimage () {

IMG = New CalculatorImage (Width, Height, this)

Return img.getimage ();

}

// Start Thread to Produce Data ...

Public void start (int Pix [], CalculateFilterNotify filter) {

THIS.PIX = PIX;

THIS.FILTER = Filter;

New thread (this) .start ();

}

// See if User Wants to Stop Before Completion ...

Public void stop () {

Synchronized (stopcalc) {

Stopcalc = Boolean.true;

}

System.out.println ("GOT STOP!");

}

// CREATE DATA HERE ...

Public void run () {

// Establish Mandelbrot Parameters ...

Double Q [] = new double [height];

// pixdata is for image filter file updates ...

INT PIXDATA [] = new int [height];

Double P, DIFFP, DIFFQ, X, Y, X2, Y2;

Int Color, Row, Column, INDEX

System.out.println ("Realmax =" Realmax "Realmin =" Realmin

"Imaginemax =" imaginemax "imaginemin =" imaginemin);

// setup Calculation Parameters ...

DIFFP = (Realmax - Realmin) / (Width);

DIFFQ = (Imaginemax - Imaginemin) / (HEIGHT);

Q [0] = imaginemax;

COLOR = 0;

// setup delta parameters ...

For (ROW = 1; ROW

Q [ROW] = Q [ROW-1] - DIFFQ;

P = realmin;

// Start Calculating!

For (Column = 0; Column

X = y = x2 = y2 = 0.0;

COLOR = 1;

While (Color

((x2 y2)

X2 = x * x;

Y2 = y * y;

Y = (2 * x * y) q [ROW];

X = x2 - y2 p;

Color;

}

// Plot ...

INDEX = (ROW * WIDTH) Column;

PIX [INDEX] = (int);

Pixdata [ROW] = PIX [INDEX];

} // end row

// Update Column After Each Iteration ...

Filter.DataUpdateColumn (Column, Pixdata);

P = DIFFP;

// see if we become told to stop ...

Synchronized (stopcalc) {

IF (stopcalc == boolean.true) {

COLUMN = Width;

System.out.println ("Run: Got Stop Calc!");

}

} // end sync

} // end col

// Tell Filter That We're Done Producing Data ...

System.out.Println ("Filter: Data Complete!");

Filter.setComplete ();

}

// Save the Mandelbrot Set as a bmp file ...

Public void savebmp (string filename) {

IMG.SaveBMP (filename, pix);

}

}

CalculatefilterNotify Interface

The CalculatefilterNotify Interface Defines The Methods Needed to Update An

Image filter That Works with a Calculation Thread. AS Shown in Listing

14.2, The "Data" Methods Are Used for Conveying a New Batch of Data To The

Filter. The setcomplete () Method Indicates That The Calculation Are

COMPLETE.

Listing 14.2. The CalculateFilterNotify Interface.

/ * Interface for defining methods for Updating A

Calulator filter ... * /

Public interface calculatefilterNotify {

Public void dataupdate (); // update everything ...

Public void DataUpdaterow (int Row); // update ONE ROW ...

Public void DataUpdateColumn (int COL, INT PIXDATA []); // Update OneColumn ...

Public void setcomplete ();

}

CalculatorProducer Interface

The CalculatorProducer Interface, AS Shown in Listing 14.3, Defines The

Method Called WHEN A Calculation Filter Is Ready To Kick Off A Thread That

Products The data used to generate an image. The calculatefilternotify

Object passed to the start () Method Is Called by The Producer WHENEVER NEW

Data is yielded.

Listing 14.3. The CalculatorProducer Interface.

// Interface for a Large Calculation To Product Image ...

Interface CalculatorProducer {

Public Void Start (int Pix [], CalculatefilterNotify CF);

}

The CalculatorFilter Class

The Calculatorfilter Class in Listing 14.4 Is A Subclass of ImageFilter.

ITS Purpose Is To Receive Image Data Product by Some Long Calculation

(Like the Mandelbrot Set) and update any consumer of the the new data's

Image. The CalculatorProducer, Indicated by Variable CP, IS What Produces

The data.

Since The ImageFilter Class Was Explained in Detail in Part III, Issues

Related to this class area NOT REPEATED Here. However, a couple of things

SHOULD BE POINTED OUT. WHEN The Image Is First Requested, The Filter Gets

The Dimensions The Consumer Wants by a call of the setdimensions () Method.

At this point, The Calculatorfilter Will Allocate a Large array Holding The

Color Values ​​for Each Pixel.

When the Original ImageProducer Is Finished Creating The Original Image,

The filter's imagecomplete () Method Will Be Called, But The Filter Needs To

Override this method. in this case, The Calculatorfilter Will Start THE

CalculatorProducer Thread, Passing It The Pixel Array To Put in ITS

Updates. WHENEVER THE CALCULATORPROducer Has New Data, IT Will Call ONE OFTHE FORMRETHODS Specified by The CalculateFilterNotify Interface:

DataUpdate (), DataUpdaterow (), DataUpdateColumn (), or setcomplete ().

DataUpdateColumn () Method Is Called by The Mandelbrot Calculation Since IT

Operates on a column basis. in Each of these Cases, The Filter Updates the

ApproPriate Consumer Pixels by Using The Setpixels () Method, THEN CALLS The

Consumer's imagecomplete () Method to indeicate the nature of the change. for

The Three "Data" Methods, The Updates Are Only Partial, SO A

SINGLEFRAMEDONE FLAG IS SENT. The setcomplete () Method, on The Other Hand,

Indicates That Everything is Complete, SO IT Sets a staticimagedone flag.

Listing 14.4. The CalculatorFilter Class.

Import java.awt.image. *;

Import Java.awt.Image;

Import java.awt.toolkit;

Import java.lang. *;

Public Class CalculatorFilter Extends ImageFilter

Implements CalculateFilterNotify {

Private ColorModel DefaultrGBModel;

Private int width, height;

Private int Pix [];

Private Boolean Complete = FALSE;

PRIVATE CALCULATORPRODUCER CP;

Private boolean cpstart = false;

Public CalculatorFilter (ColorModel CM, CalculatorProducer CP) {

Defaultrgbmodel = cm;

THIS.CP = CP;

}

Public void setdimensions (int width, int hotht) {

THIS.WIDTH = Width;

THISHEIGHT = HEIGHT;

PIX = new int [width * height];

Consumer.SetDimensions (Width, Height);

}

Public void setcolormodel (ColorModel model) {

Consumer.SetColormodel (DefaultRGBModel);

}

Public void setHints (int hints) {

Consumer.SetHints (ImageConSumer.randompixelORDER);

}

Public Void ResendTopdownLTRight (ImageProducer P) {

}

Public void setpixels (int X, int y, int w, int h, color mod moDel, int pixels [], int off, int scansize) {

}

Public void imagecomplete (int status) {

IF (! cpstart) {

cpstart = true;

DataUpdate (); // show empty pixels ...

Cp.Start (PIX, this);

} // end if

IF (Complete)

Consumer.ImageComplete (ImageConsumer.StaticImaged);

}

// Called Externally to Notify That More Data Has Been Created

// Notify Consumer So They Can Repaint ...

Public void dataupdate () {

Consumer.Setpixels (0, 0, Width, Height,

DefaultrGBModel, PIX, 0, Width;

Consumer.ImageComplete (ImageConsumer.singleframedone);

}

// External Call to Update a Specific Pixel Row ...

Public void dataupdaterow (int in) {

// the key thing thing is the second to last parameter (offset)

// Which States where to start getting data from the pipe array ...

Consumer.Setpixels (0, Row, Width, 1,

Defaultrgbmodel, PIX, (Width * Row), Width;

Consumer.ImageComplete (ImageConsumer.singleframedone);

}

// External Call to Update a Specific Pixel Column ...

Public void DataUpdateColumn (int COL, INT PIXDATA []) {

// the key thing thing is the second to last parameter (offset)

// Which States where to start getting data from the pipe array ...

Consumer.Setpixels (Col, 0, 1, Height,

DefaultrGBModel, Pixdata, 0, 1);

Consumer.ImageComplete (ImageConsumer.singleframedone);

}

// Called from External Calculating Program When Data HAS

// Finished Being Calculate ...

Public void setcomplete () {

Complete = true;

Consumer.Setpixels (0, 0, Width, Height,

DefaultrGBModel, PIX, 0, Width;

Consumer.ImageComplete (ImageConsumer.StaticImaged);

}

}

The CalculatorImage Class

The CalculatorImage Class, Shown in Listing 14.5, Is The Glue Between THE

CalculatorProducer Class That Produces The Image Data And Thecalculatorfilter That Manages It .hen An Image Is Requested with The

GetImage () Method, The CalculatorImage Creates a Color Palette Through AN

Instance of the ImagecolorModel Class, Then Creates a MemoryImageSource

Object. This ImageProducer Object Produces An Image Initialized to All

Zeros (Black). It is combined with an all instance of the calculatorfilter

Class to produce a filteredimagesource .hen the createImage () Method of

The Toolkit Is Called, Production of The Calculate Image Begins.

The Color Palette Is A Randomly Generated Series of Pixel Values. Depending

ON Your Luck, Thase Colors Can Be Attractive or Uninspiring. The

CreatePalette () Method Is a Good Place To Create a Custom Set of Colors for

this applet, if you want to have some control over its appearance. you

Should Replace The Random Colors with Hard-Coded Rgb Values, And you might

Want to Download a URL File That Specifies a Special Color Mapping.

Listing 14.5. The CalculatorImage Class.

// this class takes a CalculatorProducer and sets up THE

// Environment for Creating a Calculated Image. TIES THE

// producer to the calculatorfilter so incremental Updates CAN

// be Made ...

Public class CalculatorImage {

Int width; // The Dimensions of the Image ...

INT height;

CalculatorProducer CP; // What produus the Image Data ...

IndexcolorModel Palette; // The Colors of the Image ...

// CREATE PALETTE ONLY ONCE Per session ...

Static IndexcolorModel Prvpalette = NULL;

Int numcolors = 256; // Number of Colors in Palette ...

// use defines how big of an image They want ...

Public CalculatorImage (int Width, Int Height, CalculatorProducer CP) {

THIS.WIDTH = Width;

THISHEIGHT = HEIGHT; this.cp = cp;

}

// Start Producting The Calculator Image ...

Public synchronized image getImage () {

// Hook Into the filter ...

CreatePalette ();

ImageProducer P = New FilteredImagesource

New MemoryImagesource (Width, Height, Palette,

(New int [width * height]), 0, width,

New CalculatorFilter (Palette, CP));

// Return the Image ...

Return Toolkit.getDefaultToolkit (). CreateImage (P);

}

// Create A 256 Color Palette ...

// Use default color model ...

Void createpalette () {

// CREATE PALETTE ONLY ONCE Per session ...

IF (Prvpalette! = NULL) {

Palette = prvpaalette;

Return;

}

// Create a Palette Out of Random RGB Combinations ...

Byte Blues [], Reds [], GREENS [];

Reds = new byte [Numcolors];

Blues = new byte [Numcolors];

Greens = New byte [Numcolors];

// first and last entries Are Black and White ...

Blues [0] = Reds [0] = Greens [0] = (byte) 0;

Blues [255] = Reds [255] = Greens [255] = (BYTE) 255;

// Fill in Other Entries ...

For (int x = 1; x <254; x ) {

Reds [x] = (byte) (255 * math.random ());

Blues [x] = (byte) (255 * math.random ());

Greens [x] = (byte) (255 * math.random ());

}

// CREATE INDEX color model ...

Palette = New Indexcolormodel (8,256, Reds, Greens, Blues);

PrvPalette = Palette;

}

// save the image set as a bmp file ...

Public void savebmp (string filename, int pix ") {

Try {

Bmpimage.savebitmap (filename, Palette,

PIX, Width, Height;

}

Catch (IOException IoE) {

System.out.println ("ERROR SAVING FILE!");

}

}

}

The Mandelapp Class

The Mandelapp Class, Shown in Listing 14.6, Creates and Displays the Full

Mandelbrot Set; The End RESULT IS Shown in Figure 14.2. An instance of the

Mandelbrot Class Is Created In The init () Method. WHENEVER THE MANDELBROALCALCALCALCALCAL, IT CALLS The ImageObserver-based

Method, ImageUpdate (). THIS WILL PROBABLY RESULT IN THE APPLET Being

Repainted to show the new data. if the image is intrumpte, an internal flag

IS set. after this, if you click the mouse, The Image will be saved to a

BMP Formatted File Called Mandel.bmp.

Listing 14.6. The Mandelapp Class.

Import java.awt. *;

Import java.lang. *;

IMPORT JAVA.Applet.applet;

// this applet displays the mandlebrot set through

// use of the masterelbrot class ...

Public class mandelapp extends applet {

Image im; // Image That Displays Mandelbrot Set ...

Mandelbrot M; // Creates the Mandelbrot Image ...

INT Numcols = 640; // Dimensions Image Display ...

Int nuMrows = 350;

Boolean Complete = FALSE;

// set up the masterbrot set ...

Public void init () {

M = New Mandelbrot (Numcols, Numrows);

IM = m.getimage ();

}

// Will Get Updates as set is being create.

// repaint when occur ...

Public Boolean ImageUpdate (Image Im, Int Flags,

INT X, INT Y, INT W, INT H) {

IF ((Flags & Framebits)! = 0) {

Showstatus ("Calculating ...");

Repaint ();

Return True;

}

IF ((Flags & Allbits)! = 0) {

Showstatus ("Image Complete!");

Repaint ();

Complete = true;

Return False;

}

Return True;

}

// Paint on Update ...

Public void Update (graphics g) {

Paint;

}

Public Synchronized Void Paint (Graphics G) {

g.drawImage (IM, 0, 0, THIS);

}

// Save Bitmap on Mouse Down When Image Complete ...

Public Boolean MouseDown (Event EVT, INT X, INT Y) {

IF (Complete) {

Showstatus ("Save Bitmap ...");

M.SaveBMP ("Mandel.BMP");

Showstatus ("Bitmap Saved!"); Return True;

} // end if

Return False;

}

}

The MandelzoomApp Class

Listing 14.7 Shows The MandelzoomApp Class, Which Repesents this Chapter's

Main applet; ITS Function Was Described Earlier, in The section Using THE

Applets. "See this section section section section section 14.1 for how to use the applet.

THE MOSTING FEATURES in The Code Are The Routines for Marking The

Region to be highlighted. Each Pixel on The Displayed Mandelbrot Image Maps

An X-Y Value to a real-imaginary value of the c value of the masterelbrot

Formula Shown in formula 14.1. WHENEVER You Move The Cursor, The Current

Real-Imaginary Values ​​Are Shown In The Browser's Status bar. When You

Highlight an area to zoom in, you are really picking a range of c Values

To Be Explored. All The Double Variables Are Used for Tracking this Range

Of Values. Thase Values ​​Are Read in Atitialization by The

Loadparameters () Method to match the bitmap That's displayed. you can

Specify Other Mandelbrot Bmp Files and Corresponding Data Files By Changing

The FileName Parameter of the applet's

TAG.

The zoom () Method Takes The Currently Highlighted Range and Brings Up A New

Mandelbrot Image That Corresponds to this Range. It uses the same

Calculation-Image Filtering Techniques That The ManDelapp Class Does.

Listing 14.7. The MandelzoomApp Class.

// this applet displays the masterelbrot set Bitmap Specified

// in the applet tag parameters. You can life zoom and in

// and out of the bitmap by Dragging a region to pie.

// and the copy on the appropriate Option ...

// z or z - zoom

// s or s - save.

Public class masterelzoomapp extends applet {

Image IMG;

Boolean Zoomon = FALSE;

Double XLEFT, XRIGHT, YTOP, YBOTTOM, XDELTA, YDELTA; Double Currentx, Currenty

Double StartX, Starty, Endx, Endy; // Zooming Coordinates ...

Rectangle MarkingRectangle; // Zooming Rectangle ...

Mandelbrot M; // Creates the Mandelbrot Image ...

INT Numcols = 640; // Dimensions Image Display ...

Int nuMrows = 350;

Boolean Complete = FALSE;

// Array for Keeping TRACK OF MANDELBROT ENTRIES ...

MandelenTry Me [];

Int LastIndex; // Top of Array ...

int currentindex;

// set up the masterbrot set specified in the parameters ...

Public void init () {

IMG = NULL;

m = NULL;

// Get Parameter Of Bitmap to Display ...

String filename;

IF ((filename = getparameter ("filename") == null)

FileName = "Mandel1";

// load the bitmap ...

Loadbitmap (filename);

// Initialize Mandelbrot Array ...

ME = New MandelenTry [40];

ME [0] = New MandelenTry (NULL, IMG, XLEFT, XRIGHT, YTOP, YBOTTOM);

LastIndex = 0;

CurrentIndex = 0;

}

// Zoom Onto Mandelbrot Set IF All Is Good ...

Void zoom () {

// no zooming if off or no rectangle ...

IF ((! zoom) || (MarkingRectangle == Null) {

Showmsg ("Nothing Marked Or Zooming Disable ...");

Return;

} // end if

// See if Mandelbrot Table Is Full ...

IF (LastIndex 1)> = me.length) {

Showmsg ("Mandelbrot Table Full. Clear with c before zooming");

Return;

}

Showmsg ("zoom: SX =" StartX "SY =" Starty "EX =" ENDX "EY ="

Endy;

// load new Mandelbrot ...

Complete = false;

Zoomon = false;

MarkingRectangle = NULL; // RESET MARKING Rectangle ...

m = new Mandelbrot (Numcols, Numrows, Endx, StartX,

Endy, starty);

IMG = m.getimage (); // store in Mandelbrot Table ...

XLEFT = STARTX;

XRight = ENDX;

YTOP = Starty;

Ybottom = endy;

XDELTA = Math.abs (XRight - Xleft);

YDELTA = Math.Abs ​​(Ybottom - Ytop);

LastIndex;

ME [LastIndex] = New MandelenTry (M, IMG, StartX, ENDX, STARTY, Endy);

CurrentIndex = LastIndex;

SHOWMSG ("Calculating ...");

Repaint ();

}

// Paint on Update ...

Public void Update (graphics g) {

Paint;

}

Public Synchronized Void Paint (Graphics G) {

IF (IMG == NULL)

Return;

// show image ...

g.drawImage (IMG, 0, 0, this);

// Show Marking Rectangle IF EXISTS ...

IF (MarkingRectangle! = NULL) {

g.drawRect (MarkingRectangle.x, MarkingRectangle.y,

MarkingRectangle.Width, MarkingRectangle.Height);

} // end if

}

// Will Get Updates as set is being create.

// repaint when occur ...

Public Boolean ImageUpdate (Image Im, Int Flags,

INT X, INT Y, INT W, INT H) {

IF ((Flags & Framebits)! = 0) {

Repaint ();

Return True;

}

IF ((Flags & Allbits)! = 0) {

Showmsg ("Image Complete!");

Repaint ();

Complete = true;

zoomon = true;

Return False;

}

Return True;

}

// load a bitmap and recognization data file ...

Void loadingBitmap (string filename) {

// zoom is false Unless Both succeed ...

Zoomon = false;

MarkingRectangle = NULL; // RESET MARKING Rectangle ...

// load the bitmap ...

Try {

SHOWMSG ("Load Image ...");

ImageProducer Producter = Bmpimage.GetImageProducer

GetDocumentBase (), filename ".bmp");

IMG = CREATEIMAGE (Producer);

Showmsg ("Image loaded ...");

}

Catch (AWTEXCEPTION E) {

IMG = NULL;

Showmsg ("Cannot Open File";

Return;

}

// load the zoom parameters.// Turn Zoom on iF all works ...

Try {

LoadParameters (filename);

zoomon = true;

Complete = true;

}

Catch (IOException E) {

"" Cannot Load Parameter Data " E.GetMessage ());

}

}

// load the parameters. Throw Io Exception ...

Public void loadparameters (String filename) throws oException {

// CREATE URL for Data ...

URL u;

Try {

u = new url (getDocumentbase (), filename ".dat");

}

Catch (Malformedurlexcection E) {

Showmsg ("Bad Data URL");

Throw new oException ("BAD URL");

}

// now load the data by open a stream

// to the URL ...

DataInputStream Dis = New DataInputStream

New BufferedInputStream (u.openStream ()))

// r r on1 first line ...

String param = disp.readline ();

// tokenize out the boundary value ....

StringTokenizer S = New StringTokenizer (Param, ",");

Try {

XLEFT = Double.Valueof (S.NEXTTOKEN ()). DoubleValue ();

XRight = double.Valueof (S.NEXTTOKEN ()). DoubleValue ();

Ytop = Double.Valueof (S.NEXTTOKEN ()). DoubleValue ();

YBOTTOM = Double.Valueof (S.NEXTTOKEN ()). DoubleValue ();

XDELTA = Math.abs (XRight - Xleft);

YDELTA = Math.Abs ​​(Ybottom - Ytop);

}

Catch (NumberFormatexception E) {

Throw new oException ("Improperly Formatted Data ...");

}

Catch (Nosuchelementexception E) {

Throw new oException ("Improperly Formatted Data ...");

}

}

// TRACK MOUSE to show Fractal Values ​​and to

// Mark Area to zoom

Public Boolean Handleevent (Event EVT) {

Switch (evt.id) {

Case Event.key_press: {

// z or z means zoom

IF ((est.key == 'z') || (est.key == 'z'))))

ZOOM ();

// s or s means save

IF ((est.key == 's') || (est.key == 's') SaveFile ();

// a man people Abort zoom Calculation ...

IF ((est.key == 'a') || (est.key == 'a')) {

IF (M! = null) {

SHOWMSG ("Aborting Calculation ...");

m.stop ();

} // end if

}

// p or p means previous image ...

IF ((est.key == 'p') || (est.key == 'p')))

PreviousImage ();

// b or b means previous image ...

IF ((est.key == 'b') || (est.key == 'b'))))

PreviousImage ();

// n or n means next image ...

IF ((est.key == 'n') || (est.key == 'n'))))

NextImage ();

// f or f means next image ...

IF ((est.key == 'f') || (est.key == 'f'))

NextImage ();

// c or c means clear images

IF ((est.key == 'c') || (est.key == 'c')))

ClearImage ();

Return True;

}

// mouse clicks. Start Marking ...

Case Event.mouse_down: {

STARTMARKING (Evt.x, evt.y);

Return False;

}

Case Event.mouse_drag: {

Dragmarking (est.x, evt.y);

Return False;

}

Case Event.mouse_up: {

Stopmarking (est.x, evt.y);

Return False;

}

Case Event.mouse_move: {

ShowPosition (est.x, evt.y);

Return False;

}

DEFAULT:

Return False;

}

}

// save the image as a file ...

Void savefile () {

// Don't Save IF WE Are Loading ...

IF (! company)

Return;

// Get Mandelbrot Reference, IF EXISTS ...

Mandelbrot MB = me [currentIndex] .getMandelbrot ();

IF (MB == NULL) {

ShowStatus ("Cannot Save. Not Generated");

Return;

} // end if

// generate the filename ...

String filename = "TempMandel" (CurrentIndex 1) ".bmp";

// security test ... try {

System.getSecurityManager (). Checkwrite (filename);

}

Catch (SecurityExcect e) {

ShowStatus ("Write Not Permitted!");

Return;

}

// save the image ...

ShowStatus ("Saving Image As" FileName "...");

Mb.savebmp (filename);

ShowStatus ("Image Saved AS" FileName;

}

// Routines for Moving Through Mandelbrot Table ...

// load previous image ...

Void previousimage () {

// Nothing if we are loading ...

IF (! company)

Return;

// do nothing if at top index ...

IF (currentIndex == 0) {

Showmsg ("at top index");

Return;

}

// Go to Previous Image ...

ReloadImage (CurrentIndex - 1);

}

// load next image ...

Void nextImage () {

// Nothing if we are loading ...

IF (! company)

Return;

// Do Not At Last Index ...

IF (currentIndex == lastindex) {

Showmsg ("At Last Index");

Return;

}

// Go to Next Image ...

ReloadImage (CurrentIndex 1);

}

// Reload Index from Mandelbrot Array ...

Void reloadimage (int index) {

SHOWMSG ("Reloading Image ...");

CurrentIndex = Index;

Complete = true;

zoomon = true;

MarkingRectangle = NULL; // RESET MARKING Rectangle ...

// Get Data from Mandelbrot Table ...

IMG = me [currentIndIndex] .Getimage ();

XLEFT = me [currentIndex] .GetxLeft ();

XRight = me [currentIndex] .GETXRIGHT ();

YTOP = me [currentIndex] .geTytop ();

Ybottom = me [currentIndex] .getybottom ();

XDELTA = Math.abs (XRight - Xleft);

YDELTA = Math.Abs ​​(Ybottom - Ytop);

Repaint ();

}

// Remove Everything Butfirst Image from Stack ...

Void ClearImage () {

For (INT i = 1; i <= lastindex; i)

ME [I] = null;

// Go Back to first image ...

LastIndex = 0; reloadimage (0);

}

// ********************************************

// routines for mouse tracking ...

// ********************************************

Boolean trackingon = false;

INT leftx, top;

// Start Marking a zoom Rectangle, ERASE EXISTING ONE ...

Void Startmarking (int X, int y) {

// Get Current positions ... Clear Marking if INVALID ...

IF (! showPosition (x, y)) {

TRACKINGON = FALSE;

MarkingRectangle = NULL;

Repaint ();

Return;

} // end if

// else, start marking ...

TRACKINGON = true;

StartX = CURRENTX;

Starty = CURRENTY;

ENDX = CURRENTX;

Endy = Currenty;

Leftx = x;

TOPY = Y;

// set Marking Rectangle and repaint ...

MarkingRectangle = New Rectangle (x, y, 1, 1);

Repaint ();

}

// Expand Square of Dragging Unless ...

Void Dragmarking (int x, int y) {

// Get Current positions ... Clear Marking if INVALID ...

Boolean good = showPosition (x, y);

// see if other marking conditions hold.

// Such as going in a bad direction ...

IF (good) {

IF ((! Trackingon) || (x

Good = false;

}

// Clear Out IF Marking is Bad ...

IF (! good) {

TRACKINGON = FALSE;

MarkingRectangle = NULL;

Repaint ();

Return;

} // end if

// set new Marking Rectangle and repaint ...

ENDX = CURRENTX;

Endy = Currenty;

MarkingRectangle = New Rectangle (Leftx, TOPY,

X - Leftx, Y - TOPY;

Repaint (Leftx, TOPY, MarkingRectangle.width 1,

MarkingRectangle.height 1);

}

// stop marking ...

Void stopmarking (int x, int y) {

ShowPosition (X, Y);

TRACKINGON = false;

// Kill if Too Small ...

IF (MarkingRectangle! = NULL) {

IF ((MarkingRectangle.Width <3) ||

(MarkingRectangle.height <3)) {

MarkingRectangle = NULL;} // end if

}

Repaint ();

}

// show current position to status if an image has

// been prepared ...

// Returns True if Good position, Else Bad ...

Boolean showPosition (int x, int y) {

// Return if not Ready to zoom ...

IF (IMG == Null) || (! zoomon))

Return False;

// See if we are in the display area ...

INT width = img.getwidth (this);

INT Height = img.getheight (this);

IF ((x> width) || y> height) {

Showstatus ("" ");

Return False;

} // end if

Currentx = XLEFT (XDELTA * ((Double) x) / ((Double) Width)));

Currenty = YTOP (YDELTA * ((Double) Y) / ((Double) HEIGHT));

ShowStatus (Currentx ":" Currenty);

Return True;

}

// Print a Message to Standard Out and the status bar ...

Public void showmsg (string s) {

System.out.println (s);

Showstatus (s);

}

}

A cache is maintained so that you can move back and forth betWeen images.

The cache is an array of mandelentry accessor objects; the MandelenTry

Class Is Shown in Listing 14.8. The Cache IS Set To Store Up to 40 Images.

If you fill up the cache, Press C or c to clear the cache of everything but

The Full Mandelbrot Set Image. as an an an estuel, you mightow to make the

Caching Mechanism More Sophistated So That It Can Bring in EXISTING

Files, Delete Individual Images, And So Forth.

Note That there is a little trick in the savefile () method. It uses the

SecurityManager to See WHETHER File Writes are allowed. This is a way of

Checking The Browser's Security Before A Write Is Attempted. If File

Writing is prohibited, a securityException is thrown. How this works WILL

Differ from browser to browser.

Listing 14.8. The MandelenTry Class.

// Store Mandelbrot Images and Corresponding Coordinates ... Class MandelenTry {

Mandelbrot M;

Image IMG;

Double XLEFT, XRIGHT, YTOP, YBOTTOM

// Constructor: Store Data ...

Public MandelenTry (Mandelbrot M, Image IMG, Double XLEFT,

Double Xright, Double Ytop, Double Ybottom {

THIS.M = m;

THIS.IMG = IMG;

THIS.XLEFT = XLEFT;

THIS.XRIGHT = XRight;

THIS.YTOP = YTOP;

THIS.YBOTTOM = ybottom;

}

// Accessor Methods ...

Public Mandelbrot getMandelbrot () {

Return M;

}

Public image getimage () {

Return IMG;

}

Public double getXLEFT () {

Return XLEFT;

}

Public double getXright () {

Return XRight;

}

Public double getytop () {

Return YTOP;

}

Public Double getybottom () {

Return Ybottom;

}

}

The Bmpimage Class

The Bmpimage Class, Introducted in Part Iii of this Book, Reads images

Stored in the BMP Format and Converts THEM INTO A FORM JAVA CAN USE. IN

This Chapter, More Functions Were Added to the Class So That IT Could Write

The Bmp Back Out To a File (Shown in Listing 14.9). It's Basically The

Opposite of The Reading Process Discussed in Part III.

Listing 14.9. Added bmp saving to the bmpimage class.

Import java.lang.string;

Import java.io. *;

Import java.net. *;

Import java.awt. *;

Import java.awt.image. *;

/ **

* This is a class what reads and write a

* BMP Formatted File

* /

Public class bmpimage

{

// ... EXInsting code Goes here !!!

/ **

* Write Out A Bitmap ...

* Current Only Supporting 8 BITS Per Pixel ...

* @String FileName - The File to Save IT AS ...

* @IndexcolorModel ICM - Palette to use

* @int Pix [] - Pixels to Save

* @int width - Width of Data

* @int Height - Height of Data

* /

Public Static Void SaveBitmap (String FileName,

Indexcolormodel ICM, INT PIX [], Int Width, Int Height) throws oews oException {

// CREATE OUTPUT STREAM ...

Bmpimage b = new bmpimage (filename);

DataOutputstream OS = New DataOutputStream

New bufferedoutputstream

New fileOutputStream (filename))));

B.WritefileHeader (OS, ICM, Width, Height);

B.Write8Bitwindowsheader (OS, ICM, Width, Height);

B.Write8BitColorIndex (OS, ICM);

B.Write8bitData (OS, PIX, Width, Height);

Os.Close ();

}

/ **

* Write Out the file header

* @DataOutputstream Os - The Output Stream To Write

* @IndexcolorModel ICM - Palette to use

* @int width - Width of Data

* @int Height - Height of Data

* /

Public Void WritefileHeader (Dataoutputstream OS,

IndexcolorModel ICM,

INT Width, int Height) throws oException {

Byte b [] = new byte [4];

// Write out Magic Code ...

B [0] = 'b';

B [1] = 'm';

Os.write (B, 0, 2);

// Calculate size and offset ..

INT PALETTESIZE = (ICM.GETMAPSIZE () * 4);

INT OFFSET = 54 Palettesize;

INT filesize = offset (width * height);

// Write out size & offset ...

Pushval (OS, FileSize, 4);

Pushval (OS, 0, 4);

Pushval (OS, Offset, 4);

}

/ **

* Write The Bitmap Header Out to Windows ...

* @DataOutputstream Os - The Output Stream To Write

* @IndexcolorModel ICM - Palette to use

* @int width - Width of Data

* @int Height - Height of Data

* /

Public void Write8bitWindowsHeader (DataOutputstream OS,

IndexcolorModel ICM,

INT Width, int Height) throws oException {

Pushval (OS, 40, 4); // Bytes in Header

Pushval (OS, Width, 4); // size in pixels ...

Pushval (OS, HEIGHT, 4);

Pushval (OS, 1, 2); // # Color Plaso

Pushval (OS, 8, 2); // Bits Per Pixel ...

Pushval (OS, 0, 4); // no compression ...

Pushval (Os, Width * Height, 4); // size of image ... // later put in real data pixels / meter

Pushval (OS, 3790, 4); // TBD: Horizontal Res Pixels / Meter

Pushval (OS, 3790, 4); // TBD: Vertical Res Pixels / Meter

Pushval (OS, ICM.GETMAPSIZE (), 4); // Indexes in Bitmap ...

Pushval (OS, ICM.GETMAPSIZE (), 4); // Indexes in Bitmap ...

}

/ **

* Write The Bitmap Header Out to Windows ...

* @DataOutputstream Os - The Output Stream To Write

* @IndexcolorModel ICM - Palette to use

* /

Public Void Write8bitColorindex (Dataoutputstream OS,

Indexcolormodel ICM) throws oException {

// CREATE RGB Array ...

Int Palettesize = ICM.GETMAPSIZE ();

BYTE BLUES [] = New byte [Palettesize];

Byte grees [] = new byte [Palettesize];

Byte reds [] = new byte [palettesize];

Byte b [] = new byte [4];

// Copy RGB Arrays ...

ICM.GetBlues (Blues);

ICM.GETGREENS (REDS);

ICM.GetReds (Reds);

// Write Out Palette ...

For (int i = 0; i

B [0] = (Byte) Blues [i];

B [1] = (Byte) Greens [i];

B [2] = (Byte) Reds [i];

B [3] = (Byte) 0;

Os.Write (B, 0, 4);

} // end for

}

/ **

* Write Out Data of Bitmap ...

* @DataOutputstream Os - The Output Stream To Write

* @IndexcolorModel ICM - Palette to use

* @int Pix [] - Pixels to Save

* @int width - Width of Data

* @int Height - Height of Data

* /

Public void writ8bitdata (DataOutputstream OS,

INT PIX [], int width, int Height "ooException {

// bytes b ...

Byte b [] = new byte [width];

For (int i = 0; i <4; i)

B [i] = 0;

// Calculate Padding

INT PADDING = 0;

INT OVERAGE = Width% 4;

IF (Overage! = 0)

Padding = 4 - Overage;

// Write out starting from bottom of heiGHT

INT INDEX, X, Y;

For (y = (HEIGHT - 1); Y> = 0; --y) {// Write Out Each Row, Send to Big Buffer ...

INDEX = (Y * Width);

FOR (x = 0; x

B [x] = (byte) PIX [index];

// Write Out A Big Block ...

Os.Write (B, 0, Width);

// send Out Padding ...

IF (padding! = 0) {

For (int i = 0; i <4; i)

B [i] = 0;

Os.Write (B, 0, Padding);

}

System.out.print ("."); System.out.flush ();

} // end y

System.out.println ("Write Done!");

}

/ **

* Write out Integer to Little Endian Stream ...

* @DataOutputstream Os - The Output Stream To Write

* @int Data - Data to Convert

* @INT LEN - Length of Array to Convert

* /

Private void Pushval (DataOutputstream OS,

INT DATA, INT LEN) THROWS IOEXCEPTION {

Byte b [] = new byte [len];

For (int i = 0; i

B [i] = (byte) (DATA >> (i * 8));

}

Os.Write (B, 0, LEN);

}

Automatic Documentation with javadoc

The Last Thing Covered In this chapter is how to auto-document your code.

The Tool Javadoc, Provided with the JDK, Can Take a Properly Formatted File

And Convert It Into An Html File, Complete with Links To The Classes IT

References (Assuming Those Classes Are Also Run THROUGH JAVADOC). The

Bmpimage.java Is Such A File; ITS HTML Output from Javadoc Is Shown in

Figure 14.7 and is include on this book's CD-ROM.

Comments That SHOULD APPEAR in HTML Are Marked by Appearing BetWeen / **

And * /, as shown at the beginning of the source code in listing 14.9. The

Javadoc Tool Figures Out A Lot of Things on Its Own, Such The Superclass,

What External Classes Are Used, and The Individual Parts of a Method OR

Variable declaration. You Can Specify Additional Information for Eachmethod by Preceding Certain Keywords INCLUDE

Param, Returns, And Exception For Documenting Parameters, Return Values,

And Exceptions thrown, respectiveness. for example, here is the decaration

For getImageProducer ():

/ **

* A Method to Retreive An ImageProducer Given Just A BMP URL.

* @Param Context Contains The Base Url (from getcodebase () or Such)

* @returns an imageproducer

* @Exception AWTEXCEPTION ON Stream or Bitmap Data Erro

* /

Look at the html to see what this looks like.

You will need to place the html output in the right directory for

Everything to work properly. You can also document an entire package by

Passing the package name to javadoc.

Figure 14.7. Bmpimage HTML After Being Run Through Javadoc.

Summary

The Major Work of this Book Began in Part Ii with a series of discussions

On How to Use the AWT Package. The Spreadsheet Applet Was Used to Show How

To incrementally build an applet sale offer. Since awt is the basis for

Constructing the user interface of your java applets, you need to know the

Package Well. While Constructing The Spreadsheet, you also Learned Thae

Subtleties of the java.io package and how to create exception handlers. by

The end of part ii, you had seen mot of the basics of java applet

Programming.

Part III TOOK EVERYTHING A Step Further. You Discovered The underlying

Classes Behind Applets and Images and Saw How Threads Can Be Used To

Enhance Your Application. Part III Concluded with showing you how place, the

Applet Classes, Images, And Threads Could Be Brought Together To Create A

Catalog Applet, Whose Key Element WAS A Background Image Loader Running Asa Thread. Although this Applet Was Not a final Product, It could 梒 Ombined

With the client / server mechanism of part iv 梑 e the Basis for producing a

Serious Catalog Application for Use on The World Wide Web.

In part iv, you incorporated the lessons of the previous chapter to create

The Most Complex Application of The Book. You Saw How To Use the Java

Network classes to create a client-server application, and how to us

Native Methods To Take Full Advantage of a Particular Platform's Features.

The Client Applet Demonstrated How Java Could Be Used to Represent Data AS

IT Changes in Real Time. The Electrion Applet in Part IV WAS JUST THE

Beginning of what you can create with Java Client-Server Technology.

Part V allowed you to focus on some of the more advanced features of java.

You Saw How HotJava, Although Still in Its Infancy, Has Features That

INDICATE The Future of Browsers and Java Programming. You Also Saw How To

Use java's image classes to create advanced animation and image-processing

Applets. with a knowledge of these advanced imaging techniques, you can now

Use Java to Product Image More Sophistated Than Just A Banner Moving

Across the screen.

You Have Be Given The Tools to Write Great Java Applets for the Internet,

The intranet, or Anywhere Else Java Calls. Go for IT!

BBS Shuimu Tsinghua Station: Essence

转载请注明原文地址:https://www.9cbs.com/read-3550.html

New Post(0)