Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'examples/org.eclipse.swt.examples/Eclipse SWT Examples/common/org/eclipse/swt/examples/imageexample/ImageAnalyzer.java')
-rwxr-xr-xexamples/org.eclipse.swt.examples/Eclipse SWT Examples/common/org/eclipse/swt/examples/imageexample/ImageAnalyzer.java1801
1 files changed, 1801 insertions, 0 deletions
diff --git a/examples/org.eclipse.swt.examples/Eclipse SWT Examples/common/org/eclipse/swt/examples/imageexample/ImageAnalyzer.java b/examples/org.eclipse.swt.examples/Eclipse SWT Examples/common/org/eclipse/swt/examples/imageexample/ImageAnalyzer.java
new file mode 100755
index 0000000000..c4135f4bed
--- /dev/null
+++ b/examples/org.eclipse.swt.examples/Eclipse SWT Examples/common/org/eclipse/swt/examples/imageexample/ImageAnalyzer.java
@@ -0,0 +1,1801 @@
+package org.eclipse.swt.examples.imageexample;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.layout.*;
+import org.eclipse.swt.graphics.*;
+import java.util.ResourceBundle;
+import java.text.MessageFormat;
+
+public class ImageAnalyzer {
+ private static ResourceBundle bundle = ResourceBundle.getBundle("examples_images");
+
+ Shell shell;
+ Canvas imageCanvas, paletteCanvas;
+ Label typeLabel, sizeLabel, depthLabel, transparentPixelLabel,
+ screenSizeLabel, backgroundPixelLabel, locationLabel,
+ disposalMethodLabel, delayTimeLabel, repeatCountLabel,
+ paletteLabel, dataLabel, statusLabel;
+ Combo backgroundCombo, scaleXCombo, scaleYCombo, alphaCombo;
+ Button incrementalCheck, transparentCheck, maskCheck, backgroundCheck;
+ Button previousButton, nextButton, animateButton;
+ Text dataText;
+ Display display;
+ Color whiteColor, blackColor, redColor, greenColor, blueColor, canvasBackground;
+ Font fixedWidthFont;
+ Cursor crossCursor;
+ GC imageCanvasGC;
+
+ int paletteWidth = 140; // recalculated and used as a width hint
+ int ix = 0, iy = 0, py = 0; // used to scroll the image and palette
+ float xscale = 1, yscale = 1; // used to scale the image
+ int alpha = 255; // used to modify the alpha value of the image
+ boolean incremental = false; // used to incrementally display an image
+ boolean transparent = true; // used to display an image with transparency
+ boolean showMask = false; // used to display an icon mask or transparent image mask
+ boolean showBackground = false; // used to display the background of an animated image
+ boolean animate = false; // used to animate a multi-image file
+ Thread animateThread;
+ String lastPath; // used to seed the file dialog
+ String fileName; // the current image file
+ ImageLoader loader; // the loader for the current image file
+ ImageData[] imageDataArray; // all image data read from the current file
+ int imageDataIndex; // the index of the current image data
+ ImageData imageData; // the currently-displayed image data
+ Image image; // the currently-displayed image
+ int drawIncrement = 0; // the index of the current incremental imageData to draw
+ int finalIncrement = 0; // the index of the final incremental imageData to draw
+
+ public static final int ALPHA_CONSTANT = 0;
+ public static final int ALPHA_X = 1;
+ public static final int ALPHA_Y = 2;
+
+ public static void main(String [] args) {
+ ImageAnalyzer imageAnalyzer = new ImageAnalyzer();
+ imageAnalyzer.open();
+ }
+
+ void open() {
+ // Create a window and set its title.
+ shell = new Shell();
+ shell.setText(bundle.getString("Image_analyzer"));
+
+ // Hook resize and dispose listeners.
+ shell.addControlListener(new ControlAdapter() {
+ public void controlResized(ControlEvent event) {
+ resizeShell(event);
+ }
+ });
+ shell.addShellListener(new ShellAdapter() {
+ public void shellClosed(ShellEvent event) {
+ if (animate && animateThread != null) {
+ // Stop the animation and wait for the
+ // thread to die before disposing the shell.
+ animate = false;
+ while (animateThread.isAlive()) {
+ if (!display.readAndDispatch()) display.sleep();
+ }
+ }
+ }
+ });
+
+ // Create colors and fonts.
+ display = shell.getDisplay();
+ whiteColor = new Color(display, 255, 255, 255);
+ blackColor = new Color(display, 0, 0, 0);
+ redColor = new Color(display, 255, 0, 0);
+ greenColor = new Color(display, 0, 255, 0);
+ blueColor = new Color(display, 0, 0, 255);
+ fixedWidthFont = new Font(display, "courier", 10, 0);
+ crossCursor = new Cursor(display, SWT.CURSOR_CROSS);
+
+ // Add a menu bar and widgets.
+ Menu menuBar = createMenuBar();
+ createWidgets();
+ shell.pack();
+
+ // Create a GC for drawing.
+ imageCanvasGC = new GC(imageCanvas);
+
+ // Open the window, and run an event loop until the window is closed.
+ shell.open();
+ while (!shell.isDisposed())
+ if (!display.readAndDispatch()) display.sleep();
+
+ // Clean up.
+ if (image != null)
+ image.dispose();
+ whiteColor.dispose();
+ blackColor.dispose();
+ redColor.dispose();
+ greenColor.dispose();
+ blueColor.dispose();
+ fixedWidthFont.dispose();
+ crossCursor.dispose();
+ imageCanvasGC.dispose();
+ }
+
+ void createWidgets() {
+ // Add the widgets to the shell in a grid layout.
+ GridLayout layout = new GridLayout();
+ layout.marginHeight = 0;
+ layout.numColumns = 2;
+ shell.setLayout(layout);
+
+ // Separate the menu bar from the rest of the widgets.
+ Label separator = new Label(shell, SWT.SEPARATOR | SWT.HORIZONTAL);
+ GridData gridData = new GridData();
+ gridData.horizontalSpan = 2;
+ gridData.horizontalAlignment = GridData.FILL;
+ separator.setLayoutData(gridData);
+
+ // Add a composite to contain some control widgets across the top.
+ Composite controls = new Composite(shell, SWT.NULL);
+ RowLayout rowLayout = new RowLayout();
+ rowLayout.marginTop = 0;
+ rowLayout.marginBottom = 5;
+ rowLayout.spacing = 8;
+ controls.setLayout(rowLayout);
+ gridData = new GridData();
+ gridData.horizontalSpan = 2;
+ controls.setLayoutData(gridData);
+
+ // Combo to change the background.
+ Group group = new Group(controls, SWT.NULL);
+ group.setLayout(new RowLayout());
+ group.setText(bundle.getString("Background"));
+ backgroundCombo = new Combo(group, SWT.DROP_DOWN | SWT.READ_ONLY);
+ backgroundCombo.setItems(new String[] {
+ bundle.getString("None"),
+ bundle.getString("White"),
+ bundle.getString("Black"),
+ bundle.getString("Red"),
+ bundle.getString("Green"),
+ bundle.getString("Blue")});
+ backgroundCombo.select(backgroundCombo.indexOf(bundle.getString("White")));
+ backgroundCombo.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent event) {
+ changeBackground();
+ }
+ });
+
+
+ // Combo to change the x scale.
+ String[] values = {
+ "0.1", "0.2", "0.3", "0.4", "0.5", "0.6", "0.7", "0.8", "0.9", "1",
+ "1.1", "1.2", "1.3", "1.4", "1.5", "1.6", "1.7", "1.8", "1.9", "2",
+ "3", "4", "5", "6", "7", "8", "9", "10",};
+ group = new Group(controls, SWT.NULL);
+ group.setLayout(new RowLayout());
+ group.setText(bundle.getString("X_scale"));
+ scaleXCombo = new Combo(group, SWT.DROP_DOWN);
+ for (int i = 0; i < values.length; i++) {
+ scaleXCombo.add(values[i]);
+ }
+ scaleXCombo.select(scaleXCombo.indexOf("1"));
+ scaleXCombo.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent event) {
+ scaleX();
+ }
+ });
+
+ // Combo to change the y scale.
+ group = new Group(controls, SWT.NULL);
+ group.setLayout(new RowLayout());
+ group.setText(bundle.getString("Y_scale"));
+ scaleYCombo = new Combo(group, SWT.DROP_DOWN);
+ for (int i = 0; i < values.length; i++) {
+ scaleYCombo.add(values[i]);
+ }
+ scaleYCombo.select(scaleYCombo.indexOf("1"));
+ scaleYCombo.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent event) {
+ scaleY();
+ }
+ });
+
+ // Combo to change the alpha value.
+ group = new Group(controls, SWT.NULL);
+ group.setLayout(new RowLayout());
+ group.setText(bundle.getString("Alpha_K"));
+ alphaCombo = new Combo(group, SWT.DROP_DOWN | SWT.READ_ONLY);
+ for (int i = 0; i <= 255; i += 5) {
+ alphaCombo.add(String.valueOf(i));
+ }
+ alphaCombo.select(alphaCombo.indexOf("255"));
+ alphaCombo.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent event) {
+ alpha();
+ }
+ });
+
+ // Check box to request incremental display.
+ group = new Group(controls, SWT.NULL);
+ group.setLayout(new RowLayout());
+ group.setText(bundle.getString("Display"));
+ incrementalCheck = new Button(group, SWT.CHECK);
+ incrementalCheck.setText(bundle.getString("Incremental"));
+ incrementalCheck.setSelection(incremental);
+ incrementalCheck.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent event) {
+ incremental = ((Button)event.widget).getSelection();
+ }
+ });
+
+ // Check box to request transparent display.
+ transparentCheck = new Button(group, SWT.CHECK);
+ transparentCheck.setText(bundle.getString("Transparent"));
+ transparentCheck.setSelection(transparent);
+ transparentCheck.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent event) {
+ transparent = ((Button)event.widget).getSelection();
+ if (image != null) {
+ imageCanvas.redraw();
+ }
+ }
+ });
+
+ // Check box to request mask display.
+ maskCheck = new Button(group, SWT.CHECK);
+ maskCheck.setText(bundle.getString("Mask"));
+ maskCheck.setSelection(showMask);
+ maskCheck.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent event) {
+ showMask = ((Button)event.widget).getSelection();
+ if (image != null) {
+ imageCanvas.redraw();
+ }
+ }
+ });
+
+ // Check box to request background display.
+ backgroundCheck = new Button(group, SWT.CHECK);
+ backgroundCheck.setText(bundle.getString("Background"));
+ backgroundCheck.setSelection(showBackground);
+ backgroundCheck.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent event) {
+ showBackground = ((Button)event.widget).getSelection();
+ }
+ });
+
+ // Group the animation buttons.
+ group = new Group(controls, SWT.NULL);
+ group.setLayout(new RowLayout());
+ group.setText(bundle.getString("Animation"));
+
+ // Push button to display the previous image in a multi-image file.
+ previousButton = new Button(group, SWT.PUSH);
+ previousButton.setText(bundle.getString("Previous"));
+ previousButton.setEnabled(false);
+ previousButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent event) {
+ previous();
+ }
+ });
+
+ // Push button to display the next image in a multi-image file.
+ nextButton = new Button(group, SWT.PUSH);
+ nextButton.setText(bundle.getString("Next"));
+ nextButton.setEnabled(false);
+ nextButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent event) {
+ next();
+ }
+ });
+
+ // Push button to toggle animation of a multi-image file.
+ animateButton = new Button(group, SWT.PUSH);
+ animateButton.setText(bundle.getString("Animate"));
+ animateButton.setEnabled(false);
+ animateButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent event) {
+ animate();
+ }
+ });
+
+ // Separate the control widgets from the rest of the widgets.
+// Label separator = new Label(shell, SWT.SEPARATOR | SWT.HORIZONTAL);
+// gridData = new GridData();
+// gridData.horizontalSpan = 2;
+// gridData.horizontalAlignment = GridData.FILL;
+// separator.setLayoutData(gridData);
+
+ // Label to show the image file type.
+ typeLabel = new Label(shell, SWT.NULL);
+ typeLabel.setText(bundle.getString("Type_initial"));
+ typeLabel.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
+
+ // Canvas to show the image.
+ imageCanvas = new Canvas(shell, SWT.V_SCROLL | SWT.H_SCROLL | SWT.NO_REDRAW_RESIZE);
+ imageCanvas.setBackground(whiteColor);
+ imageCanvas.setCursor(crossCursor);
+ gridData = new GridData();
+ gridData.verticalSpan = 14;
+ gridData.horizontalAlignment = GridData.FILL;
+ gridData.verticalAlignment = GridData.FILL;
+ gridData.grabExcessHorizontalSpace = true;
+ gridData.grabExcessVerticalSpace = true;
+ imageCanvas.setLayoutData(gridData);
+ imageCanvas.addPaintListener(new PaintListener() {
+ public void paintControl(PaintEvent event) {
+ if (image != null)
+ paintImage(event);
+ }
+ });
+ imageCanvas.addMouseMoveListener(new MouseMoveListener() {
+ public void mouseMove(MouseEvent event) {
+ if (image != null) {
+ showColorAt(event.x, event.y);
+ }
+ }
+ });
+
+ // Set up the image canvas scroll bars.
+ ScrollBar horizontal = imageCanvas.getHorizontalBar();
+ horizontal.setVisible(true);
+ horizontal.setMinimum(0);
+ horizontal.setEnabled(false);
+ horizontal.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent event) {
+ scrollHorizontally((ScrollBar)event.widget);
+ }
+ });
+ ScrollBar vertical = imageCanvas.getVerticalBar();
+ vertical.setVisible(true);
+ vertical.setMinimum(0);
+ vertical.setEnabled(false);
+ vertical.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent event) {
+ scrollVertically((ScrollBar)event.widget);
+ }
+ });
+
+ // Label to show the image size.
+ sizeLabel = new Label(shell, SWT.NULL);
+ sizeLabel.setText(bundle.getString("Size_initial"));
+ sizeLabel.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
+
+ // Label to show the image depth.
+ depthLabel = new Label(shell, SWT.NULL);
+ depthLabel.setText(bundle.getString("Depth_initial"));
+ depthLabel.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
+
+ // Label to show the transparent pixel.
+ transparentPixelLabel = new Label(shell, SWT.NULL);
+ transparentPixelLabel.setText(bundle.getString("Transparent_pixel_initial"));
+ transparentPixelLabel.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
+
+ // Separate the animation fields from the rest of the fields.
+ separator = new Label(shell, SWT.SEPARATOR | SWT.HORIZONTAL);
+ separator.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
+
+ // Label to show the logical screen size for animation.
+ screenSizeLabel = new Label(shell, SWT.NULL);
+ screenSizeLabel.setText(bundle.getString("Animation_size_initial"));
+ screenSizeLabel.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
+
+ // Label to show the background pixel.
+ backgroundPixelLabel = new Label(shell, SWT.NULL);
+ backgroundPixelLabel.setText(bundle.getString("Background_pixel_initial"));
+ backgroundPixelLabel.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
+
+ // Label to show the image location (x, y).
+ locationLabel = new Label(shell, SWT.NULL);
+ locationLabel.setText(bundle.getString("Image_location_initial"));
+ locationLabel.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
+
+ // Label to show the image disposal method.
+ disposalMethodLabel = new Label(shell, SWT.NULL);
+ disposalMethodLabel.setText(bundle.getString("Disposal_initial"));
+ disposalMethodLabel.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
+
+ // Label to show the image delay time.
+ delayTimeLabel = new Label(shell, SWT.NULL);
+ delayTimeLabel.setText(bundle.getString("Delay_initial"));
+ delayTimeLabel.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
+
+ // Label to show the background pixel.
+ repeatCountLabel = new Label(shell, SWT.NULL);
+ repeatCountLabel.setText(bundle.getString("Repeats_initial"));
+ repeatCountLabel.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
+
+ // Separate the animation fields from the palette.
+ separator = new Label(shell, SWT.SEPARATOR | SWT.HORIZONTAL);
+ separator.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
+
+ // Label to show if the image has a direct or indexed palette.
+ paletteLabel = new Label(shell, SWT.NULL);
+ paletteLabel.setText(bundle.getString("Palette_initial"));
+ paletteLabel.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
+
+ // Canvas to show the image's palette.
+ paletteCanvas = new Canvas(shell, SWT.BORDER | SWT.V_SCROLL | SWT.NO_REDRAW_RESIZE);
+ paletteCanvas.setFont(fixedWidthFont);
+ paletteCanvas.getVerticalBar().setVisible(true);
+ gridData = new GridData();
+ gridData.horizontalAlignment = GridData.FILL;
+ gridData.verticalAlignment = GridData.FILL;
+ GC gc = new GC(paletteLabel);
+ paletteWidth = gc.stringExtent(bundle.getString("Max_length_string")).x;
+ gc.dispose();
+ gridData.widthHint = paletteWidth;
+ gridData.heightHint = 16 * 11; // show at least 16 colors
+ paletteCanvas.setLayoutData(gridData);
+ paletteCanvas.addPaintListener(new PaintListener() {
+ public void paintControl(PaintEvent event) {
+ if (image != null)
+ paintPalette(event);
+ }
+ });
+
+ // Set up the palette canvas scroll bar.
+ vertical = paletteCanvas.getVerticalBar();
+ vertical.setVisible(true);
+ vertical.setMinimum(0);
+ vertical.setIncrement(10);
+ vertical.setEnabled(false);
+ vertical.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent event) {
+ scrollPalette((ScrollBar)event.widget);
+ }
+ });
+
+ // Sash to see more of image or image data.
+ Sash sash = new Sash(shell, SWT.HORIZONTAL);
+ gridData = new GridData();
+ gridData.horizontalSpan = 2;
+ gridData.horizontalAlignment = GridData.FILL;
+ sash.setLayoutData(gridData);
+
+ // Label to show data-specific fields.
+ dataLabel = new Label(shell, SWT.NULL);
+ dataLabel.setText(bundle.getString("Pixel_data_initial"));
+ gridData = new GridData();
+ gridData.horizontalSpan = 2;
+ gridData.horizontalAlignment = GridData.FILL;
+ dataLabel.setLayoutData(gridData);
+
+ // Text to show a dump of the data.
+ dataText = new Text(shell, SWT.BORDER | SWT.MULTI | SWT.READ_ONLY | SWT.V_SCROLL | SWT.H_SCROLL);
+ dataText.setFont(fixedWidthFont);
+ gridData = new GridData();
+ gridData.horizontalSpan = 2;
+ gridData.horizontalAlignment = GridData.FILL;
+ gridData.verticalAlignment = GridData.FILL;
+ gridData.heightHint = 128;
+ gridData.grabExcessVerticalSpace = true;
+ dataText.setLayoutData(gridData);
+ dataText.addMouseListener(new MouseAdapter() {
+ public void mouseDown(MouseEvent event) {
+ if (image != null && event.button == 1) {
+ showColorForData();
+ }
+ }
+ });
+ dataText.addKeyListener(new KeyAdapter() {
+ public void keyPressed(KeyEvent event) {
+ if (image != null) {
+ showColorForData();
+ }
+ }
+ });
+
+ // Label to show status and cursor location in image.
+ statusLabel = new Label(shell, SWT.NULL);
+ statusLabel.setText("");
+ gridData = new GridData();
+ gridData.horizontalSpan = 2;
+ gridData.horizontalAlignment = GridData.FILL;
+ statusLabel.setLayoutData(gridData);
+ }
+
+ Menu createMenuBar() {
+ // Menu bar.
+ Menu menuBar = new Menu(shell, SWT.BAR);
+ shell.setMenuBar(menuBar);
+
+ createFileMenu(menuBar);
+ createAlphaMenu(menuBar);
+
+ return menuBar;
+ }
+
+ void createFileMenu(Menu menuBar) {
+ // File menu
+ MenuItem item = new MenuItem(menuBar, SWT.CASCADE);
+ item.setText(bundle.getString("File"));
+ Menu fileMenu = new Menu(shell, SWT.DROP_DOWN);
+ item.setMenu(fileMenu);
+
+ // File -> Open...
+ item = new MenuItem(fileMenu, SWT.NULL);
+ item.setText(bundle.getString("Open"));
+ item.setAccelerator(SWT.CTRL + 'O');
+ item.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent event) {
+ menuOpen();
+ }
+ });
+
+ // File -> Reopen
+ item = new MenuItem(fileMenu, SWT.NULL);
+ item.setText(bundle.getString("Reopen"));
+ item.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent event) {
+ menuReopen();
+ }
+ });
+
+ new MenuItem(fileMenu, SWT.SEPARATOR);
+
+ // File -> Save
+ item = new MenuItem(fileMenu, SWT.NULL);
+ item.setText(bundle.getString("Save"));
+ item.setAccelerator(SWT.CTRL + 'S');
+ item.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent event) {
+ menuSave();
+ }
+ });
+
+ // File -> Save As...
+ item = new MenuItem(fileMenu, SWT.NULL);
+ item.setText(bundle.getString("Save_as"));
+ item.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent event) {
+ menuSaveAs();
+ }
+ });
+
+ // File -> Save Mask As...
+ item = new MenuItem(fileMenu, SWT.NULL);
+ item.setText(bundle.getString("Save_mask_as"));
+ item.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent event) {
+ menuSaveMaskAs();
+ }
+ });
+
+ new MenuItem(fileMenu, SWT.SEPARATOR);
+
+ // File -> Exit
+ item = new MenuItem(fileMenu, SWT.NULL);
+ item.setText(bundle.getString("Exit"));
+ item.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent event) {
+ animate = false; // stop any animation in progress
+ shell.close();
+ }
+ });
+
+ }
+
+ void createAlphaMenu(Menu menuBar) {
+ // Alpha menu
+ MenuItem item = new MenuItem(menuBar, SWT.CASCADE);
+ item.setText(bundle.getString("Alpha"));
+ Menu alphaMenu = new Menu(shell, SWT.DROP_DOWN);
+ item.setMenu(alphaMenu);
+
+ // Alpha -> K
+ item = new MenuItem(alphaMenu, SWT.NULL);
+ item.setText("K");
+ item.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent event) {
+ menuComposeAlpha(ALPHA_CONSTANT);
+ }
+ });
+
+ // Alpha -> (K + x) % 256
+ item = new MenuItem(alphaMenu, SWT.NULL);
+ item.setText("(K + x) % 256");
+ item.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent event) {
+ menuComposeAlpha(ALPHA_X);
+ }
+ });
+
+ // Alpha -> (K + y) % 256
+ item = new MenuItem(alphaMenu, SWT.NULL);
+ item.setText("(K + y) % 256");
+ item.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent event) {
+ menuComposeAlpha(ALPHA_Y);
+ }
+ });
+ }
+
+ void menuComposeAlpha(int alpha_op) {
+ if (image == null) return;
+ animate = false; // stop any animation in progress
+
+ Cursor waitCursor = new Cursor(display, SWT.CURSOR_WAIT);
+ shell.setCursor(waitCursor);
+ try {
+ if (alpha_op == ALPHA_CONSTANT) {
+ imageData.alpha = alpha;
+ } else {
+ imageData.alpha = -1;
+ switch (alpha_op) {
+ case ALPHA_X:
+ for (int y = 0; y < imageData.height; y++) {
+ for (int x = 0; x < imageData.width; x++) {
+ imageData.setAlpha(x, y, (x + alpha) % 256);
+ }
+ }
+ break;
+ case ALPHA_Y:
+ for (int y = 0; y < imageData.height; y++) {
+ for (int x = 0; x < imageData.width; x++) {
+ imageData.setAlpha(x, y, (y + alpha) % 256);
+ }
+ }
+ break;
+ default: break;
+ }
+ }
+ displayImage(imageData);
+ } finally {
+ shell.setCursor(null);
+ waitCursor.dispose();
+ }
+ }
+
+ void menuOpen() {
+ animate = false; // stop any animation in progress
+ resetScaleCombos();
+
+ // Get the user to choose an image file.
+ FileDialog fileChooser = new FileDialog(shell, SWT.OPEN);
+ if (lastPath != null)
+ fileChooser.setFilterPath(lastPath);
+ fileChooser.setFilterExtensions(new String[] { "*.bmp; *.gif; *.ico; *.jpg; *.pcx; *.png; *.tif", "*.bmp", "*.gif", "*.ico", "*.jpg", "*.pcx", "*.png", "*.tif" });
+ fileChooser.setFilterNames(new String[] { bundle.getString("All_images") + " (bmp, gif, ico, jpg, pcx, png, tif)",
+ "BMP (*.bmp)", "GIF (*.gif)", "ICO (*.ico)", "JPEG (*.jpg)", "PCX (*.pcx)", "PNG (*.png)", "TIFF (*.tif)" });
+ String filename = fileChooser.open();
+ lastPath = fileChooser.getFilterPath();
+ if (filename == null)
+ return;
+
+ Cursor waitCursor = new Cursor(display, SWT.CURSOR_WAIT);
+ shell.setCursor(waitCursor);
+ try {
+ loader = new ImageLoader();
+ if (incremental) {
+ // Prepare to handle incremental images.
+ drawIncrement = 0;
+ finalIncrement = 0;
+ loader.addImageLoaderListener(new ImageLoaderListener() {
+ public void imageDataLoaded(ImageLoaderEvent event) {
+ incrementalDataLoaded(event);
+ }
+ });
+ }
+ // Read the new image(s) from the chosen file.
+ imageDataArray = loader.load(filename);
+ if (imageDataArray.length > 0) {
+
+ // Cache the filename.
+ fileName = filename;
+
+ // If there are multiple images in the file (typically GIF)
+ // then enable the Previous, Next and Animate buttons.
+ previousButton.setEnabled(imageDataArray.length > 1);
+ nextButton.setEnabled(imageDataArray.length > 1);
+ animateButton.setEnabled(imageDataArray.length > 1 && loader.logicalScreenWidth > 0 && loader.logicalScreenHeight > 0);
+
+ // Display the first image in the file.
+ imageDataIndex = 0;
+ displayImage(imageDataArray[imageDataIndex]);
+ resetScrollBars();
+ }
+ } catch (SWTException e) {
+ showErrorDialog(bundle.getString("Loading_lc"), filename, e);
+ } finally {
+ shell.setCursor(null);
+ waitCursor.dispose();
+ }
+ }
+
+ /*
+ * Called when incremental image data has been loaded,
+ * for example, for interlaced GIF/PNG or progressive JPEG.
+ */
+ void incrementalDataLoaded(final ImageLoaderEvent event) {
+ if (event.endOfImage) {
+ finalIncrement = event.incrementCount;
+ } else {
+ Thread incrementalThread = new Thread("Incremental") {
+ public void run() {
+ // make absolutely certain that threads draw in order
+ while (event.incrementCount != drawIncrement) {
+ yield();
+ }
+
+ // lock so threads draw one at a time
+ synchronized (imageCanvas) {
+ drawIncrement++;
+ if (image != null) image.dispose();
+ image = new Image(null, event.imageData);
+ imageData = event.imageData;
+ imageCanvasGC.drawImage(
+ image,
+ 0,
+ 0,
+ imageData.width,
+ imageData.height,
+ imageData.x,
+ imageData.y,
+ imageData.width,
+ imageData.height);
+ }
+ display.wake();
+ }
+ };
+ incrementalThread.start();
+ }
+ }
+
+ void menuSave() {
+ if (image == null) return;
+ animate = false; // stop any animation in progress
+
+ // If the image file type is unknown, we can't 'Save',
+ // so we have to use 'Save As...'.
+ if (imageData.type == SWT.IMAGE_UNDEFINED) {
+ menuSaveAs();
+ return;
+ }
+
+ Cursor waitCursor = new Cursor(display, SWT.CURSOR_WAIT);
+ shell.setCursor(waitCursor);
+ try {
+ // Save the current image to the current file.
+ loader.data = new ImageData[] {imageData};
+ loader.save(fileName, imageData.type);
+
+ } catch (SWTException e) {
+ showErrorDialog(bundle.getString("Saving_lc"), fileName, e);
+ } finally {
+ shell.setCursor(null);
+ waitCursor.dispose();
+ }
+ }
+
+ void menuSaveAs() {
+ if (image == null) return;
+ animate = false; // stop any animation in progress
+
+ // Get the user to choose a file name and type to save.
+ FileDialog fileChooser = new FileDialog(shell, SWT.SAVE);
+ fileChooser.setFilterPath(lastPath);
+ fileChooser.setFileName(fileName);
+ fileChooser.setFilterExtensions(new String[] { "*.bmp", "*.gif", "*.ico", "*.jpg", "*.png" });
+ fileChooser.setFilterNames(new String[] { "BMP (*.bmp)", "GIF (*.gif)", "ICO (*.ico)", "JPEG (*.jpg)", "PNG (*.png)" });
+ String filename = fileChooser.open();
+ lastPath = fileChooser.getFilterPath();
+ if (filename == null)
+ return;
+
+ // Figure out what file type the user wants saved.
+ // We need to rely on the file extension because FileDialog
+ // does not have API for asking what filter type was selected.
+ int filetype = determineFileType(filename);
+ if (filetype == SWT.IMAGE_UNDEFINED) {
+ MessageBox box = new MessageBox(shell, SWT.ICON_ERROR);
+ box.setMessage(createMsg(bundle.getString("Unknown_extension"),
+ filename.substring(filename.lastIndexOf('.') + 1)));
+ box.open();
+ return;
+ }
+
+ if (new java.io.File(filename).exists()) {
+ MessageBox box = new MessageBox(shell, SWT.ICON_QUESTION | SWT.OK | SWT.CANCEL);
+ box.setMessage(createMsg(bundle.getString("Overwrite"), filename));
+ if (box.open() == SWT.CANCEL)
+ return;
+ }
+
+ Cursor waitCursor = new Cursor(display, SWT.CURSOR_WAIT);
+ shell.setCursor(waitCursor);
+ try {
+ // Save the current image to the specified file.
+ loader.data = new ImageData[] {imageData};
+ loader.save(filename, filetype);
+
+ // Update the shell title and file type label,
+ // and use the new file.
+ fileName = filename;
+ shell.setText(createMsg(bundle.getString("Analyzer_on"), filename));
+ typeLabel.setText(createMsg(bundle.getString("Type_string"), fileTypeString(filetype)));
+
+ } catch (SWTException e) {
+ showErrorDialog(bundle.getString("Saving_lc"), filename, e);
+ } finally {
+ shell.setCursor(null);
+ waitCursor.dispose();
+ }
+ }
+
+ void menuSaveMaskAs() {
+ if (image == null || !showMask) return;
+ if (imageData.getTransparencyType() == SWT.TRANSPARENCY_NONE) return;
+ animate = false; // stop any animation in progress
+
+ // Get the user to choose a file name and type to save.
+ FileDialog fileChooser = new FileDialog(shell, SWT.SAVE);
+ fileChooser.setFilterPath(lastPath);
+ fileChooser.setFileName(fileName);
+ fileChooser.setFilterExtensions(new String[] { "*.bmp", "*.gif", "*.ico", "*.jpg", "*.png" });
+ fileChooser.setFilterNames(new String[] { "BMP (*.bmp)", "GIF (*.gif)", "ICO (*.ico)", "JPEG (*.jpg)", "PNG (*.png)" });
+ String filename = fileChooser.open();
+ lastPath = fileChooser.getFilterPath();
+ if (filename == null)
+ return;
+
+ // Figure out what file type the user wants saved.
+ // We need to rely on the file extension because FileDialog
+ // does not have API for asking what filter type was selected.
+ int filetype = determineFileType(filename);
+ if (filetype == SWT.IMAGE_UNDEFINED) {
+ MessageBox box = new MessageBox(shell, SWT.ICON_ERROR);
+ box.setMessage(createMsg(bundle.getString("Unknown_extension"),
+ filename.substring(filename.lastIndexOf('.') + 1)));
+ box.open();
+ return;
+ }
+
+ if (new java.io.File(filename).exists()) {
+ MessageBox box = new MessageBox(shell, SWT.ICON_QUESTION | SWT.OK | SWT.CANCEL);
+ box.setMessage(createMsg(bundle.getString("Overwrite"), filename));
+ if (box.open() == SWT.CANCEL)
+ return;
+ }
+
+ Cursor waitCursor = new Cursor(display, SWT.CURSOR_WAIT);
+ shell.setCursor(waitCursor);
+ try {
+ // Save the mask of the current image to the specified file.
+ ImageData maskImageData = imageData.getTransparencyMask();
+ loader.data = new ImageData[] {maskImageData};
+ loader.save(filename, filetype);
+
+ } catch (SWTException e) {
+ showErrorDialog(bundle.getString("Saving_lc"), filename, e);
+ } finally {
+ shell.setCursor(null);
+ waitCursor.dispose();
+ }
+ }
+
+ void menuReopen() {
+ if (fileName == null) return;
+ animate = false; // stop any animation in progress
+ resetScrollBars();
+ resetScaleCombos();
+
+ Cursor waitCursor = new Cursor(display, SWT.CURSOR_WAIT);
+ shell.setCursor(waitCursor);
+ try {
+ loader = new ImageLoader();
+ ImageData[] newImageData = loader.load(fileName);
+ imageDataIndex = 0;
+ displayImage(newImageData[imageDataIndex]);
+
+ } catch (SWTException e) {
+ showErrorDialog(bundle.getString("Reloading_lc"), fileName, e);
+ } finally {
+ shell.setCursor(null);
+ waitCursor.dispose();
+ }
+ }
+
+ void changeBackground() {
+ String background = backgroundCombo.getText();
+ if (background.equals(bundle.getString("White"))) {
+ imageCanvas.setBackground(whiteColor);
+ } else if (background.equals(bundle.getString("Black"))) {
+ imageCanvas.setBackground(blackColor);
+ } else if (background.equals(bundle.getString("Red"))) {
+ imageCanvas.setBackground(redColor);
+ } else if (background.equals(bundle.getString("Green"))) {
+ imageCanvas.setBackground(greenColor);
+ } else if (background.equals(bundle.getString("Blue"))) {
+ imageCanvas.setBackground(blueColor);
+ } else {
+ imageCanvas.setBackground(null);
+ }
+ // Fill the image canvas with the background color.
+ Rectangle clientArea = imageCanvas.getClientArea();
+ imageCanvasGC.fillRectangle(
+ clientArea.x,
+ clientArea.y,
+ clientArea.width,
+ clientArea.height);
+ if (image != null) {
+ imageCanvas.redraw();
+ }
+ }
+
+ /*
+ * Called when the ScaleX combo selection changes.
+ */
+ void scaleX() {
+ try {
+ xscale = Float.parseFloat(scaleXCombo.getText());
+ } catch (NumberFormatException e) {
+ xscale = 1;
+ scaleXCombo.select(scaleXCombo.indexOf("1"));
+ }
+ if (image != null) {
+ resizeScrollBars();
+ imageCanvas.redraw();
+ }
+ }
+
+ /*
+ * Called when the ScaleY combo selection changes.
+ */
+ void scaleY() {
+ try {
+ yscale = Float.parseFloat(scaleYCombo.getText());
+ } catch (NumberFormatException e) {
+ yscale = 1;
+ scaleYCombo.select(scaleYCombo.indexOf("1"));
+ }
+ if (image != null) {
+ resizeScrollBars();
+ imageCanvas.redraw();
+ }
+ }
+
+ /*
+ * Called when the Alpha combo selection changes.
+ */
+ void alpha() {
+ try {
+ alpha = Integer.parseInt(alphaCombo.getText());
+ } catch (NumberFormatException e) {
+ alphaCombo.select(alphaCombo.indexOf("255"));
+ alpha = 255;
+ }
+ }
+
+ /*
+ * Called when the mouse moves in the image canvas.
+ * Show the color of the image at the point under the mouse.
+ */
+ void showColorAt(int mx, int my) {
+ int x = mx - imageData.x - ix;
+ int y = my - imageData.y - iy;
+ showColorForPixel(x, y);
+ }
+
+ /*
+ * Called when a mouse down or key press is detected
+ * in the data text. Show the color of the pixel at
+ * the caret position in the data text.
+ */
+ void showColorForData() {
+ int delimiterLength = dataText.getLineDelimiter().length();
+ int charactersPerLine = 6 + 3 * imageData.bytesPerLine + delimiterLength;
+ int position = dataText.getCaretPosition();
+ int y = position / charactersPerLine;
+ if ((position - y * charactersPerLine) < 6 || ((y + 1) * charactersPerLine - position) <= delimiterLength) {
+ statusLabel.setText("");
+ return;
+ }
+ int dataPosition = position - 6 * (y + 1) - delimiterLength * y;
+ int byteNumber = dataPosition / 3;
+ int where = dataPosition - byteNumber * 3;
+ int xByte = byteNumber % imageData.bytesPerLine;
+ int x = -1;
+ int depth = imageData.depth;
+ if (depth == 1) { // 8 pixels per byte (can only show 3 of 8)
+ if (where == 0) x = xByte * 8;
+ if (where == 1) x = xByte * 8 + 3;
+ if (where == 2) x = xByte * 8 + 7;
+ }
+ if (depth == 2) { // 4 pixels per byte (can only show 3 of 4)
+ if (where == 0) x = xByte * 4;
+ if (where == 1) x = xByte * 4 + 1;
+ if (where == 2) x = xByte * 4 + 3;
+ }
+ if (depth == 4) { // 2 pixels per byte
+ if (where == 0) x = xByte * 2;
+ if (where == 1) x = xByte * 2;
+ if (where == 2) x = xByte * 2 + 1;
+ }
+ if (depth == 8) { // 1 byte per pixel
+ x = xByte;
+ }
+ if (depth == 16) { // 2 bytes per pixel
+ x = xByte / 2;
+ }
+ if (depth == 24) { // 3 bytes per pixel
+ x = xByte / 3;
+ }
+ if (depth == 32) { // 4 bytes per pixel
+ x = xByte / 4;
+ }
+ if (x != -1) {
+ showColorForPixel(x, y);
+ } else {
+ statusLabel.setText("");
+ }
+ }
+
+ /*
+ * Set the status label to show color information
+ * for the specified pixel in the image.
+ */
+ void showColorForPixel(int x, int y) {
+ if (x >= 0 && x < imageData.width && y >= 0 && y < imageData.height) {
+ int pixel = imageData.getPixel(x, y);
+ RGB rgb = imageData.palette.getRGB(pixel);
+
+ Object[] args = {new Integer(x),
+ new Integer(y),
+ new Integer(pixel),
+ Integer.toHexString(pixel),
+ rgb};
+ if(pixel == imageData.transparentPixel){
+ statusLabel.setText(createMsg(bundle.getString("Color_at_trans"), args));
+ } else {
+ statusLabel.setText(createMsg(bundle.getString("Color_at"), args));
+ }
+ } else {
+ statusLabel.setText("");
+ }
+ }
+
+ /*
+ * Called when the Animate button is pressed.
+ */
+ void animate() {
+ animate = !animate;
+ if (animate && image != null && imageDataArray.length > 1) {
+ animateThread = new Thread(bundle.getString("Animation")) {
+ public void run() {
+ // Pre-animation widget setup.
+ preAnimation();
+
+ // Animate.
+ try {
+ animateLoop();
+ } catch (final SWTException e) {
+ display.syncExec(new Runnable() {
+ public void run() {
+ showErrorDialog(createMsg(bundle.getString("Creating_image"),
+ new Integer(imageDataIndex+1)),
+ fileName, e);
+ }
+ });
+ }
+
+ // Post animation widget reset.
+ postAnimation();
+ }
+ };
+ animateThread.start();
+ }
+ }
+
+ /*
+ * Loop through all of the images in a multi-image file
+ * and display them one after another.
+ */
+ void animateLoop() {
+ // Create an off-screen image to draw on, and a GC to draw with.
+ // Both are disposed after the animation.
+ Image offScreenImage = new Image(null, loader.logicalScreenWidth, loader.logicalScreenHeight);
+ GC offScreenImageGC = new GC(offScreenImage);
+
+ try {
+ // Use syncExec to get the background color of the imageCanvas.
+ display.syncExec(new Runnable() {
+ public void run() {
+ canvasBackground = imageCanvas.getBackground();
+ }
+ });
+
+ // Fill the off-screen image with the background color of the canvas.
+ offScreenImageGC.setBackground(canvasBackground);
+ offScreenImageGC.fillRectangle(
+ 0,
+ 0,
+ loader.logicalScreenWidth,
+ loader.logicalScreenHeight);
+
+ // Draw the current image onto the off-screen image.
+ offScreenImageGC.drawImage(
+ image,
+ 0,
+ 0,
+ imageData.width,
+ imageData.height,
+ imageData.x,
+ imageData.y,
+ imageData.width,
+ imageData.height);
+
+ int repeatCount = loader.repeatCount;
+ while (animate && (loader.repeatCount == 0 || repeatCount > 0)) {
+ if (imageData.disposalMethod == SWT.DM_FILL_BACKGROUND) {
+ // Fill with the background color before drawing.
+ Color bgColor = null;
+ int backgroundPixel = loader.backgroundPixel;
+ if (showBackground && backgroundPixel != -1) {
+ // Fill with the background color.
+ RGB backgroundRGB = imageData.palette.getRGB(backgroundPixel);
+ bgColor = new Color(null, backgroundRGB);
+ }
+ try {
+ offScreenImageGC.setBackground(bgColor != null ? bgColor : canvasBackground);
+ offScreenImageGC.fillRectangle(
+ imageData.x,
+ imageData.y,
+ imageData.width,
+ imageData.height);
+ } finally {
+ if (bgColor != null) bgColor.dispose();
+ }
+ } else if (imageData.disposalMethod == SWT.DM_FILL_PREVIOUS) {
+ // Restore the previous image before drawing.
+ offScreenImageGC.drawImage(
+ image,
+ 0,
+ 0,
+ imageData.width,
+ imageData.height,
+ imageData.x,
+ imageData.y,
+ imageData.width,
+ imageData.height);
+ }
+
+ // Get the next image data.
+ imageDataIndex = (imageDataIndex + 1) % imageDataArray.length;
+ imageData = imageDataArray[imageDataIndex];
+ image.dispose();
+ image = new Image(null, imageData);
+
+ // Draw the new image data.
+ offScreenImageGC.drawImage(
+ image,
+ 0,
+ 0,
+ imageData.width,
+ imageData.height,
+ imageData.x,
+ imageData.y,
+ imageData.width,
+ imageData.height);
+
+ // Draw the off-screen image to the screen.
+ imageCanvasGC.drawImage(offScreenImage, 0, 0);
+
+ // Sleep for the specified delay time before drawing again.
+ try {
+ Thread.sleep(visibleDelay(imageData.delayTime * 10));
+ } catch (InterruptedException e) {
+ }
+
+ // If we have just drawn the last image in the set,
+ // then decrement the repeat count.
+ if (imageDataIndex == imageDataArray.length - 1) repeatCount--;
+ }
+ } finally {
+ offScreenImage.dispose();
+ offScreenImageGC.dispose();
+ }
+ }
+
+ /*
+ * Pre animation setup.
+ */
+ void preAnimation() {
+ display.syncExec(new Runnable() {
+ public void run() {
+ // Change the label of the Animate button to 'Stop'.
+ animateButton.setText(bundle.getString("Stop"));
+
+ // Disable anything we don't want the user
+ // to select during the animation.
+ previousButton.setEnabled(false);
+ nextButton.setEnabled(false);
+ backgroundCombo.setEnabled(false);
+ scaleXCombo.setEnabled(false);
+ scaleYCombo.setEnabled(false);
+ alphaCombo.setEnabled(false);
+ incrementalCheck.setEnabled(false);
+ transparentCheck.setEnabled(false);
+ maskCheck.setEnabled(false);
+ // leave backgroundCheck enabled
+
+ // Reset the scale combos and scrollbars.
+ resetScaleCombos();
+ resetScrollBars();
+ }
+ });
+ }
+
+ /*
+ * Post animation reset.
+ */
+ void postAnimation() {
+ display.syncExec(new Runnable() {
+ public void run() {
+ // Enable anything we disabled before the animation.
+ previousButton.setEnabled(true);
+ nextButton.setEnabled(true);
+ backgroundCombo.setEnabled(true);
+ scaleXCombo.setEnabled(true);
+ scaleYCombo.setEnabled(true);
+ alphaCombo.setEnabled(true);
+ incrementalCheck.setEnabled(true);
+ transparentCheck.setEnabled(true);
+ maskCheck.setEnabled(true);
+
+ // Reset the label of the Animate button.
+ animateButton.setText(bundle.getString("Animate"));
+
+ if (animate) {
+ // If animate is still true, we finished the
+ // full number of repeats. Leave the image as-is.
+ animate = false;
+ } else {
+ // Redisplay the current image and its palette.
+ displayImage(imageDataArray[imageDataIndex]);
+ }
+ }
+ });
+ }
+
+ /*
+ * Called when the Previous button is pressed.
+ * Display the previous image in a multi-image file.
+ */
+ void previous() {
+ if (image != null && imageDataArray.length > 1) {
+ if (imageDataIndex == 0) {
+ imageDataIndex = imageDataArray.length;
+ }
+ imageDataIndex = imageDataIndex - 1;
+ displayImage(imageDataArray[imageDataIndex]);
+ }
+ }
+
+ /*
+ * Called when the Next button is pressed.
+ * Display the next image in a multi-image file.
+ */
+ void next() {
+ if (image != null && imageDataArray.length > 1) {
+ imageDataIndex = (imageDataIndex + 1) % imageDataArray.length;
+ displayImage(imageDataArray[imageDataIndex]);
+ }
+ }
+
+ void displayImage(ImageData newImageData) {
+ if (incremental) {
+ // Wait until all incremental threads have finished drawing
+ while (drawIncrement < finalIncrement) {
+ if (!display.readAndDispatch()) display.sleep();
+ }
+ }
+
+ // Dispose of the old image, if there was one.
+ if (image != null) image.dispose();
+
+ try {
+ // Cache the new image and imageData.
+ image = new Image(null, newImageData);
+ imageData = newImageData;
+
+ } catch (SWTException e) {
+ showErrorDialog(bundle.getString("Creating_from") + " ", fileName, e);
+ image = null;
+ return;
+ }
+
+ // Update the widgets with the new image info.
+ String string = createMsg(bundle.getString("Analyzer_on"), fileName);
+ shell.setText(string);
+
+ if(imageDataArray.length > 1){
+ string = createMsg(bundle.getString("Type_index"),
+ new Object[] {fileTypeString(imageData.type),
+ new Integer(imageDataIndex + 1),
+ new Integer(imageDataArray.length)});
+ } else {
+ string = createMsg(bundle.getString("Type_string"), fileTypeString(imageData.type));
+ }
+ typeLabel.setText(string);
+
+ string = createMsg(bundle.getString("Size_value"),
+ new Object[] {new Integer(imageData.width),
+ new Integer(imageData.height)});
+ sizeLabel.setText(string);
+
+ string = createMsg(bundle.getString("Depth_value"), new Integer(imageData.depth));
+ depthLabel.setText(string);
+
+ string = createMsg(bundle.getString("Transparent_pixel_value"), pixelInfo(imageData.transparentPixel));
+ transparentPixelLabel.setText(string);
+
+ string = createMsg(bundle.getString("Animation_size_value"),
+ new Object[] {new Integer(loader.logicalScreenWidth),
+ new Integer(loader.logicalScreenHeight)});
+ screenSizeLabel.setText(string);
+
+ string = createMsg(bundle.getString("Background_pixel_value"), pixelInfo(loader.backgroundPixel));
+ backgroundPixelLabel.setText(string);
+
+ string = createMsg(bundle.getString("Image_location_value"),
+ new Object[] {new Integer(imageData.x), new Integer(imageData.y)});
+ locationLabel.setText(string);
+
+ string = createMsg(bundle.getString("Disposal_value"),
+ new Object[] {new Integer(imageData.disposalMethod),
+ disposalString(imageData.disposalMethod)});
+ disposalMethodLabel.setText(string);
+
+ int delay = imageData.delayTime * 10;
+ int delayUsed = visibleDelay(delay);
+ if(delay != delayUsed){
+ string = createMsg(bundle.getString("Delay_value"),
+ new Object[] {new Integer(delay), new Integer(delayUsed)});
+ } else {
+ string = createMsg(bundle.getString("Delay_used"), new Integer(delay));
+ }
+ delayTimeLabel.setText(string);
+
+ if(loader.repeatCount == 0){
+ string = createMsg( bundle.getString("Repeats_forever"), new Integer(loader.repeatCount));
+ } else {
+ string = createMsg(bundle.getString("Repeats_value"), new Integer(loader.repeatCount));
+ }
+ repeatCountLabel.setText(string);
+
+ if(imageData.palette.isDirect){
+ string = bundle.getString("Palette_direct");
+ } else {
+ string = createMsg(bundle.getString("Palette_value"), new Integer(imageData.palette.getRGBs().length));
+ }
+ paletteLabel.setText(string);
+
+ string = createMsg(bundle.getString("Pixel_data_value"),
+ new Object[] {new Integer(imageData.bytesPerLine),
+ new Integer(imageData.scanlinePad),
+ depthInfo(imageData.depth)});
+ dataLabel.setText(string);
+
+ dataText.setText(dataHexDump(dataText.getLineDelimiter()));
+ statusLabel.setText("");
+
+ // Redraw both canvases.
+ paletteCanvas.redraw();
+ imageCanvas.redraw();
+ }
+
+ void paintImage(PaintEvent event) {
+ Image paintImage = image;
+ int transparentPixel = imageData.transparentPixel;
+ if (transparentPixel != -1 && !transparent) {
+ imageData.transparentPixel = -1;
+ paintImage = new Image(display, imageData);
+ }
+ int w = Math.round(imageData.width * xscale);
+ int h = Math.round(imageData.height * yscale);
+ event.gc.drawImage(
+ paintImage,
+ 0,
+ 0,
+ imageData.width,
+ imageData.height,
+ ix + imageData.x,
+ iy + imageData.y,
+ w,
+ h);
+ if (showMask && (imageData.getTransparencyType() != SWT.TRANSPARENCY_NONE)) {
+ ImageData maskImageData = imageData.getTransparencyMask();
+ Image maskImage = new Image(display, maskImageData);
+ event.gc.drawImage(
+ maskImage,
+ 0,
+ 0,
+ imageData.width,
+ imageData.height,
+ w + 10 + ix + imageData.x,
+ iy + imageData.y,
+ w,
+ h);
+ maskImage.dispose();
+ }
+ if (transparentPixel != -1 && !transparent) {
+ imageData.transparentPixel = transparentPixel;
+ paintImage.dispose();
+ }
+ }
+
+ void paintPalette(PaintEvent event) {
+ GC gc = event.gc;
+ gc.fillRectangle(paletteCanvas.getClientArea());
+ if (imageData.palette.isDirect) {
+ // For a direct palette, display the masks.
+ int y = py + 10;
+ int xTab = 50;
+ gc.drawString("rMsk", 10, y, true);
+ gc.drawString(toHex4ByteString(imageData.palette.redMask), xTab, y, true);
+ gc.drawString("gMsk", 10, y+=12, true);
+ gc.drawString(toHex4ByteString(imageData.palette.greenMask), xTab, y, true);
+ gc.drawString("bMsk", 10, y+=12, true);
+ gc.drawString(toHex4ByteString(imageData.palette.blueMask), xTab, y, true);
+ gc.drawString("rShf", 10, y+=12, true);
+ gc.drawString(Integer.toString(imageData.palette.redShift), xTab, y, true);
+ gc.drawString("gShf", 10, y+=12, true);
+ gc.drawString(Integer.toString(imageData.palette.greenShift), xTab, y, true);
+ gc.drawString("bShf", 10, y+=12, true);
+ gc.drawString(Integer.toString(imageData.palette.blueShift), xTab, y, true);
+ } else {
+ // For an indexed palette, display the palette colors and indices.
+ RGB[] rgbs = imageData.palette.getRGBs();
+ if (rgbs != null) {
+ int xTab1 = 40, xTab2 = 100;
+ for (int i = 0; i < rgbs.length; i++) {
+ int y = (i+1) * 10 + py;
+ gc.drawString(String.valueOf(i), 10, y, true);
+ gc.drawString(toHexByteString(rgbs[i].red) + toHexByteString(rgbs[i].green) + toHexByteString(rgbs[i].blue), xTab1, y, true);
+ Color color = new Color(display, rgbs[i]);
+ gc.setBackground(color);
+ gc.fillRectangle(xTab2, y+2, 10, 10);
+ color.dispose();
+ }
+ }
+ }
+ }
+
+ void resizeShell(ControlEvent event) {
+ if (image == null || shell.isDisposed())
+ return;
+ resizeScrollBars();
+ }
+
+ // Reset the scale combos to 1.
+ void resetScaleCombos() {
+ xscale = 1; yscale = 1;
+ scaleXCombo.select(scaleXCombo.indexOf("1"));
+ scaleYCombo.select(scaleYCombo.indexOf("1"));
+ }
+
+ // Reset the scroll bars to 0.
+ void resetScrollBars() {
+ if (image == null) return;
+ ix = 0; iy = 0; py = 0;
+ resizeScrollBars();
+ imageCanvas.getHorizontalBar().setSelection(0);
+ imageCanvas.getVerticalBar().setSelection(0);
+ paletteCanvas.getVerticalBar().setSelection(0);
+ }
+
+ void resizeScrollBars() {
+ // Set the max and thumb for the image canvas scroll bars.
+ ScrollBar horizontal = imageCanvas.getHorizontalBar();
+ ScrollBar vertical = imageCanvas.getVerticalBar();
+ Rectangle canvasBounds = imageCanvas.getClientArea();
+ int width = Math.round(imageData.width * xscale);
+ if (width > canvasBounds.width) {
+ // The image is wider than the canvas.
+ horizontal.setEnabled(true);
+ horizontal.setMaximum(width);
+ horizontal.setThumb(canvasBounds.width);
+ horizontal.setPageIncrement(canvasBounds.width);
+ } else {
+ // The canvas is wider than the image.
+ horizontal.setEnabled(false);
+ if (ix != 0) {
+ // Make sure the image is completely visible.
+ ix = 0;
+ imageCanvas.redraw();
+ }
+ }
+ int height = Math.round(imageData.height * yscale);
+ if (height > canvasBounds.height) {
+ // The image is taller than the canvas.
+ vertical.setEnabled(true);
+ vertical.setMaximum(height);
+ vertical.setThumb(canvasBounds.height);
+ vertical.setPageIncrement(canvasBounds.height);
+ } else {
+ // The canvas is taller than the image.
+ vertical.setEnabled(false);
+ if (iy != 0) {
+ // Make sure the image is completely visible.
+ iy = 0;
+ imageCanvas.redraw();
+ }
+ }
+
+ // Set the max and thumb for the palette canvas scroll bar.
+ vertical = paletteCanvas.getVerticalBar();
+ if (imageData.palette.isDirect) {
+ vertical.setEnabled(false);
+ } else { // indexed palette
+ canvasBounds = paletteCanvas.getClientArea();
+ int paletteHeight = imageData.palette.getRGBs().length * 10 + 20; // 10 pixels each index + 20 for margins.
+ vertical.setEnabled(true);
+ vertical.setMaximum(paletteHeight);
+ vertical.setThumb(canvasBounds.height);
+ vertical.setPageIncrement(canvasBounds.height);
+ }
+ }
+
+ /*
+ * Called when the image canvas' horizontal scrollbar is selected.
+ */
+ void scrollHorizontally(ScrollBar scrollBar) {
+ if (image == null) return;
+ Rectangle canvasBounds = imageCanvas.getClientArea();
+ int width = Math.round(imageData.width * xscale);
+ int height = Math.round(imageData.height * yscale);
+ if (width > canvasBounds.width) {
+ // Only scroll if the image is bigger than the canvas.
+ int x = -scrollBar.getSelection();
+ if (x + width < canvasBounds.width) {
+ // Don't scroll past the end of the image.
+ x = canvasBounds.width - width;
+ }
+ imageCanvas.scroll(x, iy, ix, iy, width, height, false);
+ ix = x;
+ }
+ }
+
+ /*
+ * Called when the image canvas' vertical scrollbar is selected.
+ */
+ void scrollVertically(ScrollBar scrollBar) {
+ if (image == null) return;
+ Rectangle canvasBounds = imageCanvas.getClientArea();
+ int width = Math.round(imageData.width * xscale);
+ int height = Math.round(imageData.height * yscale);
+ if (height > canvasBounds.height) {
+ // Only scroll if the image is bigger than the canvas.
+ int y = -scrollBar.getSelection();
+ if (y + height < canvasBounds.height) {
+ // Don't scroll past the end of the image.
+ y = canvasBounds.height - height;
+ }
+ imageCanvas.scroll(ix, y, ix, iy, width, height, false);
+ iy = y;
+ }
+ }
+
+ /*
+ * Called when the palette canvas' vertical scrollbar is selected.
+ */
+ void scrollPalette(ScrollBar scrollBar) {
+ if (image == null) return;
+ Rectangle canvasBounds = paletteCanvas.getClientArea();
+ int paletteHeight = imageData.palette.getRGBs().length * 10 + 20;
+ if (paletteHeight > canvasBounds.height) {
+ // Only scroll if the palette is bigger than the canvas.
+ int y = -scrollBar.getSelection();
+ if (y + paletteHeight < canvasBounds.height) {
+ // Don't scroll past the end of the palette.
+ y = canvasBounds.height - paletteHeight;
+ }
+ paletteCanvas.scroll(0, y, 0, py, paletteWidth, paletteHeight, false);
+ py = y;
+ }
+ }
+
+ /*
+ * Return a String containing a line-by-line dump of
+ * the data in the current imageData. The lineDelimiter
+ * parameter must be a string of length 1 or 2.
+ */
+ String dataHexDump(String lineDelimiter) {
+ if (image == null) return "";
+ char[] dump = new char[imageData.height * (6 + 3 * imageData.bytesPerLine + lineDelimiter.length())];
+ int index = 0;
+ for (int i = 0; i < imageData.data.length; i++) {
+ if (i % imageData.bytesPerLine == 0) {
+ int line = i / imageData.bytesPerLine;
+ dump[index++] = Character.forDigit(line / 1000 % 10, 10);
+ dump[index++] = Character.forDigit(line / 100 % 10, 10);
+ dump[index++] = Character.forDigit(line / 10 % 10, 10);
+ dump[index++] = Character.forDigit(line % 10, 10);
+ dump[index++] = ':';
+ dump[index++] = ' ';
+ }
+ byte b = imageData.data[i];
+ dump[index++] = Character.forDigit((b & 0xF0) >> 4, 16);
+ dump[index++] = Character.forDigit(b & 0x0F, 16);
+ dump[index++] = ' ';
+ if ((i + 1) % imageData.bytesPerLine == 0) {
+ dump[index++] = lineDelimiter.charAt(0);
+ if (lineDelimiter.length() > 1)
+ dump[index++] = lineDelimiter.charAt(1);
+ }
+ }
+ return new String(dump);
+ }
+
+ /*
+ * Open an error dialog displaying the specified information.
+ */
+ void showErrorDialog(String operation, String filename, SWTException e) {
+ MessageBox box = new MessageBox(shell, SWT.ICON_ERROR);
+ String message = createMsg(bundle.getString("Error"), new String[] {operation, filename});
+
+ String errorMessage = e.getMessage();
+ if (e.throwable != null) {
+ errorMessage += ":\n" + e.throwable.toString();
+ }
+ box.setMessage(message + errorMessage);
+ box.open();
+ }
+
+ /*
+ * Return a String describing how to analyze the bytes
+ * in the hex dump.
+ */
+ static String depthInfo(int depth) {
+ Object[] args = {new Integer(depth), ""};
+
+ switch(depth){
+ case 1:
+ args[1] = createMsg(bundle.getString("Multi_pixels"),
+ new Object[] {new Integer(8), " [01234567]"});
+ break;
+ case 2:
+ args[1] = createMsg(bundle.getString("Multi_pixels"),
+ new Object[] {new Integer(4), "[00112233]"});
+ break;
+ case 4:
+ args[1] = createMsg(bundle.getString("Multi_pixels"),
+ new Object[] {new Integer(2), "[00001111]"});
+ break;
+ case 8:
+ args[1] = bundle.getString("One_byte");
+ break;
+ case 16:
+ args[1] = createMsg(bundle.getString("Multi_bytes"), new Integer(2));
+ break;
+ case 24:
+ args[1] = createMsg(bundle.getString("Multi_bytes"), new Integer(3));
+ break;
+ case 32:
+ args[1] = createMsg(bundle.getString("Multi_bytes"), new Integer(4));
+ break;
+ default:
+ args[1] = bundle.getString("Unsupported_lc");
+ }
+ return createMsg(bundle.getString("Depth_info"), args);
+ }
+
+ /*
+ * Return the specified number of milliseconds.
+ * If the specified number of milliseconds is too small
+ * to see a visual change, then return a higher number.
+ */
+ static int visibleDelay(int ms) {
+ if (ms < 20) return ms + 30;
+ if (ms < 30) return ms + 10;
+ return ms;
+ }
+
+
+ /*
+ * Return the specified byte value as a hex string,
+ * preserving leading 0's.
+ */
+ static String toHexByteString(int i) {
+ if (i <= 0x0f)
+ return "0" + Integer.toHexString(i);
+ return Integer.toHexString(i & 0xff);
+ }
+
+ /*
+ * Return the specified 4-byte value as a hex string,
+ * preserving leading 0's.
+ * (a bit 'brute force'... should probably use a loop...)
+ */
+ static String toHex4ByteString(int i) {
+ String hex = Integer.toHexString(i);
+ if (hex.length() == 1)
+ return "0000000" + hex;
+ if (hex.length() == 2)
+ return "000000" + hex;
+ if (hex.length() == 3)
+ return "00000" + hex;
+ if (hex.length() == 4)
+ return "0000" + hex;
+ if (hex.length() == 5)
+ return "000" + hex;
+ if (hex.length() == 6)
+ return "00" + hex;
+ if (hex.length() == 7)
+ return "0" + hex;
+ return hex;
+ }
+
+ /*
+ * Return a String describing the specified
+ * transparent or background pixel.
+ */
+ static String pixelInfo(int pixel) {
+ if (pixel == -1)
+ return pixel + " (" + bundle.getString("None_lc") + ")";
+ else
+ return pixel + " (0x" + Integer.toHexString(pixel) + ")";
+ }
+
+ /*
+ * Return a String describing the specified disposal method.
+ */
+ static String disposalString(int disposalMethod) {
+ switch (disposalMethod) {
+ case SWT.DM_FILL_NONE: return bundle.getString("None_lc");
+ case SWT.DM_FILL_BACKGROUND: return bundle.getString("Background_lc");
+ case SWT.DM_FILL_PREVIOUS: return bundle.getString("Previous_lc");
+ }
+ return bundle.getString("Unspecified_lc");
+ }
+
+ /*
+ * Return a String describing the specified image file type.
+ */
+ static String fileTypeString(int filetype) {
+ if (filetype == SWT.IMAGE_BMP)
+ return "BMP";
+ if (filetype == SWT.IMAGE_GIF)
+ return "GIF";
+ if (filetype == SWT.IMAGE_ICO)
+ return "ICO";
+ if (filetype == SWT.IMAGE_JPEG)
+ return "JPEG";
+ if (filetype == SWT.IMAGE_PNG)
+ return "PNG";
+ return bundle.getString("Unknown_ac");
+ }
+
+ /*
+ * Return the specified file's image type, based on its extension.
+ * Note that this is not a very robust way to determine image type,
+ * and it is only to be used in the absence of any better method.
+ */
+ static int determineFileType(String filename) {
+ String ext = filename.substring(filename.lastIndexOf('.') + 1);
+ if (ext.equalsIgnoreCase("bmp"))
+ return SWT.IMAGE_BMP;
+ if (ext.equalsIgnoreCase("gif"))
+ return SWT.IMAGE_GIF;
+ if (ext.equalsIgnoreCase("ico"))
+ return SWT.IMAGE_ICO;
+ if (ext.equalsIgnoreCase("jpg") || ext.equalsIgnoreCase("jpeg"))
+ return SWT.IMAGE_JPEG;
+ if (ext.equalsIgnoreCase("png"))
+ return SWT.IMAGE_PNG;
+ return SWT.IMAGE_UNDEFINED;
+ }
+
+ static String createMsg(String msg, Object[] args){
+ MessageFormat formatter = new MessageFormat(msg);
+ return formatter.format(args);
+ }
+ static String createMsg(String msg, Object arg){
+ MessageFormat formatter = new MessageFormat(msg);
+ return formatter.format(new Object[]{arg});
+ }
+
+}
+
+

Back to the top