FileDocCategorySizeDatePackage
ImageResizer.javaAPI DocAzureus 3.0.3.415387Thu Mar 01 23:47:32 GMT 2007com.aelitis.azureus.ui.swt.utils

ImageResizer

public class ImageResizer extends Object

Fields Summary
private static final int
RESIZE_STEPS
private static final int
MARGIN
private int
minWidth
private int
minHeight
private int
displayWidth
private int
displayHeight
private Display
display
private Shell
parent
private Shell
shell
private Cursor
cursor
private Canvas
canvas
private Scale
scale
private long
lastUpdate
private Image
original
private int
originalWidth
private int
originalHeight
private Image
currentImage
private Image
overlay
private Image
overlayDragging
private Image
overlayNotDragging
private boolean
done
private Image
result
private float
zoomRatio
private float
minZoomRatio
private float
maxZoomRatio
private Point
offset
private Listener
moveImageListener
Constructors Summary
public ImageResizer(Display display, int width, int height, Shell parent)


	         
		this.parent = parent;
		this.display = display;
		this.minWidth = width;
		this.minHeight = height;
	
Methods Summary
private booleancheckSize(Image image)

		//If the image is smaller than the minimal size, we shouldn't accept it
		Rectangle size = image.getBounds();
		if (size.width < minWidth || size.height < minHeight) {
			return false;
		}

		float minHRatio = (float) (minHeight) / size.height;
		float minWRatio = (float) (minWidth) / size.width;

		float maxHRatio = (float) (minHeight * 4) / size.height;
		float maxWRatio = (float) (minWidth * 4) / size.width;

		//We must keep the min zoom bigger than the "biggest" ratio (ie, smallest zoom out)
		minZoomRatio = minHRatio > minWRatio ? minHRatio : minWRatio;
		maxZoomRatio = maxHRatio > maxWRatio ? maxHRatio : maxWRatio;

		if (maxZoomRatio > 1) {
			maxZoomRatio = 1;
		}

		zoomRatio = minZoomRatio;

		return true;
	
private ImagecomputeResultImage()

		Image img = new Image(display, minWidth, minHeight);

		/*ImageData srcData = original.getImageData();
		 ImageData dstData = new ImageData(
		 currentImage.getBounds().width,
		 currentImage.getBounds().height,
		 32,
		 new PaletteData(0xFF,0xFF00,0xFF0000));
		 Resample resample = new Resample();		
		 resample.setFilter(Resample.FILTER_TYPE_LANCZOS3, 7.0f);
		 resample.process(srcData, dstData);
		 Image filtered = new Image(display,dstData);
		 */
		GC gc = new GC(img);
		gc.drawImage(currentImage, offset.x, offset.y);
		gc.dispose();
		//filtered.dispose();
		return img;
	
private ImagecreateOverlayImage(byte marginAlpha, int marginColor, byte borderAlpha, int borderColor)


		int width = displayWidth;
		int height = displayHeight;

		ImageData data = new ImageData(width, height, 32, new PaletteData(
				0x000000FF, 0x0000FF00, 0x00FF0000));

		byte[] transparency = new byte[width * height];
		int[] pixels = new int[width * height];

		byte rowAlpha[] = new byte[width];
		int rowPixels[] = new int[width];
		//Top
		//Pattern
		for (int i = 0; i < width; i++) {
			rowAlpha[i] = marginAlpha;
			rowPixels[i] = marginColor;
		}
		//Fill
		for (int i = 0; i < MARGIN; i++) {
			System.arraycopy(rowAlpha, 0, transparency, i * width, width);
			System.arraycopy(rowPixels, 0, pixels, i * width, width);
		}

		//Main area
		//Pattern
		for (int i = 0; i < MARGIN; i++) {
			rowAlpha[i] = marginAlpha;
			rowAlpha[width - i - 1] = marginAlpha;
		}
		for (int i = MARGIN; i < width - MARGIN; i++) {
			rowAlpha[i] = 0;
		}
		//Fill
		for (int i = MARGIN; i < height - MARGIN; i++) {
			System.arraycopy(rowAlpha, 0, transparency, i * width, width);
			System.arraycopy(rowPixels, 0, pixels, i * width, width);
		}

		//Bottom
		//Pattern
		for (int i = 0; i < width; i++) {
			rowAlpha[i] = marginAlpha;
		}
		//Fill
		for (int i = height - MARGIN - 1; i < height; i++) {
			System.arraycopy(rowAlpha, 0, transparency, i * width, width);
			System.arraycopy(rowPixels, 0, pixels, i * width, width);
		}

		//Let's do the border part		
		for (int i = MARGIN; i < width - MARGIN; i++) {
			transparency[width * MARGIN + i] = borderAlpha;
			pixels[width * MARGIN + i] = borderColor;
		}
		for (int j = MARGIN; j < height - MARGIN; j++) {

			transparency[j * width + MARGIN] = borderAlpha;
			pixels[j * width + MARGIN] = borderColor;

			transparency[j * width + width - MARGIN - 1] = borderAlpha;
			pixels[j * width + width - MARGIN - 1] = borderColor;

		}
		for (int i = MARGIN; i < width - MARGIN; i++) {
			transparency[width * (height - MARGIN - 1) + i] = borderAlpha;
			pixels[width * (height - MARGIN - 1) + i] = borderColor;
		}

		data.alphaData = transparency;
		data.setPixels(0, 0, width * height, pixels, 0);

		Image overlay = new Image(display, data);

		return overlay;
	
private voiddispose()

		if (shell != null && !shell.isDisposed()) {
			shell.dispose();
		}

		if (currentImage != null && !currentImage.isDisposed()) {
			currentImage.dispose();
		}

		if (overlayDragging != null && !overlayDragging.isDisposed()) {
			overlayDragging.dispose();
		}

		if (overlayNotDragging != null && !overlayNotDragging.isDisposed()) {
			overlayNotDragging.dispose();
		}

		if (cursor != null && !cursor.isDisposed()) {
			cursor.dispose();
		}
	
private voiddrawCurrentImage()

		GC gcCanvas = new GC(canvas);

		Image temp = new Image(display, displayWidth, displayHeight);
		GC gc = new GC(temp);
		gc.drawImage(currentImage, offset.x + MARGIN + 1, offset.y + MARGIN + 1);
		//gc.setAlpha(128);
		gc.drawImage(overlay, 0, 0);
		//gc.setTextAntialias(SWT.ON);
		//gc.drawText("This is a test", 15, displayHeight-15,true);
		gc.dispose();

		gcCanvas.drawImage(temp, 0, 0);
		temp.dispose();

		gcCanvas.dispose();
	
private voidinitUI()


		cursor = new Cursor(display, SWT.CURSOR_HAND);

		if (parent != null) {
			shell = new Shell(parent, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
		} else {
			shell = new Shell(display, SWT.CLOSE | SWT.BORDER);
		}
		shell.setText("Thumbnail Assistant");

		Utils.setShellIcon(shell);

		shell.addListener(SWT.Close, new Listener() {
			public void handleEvent(Event event) {
				event.doit = false;
				result = null;
				done = true;
			}
		});

		FormLayout layout = new FormLayout();
		layout.marginBottom = 5;
		layout.marginTop = 5;
		layout.marginLeft = 5;
		layout.marginRight = 5;

		FormData data;
		shell.setLayout(layout);

		Label title = new Label(shell, SWT.WRAP);
		title.setText("This tool lets you preview how your thumbnail is going to look like on the Azureus Platform");

		data = new FormData();
		data.width = displayWidth;
		title.setLayoutData(data);

		canvas = new Canvas(shell, SWT.BORDER);
		canvas.setCursor(cursor);
		data = new FormData();
		data.width = displayWidth;
		data.height = displayHeight;
		data.top = new FormAttachment(title, 5);
		canvas.setLayoutData(data);

		canvas.addListener(SWT.MouseDown, moveImageListener);
		canvas.addListener(SWT.MouseUp, moveImageListener);
		canvas.addListener(SWT.MouseMove, moveImageListener);

		canvas.addPaintListener(new PaintListener() {
			public void paintControl(PaintEvent arg0) {
				drawCurrentImage();
			}
		});

		offset.x = (minWidth - currentImage.getBounds().width) / 2;
		offset.y = (minHeight - currentImage.getBounds().height) / 2;

		Label label = new Label(shell, SWT.WRAP);
		//The label text depends on the presence of the scale,
		//Thefore we delay the size computation as well as
		//Assiging any FormData (layout) to it see (1)

		//The Control to witch the Buttons OK and Cancel are going to be attached
		//Depends on the presence of the scale
		Control attach = label;

		if (minZoomRatio < 1) {
			scale = new Scale(shell, SWT.HORIZONTAL);
			data = new FormData();
			data.width = displayWidth;
			data.top = new FormAttachment(label, 5);
			scale.setLayoutData(data);
			scale.setMaximum((int) (RESIZE_STEPS * maxZoomRatio));
			scale.setMinimum((int) (RESIZE_STEPS * minZoomRatio));
			scale.setIncrement((int) ((maxZoomRatio - minZoomRatio) * RESIZE_STEPS / 10));
			scale.setPageIncrement((int) ((maxZoomRatio - minZoomRatio)
					* RESIZE_STEPS / 10));

			scale.addListener(SWT.Selection, new Listener() {
				public void handleEvent(Event arg0) {
					final long timestamp = SystemTime.getCurrentTime();
					lastUpdate = timestamp;

					final int position = scale.getSelection();

					AEThread t = new AEThread("") {
						public void runSupport() {
							try {
								Thread.sleep(150);
							} catch (Exception e) {
								e.printStackTrace();
							}

							if (timestamp == lastUpdate) {
								if (display != null && !display.isDisposed()) {
									display.asyncExec(new Runnable() {
										public void run() {
											refreshCurrentImage(position);
										}
									});
								}
							}
						}
					};
					t.setDaemon(true);
					t.start();

				}
			});
			attach = scale;
			label.setText("Move the image by dragging it, resize it by using the slider below");
		} else {
			label.setText("Move the image by dragging it");
		}

		// (1) Layout of the label, depending on the text in it
		int width = label.computeSize(SWT.DEFAULT, SWT.DEFAULT).x;
		if (width > displayWidth) {
			width = displayWidth;
		}

		data = new FormData();
		data.width = width;
		data.top = new FormAttachment(canvas, 5);
		data.left = new FormAttachment(canvas, 0, SWT.CENTER);
		label.setLayoutData(data);

		Button btnCancel = new Button(shell, SWT.PUSH);
		btnCancel.setText("Cancel");
		data = new FormData();
		data.width = 70;
		data.top = new FormAttachment(attach, 10);
		data.right = new FormAttachment(100, -10);
		btnCancel.setLayoutData(data);
		btnCancel.addListener(SWT.Selection, new Listener() {
			public void handleEvent(Event arg0) {
				result = null;
				done = true;
			}
		});

		Button btnOk = new Button(shell, SWT.PUSH);
		btnOk.setText("OK");
		data = new FormData();
		data.width = 70;
		data.top = new FormAttachment(attach, 10);
		data.right = new FormAttachment(btnCancel, -10);
		btnOk.setLayoutData(data);
		btnOk.addListener(SWT.Selection, new Listener() {
			public void handleEvent(Event arg0) {
				result = computeResultImage();
				done = true;
			}
		});

		shell.setDefaultButton(btnOk);
		btnOk.setFocus();
		shell.setSize(shell.computeSize(SWT.DEFAULT, SWT.DEFAULT));

		if (parent != null) {
			Utils.centerWindowRelativeTo(shell, parent);
		}

		shell.open();
		drawCurrentImage();

	
private voidinsureOffsetIsCorrect()

		int minX = minWidth - currentImage.getBounds().width;
		if (offset.x < minX) {
			offset.x = minX;
		}

		int minY = minHeight - currentImage.getBounds().height;
		if (offset.y < minY) {
			offset.y = minY;
		}

		if (offset.x > 0) {
			offset.x = 0;
		}

		if (offset.y > 0) {
			offset.y = 0;
		}

	
private ImageDatainternalResize(Image image, int newWidth, int newHeight)


		ImageData srcData = image.getImageData();

		//int width = srcData.width,height = srcData.height;

		ImageData data = srcData;
		//int newWidth = (int)(width*zoomRatio);
		//int newHeight = (int)(height*zoomRatio);

		final ImageData copy = new ImageData(newWidth, newHeight, 24,
				new PaletteData(0x00FF0000, 0x0000FF00, 0x000000FF));

		Image src = new Image(display, srcData);
		Image dst = new Image(display, copy);

		GC gc = new GC(dst);
		gc.setAdvanced(true);
		try {
			gc.setInterpolation(SWT.HIGH);
		} catch (Exception e) {
			// may not be avail
		}
		gc.drawImage(src, 0, 0, srcData.width, srcData.height, 0, 0, copy.width,
				copy.height);
		//gc.setAlpha(50);
		//gc.drawImage(src,2,2,srcData.width-2,srcData.height-2,0,0,copy.width,copy.height);
		gc.dispose();

		data = dst.getImageData();

		src.dispose();
		dst.dispose();

		return data;
	
public static voidmain(java.lang.String[] args)

		Display display = Display.getDefault();
		Shell test = new Shell(display);
		ImageResizer resizer = new ImageResizer(display, 228, 128, null);
		String file = new FileDialog(test).open();
		Image img = new Image(display, file);
		Image thumbnail = resizer.resize(img);

		System.out.println(thumbnail);

		thumbnail.dispose();
		test.dispose();
		if (args.length == 0) {
			display.dispose();
		}
	
private voidrefreshCurrentImage(int position)

		float previousZoom = zoomRatio;
		zoomRatio = (float) position / RESIZE_STEPS;
		if (zoomRatio > 1) {
			zoomRatio = 1;
		}
		if (zoomRatio < minZoomRatio) {
			zoomRatio = minZoomRatio;
		}
		if (previousZoom != zoomRatio) {
			Image previous = currentImage;
			currentImage = new Image(display,
					internalResize(original, (int) (originalWidth * zoomRatio),
							(int) (originalHeight * zoomRatio)));

			//float ratio = zoomRatio / previousZoom;
			offset.x += (previous.getBounds().width - currentImage.getBounds().width) / 2;
			offset.y += (previous.getBounds().height - currentImage.getBounds().height) / 2;

			if (previous != null && !previous.isDisposed()) {
				previous.dispose();
			}

			insureOffsetIsCorrect();
			drawCurrentImage();
		}
	
public Imageresize(Image original)


		this.original = original;

		//If the image is too small, let's just not deal with it
		if (!checkSize(original)) {
			dispose();
			throw new ImageResizeException(
					"The image provided is too small (has to be at least " + minWidth
							+ " x " + minHeight + "), please choose a different one");
		}

		originalWidth = original.getBounds().width;
		originalHeight = original.getBounds().height;

		currentImage = new Image(display, internalResize(original,
				(int) (originalWidth * zoomRatio), (int) (originalHeight * zoomRatio)));
		offset = new Point(0, 0);

		if (minWidth != original.getBounds().width
				|| minHeight != original.getBounds().height) {

			displayWidth = minWidth + 2 * (MARGIN + 1);
			displayHeight = minHeight + 2 * (MARGIN + 1);

			overlay = overlayNotDragging = createOverlayImage((byte) 255, 0x00FFFFFF,
					(byte) 255, 0x00000000);
			overlayDragging = createOverlayImage((byte) 80, 0x00FFFFFF, (byte) 255,
					0x00FFFFFF);

			initUI();

			done = false;
			while (!done) {
				if (!display.readAndDispatch()) {
					display.sleep();
				}
			}
		} else {
			result = computeResultImage();
		}

		dispose();

		return result;