|
|||
Вступление Примеры Словарь Вопросы Sun Microsystems |
Примеры программирования на Java
//******************************************************************************
//
// ImageErase.java: Applet - стирание частей изображения, под которым лежит
// другое изображение
//******************************************************************************
import java.applet.*;
import java.awt.*;
import java.awt.image.*;
import java.util.*;
//==============================================================================
// Основной класс - applet ImgErase
//
//==============================================================================
public class ImgErase extends Applet implements Runnable
{
//нить загрузки изображений
private Thread m_ImgErase = null;
//контекст рисования для ускорения перерисовки
private Graphics m_Graphics;
//текущее изображение для рисования
private Image m_imgPaint;
//пикселы фонового изображения
private int m_nBackPixels[];
//пикселы стираемого изображения
private int m_nPaintPixels[];
//размеры изображений
private int m_nImgWidth = 0;
private int m_nImgHeight = 0;
//флаг загрузки изображений
private boolean m_fAllLoaded = false;
//имена изображений для загрузки
private String m_sImgBack = "backgr.jpg";
private String m_sImgFore = "foregr.jpg";
//размеры ластика
private int m_nEraserWidth = 8;
private int m_nEraserHeight = 8;
//сдвиг ластика по отношению к курсору мыши
private int m_nEraserOffsetX = 4;
private int m_nEraserOffsetY = 4;
//цвет фона апплета
private Color m_clrBk = Color.white;
//флаг активности ластика
private boolean m_fErasing = false;
//разрешенная область стирания
Rectangle m_rcEraseArea = new Rectangle(0,0,0,0);
//левый верхний угол изображения
Point m_ptPict = new Point(0, 0);
//текущая позиция ластика
Point m_ptEraser = new Point(-100, -100);
// Имена параметров апплета
//--------------------------------------------------------------------------
private final String PARAM_BackgrImage = "BackgrImage";
private final String PARAM_ForegrImage = "ForegrImage";
private final String PARAM_EraserWidth = "EraserWidth";
private final String PARAM_EraserHeight = "EraserHeight";
private final String PARAM_BkColor = "BkColor";
// ImgErase конструктор
//--------------------------------------------------------------------------
public ImgErase()
{
}
//---------------------------------------------------------------------------
public String[][] getParameterInfo()
{
String[][] info =
{
{ PARAM_BackgrImage, "String", "Image in background" },
{ PARAM_ForegrImage, "String", "Image in foreground" },
{ PARAM_EraserWidth, "int", "Width of eraser" },
{ PARAM_EraserHeight, "int", "Height of eraser" },
{ PARAM_BkColor, "String", "Background color"}
};
return info;
}
// В методе init() происходит первичная инициализация апплета
// и получение значений параметров
//--------------------------------------------------------------------------
public void init()
{
String param;
//фоновое изображение
param = getParameter(PARAM_BackgrImage);
if (param != null)
m_sImgBack = param;
//стираемое изображение
param = getParameter(PARAM_ForegrImage);
if (param != null)
m_sImgFore = param;
//размеры ластика
param = getParameter(PARAM_EraserWidth);
if (param != null)
m_nEraserWidth = Integer.parseInt(param);
param = getParameter(PARAM_EraserHeight);
if (param != null)
m_nEraserHeight = Integer.parseInt(param);
//цвет фона
param = getParameter(PARAM_BkColor);
if (param != null)
{
//разбор строки цвета фона в форме "r,g,b"
StringTokenizer st = new StringTokenizer(param, ",.");
if( st.countTokens() == 3 )
{
int nRed = Integer.parseInt(st.nextToken());
int nGreen = Integer.parseInt(st.nextToken());
int nBlue = Integer.parseInt(st.nextToken());
m_clrBk = new Color(nRed, nGreen, nBlue);
}
}
//установить цвет фона апплета
setBackground(m_clrBk);
}
public void destroy()
{
}
//displayImage - отрисовывает текущее изображение в середине апплета
//случае если оно загружено
//----------------------------------------------------------
private void displayImage(Graphics g)
{
if (!m_fAllLoaded)
return;
g.drawImage(m_imgPaint, m_ptPict.x, m_ptPict.y, null);
}
//paint - если загружено изображение, то отрисовывает его в середине апплета,
//иначе - выдаем строчку о загрузке
//----------------------------------------------------------
public void paint(Graphics g)
{
if (m_fAllLoaded)
displayImage(g);
else
g.drawString("Loading images...", 10, 20);
}
// Запуск апплета - запускаем нить (thread) m_ImgErase, которая загружает
// изображения
//--------------------------------------------------------------------------
public void start()
{
if (m_ImgErase == null)
{
m_ImgErase = new Thread(this);
m_ImgErase.start();
}
}
// Метод stop() - останавливаем выполнение нити m_ImgErase
//--------------------------------------------------------------------------
public void stop()
{
if (m_ImgErase != null)
{
m_ImgErase.stop();
m_ImgErase = null;
}
}
// Нить загрузки изображений и ожидания окончания с помощью MediaTracker.
// после загрузки изображений создаем рисуемое изображение и получаем пикселы
// стираемого и фонового изображения в виде массивов int
//--------------------------------------------------------------------------
public void run()
{
// При повторном входе в страницу изображения уже загружены, поэтому
// не делаем этого опять (m_fAllLoaded == TRUE).
if (!m_fAllLoaded)
{
//перерисовка чтобы показать статусное сообщение
repaint();
//запоминаем контекст рисования
m_Graphics = getGraphics();
//стираемое и фоновое изображения
Image imgBack, imgFore;
//tracker позволяет отслеживать загрузку изображений
MediaTracker tracker = new MediaTracker(this);
//загружам изображения
imgBack = getImage(getDocumentBase(), m_sImgBack);
imgFore = getImage(getDocumentBase(), m_sImgFore);
//регистрируем изображения в tracker
tracker.addImage(imgBack, 0);
tracker.addImage(imgFore, 0);
boolean fLoaded = false; //флаг ошибки при загрузке
try
{
tracker.waitForAll();
fLoaded = !tracker.isErrorAny();
}
catch (InterruptedException e)
{
}
//если обнаружена ошибка при загрузке - остановить выполнение нити и
//вывести сообщение
if (!fLoaded)
{
m_fAllLoaded = false;
stop();
m_Graphics.drawString("Error loading images!", 10, 40);
return;
}
//получаем размеры изображения
//(подразумевается, что изображения одинакового размера)
m_nImgWidth = imgFore.getWidth(this);
m_nImgHeight = imgFore.getHeight(this);
//инициация массива для пикселов фонового изображеня
m_nBackPixels = new int[m_nImgWidth * m_nImgHeight];
//инициация массива для пикселов отрисовываемого изображения
m_nPaintPixels = new int[m_nImgWidth * m_nImgHeight];
//получаем пикселы изображений с помощью обьектов PixelGrabber
//
PixelGrabber grabBack = new PixelGrabber(imgBack.getSource(),
0, 0, m_nImgWidth, m_nImgHeight,
m_nBackPixels, 0, m_nImgWidth);
//в начале изображение полностью совпадает со стираемым
PixelGrabber grabPaint = new PixelGrabber(imgFore.getSource(),
0,0, m_nImgWidth, m_nImgHeight,
m_nPaintPixels, 0, m_nImgWidth);
try
{
grabBack.grabPixels();
grabPaint.grabPixels();
}
catch ( Exception e )
{
}
//создаем изображение для рисования
m_imgPaint = createImage( new MemoryImageSource(m_nImgWidth, m_nImgHeight,
m_nPaintPixels, 0, m_nImgWidth));
//вычисляем левую верхнюю точку рисования изображения,
//так, чтобы оно находилсь в середине апплета
m_ptPict.x = (size().width - m_nImgWidth) / 2;
m_ptPict.y = (size().height - m_nImgHeight) / 2;
//область разрешенного стирания - больше изображения на
//ширину ластика с каждой стороны
m_rcEraseArea.x = m_ptPict.x - m_nEraserWidth;
m_rcEraseArea.y = m_ptPict.y - m_nEraserHeight;
m_rcEraseArea.width = m_nImgWidth + m_nEraserWidth*2;
m_rcEraseArea.height = m_nImgHeight + m_nEraserHeight*2;
//сдвиг ластика по отношению у указателю мыши - половина ширины
//и высоты ластика
m_nEraserOffsetX = m_nEraserWidth / 2;
m_nEraserOffsetY = m_nEraserHeight / 2;
m_fAllLoaded = true;
}
//перерисовка после загрузки
repaint();
}
// DrawEraser рисует контуры ластика в XOR режиме.
// При повторном рисовании в том же месте контур исчезнет.
//----------------------------------------------------------------------------
private void DrawEraser()
{
m_Graphics.setXORMode(Color.white);
m_Graphics.drawRect(m_ptEraser.x, m_ptEraser.y,
m_nEraserWidth, m_nEraserHeight );
m_Graphics.setPaintMode();
}
//ShowEraser первый раз показывает контур ластика в заданной точке
//cо сдвигом относительно курсора мыши
//----------------------------------------------------------------------------
private void ShowEraser(int x, int y)
{
m_ptEraser.move(x - m_nEraserOffsetX, y - m_nEraserOffsetY);
DrawEraser();
}
//HideEraser убирает контур ластика
//и перемещает ластик в невидимую отрицательную область
//----------------------------------------------------------------------------
private void HideEraser()
{
DrawEraser();
m_ptEraser.move( - (m_nEraserWidth + 2), -(m_nEraserHeight + 2) );
}
//MoveEraser убирает контур ластика в текущей точке,
//перемещает ластик в заданную точку со сдвигом относительно курсора мыши
//и рисует контур ластика в новой точке
//----------------------------------------------------------------------------
private void MoveEraser(int x, int y)
{
DrawEraser();
m_ptEraser.move(x - m_nEraserOffsetX, y - m_nEraserOffsetY);
DrawEraser();
}
//ErasePixels стирает часть изображения, копируя в эту часть
//соответствующую область фонового изображения
//x, y - левая верхняя точка области (относительно левого верхнего угла картинки)
//w, h - ширина и высота области
//----------------------------------------------------------------------------
private void ErasePixels(int x, int y, int w, int h)
{
int nXEnd, nYEnd;
//правая нижняя точка области
nXEnd = x + w;
nYEnd = y + h;
//проверяем граничные значения
//правой нижней точки области (>= 0 и <= размеров изображения)
if( nXEnd > m_nImgWidth ) nXEnd= m_nImgWidth;
else if( nXEnd < 0 ) nXEnd = 0;
if( nYEnd > m_nImgHeight ) nYEnd= m_nImgHeight;
else if( nYEnd < 0 ) nYEnd = 0;
//проверяем граничные значения
//левой верхней точки стираемой области (>= 0 и <= размеров изображения)
if(x < 0) x = 0;
else if( x > m_nImgWidth ) x = m_nImgWidth;
if( y < 0) y = 0;
else if( y > m_nImgHeight ) y = m_nImgHeight;
//nEndi - линейный индекс начала последней стираемой строки
int nEndi = nYEnd * m_nImgWidth;
//цикл от первой до последней стираемой строки
for(int i = y * m_nImgWidth; i < nEndi; i +=m_nImgWidth )
{
//nEndj - линейный индекс последнего стираемого пиксела в данной строке
int nEndj = i + nXEnd;
//цикл от первого до последнего стираемого пиксела в данной строке
for(int j = i + x; j< nEndj ; j++)
{
//копируем пиксел из фонового в рисуемое изображение
m_nPaintPixels[j] = m_nBackPixels[j];
}
}
//обновляем отрисовываемое изображение освобождением его памяти
//будет воссоздано системой из m_nPaintPixels, измененных выше
m_imgPaint.flush();
//убрать с экрана контур ластика
DrawEraser();
//cropFilter выделяет только изменившуюся (cтертую) часть изображения
//в виде нового изображения. Это значительно ускоряет рисование
CropImageFilter cropFilter = new CropImageFilter(x, y, nXEnd-x, nYEnd-y);
Image imgPart = createImage( new FilteredImageSource( m_imgPaint.getSource(),
cropFilter) );
//нарисовать изменившуюся часть
m_Graphics.drawImage( imgPart, m_ptPict.x + x, m_ptPict.y + y, null);
//показать контуры ластика
DrawEraser();
//освободить память частичного изображения
imgPart.flush();
}
// mouseDown включает режим рисования, если изображения загружены
public boolean mouseDown(Event evt, int x, int y)
{
if( m_fAllLoaded )
m_fErasing = true;
return true;
}
// mouseUp выключает режим рисования, если изображения загружены
public boolean mouseUp(Event evt, int x, int y)
{
if( m_fAllLoaded )
m_fErasing = false;
return true;
}
//mouseDrag вызывается при перемещении мыши с нажатой клавишей.
//Если изображения загружены, перемещаем контур ластика в новую точку.
//Стираем часть изображения, если включен режим стирания
public boolean mouseDrag(Event evt, int x, int y)
{
if( m_fAllLoaded )
{
MoveEraser(x,y);
//Если включен режим стирания и курсор находится в разрешенной области,
//стираем часть изображения
if( m_fErasing && m_rcEraseArea.inside(x,y) )
{
//левая верхняя точка стирания берется со
//сдвигом относительно картинки и курсора мыши
ErasePixels( x - m_nEraserOffsetX - m_ptPict.x,
y - m_nEraserOffsetY - m_ptPict.y,
m_nEraserWidth, m_nEraserHeight );
}
//если мы вышли за пределы апплета - убрать контур ластика
if( x <= 0 || y <= 0 || x > size().width-1 || y > size().height-1 )
mouseExit( evt, x, y);
}
return true;
}
//при перемещении курсора перемещаем контур ластика
public boolean mouseMove(Event evt, int x, int y)
{
if( m_fAllLoaded ) //только если загружены изображения
MoveEraser(x,y);
return true;
}
//при входе курсора в пределы апплета - показать контур ластика
public boolean mouseEnter(Event evt, int x, int y)
{
if( m_fAllLoaded ) //только если загружены изображения
ShowEraser(x,y);
return true;
}
//если мы вышли за пределы апплета - убрать контур ластика
public boolean mouseExit(Event evt, int x, int y)
{
if( m_fAllLoaded ) //только если загружены изображения
HideEraser();
return true;
}
}
|
||