ignoredPixelColors, InverseBlockList inverseBlockList) {
+ pixelMapping.put(C64Utility.BLACK, PF1);
+ pixelMapping.put(C64Utility.WHITE, PF2);
+ pixelMapping.put(C64Utility.DARK_GRAY, PF3);
+
+ ignoredPixelColors.add(C64Utility.BLACK);
+ ignoredPixelColors.add(C64Utility.WHITE);
+ ignoredPixelColors.add(C64Utility.DARK_GRAY);
+
+ // Brown Ship
+ inverseBlockList.add(16, 18, 5, 7, C64Utility.BROWN, true);
+ // Blue Planet
+ inverseBlockList.add(0, 39, 0, 6, C64Utility.LIGHT_BLUE, true);
+
+ // Cybernoid
+ inverseBlockList.add(0, 39, 8, 19, C64Utility.LIGHT_RED, false);
+
+ // Yellow Explosion
+ inverseBlockList.add(4, 11, 20, 24, C64Utility.BROWN, true);
+ }
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/CharMapGraphics12Converter.js b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/CharMapGraphics12Converter.js
new file mode 100644
index 00000000..75e6ba6a
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/CharMapGraphics12Converter.js
@@ -0,0 +1,4 @@
+function convertToFileData(data) {
+ // This is not yet implemented
+ // com.wudsn.ide.gfx.converter.atari8bit.CharMapGraphics12Converter.convertToFileData(data);
+}
\ No newline at end of file
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapAP3Converter.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapAP3Converter.java
new file mode 100644
index 00000000..c65b00d7
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapAP3Converter.java
@@ -0,0 +1,101 @@
+/**
+ * Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.atari8bit;
+
+import com.wudsn.ide.gfx.converter.FilesConverterData;
+import com.wudsn.ide.gfx.converter.PaletteMapper;
+import com.wudsn.ide.gfx.converter.generic.LinearBitMapConverter;
+import com.wudsn.ide.gfx.model.Palette;
+
+public class LinearBitMapAP3Converter extends LinearBitMapConverter {
+
+ public LinearBitMapAP3Converter() {
+
+ }
+
+ @Override
+ public boolean canConvertToImage(byte[] bytes) {
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+ return bytes.length == 15872;
+ }
+
+ @Override
+ public void convertToImageSizeAndPalette(FilesConverterData data,
+ byte[] bytes) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+ setImageSizeAndPalette(data, 40, 192, Palette.TRUE_COLOR, null);
+
+ }
+
+ @Override
+ public void convertToImageDataSize(FilesConverterData data) {
+ data.setImageDataWidth(data.getParameters().getColumns() * 2);
+ data.setImageDataHeight(data.getParameters().getRows());
+ }
+
+ @Override
+ public boolean convertToImageData(FilesConverterData data) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+
+ int columns = data.getParameters().getColumns();
+ PaletteMapper paletteMapper = new Atari8BitPaletteMapper();
+
+ int offset1 = 8192;
+ int offset2 = 0;
+ int xpixels = 2;
+
+ for (int y1 = 0; y1 < data.getParameters().getRows(); y1 = y1 + 1) {
+ for (int x1 = 0; x1 < columns; x1++) {
+ int c = data.getSourceFileByte(BIT_MAP_FILE, offset1++);
+ if (c < 0) {
+ return true;
+ }
+ int b = data.getSourceFileByte(BIT_MAP_FILE, offset2++);
+ if (b < 0) {
+ return true;
+ }
+ for (int x2 = 0; x2 < 2; x2++) {
+ int x = x1 * xpixels + x2;
+
+ int color = (c & mask_4bit[x2]) >>> shift_4bit[x2];
+ int brightness = (b & mask_4bit[x2]) >>> shift_4bit[x2];
+ int atariColor = color << 4 | brightness;
+ int directColor = paletteMapper.getRGBColor(atariColor);
+ data.setDirectPixel(x, y1, directColor);
+ }
+
+ }
+ }
+ return true;
+ }
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapAPACConverter.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapAPACConverter.java
new file mode 100644
index 00000000..87f6f65f
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapAPACConverter.java
@@ -0,0 +1,98 @@
+/**
+ * Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.atari8bit;
+
+import com.wudsn.ide.gfx.converter.FilesConverterData;
+import com.wudsn.ide.gfx.converter.PaletteMapper;
+import com.wudsn.ide.gfx.converter.generic.LinearBitMapConverter;
+import com.wudsn.ide.gfx.model.Palette;
+
+public class LinearBitMapAPACConverter extends LinearBitMapConverter {
+
+ public LinearBitMapAPACConverter() {
+
+ }
+
+ @Override
+ public boolean canConvertToImage(byte[] bytes) {
+ if (bytes == null) {
+ throw new IllegalArgumentException("Parameter 'bytes' must not be null.");
+ }
+ return bytes.length > 40 && bytes.length % 40 == 0;
+ }
+
+ @Override
+ public void convertToImageSizeAndPalette(FilesConverterData data, byte[] bytes) {
+ if (data == null) {
+ throw new IllegalArgumentException("Parameter 'data' must not be null.");
+ }
+ if (bytes == null) {
+ throw new IllegalArgumentException("Parameter 'bytes' must not be null.");
+ }
+ setImageSizeAndPalette(data, 40, (bytes.length + 40 - 1) / 40, Palette.TRUE_COLOR, null);
+
+ }
+
+ @Override
+ public void convertToImageDataSize(FilesConverterData data) {
+ data.setImageDataWidth(data.getParameters().getColumns() * 2);
+ data.setImageDataHeight(data.getParameters().getRows());
+ }
+
+ @Override
+ public boolean convertToImageData(FilesConverterData data) {
+ if (data == null) {
+ throw new IllegalArgumentException("Parameter 'data' must not be null.");
+ }
+
+ int columns = data.getParameters().getColumns();
+ int rows = data.getParameters().getRows();
+ int offset1 = 0;
+ int offset2 = columns;
+ int xpixels = 2;
+ PaletteMapper paletteMapper = new Atari8BitPaletteMapper();
+
+ for (int y1 = 0; y1 < rows; y1 = y1 + 1) {
+ for (int x1 = 0; x1 < columns; x1++) {
+ int c = data.getSourceFileByte(BIT_MAP_FILE, offset1++);
+ if (c < 0) {
+ return true;
+ }
+ int b = data.getSourceFileByte(BIT_MAP_FILE, offset2++);
+ if (b < 0) {
+ return true;
+ }
+ for (int x2 = 0; x2 < 2; x2++) {
+ int x = x1 * xpixels + x2;
+
+ int color = (c & mask_4bit[x2]) >>> shift_4bit[x2];
+ int brightness = (b & mask_4bit[x2]) >>> shift_4bit[x2];
+ int atariColor = color << 4 | brightness;
+ int directColor = paletteMapper.getRGBColor(atariColor);
+ data.setDirectPixel(x, y1, directColor);
+ }
+
+ }
+ offset1 = offset1 + columns;
+ offset2 = offset2 + columns;
+ }
+ return true;
+ }
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapAPACConverter.js b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapAPACConverter.js
new file mode 100644
index 00000000..73fd38f1
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapAPACConverter.js
@@ -0,0 +1,14 @@
+function convertToFileData(data) {
+ var bpsl = (data.getImageDataWidth() + 1) / 2;
+ var bytes = []
+ var offset = 0;
+ for (var y = 0; y < data.getImageDataHeight(); y++) {
+ for (var x = 0; x < data.getImageDataWidth(); x = x + 2) {
+ var c1 = data.getPixelRGB(x, y);
+ var c2 = data.getPixelRGB(x + 1, y);
+ var b = c1 << 4 | c2;
+ bytes[offset++] = b;
+ }
+ }
+ data.setTargetFileObject(0, bytes);
+}
\ No newline at end of file
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapAPCConverter.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapAPCConverter.java
new file mode 100644
index 00000000..e4a6c4c7
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapAPCConverter.java
@@ -0,0 +1,105 @@
+/**
+ * Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.atari8bit;
+
+import com.wudsn.ide.gfx.converter.FilesConverterData;
+import com.wudsn.ide.gfx.converter.PaletteMapper;
+import com.wudsn.ide.gfx.converter.generic.LinearBitMapConverter;
+import com.wudsn.ide.gfx.model.Palette;
+
+public class LinearBitMapAPCConverter extends LinearBitMapConverter {
+
+ public LinearBitMapAPCConverter() {
+
+ }
+
+ @Override
+ public boolean canConvertToImage(byte[] bytes) {
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+ // 7680 bytes of bitmap, optionally 40 bytes of text in ATASCII screen
+ // code
+ return bytes.length == 7680 || bytes.length == 7680 + 40;
+ }
+
+ @Override
+ public void convertToImageSizeAndPalette(FilesConverterData data,
+ byte[] bytes) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+ setImageSizeAndPalette(data, 40, 96, Palette.TRUE_COLOR, null);
+
+ }
+
+ @Override
+ public void convertToImageDataSize(FilesConverterData data) {
+ data.setImageDataWidth(data.getParameters().getColumns() * 2);
+ data.setImageDataHeight(data.getParameters().getRows());
+ }
+
+ @Override
+ public boolean convertToImageData(FilesConverterData data) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+
+ int columns = data.getParameters().getColumns();
+
+ int offset1 = 0;
+ int offset2 = columns;
+ int xpixels = 2;
+ PaletteMapper paletteMapper = new Atari8BitPaletteMapper();
+
+ for (int y1 = 0; y1 < data.getParameters().getRows(); y1 = y1 + 1) {
+ for (int x1 = 0; x1 < columns; x1++) {
+ int c = data.getSourceFileByte(BIT_MAP_FILE, offset1++);
+ if (c < 0) {
+ return true;
+ }
+ int b = data.getSourceFileByte(BIT_MAP_FILE, offset2++);
+ if (b < 0) {
+ return true;
+ }
+ for (int x2 = 0; x2 < 2; x2++) {
+ int x = x1 * xpixels + x2;
+
+ int color = (c & mask_4bit[x2]) >>> shift_4bit[x2];
+ int brightness = (b & mask_4bit[x2]) >>> shift_4bit[x2];
+ int atariColor = color << 4 | brightness;
+ int directColor = paletteMapper.getRGBColor(atariColor);
+ data.setDirectPixel(x, y1, directColor);
+ }
+
+ }
+ offset1 = offset1 + columns;
+ offset2 = offset2 + columns;
+ }
+ return true;
+ }
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapCINConverter.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapCINConverter.java
new file mode 100644
index 00000000..26e422b3
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapCINConverter.java
@@ -0,0 +1,195 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.atari8bit;
+
+import com.wudsn.ide.gfx.converter.FilesConverterData;
+import com.wudsn.ide.gfx.converter.FilesConverterParameters.SourceFile;
+import com.wudsn.ide.gfx.converter.PaletteMapper;
+import com.wudsn.ide.gfx.converter.generic.LinearBitMapConverter;
+import com.wudsn.ide.gfx.model.Palette;
+
+/**
+ * Converter for CCI and CIN files.
+ *
+ * @author Peter Dell
+ *
+ * @since 1.6.0
+ */
+public class LinearBitMapCINConverter extends LinearBitMapConverter {
+
+ public LinearBitMapCINConverter() {
+
+ }
+
+ private boolean isCIN(byte[] bytes) {
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+ return bytes.length == 16384;
+ }
+
+ private boolean isCCI(byte[] bytes) {
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+ return bytes.length > 7 && bytes[0] == 'C' && bytes[1] == 'I'
+ && bytes[2] == 'N' && bytes[3] == ' ' && bytes[4] == '1'
+ && bytes[5] == '.' && bytes[6] == '2' && bytes[7] == ' ';
+ }
+
+ private boolean unpackCCI(byte[] bytes, int offset, byte[] unpackedImage) {
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+ if (offset < 0) {
+ throw new IllegalArgumentException(
+ "Parameter 'offset' must not be negative. Specified value is "
+ + offset + ".");
+ }
+ if (unpackedImage == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'unpackedImage' must not be null.");
+ }
+ // Compressed even lines of graphics 15 frame
+ int dataOffset = offset + 8;
+ int dataLength = Atari8BitUtility.getWord(bytes, dataOffset);
+ if (!Atari8BitUtility.unpackCCI(bytes, dataOffset + 2, dataLength, 80, 96,
+ unpackedImage, 0)) {
+ return false;
+ }
+
+ // Compressed odd lines of graphics 15 frame
+ dataOffset += 2 + dataLength;
+ dataLength = Atari8BitUtility.getWord(bytes, dataOffset);
+ if (!Atari8BitUtility.unpackCCI(bytes, dataOffset + 2, dataLength, 80, 96,
+ unpackedImage, 40)) {
+ return false;
+ }
+
+ // Compressed graphics 11
+ dataOffset += 2 + dataLength;
+ dataLength = Atari8BitUtility.getWord(bytes, dataOffset);
+ if (!Atari8BitUtility.unpackCCI(bytes, dataOffset + 2, dataLength, 40,
+ 192, unpackedImage, 7680)) {
+ return false;
+ }
+
+ /* compressed color values for gr15 */
+ dataOffset += 2 + dataLength;
+ dataLength = Atari8BitUtility.getWord(bytes, dataOffset);
+ if (!Atari8BitUtility.unpackCCI(bytes, dataOffset + 2, dataLength, 1,
+ 0x400, unpackedImage, 0x3C00)) {
+ return false;
+ }
+
+ dataOffset += 2 + dataLength;
+ return dataOffset == bytes.length;
+ }
+
+ @Override
+ public boolean canConvertToImage(byte[] bytes) {
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+ return isCIN(bytes) || isCCI(bytes);
+ }
+
+ @Override
+ public void convertToImageSizeAndPalette(FilesConverterData data,
+ byte[] bytes) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+
+ setImageSizeAndPalette(data, 40, 192, Palette.TRUE_COLOR, null);
+ }
+
+ @Override
+ public void convertToImageDataSize(FilesConverterData data) {
+ data.setImageDataWidth(data.getParameters().getColumns() * 4);
+ data.setImageDataHeight(data.getParameters().getRows());
+ }
+
+ @Override
+ public boolean convertToImageData(FilesConverterData data) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+
+ byte[] bytes = data.getSourceFileBytes(BIT_MAP_FILE);
+ if (bytes == null) {
+ return false;
+ }
+
+ byte[] unpackedImage;
+ SourceFile sourceFile = data.getParameters()
+ .getSourceFile(BIT_MAP_FILE);
+ int offset = sourceFile.getOffset();
+
+ if (isCCI(bytes)) {
+ unpackedImage = new byte[16384];
+ if (!unpackCCI(bytes, offset, unpackedImage)) {
+ return false;
+ }
+ } else {
+ unpackedImage = bytes;
+ }
+ int xpixels = 4;
+ PaletteMapper paletteMapper=new Atari8BitPaletteMapper();
+
+ for (int y1 = 0; y1 < data.getParameters().getRows(); y1++) {
+ for (int x1 = 0; x1 < data.getParameters().getColumns(); x1++) {
+ if (offset + 7680 >= unpackedImage.length) {
+ return true;
+ }
+ int b1 = unpackedImage[offset + 7680] & 0xff;
+ int b2 = unpackedImage[offset++] & 0xff;
+
+ for (int x2 = 0; x2 < 4; x2++) {
+ int x = x1 * xpixels + x2;
+ int x3 = x2 >>> 1;
+ int hue = (b1 & mask_4bit[x3]) >>> shift_4bit[x3];
+ int lumaRegister = (b2 & mask_2bit[x2]) >>> shift_2bit[x2];
+ int lumaOffset = 0x3c00 + lumaRegister * 0x100 + y1;
+ int luma = 0;
+ if (lumaOffset < unpackedImage.length) {
+ luma = unpackedImage[lumaOffset] & 0xe;
+ }
+
+ int color = paletteMapper.getRGBColor(hue << 4
+ | luma);
+ data.setDirectPixel(x, y1, color);
+ }
+ }
+ }
+ return true;
+ }
+
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapCPRConverter.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapCPRConverter.java
new file mode 100644
index 00000000..c32be954
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapCPRConverter.java
@@ -0,0 +1,122 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.atari8bit;
+
+import org.eclipse.swt.graphics.RGB;
+
+import com.wudsn.ide.gfx.converter.FilesConverterData;
+import com.wudsn.ide.gfx.converter.generic.LinearBitMapConverter;
+import com.wudsn.ide.gfx.model.Palette;
+import com.wudsn.ide.gfx.model.PaletteType;
+import com.wudsn.ide.gfx.model.PaletteUtility;
+
+public class LinearBitMapCPRConverter extends LinearBitMapConverter {
+
+ public LinearBitMapCPRConverter() {
+ }
+
+ @Override
+ public boolean canConvertToImage(byte[] bytes) {
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+
+ if (bytes.length < 3) {
+ return false;
+ }
+
+ byte[] unpackedImage = new byte[7684];
+ boolean result = Atari8BitUtility.unpackKoala(bytes, 1, bytes.length - 1,
+ bytes[0] & 0xff, unpackedImage);
+ return result;
+ }
+
+ @Override
+ public void convertToImageSizeAndPalette(FilesConverterData data,
+ byte[] bytes) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+
+ byte[] unpackedImage = new byte[7684];
+ boolean result = Atari8BitUtility.unpackKoala(bytes, 1, bytes.length - 1,
+ bytes[0] & 0xff, unpackedImage);
+ if (!result) {
+ return;
+ }
+
+ RGB[] paletteColors;
+ paletteColors = PaletteUtility.getPaletteColors(
+ PaletteType.ATARI_DEFAULT, Palette.HIRES_1, null);
+ setImageSizeAndPalette(data, 40, 192, Palette.HIRES_1, paletteColors);
+ }
+
+ @Override
+ public void convertToImageDataSize(FilesConverterData data) {
+ data.setImageDataWidth(data.getParameters().getColumns() * 8);
+ data.setImageDataHeight(data.getParameters().getRows());
+ }
+
+ @Override
+ public boolean convertToImageData(FilesConverterData data) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+
+ byte[] bytes = data.getSourceFileBytes(BIT_MAP_FILE);
+ if (bytes == null || bytes.length < 3) {
+ return false;
+ }
+
+ byte[] unpackedImage = new byte[7680];
+ boolean result = Atari8BitUtility.unpackKoala(bytes, 1, bytes.length - 1,
+ bytes[0] & 0xff, unpackedImage);
+
+ if (!result) {
+ return false;
+ }
+
+ int offset = 0;
+ int xpixels = 8;
+
+ for (int y1 = 0; y1 < data.getParameters().getRows(); y1++) {
+ for (int x1 = 0; x1 < data.getParameters().getColumns(); x1++) {
+ if (offset >= unpackedImage.length) {
+ return true;
+ }
+ int b = unpackedImage[offset++] & 0xff;
+ for (int x2 = 0; x2 < 8; x2++) {
+ int x = x1 * xpixels + x2;
+ int color = (b & mask_1bit[x2]) >>> shift_1bit[x2];
+ data.setPalettePixel(x, y1, color);
+ }
+
+ }
+ }
+ return true;
+ }
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapGHGConverter.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapGHGConverter.java
new file mode 100644
index 00000000..12de4594
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapGHGConverter.java
@@ -0,0 +1,100 @@
+/**
+ * Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.atari8bit;
+
+import org.eclipse.swt.graphics.RGB;
+
+import com.wudsn.ide.gfx.converter.FilesConverterData;
+import com.wudsn.ide.gfx.converter.PaletteMapper;
+import com.wudsn.ide.gfx.converter.generic.LinearBitMapConverter;
+import com.wudsn.ide.gfx.model.Palette;
+
+public class LinearBitMapGHGConverter extends LinearBitMapConverter {
+
+ public LinearBitMapGHGConverter() {
+ }
+
+ @Override
+ public boolean canConvertToImage(byte[] bytes) {
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+ return bytes.length == 0x1f43 && Atari8BitUtility.getWord(bytes, 0) > 0
+ && Atari8BitUtility.getWord(bytes, 0) <= 320
+ && (bytes[2] & 0xff) > 0 && (bytes[2] & 0xff) <= 200;
+ }
+
+ @Override
+ public void convertToImageSizeAndPalette(FilesConverterData data,
+ byte[] bytes) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+
+ int columns = (Atari8BitUtility.getWord(bytes, 0) + 7) / 8;
+ int rows = (bytes[2] & 0xff);
+ PaletteMapper paletteMapper = new Atari8BitPaletteMapper();
+
+ RGB[] paletteColors = new RGB[2];
+ paletteColors[0] = paletteMapper.getRGB(12);
+ paletteColors[1] = paletteMapper.getRGB(2);
+
+ setImageSizeAndPalette(data, columns, rows, Palette.HIRES_MANUAL,
+ paletteColors);
+ }
+
+ @Override
+ public void convertToImageDataSize(FilesConverterData data) {
+ data.setImageDataWidth(data.getParameters().getColumns() * 8);
+ data.setImageDataHeight(data.getParameters().getRows());
+ }
+
+ @Override
+ public boolean convertToImageData(FilesConverterData data) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+
+ int offset = 3;
+ int xpixels = 8;
+
+ for (int y1 = 0; y1 < data.getParameters().getRows(); y1++) {
+ for (int x1 = 0; x1 < data.getParameters().getColumns(); x1++) {
+ int b = data.getSourceFileByte(BIT_MAP_FILE, offset++);
+ if (b < 0) {
+ return true;
+ }
+ for (int x2 = 0; x2 < 8; x2++) {
+ int x = x1 * xpixels + x2;
+ int color = (b & mask_1bit[x2]) >>> shift_1bit[x2];
+ data.setPalettePixel(x, y1, color);
+ }
+ }
+ }
+ return true;
+ }
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapGraphics10Converter.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapGraphics10Converter.java
new file mode 100644
index 00000000..39c72d35
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapGraphics10Converter.java
@@ -0,0 +1,64 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.atari8bit;
+
+import com.wudsn.ide.gfx.converter.FilesConverterData;
+import com.wudsn.ide.gfx.converter.generic.LinearBitMapConverter;
+
+public class LinearBitMapGraphics10Converter extends LinearBitMapConverter {
+
+ public LinearBitMapGraphics10Converter() {
+
+ }
+
+ @Override
+ public void convertToImageDataSize(FilesConverterData data) {
+ data.setImageDataWidth(data.getParameters().getColumns() * 8);
+ data.setImageDataHeight(data.getParameters().getRows());
+ }
+
+ @Override
+ public boolean convertToImageData(FilesConverterData data) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+
+ int offset = 0;
+ int xpixels = 2;
+
+ for (int y1 = 0; y1 < data.getParameters().getRows(); y1++) {
+ for (int x1 = 0; x1 < data.getParameters().getColumns(); x1++) {
+ int b = data.getSourceFileByte(BIT_MAP_FILE, offset++);
+ if (b < 0) {
+ return true;
+ }
+ for (int x2 = 0; x2 < 2; x2++) {
+ int x = x1 * xpixels + x2;
+
+ int color = (b & mask_4bit[x2]) >>> shift_4bit[x2];
+ data.setDirectPixel(x, y1, color * 0x101010);
+ }
+
+ }
+ }
+ return true;
+ }
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapGraphics10Converter.js b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapGraphics10Converter.js
new file mode 100644
index 00000000..5703f985
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapGraphics10Converter.js
@@ -0,0 +1,14 @@
+function convertToFileData(data) {
+ var bpsl = (data.getImageDataWidth() + 1) / 2;
+ var bytes = [];
+ var offset = 0;
+ for (var y = 0; y < data.getImageDataHeight(); y++) {
+ for (var x = 0; x < data.getImageDataWidth(); x = x + 2) {
+ var c1 = data.getPixel(x, y);
+ var c2 = data.getPixel(x + 1, y);
+ var b = c1 << 4 | c2;
+ bytes[offset++] = b;
+ }
+ }
+ data.setTargetFileObject(0, bytes);
+}
\ No newline at end of file
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapGraphics15Converter.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapGraphics15Converter.java
new file mode 100644
index 00000000..6116fc98
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapGraphics15Converter.java
@@ -0,0 +1,99 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.atari8bit;
+
+import org.eclipse.swt.graphics.RGB;
+
+import com.wudsn.ide.gfx.converter.FilesConverterData;
+import com.wudsn.ide.gfx.converter.generic.LinearBitMapConverter;
+import com.wudsn.ide.gfx.model.Palette;
+import com.wudsn.ide.gfx.model.PaletteType;
+import com.wudsn.ide.gfx.model.PaletteUtility;
+
+public class LinearBitMapGraphics15Converter extends LinearBitMapConverter {
+
+ public LinearBitMapGraphics15Converter() {
+
+ }
+
+ @Override
+ public boolean canConvertToImage(byte[] bytes) {
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+ return bytes.length == 7680;
+ }
+
+ @Override
+ public void convertToImageSizeAndPalette(FilesConverterData data,
+ byte[] bytes) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+
+ int columns = 40;
+ int rows = (bytes.length + columns - 1) / columns;
+ RGB[] paletteColors;
+ paletteColors = PaletteUtility.getPaletteColors(
+ PaletteType.ATARI_DEFAULT, Palette.MULTI_1, null);
+ setImageSizeAndPalette(data, columns, rows, Palette.MULTI_1,
+ paletteColors);
+ }
+
+ @Override
+ public void convertToImageDataSize(FilesConverterData data) {
+ data.setImageDataWidth(data.getParameters().getColumns() * 4);
+ data.setImageDataHeight(data.getParameters().getRows());
+ }
+
+ @Override
+ public boolean convertToImageData(FilesConverterData data) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+
+ int offset = 0;
+ int xpixels = 4;
+
+ for (int y1 = 0; y1 < data.getParameters().getRows(); y1++) {
+ for (int x1 = 0; x1 < data.getParameters().getColumns(); x1++) {
+ int b = data.getSourceFileByte(BIT_MAP_FILE, offset++);
+ if (b < 0) {
+ return true;
+ }
+ for (int x2 = 0; x2 < 4; x2++) {
+ int x = x1 * xpixels + x2;
+
+ int color = (b & mask_2bit[x2]) >>> shift_2bit[x2];
+ data.setPalettePixel(x, y1, color);
+ }
+
+ }
+ }
+ return true;
+ }
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapGraphics15Converter.js b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapGraphics15Converter.js
new file mode 100644
index 00000000..b270fbe8
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapGraphics15Converter.js
@@ -0,0 +1,16 @@
+function convertToFileData(data) {
+ var bpsl = (data.getImageDataWidth() + 3) / 4;
+ var bytes = [];
+ var offset = 0;
+ for (var y = 0; y < data.getImageDataHeight(); y++) {
+ for (var x = 0; x < data.getImageDataWidth(); x = x + 4) {
+ var c1,c2,c3,c4;
+ c1 = data.getPixel(x, y) & 0x3;
+ c2 = data.getPixel(x+1, y) & 0x3;
+ c3 = data.getPixel(x+2, y) & 0x3;
+ c4 = data.getPixel(x+3, y) & 0x3;
+ bytes[offset++] = c1 << 6 | c2 << 4 | c3 << 2 | c4;
+ }
+ }
+ data.setTargetFileObject(0, bytes);
+}
\ No newline at end of file
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapGraphics8Converter.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapGraphics8Converter.java
new file mode 100644
index 00000000..93dce9cc
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapGraphics8Converter.java
@@ -0,0 +1,93 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.atari8bit;
+
+import org.eclipse.swt.graphics.RGB;
+
+import com.wudsn.ide.gfx.converter.FilesConverterData;
+import com.wudsn.ide.gfx.converter.generic.LinearBitMapConverter;
+import com.wudsn.ide.gfx.model.Palette;
+import com.wudsn.ide.gfx.model.PaletteType;
+import com.wudsn.ide.gfx.model.PaletteUtility;
+
+public class LinearBitMapGraphics8Converter extends LinearBitMapConverter {
+
+ public LinearBitMapGraphics8Converter() {
+ }
+
+ @Override
+ public boolean canConvertToImage(byte[] bytes) {
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+ return bytes.length == 7680;
+ }
+
+ @Override
+ public void convertToImageSizeAndPalette(FilesConverterData data,
+ byte[] bytes) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+
+ RGB[] paletteColors;
+ paletteColors = PaletteUtility.getPaletteColors(
+ PaletteType.ATARI_DEFAULT, Palette.HIRES_1, null);
+ setImageSizeAndPalette(data, 40, 192, Palette.HIRES_1, paletteColors);
+ }
+
+ @Override
+ public void convertToImageDataSize(FilesConverterData data) {
+ data.setImageDataWidth(data.getParameters().getColumns() * 8);
+ data.setImageDataHeight(data.getParameters().getRows());
+ }
+
+ @Override
+ public boolean convertToImageData(FilesConverterData data) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+
+ int offset = 0;
+ int xpixels = 8;
+
+ for (int y1 = 0; y1 < data.getParameters().getRows(); y1++) {
+ for (int x1 = 0; x1 < data.getParameters().getColumns(); x1++) {
+ int b = data.getSourceFileByte(BIT_MAP_FILE, offset++);
+ if (b < 0) {
+ return true;
+ }
+ for (int x2 = 0; x2 < 8; x2++) {
+ int x = x1 * xpixels + x2;
+ int color = (b & mask_1bit[x2]) >>> shift_1bit[x2];
+ data.setPalettePixel(x, y1, color);
+ }
+ }
+ }
+ return true;
+ }
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapGraphics8Converter.js b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapGraphics8Converter.js
new file mode 100644
index 00000000..6af9a6a9
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapGraphics8Converter.js
@@ -0,0 +1,19 @@
+function convertToFileData(data) {
+ var bpsl = (data.getImageDataWidth() + 7) / 8;
+ var bytes = [];
+ var offset = 0;
+ for (var y = 0; y < data.getImageDataHeight(); y++) {
+ for (var x = 0; x < data.getImageDataWidth(); x = x + 8) {
+ var b = 0;
+ for (var p = 0; p < 8; p++) {
+ var color;
+ color = data.getPixel(x + p, y);
+ if (color != 0) {
+ b = b | 1 << 7 - p;
+ }
+ }
+ bytes[offset++] = b;
+ }
+ }
+ data.setTargetFileObject(0, bytes);
+}
\ No newline at end of file
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapGraphics9Converter.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapGraphics9Converter.java
new file mode 100644
index 00000000..8d4db187
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapGraphics9Converter.java
@@ -0,0 +1,96 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.atari8bit;
+
+import org.eclipse.swt.graphics.RGB;
+
+import com.wudsn.ide.gfx.converter.FilesConverterData;
+import com.wudsn.ide.gfx.converter.generic.LinearBitMapConverter;
+import com.wudsn.ide.gfx.model.Palette;
+import com.wudsn.ide.gfx.model.PaletteType;
+import com.wudsn.ide.gfx.model.PaletteUtility;
+
+public class LinearBitMapGraphics9Converter extends LinearBitMapConverter {
+
+ public LinearBitMapGraphics9Converter() {
+
+ }
+
+ @Override
+ public boolean canConvertToImage(byte[] bytes) {
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+ return bytes.length == 7680;
+ }
+
+ @Override
+ public void convertToImageSizeAndPalette(FilesConverterData data,
+ byte[] bytes) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+
+ RGB[] paletteColors;
+ paletteColors = PaletteUtility.getPaletteColors(
+ PaletteType.ATARI_DEFAULT, Palette.GTIA_GREY_1, null);
+ setImageSizeAndPalette(data, 40, 192, Palette.GTIA_GREY_1,
+ paletteColors);
+ }
+
+ @Override
+ public void convertToImageDataSize(FilesConverterData data) {
+ data.setImageDataWidth(data.getParameters().getColumns() * 2);
+ data.setImageDataHeight(data.getParameters().getRows());
+ }
+
+ @Override
+ public boolean convertToImageData(FilesConverterData data) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+
+ int offset = 0;
+ int xpixels = 2;
+
+ for (int y1 = 0; y1 < data.getParameters().getRows(); y1++) {
+ for (int x1 = 0; x1 < data.getParameters().getColumns(); x1++) {
+ int b = data.getSourceFileByte(BIT_MAP_FILE, offset++);
+ if (b < 0) {
+ return true;
+ }
+ for (int x2 = 0; x2 < 2; x2++) {
+ int x = x1 * xpixels + x2;
+
+ int color = (b & mask_4bit[x2]) >>> shift_4bit[x2];
+ data.setPalettePixel(x, y1, color);
+ }
+ }
+ }
+ return true;
+ }
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapGraphics9Converter.js b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapGraphics9Converter.js
new file mode 100644
index 00000000..5703f985
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapGraphics9Converter.js
@@ -0,0 +1,14 @@
+function convertToFileData(data) {
+ var bpsl = (data.getImageDataWidth() + 1) / 2;
+ var bytes = [];
+ var offset = 0;
+ for (var y = 0; y < data.getImageDataHeight(); y++) {
+ for (var x = 0; x < data.getImageDataWidth(); x = x + 2) {
+ var c1 = data.getPixel(x, y);
+ var c2 = data.getPixel(x + 1, y);
+ var b = c1 << 4 | c2;
+ bytes[offset++] = b;
+ }
+ }
+ data.setTargetFileObject(0, bytes);
+}
\ No newline at end of file
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapHIPConverter.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapHIPConverter.java
new file mode 100644
index 00000000..060fbeac
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapHIPConverter.java
@@ -0,0 +1,193 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.atari8bit;
+
+import com.wudsn.ide.gfx.converter.FilesConverterData;
+import com.wudsn.ide.gfx.converter.PaletteMapper;
+import com.wudsn.ide.gfx.converter.generic.LinearBitMapConverter;
+import com.wudsn.ide.gfx.model.Palette;
+import com.wudsn.ide.gfx.model.RBGUtility;
+
+public class LinearBitMapHIPConverter extends LinearBitMapConverter {
+
+ public LinearBitMapHIPConverter() {
+
+ }
+
+ @Override
+ public boolean canConvertToImage(byte[] bytes) {
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+
+ // HIP image with binary file headers. Two concatenated COM files.
+ int frame1Length = Atari8BitUtility.getLengthFromBinaryHeader(bytes, 0);
+ if (frame1Length > 0 && frame1Length * 2 + 12 == bytes.length
+ && frame1Length % 40 == 0) {
+
+ int frame2Length = Atari8BitUtility.getLengthFromBinaryHeader(bytes,
+ frame1Length + 6);
+ if (frame2Length == frame1Length) {
+ return true;
+ }
+ }
+ // HIP image with graphics 10 palette.
+ else if ((bytes.length - 9) % 80 == 0) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void convertToImageSizeAndPalette(FilesConverterData data,
+ byte[] bytes) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+
+ // HIP image with binary file headers. Two concatenated COM files.
+ int rows;
+ int frame1Length = Atari8BitUtility.getLengthFromBinaryHeader(bytes, 0);
+ if (frame1Length > 0 && frame1Length * 2 + 12 == bytes.length
+ && frame1Length % 40 == 0) {
+
+ int frame2Length = Atari8BitUtility.getLengthFromBinaryHeader(bytes,
+ frame1Length + 6);
+ if (frame2Length != frame1Length) {
+ throw new IllegalStateException("Inconsistent file");
+ }
+
+ rows = frame1Length / 40;
+ }
+ // hip image with gr10 palette.
+ else if ((bytes.length - 9) % 80 == 0) {
+ rows = (bytes.length - 9) / 80;
+ } else {
+ throw new IllegalStateException("Inconsistent file");
+ }
+
+ setImageSizeAndPalette(data, 40, rows, Palette.TRUE_COLOR, null);
+ }
+
+ @Override
+ public void convertToImageDataSize(FilesConverterData data) {
+ data.setImageDataWidth(data.getParameters().getColumns() * 4 + 1);
+ data.setImageDataHeight(data.getParameters().getRows());
+ }
+
+ @Override
+ public boolean convertToImageData(FilesConverterData data) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+
+ int rows = data.getParameters().getRows();
+ int columns = data.getParameters().getColumns();
+ PaletteMapper paletteMapper=new Atari8BitPaletteMapper();
+
+ // Assume the binary is already merged in case of a 160012 bytes HIP.
+ int offset9, offset10, offsetPalette;
+
+ byte[] sourceFileBytes = data.getSourceFileBytes(BIT_MAP_FILE);
+ if (sourceFileBytes == null) {
+ return false;
+ }
+
+ // Assume grey scale colors by default.
+ int[] graphics10Colors = { 0, 0, 2, 4, 6, 8, 10, 12, 14 };
+
+ // Compute the offsets in the file.
+ int frameSize = rows * columns;
+ int rest = sourceFileBytes.length - 2 * frameSize;
+ if (rest == 0 || rest == 9) {
+ // In this case the graphics 9 picture comes first
+ offset9 = 0;
+ offset10 = offset9 + 0 + frameSize;
+ offsetPalette = offset10 + frameSize;
+ if (rest == 9) {
+ for (int i = 0; i < 9; i++) {
+ graphics10Colors[i] = sourceFileBytes[offsetPalette + i];
+ }
+ }
+ } else if (rest == 12) {
+ // In this case the graphics 10 picture comes first
+ offset10 = 6;
+ offset9 = offset10 + 6 + frameSize;
+ } else {
+ return false;
+ }
+
+ int[] buffer1 = new int[columns * 4 + 1];
+ int[] buffer2 = new int[columns * 4 + 1];
+
+ for (int y1 = 0; y1 < rows; y1++) {
+ for (int x1 = 0; x1 < columns; x1++) {
+ int byte9 = data.getSourceFileByte(BIT_MAP_FILE, offset9++);
+ if (byte9 < 0) {
+ return true;
+ }
+ int byte10 = data.getSourceFileByte(BIT_MAP_FILE, offset10++);
+ if (byte10 < 0) {
+ return true;
+ }
+
+ // Byte 1 is the GTIA 9 byte, take the values as brightness
+ // values
+ int brightness1 = (byte9 & mask_4bit[0]) >>> shift_4bit[0];
+ int brightness2 = (byte9 & mask_4bit[1]) >>> shift_4bit[1];
+
+ // Byte 2 is the GTIA 10 byte, take the values from the GTIA 10
+ // palette
+ int brightness3 = (byte10 & mask_4bit[0]) >>> shift_4bit[0];
+ int brightness4 = (byte10 & mask_4bit[1]) >>> shift_4bit[1];
+ brightness3 = graphics10Colors[Atari8BitUtility.GRAPHICS_10_REGISTERS[brightness3]];
+ brightness4 = graphics10Colors[Atari8BitUtility.GRAPHICS_10_REGISTERS[brightness4]];
+
+ // Put the color values in the row buffer, shifted by 1 pixel
+ int x = x1 << 2;
+ buffer1[x + 0] = brightness1;
+ buffer1[x + 1] = brightness1;
+ buffer1[x + 2] = brightness2;
+ buffer1[x + 3] = brightness2;
+
+ buffer2[x + 1] = brightness3;
+ buffer2[x + 2] = brightness3;
+ buffer2[x + 3] = brightness4;
+ buffer2[x + 4] = brightness4;
+ }
+
+ // Merge the two buffers into combined color values.
+ for (int x = 0; x < buffer1.length; x++) {
+ int atariColor = RBGUtility.combineRGBColor(
+ paletteMapper.getRGBColor(buffer1[x]),
+ paletteMapper.getRGBColor(buffer2[x]));
+ data.setDirectPixel(x, y1, atariColor);
+ }
+ }
+ return true;
+ }
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapHIPConverter.js b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapHIPConverter.js
new file mode 100644
index 00000000..679fa642
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapHIPConverter.js
@@ -0,0 +1,31 @@
+function convertToFileData(data) {
+ var bpsl = (data.getImageDataWidth() + 1) / 2;
+ var bptl = bpsl / 2;
+ var bytes = [];
+ var offset = 0;
+ for (var y = 0; y < data.getImageDataHeight(); y++) {
+ for (var x = 0; x < data.getImageDataWidth(); x = x + 4) {
+ var c1;
+ var c2;
+ c1 = data.getPixel(x, y);
+ if (x+2 < data.getImageDataWidth() ){
+ c2 = data.getPixel(x+2, y);
+ } else {
+ c2 = 0;
+ }
+ bytes[offset] = (color1 << 4 | color2);
+
+ c1 = data.getPixel(x+1, y);
+ if (x+3 < data.getImageDataWidth() ){
+ c2 = data.getPixel(x+3, y);
+ } else {
+ c2 = 0;
+ }
+ bytes[offset] = (color1 << 4 | color2);
+ }
+ bytes[offset++] = b;
+ }
+ offset += bptl;
+ }
+ data.setTargetFileObject(0, bytes);
+}
\ No newline at end of file
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapHR2Converter.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapHR2Converter.java
new file mode 100644
index 00000000..4aec11c3
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapHR2Converter.java
@@ -0,0 +1,122 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.atari8bit;
+
+import org.eclipse.swt.graphics.RGB;
+
+import com.wudsn.ide.gfx.converter.FilesConverterData;
+import com.wudsn.ide.gfx.converter.PaletteMapper;
+import com.wudsn.ide.gfx.converter.generic.LinearBitMapConverter;
+import com.wudsn.ide.gfx.model.Palette;
+import com.wudsn.ide.gfx.model.RBGUtility;
+
+public class LinearBitMapHR2Converter extends LinearBitMapConverter {
+
+ public LinearBitMapHR2Converter() {
+ }
+
+ @Override
+ public boolean canConvertToImage(byte[] bytes) {
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+ return bytes.length == 16006;
+ }
+
+ @Override
+ public void convertToImageSizeAndPalette(FilesConverterData data,
+ byte[] bytes) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+
+ PaletteMapper paletteMapper=new Atari8BitPaletteMapper();
+
+ RGB[] paletteColors = new RGB[8];
+ RGB[] palette1Colors = new RGB[2];
+ RGB[] palette2Colors = new RGB[4];
+ palette1Colors[0] = paletteMapper.getRGB(bytes[16000] & 0xfe);
+ palette1Colors[1] = paletteMapper.getRGB(bytes[16001] & 0xfe);
+ palette2Colors[0] = paletteMapper.getRGB(bytes[16002] & 0xfe);
+ palette2Colors[1] = paletteMapper.getRGB(bytes[16003] & 0xfe);
+ palette2Colors[2] = paletteMapper.getRGB(bytes[16004] & 0xfe);
+ palette2Colors[3] = paletteMapper.getRGB(bytes[16005] & 0xfe);
+
+ // Compute mixed interlace colors.
+ for (int x1 = 0; x1 < palette1Colors.length; x1++) {
+ for (int x2 = 0; x2 < palette2Colors.length; x2++) {
+ paletteColors[x1 * palette2Colors.length + x2] = RBGUtility
+ .combineRGB(palette1Colors[x1], palette2Colors[x2]);
+ }
+ }
+ setImageSizeAndPalette(data, 40, 200, Palette.MULTI_MANUAL,
+ paletteColors);
+ }
+
+ @Override
+ public void convertToImageDataSize(FilesConverterData data) {
+ data.setImageDataWidth(data.getParameters().getColumns() * 8);
+ data.setImageDataHeight(data.getParameters().getRows());
+ }
+
+ @Override
+ public boolean convertToImageData(FilesConverterData data) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+
+ int offset = 0;
+ int xpixels = 8;
+
+ int frameSize = 8000;
+ for (int y1 = 0; y1 < data.getParameters().getRows(); y1++) {
+ for (int x1 = 0; x1 < data.getParameters().getColumns(); x1++) {
+ int b1 = data.getSourceFileByte(BIT_MAP_FILE, offset);
+ if (b1 < 0) {
+ return true;
+ }
+ int b2 = data.getSourceFileByte(BIT_MAP_FILE, offset
+ + frameSize);
+ if (b2 < 0) {
+ return true;
+ }
+ offset++;
+
+ for (int x2 = 0; x2 < 8; x2++) {
+ int x = x1 * xpixels + x2;
+ // Graphics 8
+ int color1 = (b1 & mask_1bit[x2]) >>> shift_1bit[x2];
+ // Graphics 15, half resolution
+ int color2 = (b2 & mask_2bit[x2 >>> 1]) >>> shift_2bit[x2 >>> 1];
+ data.setPalettePixel(x, y1, (color1 << 2) + color2);
+ }
+
+ }
+ }
+ return true;
+ }
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapHRConverter.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapHRConverter.java
new file mode 100644
index 00000000..8113bd29
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapHRConverter.java
@@ -0,0 +1,108 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.atari8bit;
+
+import org.eclipse.swt.graphics.RGB;
+
+import com.wudsn.ide.gfx.converter.FilesConverterData;
+import com.wudsn.ide.gfx.converter.generic.LinearBitMapConverter;
+import com.wudsn.ide.gfx.model.Palette;
+import com.wudsn.ide.gfx.model.RBGUtility;
+import com.wudsn.ide.gfx.model.PaletteUtility;
+
+public class LinearBitMapHRConverter extends LinearBitMapConverter {
+
+ public LinearBitMapHRConverter() {
+ }
+
+ @Override
+ public boolean canConvertToImage(byte[] bytes) {
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+ return bytes.length == 16384;
+ }
+
+ @Override
+ public void convertToImageSizeAndPalette(FilesConverterData data,
+ byte[] bytes) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+
+ RGB[] paletteColors = new RGB[3];
+ paletteColors[0] = PaletteUtility.BLACK;
+ paletteColors[2] = PaletteUtility.WHITE;
+
+ // Compute mixed interlace colors.
+ paletteColors[1] = RBGUtility.combineRGB(paletteColors[0],
+ paletteColors[2]);
+ setImageSizeAndPalette(data, 32, 239, Palette.MULTI_MANUAL,
+ paletteColors);
+ }
+
+ @Override
+ public void convertToImageDataSize(FilesConverterData data) {
+ data.setImageDataWidth(data.getParameters().getColumns() * 8);
+ data.setImageDataHeight(data.getParameters().getRows());
+ }
+
+ @Override
+ public boolean convertToImageData(FilesConverterData data) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+
+ int offset = 0;
+ int xpixels = 8;
+
+ int frameSize = 8192;
+ for (int y1 = 0; y1 < data.getParameters().getRows(); y1++) {
+ for (int x1 = 0; x1 < data.getParameters().getColumns(); x1++) {
+ int b1 = data.getSourceFileByte(BIT_MAP_FILE, offset);
+ if (b1 < 0) {
+ return true;
+ }
+ int b2 = data.getSourceFileByte(BIT_MAP_FILE, offset
+ + frameSize);
+ if (b2 < 0) {
+ return true;
+ }
+ offset++;
+
+ for (int x2 = 0; x2 < 8; x2++) {
+ int x = x1 * xpixels + x2;
+ int color1 = (b1 & mask_1bit[x2]) >>> shift_1bit[x2];
+ int color2 = (b2 & mask_1bit[x2]) >>> shift_1bit[x2];
+ data.setPalettePixel(x, y1, color1 + color2);
+ }
+
+ }
+ }
+ return true;
+ }
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapILCConverter.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapILCConverter.java
new file mode 100644
index 00000000..64cc1704
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapILCConverter.java
@@ -0,0 +1,102 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.atari8bit;
+
+import com.wudsn.ide.gfx.converter.FilesConverterData;
+import com.wudsn.ide.gfx.converter.PaletteMapper;
+import com.wudsn.ide.gfx.converter.generic.LinearBitMapConverter;
+import com.wudsn.ide.gfx.model.Palette;
+
+public class LinearBitMapILCConverter extends LinearBitMapConverter {
+
+ public LinearBitMapILCConverter() {
+
+ }
+
+ @Override
+ public boolean canConvertToImage(byte[] bytes) {
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+ return bytes.length == 15360;
+ }
+
+ @Override
+ public void convertToImageSizeAndPalette(FilesConverterData data,
+ byte[] bytes) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+
+ setImageSizeAndPalette(data, 40, 192, Palette.TRUE_COLOR, null);
+ }
+
+ @Override
+ public void convertToImageDataSize(FilesConverterData data) {
+ data.setImageDataWidth(data.getParameters().getColumns() * 2);
+ data.setImageDataHeight(data.getParameters().getRows());
+ }
+
+ @Override
+ public boolean convertToImageData(FilesConverterData data) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+
+ int columns = data.getParameters().getColumns();
+
+ int offset1 = 7680;
+ int offset2 = 0;
+ int xpixels = 2;
+ PaletteMapper paletteMapper = new Atari8BitPaletteMapper();
+
+ for (int y1 = 0; y1 < data.getParameters().getRows(); y1 = y1 + 1) {
+ for (int x1 = 0; x1 < columns; x1++) {
+ int c = data.getSourceFileByte(BIT_MAP_FILE, offset1++);
+ if (c < 0) {
+ return true;
+ }
+ int b = data.getSourceFileByte(BIT_MAP_FILE, offset2++);
+ if (b < 0) {
+ return true;
+ }
+ for (int x2 = 0; x2 < 2; x2++) {
+ int x = x1 * xpixels + x2;
+
+ int color = (c & mask_4bit[x2]) >>> shift_4bit[x2];
+ int brightness = (b & mask_4bit[x2]) >>> shift_4bit[x2];
+ int atariColor = color << 4 | brightness;
+ int directColor = paletteMapper
+ .getRGBColor(atariColor);
+ data.setDirectPixel(x, y1, directColor);
+ }
+
+ }
+ }
+ return true;
+ }
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapINPConverter.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapINPConverter.java
new file mode 100644
index 00000000..2f740d21
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapINPConverter.java
@@ -0,0 +1,117 @@
+/**
+ * Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.atari8bit;
+
+import org.eclipse.swt.graphics.RGB;
+
+import com.wudsn.ide.gfx.converter.FilesConverterData;
+import com.wudsn.ide.gfx.converter.PaletteMapper;
+import com.wudsn.ide.gfx.converter.generic.LinearBitMapConverter;
+import com.wudsn.ide.gfx.model.Palette;
+import com.wudsn.ide.gfx.model.RBGUtility;
+
+/**
+ * The valid bit pattern combinations from the two images are: (0,0)=0, (0,1)=1,
+ * (1,1)=2, (1,2)=3, (2,2)=4, (2,3)=5, (3,3)=6
+ */
+
+public class LinearBitMapINPConverter extends LinearBitMapConverter {
+
+ public LinearBitMapINPConverter() {
+
+ }
+
+ @Override
+ public boolean canConvertToImage(byte[] bytes) {
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+ return bytes.length == 16004 || bytes.length == 16052;
+ }
+
+ @Override
+ public void convertToImageSizeAndPalette(FilesConverterData data,
+ byte[] bytes) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+
+ PaletteMapper paletteMapper = new Atari8BitPaletteMapper();
+ RGB[] paletteColors = new RGB[7];
+ paletteColors[0] = paletteMapper.getRGB(bytes[16000] & 0xfe);
+ paletteColors[2] = paletteMapper.getRGB(bytes[16001] & 0xfe);
+ paletteColors[4] = paletteMapper.getRGB(bytes[16002] & 0xfe);
+ paletteColors[6] = paletteMapper.getRGB(bytes[16003] & 0xfe);
+
+ // Compute mixed interlace colors.
+ paletteColors[1] = RBGUtility.combineRGB(paletteColors[0],
+ paletteColors[2]);
+ paletteColors[3] = RBGUtility.combineRGB(paletteColors[2],
+ paletteColors[4]);
+ paletteColors[5] = RBGUtility.combineRGB(paletteColors[4],
+ paletteColors[6]);
+
+ setImageSizeAndPalette(data, 40, 200, Palette.MULTI_MANUAL,
+ paletteColors);
+ }
+
+ @Override
+ public void convertToImageDataSize(FilesConverterData data) {
+ data.setImageDataWidth(data.getParameters().getColumns() * 4);
+ data.setImageDataHeight(data.getParameters().getRows());
+ }
+
+ @Override
+ public boolean convertToImageData(FilesConverterData data) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+
+ int offset = 0;
+ int xpixels = 4;
+
+ for (int y1 = 0; y1 < data.getParameters().getRows(); y1++) {
+ for (int x1 = 0; x1 < data.getParameters().getColumns(); x1++) {
+ int b1 = data.getSourceFileByte(BIT_MAP_FILE, offset + 8000);
+ int b2 = data.getSourceFileByte(BIT_MAP_FILE, offset++);
+ if (b1 < 0 || b2 < 0) {
+ return true;
+ }
+ for (int x2 = 0; x2 < 4; x2++) {
+ int x = x1 * xpixels + x2;
+
+ int color1 = (b1 & mask_2bit[x2]) >>> shift_2bit[x2];
+ int color2 = (b2 & mask_2bit[x2]) >>> shift_2bit[x2];
+ data.setPalettePixel(x, y1, color1 + color2);
+ }
+
+ }
+ }
+ return true;
+ }
+
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapINTConverter.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapINTConverter.java
new file mode 100644
index 00000000..6742f4d9
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapINTConverter.java
@@ -0,0 +1,147 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.atari8bit;
+
+import org.eclipse.swt.graphics.RGB;
+
+import com.wudsn.ide.gfx.converter.FilesConverterData;
+import com.wudsn.ide.gfx.converter.PaletteMapper;
+import com.wudsn.ide.gfx.converter.generic.LinearBitMapConverter;
+import com.wudsn.ide.gfx.model.Palette;
+import com.wudsn.ide.gfx.model.RBGUtility;
+
+/**
+ * The valid bit pattern combinations from the two images are: (0,0)=0, (0,1)=1,
+ * (1,1)=2, (1,2)=3, (2,2)=4, (2,3)=5, (3,3)=6
+ */
+
+public class LinearBitMapINTConverter extends LinearBitMapConverter {
+
+ public LinearBitMapINTConverter() {
+
+ }
+
+ @Override
+ public boolean canConvertToImage(byte[] bytes) {
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+ if (bytes.length < 10) {
+ return false;
+ }
+ if (bytes[0] != (byte) 'I'
+ || bytes[1] != (byte) 'N'
+ || bytes[2] != (byte) 'T'
+ || bytes[3] != (byte) '9'
+ || bytes[4] != (byte) '5'
+ || bytes[5] != (byte) 'a'
+ || bytes[6] == (byte) 0
+ || (bytes[6] & 0xff) > 40
+ || bytes[7] == (byte) 0
+ || (bytes[7] & 0xff) > 239
+ || bytes[8] != (byte) 0x0f
+ || bytes[9] != (byte) 0x2b
+ || 18 + (bytes[6] & 0xff) * (bytes[7] & 0xff) * 2 != bytes.length) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public void convertToImageSizeAndPalette(FilesConverterData data,
+ byte[] bytes) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+ int rows;
+ int columns;
+ rows = bytes[7] & 0xff;
+ columns = bytes[6] & 0xff;
+
+ PaletteMapper paletteMapper = new Atari8BitPaletteMapper();
+ RGB[] paletteColors = new RGB[16];
+ RGB[] palette1Colors = new RGB[4];
+ RGB[] palette2Colors = new RGB[4];
+ palette1Colors[0] = paletteMapper.getRGB(bytes[10] & 0xfe);
+ palette1Colors[1] = paletteMapper.getRGB(bytes[11] & 0xfe);
+ palette1Colors[2] = paletteMapper.getRGB(bytes[12] & 0xfe);
+ palette1Colors[3] = paletteMapper.getRGB(bytes[13] & 0xfe);
+ palette2Colors[0] = paletteMapper.getRGB(bytes[14] & 0xfe);
+ palette2Colors[1] = paletteMapper.getRGB(bytes[15] & 0xfe);
+ palette2Colors[2] = paletteMapper.getRGB(bytes[16] & 0xfe);
+ palette2Colors[3] = paletteMapper.getRGB(bytes[17] & 0xfe);
+
+ // Compute mixed interlace colors.
+ for (int x1 = 0; x1 < 4; x1++) {
+ for (int x2 = 0; x2 < 4; x2++) {
+ paletteColors[x1 * 4 + x2] = RBGUtility.combineRGB(
+ palette1Colors[x1], palette2Colors[x2]);
+ }
+
+ }
+ setImageSizeAndPalette(data, columns, rows, Palette.MULTI_MANUAL,
+ paletteColors);
+ }
+
+ @Override
+ public void convertToImageDataSize(FilesConverterData data) {
+ data.setImageDataWidth(data.getParameters().getColumns() * 4);
+ data.setImageDataHeight(data.getParameters().getRows());
+ }
+
+ @Override
+ public boolean convertToImageData(FilesConverterData data) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+
+ int offset1 = 18;
+ int offset2 = offset1 + data.getParameters().getRows()
+ * data.getParameters().getColumns();
+ int xpixels = 4;
+
+ for (int y1 = 0; y1 < data.getParameters().getRows(); y1++) {
+ for (int x1 = 0; x1 < data.getParameters().getColumns(); x1++) {
+ int b1 = data.getSourceFileByte(BIT_MAP_FILE, offset1++);
+ int b2 = data.getSourceFileByte(BIT_MAP_FILE, offset2++);
+ if (b1 < 0 || b2 < 0) {
+ return true;
+ }
+ for (int x2 = 0; x2 < 4; x2++) {
+ int x = x1 * xpixels + x2;
+
+ int color1 = (b1 & mask_2bit[x2]) >>> shift_2bit[x2];
+ int color2 = (b2 & mask_2bit[x2]) >>> shift_2bit[x2];
+ int color = 4 * color1 + color2;
+ data.setPalettePixel(x, y1, color);
+ }
+
+ }
+ }
+ return true;
+ }
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapKoalaConverter.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapKoalaConverter.java
new file mode 100644
index 00000000..b8f5b61a
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapKoalaConverter.java
@@ -0,0 +1,147 @@
+/**
+ * Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.atari8bit;
+
+import org.eclipse.swt.graphics.RGB;
+
+import com.wudsn.ide.gfx.converter.FilesConverterData;
+import com.wudsn.ide.gfx.converter.PaletteMapper;
+import com.wudsn.ide.gfx.converter.generic.LinearBitMapConverter;
+import com.wudsn.ide.gfx.model.Palette;
+
+public class LinearBitMapKoalaConverter extends LinearBitMapConverter {
+
+ public LinearBitMapKoalaConverter() {
+
+ }
+
+ @Override
+ public boolean canConvertToImage(byte[] bytes) {
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+ if (bytes.length < 22) {
+ return false;
+ }
+
+ if ((bytes[0] != (byte) 0xff || bytes[1] != (byte) 0x80
+ || bytes[2] != (byte) 0xc9 || bytes[3] != (byte) 0xc7
+ || bytes[4] < (byte) 0x1a || (bytes[4] & 0xff) >= bytes.length
+ || bytes[5] != (byte) 0 || bytes[6] != (byte) 1
+ || bytes[8] != (byte) 0x0e || bytes[9] != (byte) 0
+ || bytes[10] != (byte) 40 || bytes[11] != (byte) 0
+ || bytes[12] != (byte) 192 || bytes[20] != (byte) 0 || bytes[21] != (byte) 0)) {
+ return false;
+ }
+
+ byte[] unpackedImage = new byte[7684];
+ boolean result = Atari8BitUtility.unpackKoala(bytes,
+ (bytes[4] & 0xff) + 1, bytes.length - (bytes[4] & 0xff) - 1,
+ bytes[7] & 0xff, unpackedImage);
+
+ return result;
+ }
+
+ @Override
+ public void convertToImageSizeAndPalette(FilesConverterData data,
+ byte[] bytes) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+
+ byte[] unpackedImage = new byte[7684];
+ boolean result = Atari8BitUtility.unpackKoala(bytes,
+ (bytes[4] & 0xff) + 1, bytes.length - (bytes[4] & 0xff) - 1,
+ bytes[7] & 0xff, unpackedImage);
+
+ if (!result) {
+ throw new IllegalStateException("canConverterToImage() not called");
+ }
+
+ unpackedImage[7680] = bytes[17];
+ unpackedImage[7681] = bytes[13];
+ unpackedImage[7682] = bytes[14];
+ unpackedImage[7683] = bytes[15];
+
+ PaletteMapper paletteMapper = new Atari8BitPaletteMapper();
+ RGB[] paletteColors = new RGB[4];
+ paletteColors[0] = paletteMapper.getRGB(unpackedImage[7680] & 0xfe);
+ paletteColors[1] = paletteMapper.getRGB(unpackedImage[7681] & 0xfe);
+ paletteColors[2] = paletteMapper.getRGB(unpackedImage[7682] & 0xfe);
+ paletteColors[3] = paletteMapper.getRGB(unpackedImage[7683] & 0xfe);
+
+ setImageSizeAndPalette(data, 40, 192, Palette.MULTI_MANUAL,
+ paletteColors);
+ }
+
+ @Override
+ public void convertToImageDataSize(FilesConverterData data) {
+ data.setImageDataWidth(data.getParameters().getColumns() * 4);
+ data.setImageDataHeight(data.getParameters().getRows());
+ }
+
+ @Override
+ public boolean convertToImageData(FilesConverterData data) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+
+ byte[] bytes = data.getSourceFileBytes(BIT_MAP_FILE);
+ if (bytes == null || bytes.length < 8) {
+ return false;
+ }
+
+ byte[] unpackedImage = new byte[7684];
+ boolean result;
+
+ result = Atari8BitUtility.unpackKoala(bytes, (bytes[4] & 0xff) + 1,
+ bytes.length - (bytes[4] & 0xff) - 1, bytes[7] & 0xff,
+ unpackedImage);
+ if (!result) {
+ return false;
+ }
+
+ int offset = 0;
+ int xpixels = 4;
+
+ for (int y1 = 0; y1 < data.getParameters().getRows(); y1++) {
+ for (int x1 = 0; x1 < data.getParameters().getColumns(); x1++) {
+ if (offset >= unpackedImage.length) {
+ return true;
+ }
+ int b = unpackedImage[offset++] & 0xff;
+ for (int x2 = 0; x2 < 4; x2++) {
+ int x = x1 * xpixels + x2;
+ int color = (b & mask_2bit[x2]) >>> shift_2bit[x2];
+ data.setPalettePixel(x, y1, color);
+ }
+
+ }
+ }
+ return true;
+ }
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapMCPConverter.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapMCPConverter.java
new file mode 100644
index 00000000..ecf542c2
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapMCPConverter.java
@@ -0,0 +1,123 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.atari8bit;
+
+import org.eclipse.swt.graphics.RGB;
+
+import com.wudsn.ide.gfx.converter.FilesConverterData;
+import com.wudsn.ide.gfx.converter.PaletteMapper;
+import com.wudsn.ide.gfx.converter.generic.LinearBitMapConverter;
+import com.wudsn.ide.gfx.model.Palette;
+import com.wudsn.ide.gfx.model.RBGUtility;
+
+public class LinearBitMapMCPConverter extends LinearBitMapConverter {
+
+ public LinearBitMapMCPConverter() {
+
+ }
+
+ @Override
+ public boolean canConvertToImage(byte[] bytes) {
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+ return bytes.length == 16008;
+ }
+
+ @Override
+ public void convertToImageSizeAndPalette(FilesConverterData data,
+ byte[] bytes) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+
+ PaletteMapper paletteMapper = new Atari8BitPaletteMapper();
+ RGB[] paletteColors = new RGB[16];
+ RGB[] palette1Colors = new RGB[4];
+ RGB[] palette2Colors = new RGB[4];
+ palette1Colors[0] = paletteMapper.getRGB(bytes[16003] & 0xfe);
+ palette1Colors[1] = paletteMapper.getRGB(bytes[16000] & 0xfe);
+ palette1Colors[2] = paletteMapper.getRGB(bytes[16001] & 0xfe);
+ palette1Colors[3] = paletteMapper.getRGB(bytes[16002] & 0xfe);
+ palette2Colors[0] = paletteMapper.getRGB(bytes[16007] & 0xfe);
+ palette2Colors[1] = paletteMapper.getRGB(bytes[16004] & 0xfe);
+ palette2Colors[2] = paletteMapper.getRGB(bytes[16005] & 0xfe);
+ palette2Colors[3] = paletteMapper.getRGB(bytes[16006] & 0xfe);
+
+ // Compute mixed interlace colors.
+ for (int x1 = 0; x1 < 4; x1++) {
+ for (int x2 = 0; x2 < 4; x2++) {
+ paletteColors[x1 * 4 + x2] = RBGUtility.combineRGB(
+ palette1Colors[x1], palette2Colors[x2]);
+ }
+ }
+
+ setImageSizeAndPalette(data, 40, 200, Palette.MULTI_MANUAL,
+ paletteColors);
+ }
+
+ @Override
+ public void convertToImageDataSize(FilesConverterData data) {
+ data.setImageDataWidth(data.getParameters().getColumns() * 4);
+ data.setImageDataHeight(data.getParameters().getRows());
+ }
+
+ @Override
+ public boolean convertToImageData(FilesConverterData data) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+
+ int offset = 0;
+ int xpixels = 4;
+
+ for (int y1 = 0; y1 < data.getParameters().getRows(); y1++) {
+ for (int x1 = 0; x1 < data.getParameters().getColumns(); x1++) {
+ int b1 = data.getSourceFileByte(BIT_MAP_FILE, offset + 8000);
+ int b2 = data.getSourceFileByte(BIT_MAP_FILE, offset++);
+ if (b1 < 0 || b2 < 0) {
+ return true;
+ }
+ for (int x2 = 0; x2 < 4; x2++) {
+ int x = x1 * xpixels + x2;
+
+ int color1 = (b1 & mask_2bit[x2]) >>> shift_2bit[x2];
+ int color2 = (b2 & mask_2bit[x2]) >>> shift_2bit[x2];
+ int color;
+ if ((y1 & 1) == 1) {
+ color = 4 * color1 + color2;
+ } else {
+ color = 4 * color2 + color1;
+ }
+ data.setPalettePixel(x, y1, color);
+ }
+
+ }
+ }
+ return true;
+ }
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapMicroPainterConverter.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapMicroPainterConverter.java
new file mode 100644
index 00000000..262b5068
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapMicroPainterConverter.java
@@ -0,0 +1,107 @@
+/**
+ * Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.atari8bit;
+
+import org.eclipse.swt.graphics.RGB;
+
+import com.wudsn.ide.gfx.converter.FilesConverterData;
+import com.wudsn.ide.gfx.converter.PaletteMapper;
+import com.wudsn.ide.gfx.converter.generic.LinearBitMapConverter;
+import com.wudsn.ide.gfx.model.Palette;
+import com.wudsn.ide.gfx.model.PaletteType;
+import com.wudsn.ide.gfx.model.PaletteUtility;
+
+public class LinearBitMapMicroPainterConverter extends LinearBitMapConverter {
+
+ public LinearBitMapMicroPainterConverter() {
+
+ }
+
+ @Override
+ public boolean canConvertToImage(byte[] bytes) {
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+ return bytes.length == 7680 || bytes.length == 7684;
+ }
+
+ @Override
+ public void convertToImageSizeAndPalette(FilesConverterData data,
+ byte[] bytes) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+ PaletteMapper paletteMapper = new Atari8BitPaletteMapper();
+ RGB[] paletteColors;
+ if (bytes.length == 7684) {
+ paletteColors = new RGB[4];
+ paletteColors[0] = paletteMapper.getRGB(bytes[7680] & 0xfe);
+ paletteColors[1] = paletteMapper.getRGB(bytes[7681] & 0xfe);
+ paletteColors[2] = paletteMapper.getRGB(bytes[7682] & 0xfe);
+ paletteColors[3] = paletteMapper.getRGB(bytes[7683] & 0xfe);
+ } else {
+ paletteColors = PaletteUtility.getPaletteColors(
+ PaletteType.ATARI_DEFAULT, Palette.MULTI_1, null);
+ }
+
+ setImageSizeAndPalette(data, 40, 192, Palette.MULTI_MANUAL,
+ paletteColors);
+ }
+
+ @Override
+ public void convertToImageDataSize(FilesConverterData data) {
+ data.setImageDataWidth(data.getParameters().getColumns() * 4);
+ data.setImageDataHeight(data.getParameters().getRows());
+ }
+
+ @Override
+ public boolean convertToImageData(FilesConverterData data) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+
+ int offset = 0;
+ int xpixels = 4;
+
+ for (int y1 = 0; y1 < data.getParameters().getRows(); y1++) {
+ for (int x1 = 0; x1 < data.getParameters().getColumns(); x1++) {
+ int b = data.getSourceFileByte(BIT_MAP_FILE, offset++);
+ if (b < 0) {
+ return true;
+ }
+ for (int x2 = 0; x2 < 4; x2++) {
+ int x = x1 * xpixels + x2;
+
+ int color = (b & mask_2bit[x2]) >>> shift_2bit[x2];
+ data.setPalettePixel(x, y1, color);
+ }
+
+ }
+ }
+ return true;
+ }
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapRIPConverter.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapRIPConverter.java
new file mode 100644
index 00000000..6899f43f
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapRIPConverter.java
@@ -0,0 +1,698 @@
+/**
+ * Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.atari8bit;
+
+import com.wudsn.ide.gfx.converter.FilesConverterData;
+import com.wudsn.ide.gfx.converter.PaletteMapper;
+import com.wudsn.ide.gfx.converter.generic.LinearBitMapConverter;
+import com.wudsn.ide.gfx.model.Palette;
+import com.wudsn.ide.gfx.model.RBGUtility;
+
+/**
+ * RIP picture format description
+ *
+ * Original text by Rocky of Madteam taken from Syzygy Magazine
+ * RIP picture was shown first time in Orneta of Poland in '97 in Igor demo by
+ * Madteam. There we copied several disks of RIP images. RIP is a new graphics
+ * storage format on Atari 8-bit. It is based on already famous HIP picture
+ * format (Gr.9 + Gr.10). Theoretically it is possible to get 144 colors (there
+ * are about 40 in practice) with resolution of 160x238 (RIP mode 32; 16 lum x 9
+ * col). RIP is more complicated than HIP, because of the header which contains
+ * a lot of information about colors, resolution and a note from the author. RIP
+ * can have various vertical sizes (max. 238 lines) which cause less space on
+ * disk and faster reading.
+ *
+ *
+ * (E.g. we have a logo with 50 lines. Our logo will be saved with 200 lines as
+ * HIP and takes about 16kB but saved as RIP - only 4kB plus several bytes of
+ * header. That's a difference, isn't it?) In addition RIP can be colored and
+ * HIP can only be grey scaled. (HIP can also be colored but there is no room
+ * for color info in the header.) The first one can still be packed (algorithm
+ * in end phase) for RIP dedicated Visage viewer which is able to recognize its
+ * size, colors, compression method and displaying on screen. Saving HIP as RIP
+ * is no problem 'couse of similar data format. Adapting existing HIP viewers
+ * for RIP pictures shouldn't be problematic too; Only what has to be done is
+ * format recognition, displaying of various image height and setting colors
+ * (for Gr.10) from the header (see below).
+ *
+ *
+ * How to make a RIP picture?
+ *
+ * It can be quite difficult. There is a converter for Amiga and PC. This is not
+ * a real converter from any graphics format (GIF, IFF or Jpeg) to RIP. To make
+ * a RIP picture, you will have to use programs not only dedicated to RIP. The
+ * best for Amiga is Personal Paint and for PC - Display. It's quite a large
+ * job. One picture has to be divided into two others. Next: size modification,
+ * color palette reduction (one of these two pictures has to be 16 grey scales
+ * what can be done with almost all programs and the other picture has to be in
+ * 9 colors, what most programs for the Amiga and PC simply cannot do). The
+ * effect can be very satisfactory, but it might also be completely bad, which
+ * happens quite often (none of the pics is perfect). You can then always create
+ * a HIP picture, which is better in this case (grey scale is easier to do) but
+ * you will be limited to 200 lines. Well, life is brutal...
+ *
+ * Header description:
+ * In 'Description' filed text with quotes (") is pure ASCII string.
+ *
+ *
+ * Offset | Len | Description
+ * --------------------------------------------
+ * 0 | 3 | "RIP" - RIP image identifier
+ * 3 | 4 | version:
+ * | | "1.x " - standard RIP
+ * | | "2.0 " - Multi RIP
+ * 7 | 1 | graphics mode:
+ * | | $20 - RIP or HIP
+ * | | $30 - Multi RIP, palette at the end of file
+ * | | $0f - Graphics 8
+ * | | $4f - Graphics 9
+ * | | $8f - Graphics 10
+ * | | $cf - Graphics 11
+ * | | $0e - Graphics 15
+ * 8 | 2 | compression method:
+ * | | 0, 0 - no compress
+ * | | 0, 1 - RIPPCK
+ * 10 | 2 | header length in bytes, MSB/LSB !!!
+ * 12 | 1 | not used
+ * 13 | 1 | image width in pixels (max. 80) *see below
+ * 14 | 1 | not used
+ * 15 | 1 | image height in lines (max. 238)
+ * 16 | 1 | display option (?), standard set to $20
+ * 17 | 1 | author note length in bytes (max. 256)
+ * 18 | 2 | "T:" - text identifier
+ * 20 | n | author note
+ * 20+n | 1 | number of colors (fixed = 9 from Gr.10)
+ * 21+n | 3 | "CM:" - color map identifier
+ * 24+n | 9 | color values **see below
+ * 33+n | 3 | "PCK" - Multi RIP packed file only, means packed
+ * | | images data
+ *
+ *
+ * Directly after header images data are stored. First Gr.10, next Gr.9.
+ *
+ * HIP and RIP are 80 pixels wide pictures with shifted 9-color plan (Gr.10)
+ * relativelly to 16-grey shaded plan (Gr.9) for half pixel right. Thus, they
+ * appear as 160x200, but one pic has only 80x200;
+ *
+ * Number of colors is fixed to 9 now but it may change. So, take number of
+ * colors from 20+n byte of header (n - length of author note) for safety. (RIP
+ * mode 48 has more colors !!)
+ *
+ * Displaying RIP "1.x" picture routine is similar to HIP routine. The only
+ * difference is to set color registers with values put behind "CM:" while Gr.10
+ * line.
+ *
+ * Information above is enough for writing own procedure showing RIP 1.x
+ * picture. For now I don't have any info about Multi RIP especially for
+ * compression algorithm and color palette. The only thing I know for sure is
+ * the palette should be changed every 2 scanlines. Maybe someone else knows a
+ * little bit more about Multi RIP (or RIP mode 48 with many more colors than
+ * mode 32)...
+ *
+ * Note: This implementation is based on FAIL 1.0.1 and allows 239 lines tough
+ * the specification above states 238 as the maximum.
+ */
+// TODO Verify against FAIL 1.0.2, check if the spurious grey spot and bugs are
+// gone
+public class LinearBitMapRIPConverter extends LinearBitMapConverter {
+
+ private final static class RIPFile {
+ public static final byte RIP = 0x20;
+ public static final byte MULTI_RIP = 0x30;
+
+ private int graphicsMode;
+ private int width;
+ private int height;
+ private int[] palette;
+ private byte[] unpackedImage;
+
+ private RIPFile(int graphicsMode, int width, int height, int[] palette,
+ byte[] unpacked_image) {
+ this.graphicsMode = graphicsMode;
+ this.width = width;
+ this.height = height;
+ this.palette = palette;
+ this.unpackedImage = unpacked_image;
+
+ }
+
+ public static RIPFile createInstance(byte[] bytes) {
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+ if (bytes.length < 23) {
+ return null;
+ }
+ int graphicsMode = bytes[7];
+ int headerLength = (bytes[11] & 0xff) + 256 * (bytes[12] & 0xff);
+ int width = bytes[13] & 0xff;
+ int height = bytes[15] & 0xff;
+ int textLength = bytes[17] & 0xff;
+ if (bytes.length < 20 + textLength) {
+ return null;
+ }
+ int paletteLength = bytes[20 + textLength] & 0xff;
+ int dataLength = bytes.length - headerLength;
+
+ if (bytes[0] != 'R' || bytes[1] != 'I' || bytes[2] != 'P'
+ || width > 80 || height > 239 || textLength > 152
+ || bytes[18] != 'T' || bytes[19] != ':'
+ || paletteLength != 9 || bytes[21 + textLength] != 'C'
+ || bytes[22 + textLength] != 'M'
+ || bytes[23 + textLength] != ':') {
+ return null;
+ }
+
+ byte[] unpackedImage = new byte[24576];
+
+ // Check compression mode.
+ switch (bytes[9]) {
+ case 0:
+ // No compression.
+ if (dataLength > unpackedImage.length) {
+ return null;
+ }
+ System.arraycopy(bytes, headerLength, unpackedImage, 0,
+ dataLength);
+ break;
+
+ // Compression
+ case 1:
+ if (!ShannonFano.unpack(bytes, headerLength, dataLength,
+ unpackedImage)) {
+ return null;
+ }
+ break;
+
+ default:
+ return null;
+ }
+
+ // Check graphic mode
+ switch (graphicsMode) {
+ case RIP:
+ break;
+ case MULTI_RIP:
+ int frame_len = (width / 2) * height;
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < 8; x++) {
+ int ix = 2 * frame_len + y * 8 + x;
+ if (y > 0 && unpackedImage[ix] == 0)
+ unpackedImage[ix] = unpackedImage[ix - 8];
+ }
+ }
+ break;
+ default:
+ return null;
+ }
+
+ int[] palette = new int[paletteLength];
+ for (int i = 0; i < paletteLength; i++) {
+ palette[i] = bytes[24 + textLength + i] & 0xff;
+ }
+ RIPFile result = new RIPFile(graphicsMode, width, height, palette,
+ unpackedImage);
+ return result;
+ }
+
+ public int getGraphicsMode() {
+ return graphicsMode;
+ }
+
+ public int getWidth() {
+ return width;
+ }
+
+ public int getHeight() {
+ return height;
+ }
+
+ public int[] getPalette() {
+ return palette;
+ }
+
+ public byte[] getUnpackedImage() {
+ return unpackedImage;
+ }
+
+ }
+
+ private static final class ShannonFano {
+
+ private static void unpack_cnibl(byte data[], int dataOffset, int size,
+ int output[]) {
+ int x = dataOffset;
+ int y = 0;
+ while (y < size) {
+ int a = data[x++] & 0xff;
+ output[y++] = a >>> 4;
+ output[y++] = a & 0x0f;
+ }
+ }
+
+ private static void unpack_sort(byte data[], int dataOffset, int size,
+ int tre01[], int tre02[]) {
+ int[] pom = new int[16];
+ int y;
+ int x;
+ int md_ = 0;
+ int md = 0;
+
+ unpack_cnibl(data, dataOffset, size, tre02);
+
+ for (y = 0; y < size; y++) {
+ pom[tre02[y]]++;
+ }
+
+ x = 0;
+ do {
+ y = 0;
+ do {
+ if (x == tre02[y]) {
+ tre01[md_++] = y;
+ }
+ y++;
+ } while (y < size);
+ x++;
+ } while (x < 16);
+
+ x = 0;
+ do {
+ y = pom[x];
+ while (y != 0) {
+ tre02[md++] = x;
+ y--;
+ }
+ x++;
+ } while (x < 16);
+ }
+
+ private static void unpack_fano(byte data[], int dataOffset, int size,
+ int tre01[], int tre02[], int l0[], int h0[], int l1[],
+ int h1[], int lhOffset) {
+ int p;
+ int err;
+ int l;
+ int nxt;
+ int y;
+
+ unpack_sort(data, dataOffset, size, tre01, tre02);
+
+ clearMemory(l0, lhOffset, size);
+ clearMemory(l1, lhOffset, size);
+ clearMemory(h0, lhOffset, size);
+ clearMemory(h1, lhOffset, size);
+
+ p = 0;
+ err = 0;
+ l = 0;
+ nxt = 0;
+ y = 0;
+ do {
+ if (tre02[y] != 0) {
+ int x;
+ int tmp;
+ int val;
+ int a;
+ p += err;
+ x = tre02[y];
+ if (x != l) {
+ l = x;
+ err = 0x10000 >>> x;
+ }
+ tmp = p;
+ val = tre01[y];
+ x = tre02[y];
+ a = 0;
+ for (;;) {
+ int z = lhOffset + a;
+ x--;
+ tmp <<= 1;
+ if (tmp < 0x10000) {
+ if (x == 0) {
+ a = val;
+ l0[z] = a;
+ break;
+ }
+ a = h0[z];
+ if (a == 0) {
+ a = ++nxt;
+ h0[z] = a;
+ }
+ } else {
+ tmp &= 0xFFFF;
+ if (x == 0) {
+ a = val;
+ l1[z] = a;
+ break;
+ }
+ a = h1[z];
+ if (a == 0) {
+ a = ++nxt;
+ h1[z] = a;
+ }
+ }
+ }
+ }
+ y++;
+ } while (y < size);
+ }
+
+ private static void clearMemory(int[] array, int offset, int size) {
+ for (int i = 0; i < size; i++) {
+ array[offset + i] = 0;
+ }
+
+ }
+
+ public static boolean unpack(byte data[], int dataOffset,
+ int dataLength, byte unpackedData[]) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+ if (dataOffset < 0) {
+ throw new IllegalArgumentException(
+ "Parameter 'dataOffset' must not be negative, specified value is "
+ + dataOffset + ".");
+ }
+ if (unpackedData == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'unpackedData' must not be null.");
+ }
+ int[] adl0 = new int[576];
+ int[] adh0 = new int[576];
+ int[] adl1 = new int[576];
+ int[] adh1 = new int[576];
+
+ int[] tre01 = new int[256];
+ int[] tre02 = new int[256];
+
+ int unpacked_len;
+ int sx, sxend;
+ int cx, dx;
+ int lic, csh, c;
+
+ // "PCK" header (16 bytes) + 288 bytes shannon-fano
+ if (dataLength < 16 + 288 || data[dataOffset + 0] != 'P'
+ || data[dataOffset + 1] != 'C'
+ || data[dataOffset + 2] != 'K') {
+ return false;
+ }
+
+ unpacked_len = (data[dataOffset + 4] & 0xff) + 256
+ * (data[dataOffset + 5] & 0xff) - 33;
+ if (unpacked_len > 0x5EFE) {
+ return false;
+ }
+
+ // Buggy pictures?!
+ if (unpacked_len == 16811) {
+ unpacked_len = 16800;
+ }
+
+ unpack_fano(data, dataOffset + 16, 64, tre01, tre02, adl0, adh0,
+ adl1, adh1, 0);
+ unpack_fano(data, dataOffset + 16 + 32, 256, tre01, tre02, adl0,
+ adh0, adl1, adh1, 64);
+ unpack_fano(data, dataOffset + 16 + 160, 256, tre01, tre02, adl0,
+ adh0, adl1, adh1, 320);
+
+ sx = dataOffset + 16 + 288;
+ sxend = dataOffset + dataLength + 1;
+
+ dx = 0;
+ lic = -1;
+ csh = 0;
+
+ do {
+ // GBIT();
+ if (--lic < 0) {
+ if (sx >= sxend) {
+ return false;
+ }
+ csh = data[sx++] & 0xff;
+ lic = 7;
+ }
+ c = (csh & (1 << lic));
+
+ if (c == 0) {
+ int a = 0;
+ for (;;) {
+ int y = a;
+
+ // GBIT();
+ if (--lic < 0) {
+ if (sx >= sxend) {
+ return false;
+ }
+ csh = data[sx++] & 0xff;
+ lic = 7;
+ }
+ c = (csh & (1 << lic));
+
+ if (c == 0) {
+ if ((a = adh0[320 + y]) == 0) {
+ unpackedData[dx] = (byte) adl0[320 + y];
+ break;
+ }
+ } else {
+ if ((a = adh1[320 + y]) == 0) {
+ unpackedData[dx] = (byte) adl1[320 + y];
+ break;
+ }
+ }
+ }
+ ++dx;
+ } else {
+ int a = 0;
+ for (;;) {
+ int y = a;
+
+ // GBIT();
+ if (--lic < 0) {
+ if (sx >= sxend) {
+ return false;
+ }
+ csh = data[sx++] & 0xff;
+ lic = 7;
+ }
+ c = (csh & (1 << lic));
+
+ if (c == 0) {
+ if ((a = adh0[64 + y]) == 0) {
+ a = adl0[64 + y];
+ break;
+ }
+ } else {
+ if ((a = adh1[64 + y]) == 0) {
+ a = adl1[64 + y];
+ break;
+ }
+ }
+ }
+ cx = dx - (a + 2);
+ a = 0;
+ for (;;) {
+ int y = a;
+
+ // GBIT();
+ if (--lic < 0) {
+ if (sx >= sxend) {
+ return false;
+ }
+ csh = data[sx++] & 0xff;
+ lic = 7;
+ }
+ c = (csh & (1 << lic));
+
+ if (c == 0) {
+ if ((a = adh0[y]) == 0) {
+ a = adl0[y];
+ break;
+ }
+ } else {
+ if ((a = adh1[y]) == 0) {
+ a = adl1[y];
+ break;
+ }
+ }
+ }
+
+ if (cx > 0) {
+ System.arraycopy(unpackedData, cx, unpackedData, dx,
+ a + 2);
+ }
+ dx += a + 2;
+ }
+ } while (dx < unpacked_len);
+
+ return true;
+ }
+ }
+
+ public LinearBitMapRIPConverter() {
+
+ }
+
+ @Override
+ public boolean canConvertToImage(byte[] bytes) {
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+
+ RIPFile ripFile = RIPFile.createInstance(bytes);
+ if (ripFile == null) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public void convertToImageSizeAndPalette(FilesConverterData data,
+ byte[] bytes) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+
+ RIPFile ripFile = RIPFile.createInstance(bytes);
+ if (ripFile == null) {
+ throw new IllegalStateException("canConvertToImage() not called");
+ }
+
+ int columns;
+ int rows;
+ columns = (ripFile.getWidth() + 1) / 2;
+ rows = ripFile.getHeight();
+
+ setImageSizeAndPalette(data, columns, rows, Palette.TRUE_COLOR, null);
+ }
+
+ @Override
+ public void convertToImageDataSize(FilesConverterData data) {
+ data.setImageDataWidth(data.getParameters().getColumns() * 4 + 1);
+ data.setImageDataHeight(data.getParameters().getRows());
+ }
+
+ @Override
+ public boolean convertToImageData(FilesConverterData data) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+
+ int rows = data.getParameters().getRows();
+ int columns = data.getParameters().getColumns();
+ PaletteMapper paletteMapper = new Atari8BitPaletteMapper();
+
+ // Compute palette.
+ RIPFile ripFile = RIPFile.createInstance(data
+ .getSourceFileBytes(BIT_MAP_FILE));
+ if (ripFile == null) {
+ return false;
+ }
+
+ byte[] unpackedImage = ripFile.getUnpackedImage();
+ int[] graphics10Colors;
+ switch (ripFile.getGraphicsMode()) {
+ case RIPFile.RIP:
+ graphics10Colors = ripFile.getPalette();
+ break;
+ case RIPFile.MULTI_RIP:
+ graphics10Colors = new int[ripFile.getPalette().length];
+ break;
+ default:
+ throw new IllegalStateException("Unsupported graphics mode "
+ + ripFile.getGraphicsMode() + ".");
+
+ }
+
+ // Compute the offsets in the file.
+ int offset9, offset10;
+ int frameSize = rows * columns;
+ offset10 = 0;
+ offset9 = offset10 + frameSize;
+
+ int[] buffer1 = new int[columns * 4 + 1];
+ int[] buffer2 = new int[columns * 4 + 1];
+ for (int y1 = 0; y1 < rows; y1++) {
+
+ // MultiRIP mode?
+ if (ripFile.getGraphicsMode() == RIPFile.MULTI_RIP) {
+ int offset = frameSize * 2 + ((y1 >>> 1) << 3);
+ for (int i = 0; i < graphics10Colors.length - 1; i++) {
+ graphics10Colors[i + 1] = unpackedImage[offset + i] & 0xff;
+ }
+ }
+
+ for (int x1 = 0; x1 < columns; x1++) {
+ if (offset9 >= unpackedImage.length) {
+ return true;
+ }
+ int byte9 = unpackedImage[offset9++];
+ if (offset10 >= unpackedImage.length) {
+ return true;
+ }
+ int byte10 = unpackedImage[offset10++];
+
+ // Byte 1 is the GTIA 9 byte, take the values as brightness
+ // values
+ int color1 = (byte9 & mask_4bit[0]) >>> shift_4bit[0];
+ int color2 = (byte9 & mask_4bit[1]) >>> shift_4bit[1];
+
+ // Byte 2 is the GTIA 10 byte, take the values from the GTIA 10
+ // palette
+ int color3 = (byte10 & mask_4bit[0]) >>> shift_4bit[0];
+ int color4 = (byte10 & mask_4bit[1]) >>> shift_4bit[1];
+ color3 = graphics10Colors[Atari8BitUtility.GRAPHICS_10_REGISTERS[color3]];
+ color4 = graphics10Colors[Atari8BitUtility.GRAPHICS_10_REGISTERS[color4]];
+
+ // Put the color values in the row buffer, shifted by 1 pixel
+ int x = x1 << 2;
+ buffer1[x + 0] = color1;
+ buffer1[x + 1] = color1;
+ buffer1[x + 2] = color2;
+ buffer1[x + 3] = color2;
+
+ buffer2[x + 1] = color3;
+ buffer2[x + 2] = color3;
+ buffer2[x + 3] = color4;
+ buffer2[x + 4] = color4;
+ }
+
+ // Merge the two buffers into combined color values.
+ for (int x = 0; x < buffer1.length; x++) {
+ int atariColor = RBGUtility.combineRGBColor(
+ paletteMapper.getRGBColor(buffer1[x]),
+ paletteMapper.getRGBColor(buffer2[x]));
+ data.setDirectPixel(x, y1, atariColor);
+ }
+ }
+ return true;
+
+ }
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapTIPConverter.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapTIPConverter.java
new file mode 100644
index 00000000..757505a3
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/LinearBitMapTIPConverter.java
@@ -0,0 +1,170 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.atari8bit;
+
+import com.wudsn.ide.gfx.converter.FilesConverterData;
+import com.wudsn.ide.gfx.converter.ImageConverterData;
+import com.wudsn.ide.gfx.converter.PaletteMapper;
+import com.wudsn.ide.gfx.converter.generic.LinearBitMapConverter;
+import com.wudsn.ide.gfx.model.Palette;
+import com.wudsn.ide.gfx.model.RBGUtility;
+
+/**
+ * Layout in the TIP picture is 9 bytes header, graphics 9 picture, graphics 10
+ * picture, graphics 11 picture
+ */
+public class LinearBitMapTIPConverter extends LinearBitMapConverter {
+
+ public LinearBitMapTIPConverter() {
+
+ }
+
+ @Override
+ public boolean canConvertToImage(byte[] bytes) {
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+ if (bytes.length < 9) {
+ return false;
+ }
+
+ int frameLength = (bytes[7] & 0xff) + ((bytes[8] & 0xff) << 8);
+ if (bytes[0] != 'T' || bytes[1] != 'I' || bytes[2] != 'P'
+ || bytes[3] != 1 || bytes[4] != 0 || bytes[5] == 0
+ || (bytes[5] & 0xff) > 160 || bytes[6] == 0
+ || (bytes[6] & 0xff) > 119
+ || (9 + frameLength * 3) != bytes.length) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public void convertToImageSizeAndPalette(FilesConverterData data,
+ byte[] bytes) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+ int columns;
+ int rows;
+ columns = (bytes[5] & 0xff) / 4;
+ rows = (bytes[6] & 0xff);
+ setImageSizeAndPalette(data, columns, rows, Palette.TRUE_COLOR, null);
+ }
+
+ @Override
+ public void convertToImageDataSize(FilesConverterData data) {
+ data.setImageDataWidth(data.getParameters().getColumns() * 4 + 1);
+ data.setImageDataHeight(data.getParameters().getRows());
+ }
+
+ @Override
+ public boolean convertToImageData(FilesConverterData data) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+
+ int rows = data.getParameters().getRows();
+ int columns = data.getParameters().getColumns();
+ PaletteMapper paletteMapper=new Atari8BitPaletteMapper();
+
+ // Assume the binary is already merged in case of a 160012 bytes HIP.
+ int offset9, offset10, offset11;
+
+ // Assume grey scale colors by default.
+ int[] graphics10Colors = { 0, 0, 2, 4, 6, 8, 10, 12, 14 };
+
+ // Compute the offsets in the file.
+ int frameSize = rows * columns;
+ offset9 = 9;
+ offset10 = offset9 + frameSize;
+ offset11 = offset10 + frameSize;
+
+ int[] buffer1 = new int[columns * 4 + 1];
+ int[] buffer2 = new int[columns * 4 + 1];
+ for (int y1 = 0; y1 < rows; y1++) {
+ for (int x1 = 0; x1 < columns; x1++) {
+ int byte1 = data.getSourceFileByte(BIT_MAP_FILE, offset9++);
+ if (byte1 < 0) {
+ return true;
+ }
+ int byte2 = data.getSourceFileByte(BIT_MAP_FILE, offset10++);
+ if (byte2 < 0) {
+ return true;
+ }
+ int byte3 = data.getSourceFileByte(BIT_MAP_FILE, offset11++);
+ if (byte3 < 0) {
+ return true;
+ }
+ // Byte 1 is the GTIA 9 byte, take the values as brightness
+ // values
+ int brightness1 = (byte1 & mask_4bit[0]) >>> shift_4bit[0];
+ int brightness2 = (byte1 & mask_4bit[1]) >>> shift_4bit[1];
+
+ // Byte 2 is the GTIA 10 byte, take the values from the GTIA 10
+ // palette
+ int brightness3 = (byte2 & mask_4bit[0]) >>> shift_4bit[0];
+ int brightness4 = (byte2 & mask_4bit[1]) >>> shift_4bit[1];
+ brightness3 = graphics10Colors[Atari8BitUtility.GRAPHICS_10_REGISTERS[brightness3]];
+ brightness4 = graphics10Colors[Atari8BitUtility.GRAPHICS_10_REGISTERS[brightness4]];
+
+ // Byte 3 is the GTIA 11 byte, take the values as color values
+ int color1 = (byte3 & 0xf0);
+ int color2 = (byte3 & 0x0f) << 4;
+
+ // Put the color values in the row buffer, shifted by 1 pixel
+ int x = x1 << 2;
+ buffer1[x + 0] = color1 | brightness1;
+ buffer1[x + 1] = color1 | brightness1;
+ buffer1[x + 2] = color2 | brightness2;
+ buffer1[x + 3] = color2 | brightness2;
+
+ buffer2[x + 1] = color1 | brightness3;
+ buffer2[x + 2] = color1 | brightness3;
+ buffer2[x + 3] = color2 | brightness4;
+ buffer2[x + 4] = color2 | brightness4;
+ }
+
+ // Merge the two buffers into combined color values.
+ for (int x = 0; x < buffer1.length; x++) {
+ int atariColor = RBGUtility.combineRGBColor(
+ paletteMapper.getRGBColor(buffer1[x]),
+ paletteMapper.getRGBColor(buffer2[x]));
+ data.setDirectPixel(x, y1, atariColor);
+ }
+ }
+ return true;
+ }
+
+ public static void convertToFileData(ImageConverterData data) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+ }
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/palettes/altirra.act b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/palettes/altirra.act
new file mode 100644
index 00000000..59e9be3a
Binary files /dev/null and b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/palettes/altirra.act differ
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/palettes/atari800winplus.act b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/palettes/atari800winplus.act
new file mode 100644
index 00000000..3ee8ebf8
Binary files /dev/null and b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/palettes/atari800winplus.act differ
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/palettes/c64.act b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/palettes/c64.act
new file mode 100644
index 00000000..37f3a6eb
Binary files /dev/null and b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/palettes/c64.act differ
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/palettes/default.act b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/palettes/default.act
new file mode 100644
index 00000000..3ee8ebf8
Binary files /dev/null and b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/palettes/default.act differ
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/palettes/g2f.act b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/palettes/g2f.act
new file mode 100644
index 00000000..fb76d4cb
Binary files /dev/null and b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/palettes/g2f.act differ
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/palettes/gray.act b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/palettes/gray.act
new file mode 100644
index 00000000..3422b067
Binary files /dev/null and b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/palettes/gray.act differ
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/palettes/green.act b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/palettes/green.act
new file mode 100644
index 00000000..60858b3e
Binary files /dev/null and b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/palettes/green.act differ
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/palettes/jakub.act b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/palettes/jakub.act
new file mode 100644
index 00000000..396a5cf3
Binary files /dev/null and b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/palettes/jakub.act differ
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/palettes/laoo.act b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/palettes/laoo.act
new file mode 100644
index 00000000..5f33ecab
Binary files /dev/null and b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/palettes/laoo.act differ
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/palettes/olivierp.act b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/palettes/olivierp.act
new file mode 100644
index 00000000..ea0a70d0
Binary files /dev/null and b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/palettes/olivierp.act differ
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/palettes/real.act b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/palettes/real.act
new file mode 100644
index 00000000..e36ffd72
Binary files /dev/null and b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/palettes/real.act differ
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/palettes/xformer.act b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/palettes/xformer.act
new file mode 100644
index 00000000..ab4d10ea
Binary files /dev/null and b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atari8bit/palettes/xformer.act differ
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atarist/InterleavedBitMap4Planes.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atarist/InterleavedBitMap4Planes.java
new file mode 100644
index 00000000..c7e7cf90
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/atarist/InterleavedBitMap4Planes.java
@@ -0,0 +1,134 @@
+/**
+ * Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.atarist;
+
+import org.eclipse.swt.graphics.RGB;
+
+import com.wudsn.ide.gfx.converter.FilesConverterData;
+import com.wudsn.ide.gfx.converter.generic.LinearBitMapConverter;
+import com.wudsn.ide.gfx.model.Palette;
+import com.wudsn.ide.gfx.model.PaletteType;
+import com.wudsn.ide.gfx.model.PaletteUtility;
+
+/**
+ * TODO Implement Atari ST Conversion
+ *
+ * @author Peter Dell
+ *
+ */
+public class InterleavedBitMap4Planes extends LinearBitMapConverter {
+
+ public InterleavedBitMap4Planes() {
+ }
+
+ @Override
+ public boolean canConvertToImage(byte[] bytes) {
+ if (bytes == null) {
+ throw new IllegalArgumentException("Parameter 'bytes' must not be null.");
+ }
+ return bytes.length > 0 && bytes.length % 80 == 0;
+ }
+
+ @Override
+ public void convertToImageSizeAndPalette(FilesConverterData data, byte[] bytes) {
+ if (data == null) {
+ throw new IllegalArgumentException("Parameter 'data' must not be null.");
+ }
+ if (bytes == null) {
+ throw new IllegalArgumentException("Parameter 'bytes' must not be null.");
+ }
+
+ RGB[] paletteColors;
+ paletteColors = PaletteUtility.getPaletteColors(PaletteType.ATARI_DEFAULT, Palette.GTIA_GREY_1, null);
+ setImageSizeAndPalette(data, 40, 192, Palette.GTIA_GREY_1, paletteColors);
+ }
+
+ @Override
+ public void convertToImageDataSize(FilesConverterData data) {
+ data.setImageDataWidth(data.getParameters().getColumns() * 16);
+ data.setImageDataHeight(data.getParameters().getRows());
+ }
+
+ @Override
+ public boolean convertToImageData(FilesConverterData data) {
+
+ final int[] mask_1bit = new int[] { 0x8000, 0x4000, 0x2000, 0x1000, 0x0800, 0x0400, 0x0200, 0x0100, 0x80, 0x40,
+ 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
+ final int[] shift_1bit = new int[] { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
+
+ if (data == null) {
+ throw new IllegalArgumentException("Parameter 'data' must not be null.");
+ }
+
+ int offset_line = 0;
+ int xpixels = 16;
+
+ for (int y1 = data.getParameters().getRows() - 1; y1 >= 0; y1--) {
+ int offset = offset_line;
+ offset_line += 27 * 8;
+
+ for (int x1 = 0; x1 < data.getParameters().getColumns(); x1++) {
+ int w1 = getWord(data, offset);
+ if (w1 < 0) {
+ return true;
+ }
+ offset += 2;
+ int w2 = getWord(data, offset);
+ if (w2 < 0) {
+ return true;
+ }
+ offset += 2;
+ int w3 = getWord(data, offset);
+ if (w3 < 0) {
+ return true;
+ }
+ offset += 2;
+ int w4 = getWord(data, offset);
+ if (w4 < 0) {
+ return true;
+ }
+ offset += 2;
+
+ for (int x2 = 0; x2 < 16; x2++) {
+ int x = x1 * xpixels + 15 - x2;
+ int shift = shift_1bit[x2];
+ int mask = mask_1bit[x2];
+ int color = ((w1 & mask) >>> shift) + (((w2 & mask) >>> shift) << 1)
+ + (((w3 & mask) >>> shift) << 2) + (((w4 & mask) >>> shift) << 3);
+ data.setPalettePixel(x, y1, color);
+ }
+
+ }
+ }
+ return true;
+ }
+
+ private int getWord(FilesConverterData data, int offset) {
+ int b2 = data.getSourceFileByte(BIT_MAP_FILE, offset + 1);
+ if (b2 < 0) {
+ return b2;
+ }
+ int b1 = data.getSourceFileByte(BIT_MAP_FILE, offset);
+ if (b1 < 0) {
+ return b1;
+ }
+ return b1 + (b2 << 8);
+ }
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/c64/C64PaletteMapper.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/c64/C64PaletteMapper.java
new file mode 100644
index 00000000..df290460
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/c64/C64PaletteMapper.java
@@ -0,0 +1,57 @@
+/**
+ * Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.c64;
+
+import com.wudsn.ide.gfx.converter.PaletteMapper;
+
+// TODO C64PaletteMapper is not yet used. Will be required for Koala pictures etc.
+/**
+ * C64 to Atari Mapping
+ *
+ *
+ * 0 Black 0,0 0,2
+ * 1 White 0,15 0,14
+ * 2 Red 3,5 3,6
+ * 3 Cyan 9,11 9,12
+ * 4 Purple 4,7 5,8
+ * 5 Green 11,8 11,10
+ * 6 Blue 7,5 7,6
+ * 7 Yellow 14,14 14,14
+ * 8 Orange 1,5 1,12 (Light Brown)
+ * 9 Brown 14,4 1,8
+ * 10 Light Red 3,10 3,12 (Pink)
+ * 11 Dark Grey 0,6 0,6
+ * 12 Med Grey 0,9 0,10
+ * 13 Light Green 11,13 11,14
+ * 14 Light Blue 6,10 7,10
+ * 15 Light Grey 0,11 0,12
+ *
+ */
+public final class C64PaletteMapper extends PaletteMapper{
+
+ /**
+ * Creation is private.
+ */
+ public C64PaletteMapper() {
+ super(16);
+ // From http://unusedino.de/ec64/technical/misc/vic656x/colors/index.html
+ loadPalette("pepto.pal");
+ }
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/c64/C64Utility.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/c64/C64Utility.java
new file mode 100644
index 00000000..3d1509a9
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/c64/C64Utility.java
@@ -0,0 +1,86 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.c64;
+
+import com.wudsn.ide.base.common.NumberFactory;
+
+/**
+ * C64Utility color codes as defined by VIC II.
+ *
+ * @author Peter Dell
+ *
+ */
+public final class C64Utility {
+
+ public static final Integer BLACK = NumberFactory.getInteger(0);
+ public static final Integer WHITE = NumberFactory.getInteger(1);
+ public static final Integer RED = NumberFactory.getInteger(2);
+ public static final Integer CYAN = NumberFactory.getInteger(3);
+ public static final Integer PINK = NumberFactory.getInteger(4);
+ public static final Integer GREEN = NumberFactory.getInteger(5);
+ public static final Integer BLUE = NumberFactory.getInteger(6);
+ public static final Integer YELLOW = NumberFactory.getInteger(7);
+ public static final Integer ORANGE = NumberFactory.getInteger(8);
+ public static final Integer BROWN = NumberFactory.getInteger(9);
+ public static final Integer LIGHT_RED = NumberFactory.getInteger(10);
+ public static final Integer DARK_GRAY = NumberFactory.getInteger(11);
+ public static final Integer MEDIUM_GRAY = NumberFactory.getInteger(12);
+ public static final Integer LIGHT_GREEN = NumberFactory.getInteger(13);
+ public static final Integer LIGHT_BLUE = NumberFactory.getInteger(14);
+ public static final Integer LIGHT_GRAY = NumberFactory.getInteger(15);
+
+ /**
+ * Determines if a byte array represents a valid C64 charset.
+ *
+ * @param bytes
+ * The byte array, may be empty, not null
.
+ * @return true
if the byte array represents a valid C64
+ * charset, false
otherwise.
+ *
+ * @since 1.6.0
+ */
+ public static boolean isC64Charset(byte[] bytes) {
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+ return bytes.length == 2048 || bytes.length % 0x100 == 2
+ || (bytes.length > 2 && bytes[0] == 0x00 && bytes[1] == 0x38);
+ }
+
+ /**
+ * Determines if a byte array represents a valid C64 sprite (or many).
+ *
+ * @param bytes
+ * The byte array, may be empty, not null
.
+ * @return true
if the byte array represents a valid C64 sprite
+ * (or many), false
otherwise.
+ *
+ * @since 1.6.0
+ */
+ public static boolean isC64Sprite(byte[] bytes) {
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+ return bytes.length == 64
+ || (bytes.length > 2 + 64 && bytes[0] == 0x00);
+ }
+}
\ No newline at end of file
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/c64/SpriteConverter.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/c64/SpriteConverter.java
new file mode 100644
index 00000000..ffbe4d83
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/c64/SpriteConverter.java
@@ -0,0 +1,34 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.c64;
+
+import com.wudsn.ide.gfx.converter.Converter;
+
+public abstract class SpriteConverter extends Converter {
+
+ /**
+ * Source file ids.
+ */
+ public static final int SPRITE_FILE = 0;
+
+
+ protected SpriteConverter() {
+ }
+}
\ No newline at end of file
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/c64/SpriteHiresConverter.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/c64/SpriteHiresConverter.java
new file mode 100644
index 00000000..67db2f56
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/c64/SpriteHiresConverter.java
@@ -0,0 +1,119 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.c64;
+
+import org.eclipse.swt.graphics.RGB;
+
+import com.wudsn.ide.gfx.converter.FilesConverterData;
+import com.wudsn.ide.gfx.model.Palette;
+import com.wudsn.ide.gfx.model.PaletteType;
+import com.wudsn.ide.gfx.model.PaletteUtility;
+
+public class SpriteHiresConverter extends SpriteConverter {
+
+ public SpriteHiresConverter() {
+
+ }
+
+ @Override
+ public boolean canConvertToImage(byte[] bytes) {
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+ boolean c64Sprite = C64Utility.isC64Sprite(bytes);
+ return c64Sprite;
+ }
+
+ @Override
+ public void convertToImageSizeAndPalette(FilesConverterData data,
+ byte[] bytes) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+
+ int columns = 8;
+ int lineSize = columns * 64;
+ int rows;
+ if (bytes.length % 0x100 == 2) {
+ data.getParameters().getSourceFile(SpriteConverter.SPRITE_FILE)
+ .setOffset(2);
+ rows = (bytes.length - 2 + lineSize - 1) / lineSize;
+
+ } else {
+ rows = (bytes.length + lineSize - 1) / lineSize;
+ }
+
+ RGB[] paletteColors;
+ paletteColors = PaletteUtility.getPaletteColors(
+ PaletteType.ATARI_DEFAULT, Palette.HIRES_1, null);
+ setImageSizeAndPalette(data, columns, rows, Palette.HIRES_1,
+ paletteColors);
+ }
+
+ @Override
+ public void convertToImageDataSize(FilesConverterData data) {
+ data.setImageDataWidth(data.getParameters().getColumns()
+ * (3 * 8 + data.getParameters().getSpacingWidth()));
+ data.setImageDataHeight(data.getParameters().getRows()
+ * (21 + data.getParameters().getSpacingWidth()));
+ }
+
+ @Override
+ public boolean convertToImageData(FilesConverterData data) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+
+ int offset = 0;
+ int xpixels = 3 * 8 + data.getParameters().getSpacingWidth();
+ int ypixels = 21 + data.getParameters().getSpacingWidth();
+
+ for (int y1 = 0; y1 < data.getParameters().getRows(); y1++) {
+ for (int x1 = 0; x1 < (data.getParameters().getColumns()); x1++) {
+ for (int y2 = 0; y2 < 21; y2++) {
+ for (int x2 = 0; x2 < 3; x2++) {
+ int b = data.getSourceFileByte(SPRITE_FILE, offset++);
+ if (b < 0) {
+ return true;
+ }
+
+ int y = y1 * ypixels + y2;
+ for (int x3 = 0; x3 < 8; x3++) {
+ int x = x1 * xpixels + x2 * 8 + x3;
+
+ int color = (b & mask_1bit[x3]) >>> shift_1bit[x3];
+ data.setPalettePixel(x, y, color);
+ }
+ }
+ }
+ offset++; // 64th byte
+
+ }
+ }
+ return true;
+ }
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/c64/SpriteMultiColorConverter.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/c64/SpriteMultiColorConverter.java
new file mode 100644
index 00000000..b67d0103
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/c64/SpriteMultiColorConverter.java
@@ -0,0 +1,72 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.c64;
+
+import com.wudsn.ide.gfx.converter.FilesConverterData;
+
+public class SpriteMultiColorConverter extends SpriteConverter {
+
+ public SpriteMultiColorConverter() {
+ }
+
+ @Override
+ public void convertToImageDataSize(FilesConverterData data) {
+ data.setImageDataWidth(data.getParameters().getColumns()
+ * (3 * 4 + data.getParameters().getSpacingWidth()));
+ data.setImageDataHeight(data.getParameters().getRows()
+ * (21 + data.getParameters().getSpacingWidth()));
+ }
+
+ @Override
+ public boolean convertToImageData(FilesConverterData data) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+
+ int offset = 0;
+ int xpixels = 3 * 4 + data.getParameters().getSpacingWidth();
+ int ypixels = 21 + data.getParameters().getSpacingWidth();
+
+ for (int y1 = 0; y1 < data.getParameters().getRows(); y1++) {
+ for (int x1 = 0; x1 < (data.getParameters().getColumns()); x1++) {
+ for (int y2 = 0; y2 < 21; y2++) {
+ for (int x2 = 0; x2 < 3; x2++) {
+ int b = data.getSourceFileByte(SPRITE_FILE, offset++);
+ if (b < 0) {
+ return true;
+ }
+
+ int y = y1 * ypixels + y2;
+ for (int x3 = 0; x3 < 4; x3++) {
+ int x = x1 * xpixels + x2 * 4 + x3;
+
+ int color = (b & mask_2bit[x3]) >>> shift_2bit[x3];
+ data.setPalettePixel(x, y, color);
+ }
+ }
+ }
+ offset++; // 64th byte
+ }
+ }
+ return true;
+ }
+
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/c64/palettes/pepto.pal b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/c64/palettes/pepto.pal
new file mode 100644
index 00000000..5a54b136
Binary files /dev/null and b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/c64/palettes/pepto.pal differ
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/BitMapConverter.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/BitMapConverter.java
new file mode 100644
index 00000000..6f99d075
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/BitMapConverter.java
@@ -0,0 +1,35 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.generic;
+
+import com.wudsn.ide.gfx.converter.Converter;
+
+public abstract class BitMapConverter extends Converter {
+
+ /**
+ * Source file ids.
+ */
+ public static final int BIT_MAP_FILE = 0;
+
+ protected BitMapConverter() {
+
+ }
+
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/CharMapConverter.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/CharMapConverter.java
new file mode 100644
index 00000000..2c6c2a51
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/CharMapConverter.java
@@ -0,0 +1,36 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.generic;
+
+import com.wudsn.ide.gfx.converter.Converter;
+
+public abstract class CharMapConverter extends Converter {
+
+ /**
+ * Source file ids.
+ */
+ public static final int CHAR_SET_FILE = 0;
+ public static final int CHAR_MAP_FILE = 1;
+
+ public CharMapConverter() {
+
+ }
+
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/CharMapHiresConverter.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/CharMapHiresConverter.java
new file mode 100644
index 00000000..2096957c
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/CharMapHiresConverter.java
@@ -0,0 +1,76 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.generic;
+
+import com.wudsn.ide.gfx.converter.FilesConverterData;
+
+public class CharMapHiresConverter extends CharMapConverter {
+
+ public CharMapHiresConverter() {
+
+ }
+
+ @Override
+ public void convertToImageDataSize(FilesConverterData data) {
+ data.setImageDataWidth(data.getParameters().getColumns()
+ * (8 + data.getParameters().getSpacingWidth()));
+ data.setImageDataHeight(data.getParameters().getRows()
+ * (8 + data.getParameters().getSpacingWidth()));
+ }
+
+ @Override
+ public boolean convertToImageData(FilesConverterData data) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+ int offset = 0;
+ int xpixels = 8 + data.getParameters().getSpacingWidth();
+ int ypixels = 8 + data.getParameters().getSpacingWidth();
+
+
+ for (int y1 = 0; y1 < data.getParameters().getRows(); y1++) {
+ for (int x1 = 0; x1 < data.getParameters().getColumns(); x1++) {
+ int c = data.getSourceFileByte(CHAR_MAP_FILE, offset++) & 127;
+ if (c < 0) {
+ return true;
+ }
+ int charset_offset = c * 8;
+ for (int y2 = 0; y2 < 8; y2++) {
+ int b = data.getSourceFileByte(CHAR_SET_FILE,
+ charset_offset++);
+
+ if (b < 0) {
+ return true;
+ }
+ int y = y1 * ypixels + y2;
+ for (int x2 = 0; x2 < 8; x2++) {
+ int x = x1 * xpixels + x2;
+
+ int color = (b & mask_1bit[x2]) >>> shift_1bit[x2];
+ data.setPalettePixel(x, y, color);
+ }
+ }
+ }
+ }
+ return false;
+
+ }
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/CharMapMultiColorConverter.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/CharMapMultiColorConverter.java
new file mode 100644
index 00000000..04681b13
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/CharMapMultiColorConverter.java
@@ -0,0 +1,77 @@
+/**
+ * Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.generic;
+
+import com.wudsn.ide.gfx.converter.FilesConverterData;
+
+public class CharMapMultiColorConverter extends CharMapConverter {
+
+ public CharMapMultiColorConverter() {
+
+ }
+
+ @Override
+ public void convertToImageDataSize(FilesConverterData data) {
+ data.setImageDataWidth(data.getParameters().getColumns()
+ * (4 + data.getParameters().getSpacingWidth()));
+ data.setImageDataHeight(data.getParameters().getRows()
+ * (8 + data.getParameters().getSpacingWidth()));
+ }
+
+ @Override
+ public boolean convertToImageData(FilesConverterData data) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+
+ int offset = 0;
+ int xpixels = 4 + data.getParameters().getSpacingWidth();
+ int ypixels = 8 + data.getParameters().getSpacingWidth();
+
+// int[] fonts = new int[] { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2,
+// 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 3, 0, 1, 4,0 };
+ for (int y1 = 0; y1 < data.getParameters().getRows(); y1++) {
+ for (int x1 = 0; x1 < data.getParameters().getColumns(); x1++) {
+ int c = data.getSourceFileByte(CHAR_MAP_FILE, offset++) & 127;
+ if (c < 0) {
+ return true;
+ }
+ int charset_offset = c * 8; // + fonts[y1] * 1024;
+ for (int y2 = 0; y2 < 8; y2++) {
+ int b = data.getSourceFileByte(CHAR_SET_FILE,
+ charset_offset++);
+
+ if (b < 0) {
+ return true;
+ }
+ int y = y1 * ypixels + y2;
+ for (int x2 = 0; x2 < 4; x2++) {
+ int x = x1 * xpixels + x2;
+
+ int color = (b & mask_2bit[x2]) >>> shift_2bit[x2];
+ data.setPalettePixel(x, y, color);
+ }
+ }
+ }
+ }
+ return true;
+ }
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/CharSet1x1HiresConverter.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/CharSet1x1HiresConverter.java
new file mode 100644
index 00000000..20257c2b
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/CharSet1x1HiresConverter.java
@@ -0,0 +1,123 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.generic;
+
+import org.eclipse.swt.graphics.RGB;
+
+import com.wudsn.ide.gfx.converter.FilesConverterData;
+import com.wudsn.ide.gfx.converter.atari8bit.Atari8BitUtility;
+import com.wudsn.ide.gfx.converter.c64.C64Utility;
+import com.wudsn.ide.gfx.model.Palette;
+import com.wudsn.ide.gfx.model.PaletteType;
+import com.wudsn.ide.gfx.model.PaletteUtility;
+
+public class CharSet1x1HiresConverter extends CharSetConverter {
+
+ public CharSet1x1HiresConverter() {
+
+ }
+
+ @Override
+ public boolean canConvertToImage(byte[] bytes) {
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+ boolean atariCharset = Atari8BitUtility.isAtariCharset(bytes);
+ boolean c64Charset = C64Utility.isC64Charset(bytes);
+ return atariCharset || c64Charset;
+ }
+
+ @Override
+ public void convertToImageSizeAndPalette(FilesConverterData data,
+ byte[] bytes) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+
+ int columns = 32;
+ int lineSize = columns * 8;
+ int rows;
+ if ((bytes.length == 1024 + 6 && Atari8BitUtility
+ .getLengthFromBinaryHeader(bytes, 0) == 1024)) {
+ data.getParameters().getSourceFile(CharSetConverter.CHAR_SET_FILE)
+ .setOffset(6);
+
+ rows = (bytes.length - 6 + lineSize - 1) / lineSize;
+ } else if (bytes.length % 0x100 == 2
+ || (bytes.length > 2 && bytes[0] == 0x00 && bytes[1] == 0x38)) {
+ data.getParameters().getSourceFile(CharSetConverter.CHAR_SET_FILE)
+ .setOffset(2);
+ rows = (bytes.length - 2 + lineSize - 1) / lineSize;
+
+ } else {
+ rows = (bytes.length + lineSize - 1) / lineSize;
+ }
+
+ RGB[] paletteColors;
+ paletteColors = PaletteUtility.getPaletteColors(
+ PaletteType.ATARI_DEFAULT, Palette.HIRES_1, null);
+ setImageSizeAndPalette(data, columns, rows, Palette.HIRES_1,
+ paletteColors);
+ }
+
+ @Override
+ public void convertToImageDataSize(FilesConverterData data) {
+ data.setImageDataWidth(data.getParameters().getColumns()
+ * (8 + data.getParameters().getSpacingWidth()));
+ data.setImageDataHeight(data.getParameters().getRows()
+ * (8 + data.getParameters().getSpacingWidth()));
+ }
+
+ @Override
+ public boolean convertToImageData(FilesConverterData data) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+
+ int offset = 0;
+ int xpixels = 8 + data.getParameters().getSpacingWidth();
+ int ypixels = 8 + data.getParameters().getSpacingWidth();
+
+ for (int y1 = 0; y1 < data.getParameters().getRows(); y1++) {
+ for (int x1 = 0; x1 < data.getParameters().getColumns(); x1++) {
+ for (int y2 = 0; y2 < 8; y2++) {
+ int b = data.getSourceFileByte(CHAR_SET_FILE, offset++);
+ if (b < 0) {
+ return true;
+ }
+ int y = y1 * ypixels + y2;
+ for (int x2 = 0; x2 < 8; x2++) {
+ int x = x1 * xpixels + x2;
+ int color = (b & mask_1bit[x2]) >>> shift_1bit[x2];
+ data.setPalettePixel(x, y, color);
+ }
+ }
+ }
+ }
+ return true;
+ }
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/CharSet1x1HiresConverter.js b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/CharSet1x1HiresConverter.js
new file mode 100644
index 00000000..b1f8f6b6
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/CharSet1x1HiresConverter.js
@@ -0,0 +1,28 @@
+function convertToFileData(data) {
+ var columns = data.getImageDataWidth() / 8;
+ var rows = data.getImageDataHeight() / 8;
+ var chars = 256;
+
+ var char = 0;
+ var bytes = [];
+ var offset = 0;
+ for (var r = 0; r < rows; r++) {
+ for (var c = 0; c < columns; c++) {
+ if (char < chars) {
+ for (var l=0;l<8;l++) {
+ var b = 0;
+ for (var p = 0; p < 8; p++) {
+ var color;
+ color = data.getPixel(c*8+p, r*8+l);
+ if (color != 0) {
+ b = b | 1 << 7 - p;
+ }
+ }
+ bytes[offset++] = b;
+ }
+ char++;
+ }
+ }
+ }
+ data.setTargetFileObject(0, bytes);
+}
\ No newline at end of file
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/CharSet1x1MultiColorConverter.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/CharSet1x1MultiColorConverter.java
new file mode 100644
index 00000000..88a7fefe
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/CharSet1x1MultiColorConverter.java
@@ -0,0 +1,69 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.generic;
+
+import com.wudsn.ide.gfx.converter.FilesConverterData;
+
+public class CharSet1x1MultiColorConverter extends CharSetConverter {
+
+ public CharSet1x1MultiColorConverter() {
+ }
+
+ @Override
+ public void convertToImageDataSize(FilesConverterData data) {
+ data.setImageDataWidth(data.getParameters().getColumns()
+ * (4 + data.getParameters().getSpacingWidth()));
+ data.setImageDataHeight(data.getParameters().getRows()
+ * (8 + data.getParameters().getSpacingWidth()));
+ }
+
+
+ @Override
+ public boolean convertToImageData(FilesConverterData data) {
+
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+
+ int offset = 0;
+ int xpixels = 4 + data.getParameters().getSpacingWidth();
+ int ypixels = 8 + data.getParameters().getSpacingWidth();
+
+ for (int y1 = 0; y1 < data.getParameters().getRows(); y1++) {
+ for (int x1 = 0; x1 < data.getParameters().getColumns(); x1++) {
+ for (int y2 = 0; y2 < 8; y2++) {
+ int b = data.getSourceFileByte(CHAR_SET_FILE, offset++);
+ if (b < 0) {
+ return true;
+ }
+ int y = y1 * ypixels + y2;
+ for (int x2 = 0; x2 < 4; x2++) {
+ int x = x1 * xpixels + x2;
+ int color = (b & mask_2bit[x2]) >>> shift_2bit[x2];
+ data.setPalettePixel(x, y, color);
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/CharSet1x1MultiColorConverter.js b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/CharSet1x1MultiColorConverter.js
new file mode 100644
index 00000000..18a5307d
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/CharSet1x1MultiColorConverter.js
@@ -0,0 +1,29 @@
+function convertToFileData(data) {
+ var columns = data.getImageDataWidth() / 8;
+ var rows = data.getImageDataHeight() / 8;
+ var chars = 256;
+
+ var char = 0;
+ var bytes = [];
+ var offset = 0;
+ for (var r = 0; r < rows; r++) {
+ for (var c = 0; c < columns; c++) {
+ if (char < chars) {
+ for (var l=0;l<8;l++) {
+ var b;
+ var x,y,c1,c2,c3,c4;
+ x = c*4;
+ y = r*8 + l;
+ c1 = data.getPixel(x, y) & 0x3;
+ c2 = data.getPixel(x+1, y) & 0x3;
+ c3 = data.getPixel(x+2, y) & 0x3;
+ c4 = data.getPixel(x+3, y) & 0x3;
+ b = c1 << 6 | c2 << 4 | c3 << 2 | c4;
+ bytes[offset++] = b;
+ }
+ char++;
+ }
+ }
+ }
+ data.setTargetFileObject(0, bytes);
+}
\ No newline at end of file
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/CharSet2x1HiresConverter.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/CharSet2x1HiresConverter.java
new file mode 100644
index 00000000..bf42fee1
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/CharSet2x1HiresConverter.java
@@ -0,0 +1,127 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.generic;
+
+import org.eclipse.swt.graphics.RGB;
+
+import com.wudsn.ide.gfx.converter.FilesConverterData;
+import com.wudsn.ide.gfx.converter.atari8bit.Atari8BitUtility;
+import com.wudsn.ide.gfx.converter.c64.C64Utility;
+import com.wudsn.ide.gfx.model.Palette;
+import com.wudsn.ide.gfx.model.PaletteType;
+import com.wudsn.ide.gfx.model.PaletteUtility;
+
+public class CharSet2x1HiresConverter extends CharSetConverter {
+
+ public CharSet2x1HiresConverter() {
+
+ }
+
+ @Override
+ public boolean canConvertToImage(byte[] bytes) {
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+ boolean atariCharset = Atari8BitUtility.isAtariCharset(bytes);
+ boolean c64Charset =C64Utility.isC64Charset(bytes);
+ return atariCharset || c64Charset;
+ }
+
+ @Override
+ public void convertToImageSizeAndPalette(FilesConverterData data,
+ byte[] bytes) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+
+ int columns = 16;
+ int lineSize = columns * 8*2;
+ int rows;
+ if ((bytes.length == 1024 + 6 && Atari8BitUtility
+ .getLengthFromBinaryHeader(bytes, 0) == 1024)) {
+ data.getParameters().getSourceFile(CharSetConverter.CHAR_SET_FILE)
+ .setOffset(6);
+
+ rows = (bytes.length - 6 + lineSize - 1) / lineSize;
+ } else if (bytes.length % 0x100 == 2) {
+ data.getParameters().getSourceFile(CharSetConverter.CHAR_SET_FILE)
+ .setOffset(2);
+ rows = (bytes.length - 2 + lineSize - 1) / lineSize;
+
+ } else {
+ rows = (bytes.length + lineSize - 1) / lineSize;
+ }
+
+ RGB[] paletteColors;
+ paletteColors = PaletteUtility.getPaletteColors(
+ PaletteType.ATARI_DEFAULT, Palette.HIRES_1, null);
+ setImageSizeAndPalette(data, columns, rows, Palette.HIRES_1,
+ paletteColors);
+ }
+
+ @Override
+ public void convertToImageDataSize(FilesConverterData data) {
+ data.setImageDataWidth((data.getParameters().getColumns())
+ * (8 + data.getParameters().getSpacingWidth()));
+ data.setImageDataHeight((data.getParameters().getRows())
+ * (16 + data.getParameters().getSpacingWidth()));
+ }
+
+ @Override
+ public boolean convertToImageData(FilesConverterData data) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+
+ int offset = 0;
+ int xpixels = 8 + data.getParameters().getSpacingWidth();
+ int ypixels = 16 + data.getParameters().getSpacingWidth();
+
+ for (int y1 = 0; y1 < data.getParameters().getRows(); y1++) {
+ for (int x1 = 0; x1 < data.getParameters().getColumns(); x1++) {
+ for (int cy = 0; cy < 2; cy++) {
+ for (int cx = 0; cx < 1; cx++) {
+ for (int y2 = 0; y2 < 8; y2++) {
+ int b = data.getSourceFileByte(CHAR_SET_FILE,
+ offset++);
+ if (b < 0) {
+ return true;
+ }
+ int y = y1 * ypixels + cy * 8 + y2;
+ for (int x2 = 0; x2 < 8; x2++) {
+ int x = x1 * xpixels + cx * 8 + x2;
+ int color = (b & mask_1bit[x2]) >>> shift_1bit[x2];
+ data.setPalettePixel(x, y, color);
+ }
+ }
+ }
+ }
+ }
+ }
+ return true;
+ }
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/CharSet2x1HiresConverter.js b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/CharSet2x1HiresConverter.js
new file mode 100644
index 00000000..7874cd36
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/CharSet2x1HiresConverter.js
@@ -0,0 +1,28 @@
+function convertToFileData(data) {
+ var columns = data.getImageDataWidth() / 8;
+ var rows = data.getImageDataHeight() / 16;
+ var chars = 256;
+
+ var char = 0;
+ var bytes = [];
+ var offset = 0;
+ for (var r = 0; r < rows; r++) {
+ for (var c = 0; c < columns; c++) {
+ if (char < chars) {
+ for (var l=0;l<16;l++) {
+ var b = 0;
+ for (var p = 0; p < 8; p++) {
+ var color;
+ color = data.getPixel(c*8+p, r*16+l);
+ if (color != 0) {
+ b = b | 1 << 7 - p;
+ }
+ }
+ bytes[offset++] = b;
+ }
+ char++;
+ }
+ }
+ }
+ data.setTargetFileObject(0, bytes);
+}
\ No newline at end of file
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/CharSet2x2HiresConverter.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/CharSet2x2HiresConverter.java
new file mode 100644
index 00000000..9ed39fa9
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/CharSet2x2HiresConverter.java
@@ -0,0 +1,128 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.generic;
+
+import org.eclipse.swt.graphics.RGB;
+
+import com.wudsn.ide.gfx.converter.FilesConverterData;
+import com.wudsn.ide.gfx.converter.atari8bit.Atari8BitUtility;
+import com.wudsn.ide.gfx.converter.c64.C64Utility;
+import com.wudsn.ide.gfx.model.Palette;
+import com.wudsn.ide.gfx.model.PaletteType;
+import com.wudsn.ide.gfx.model.PaletteUtility;
+
+// TODO Have base class for n*m charset converters
+public class CharSet2x2HiresConverter extends CharSetConverter {
+
+ public CharSet2x2HiresConverter() {
+
+ }
+
+ @Override
+ public boolean canConvertToImage(byte[] bytes) {
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+ boolean atariCharset = Atari8BitUtility.isAtariCharset(bytes);
+ boolean c64Charset =C64Utility.isC64Charset(bytes);
+ return atariCharset || c64Charset;
+ }
+
+ @Override
+ public void convertToImageSizeAndPalette(FilesConverterData data,
+ byte[] bytes) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+ if (bytes == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'bytes' must not be null.");
+ }
+
+ int columns = 16;
+ int lineSize = columns * 8*4;
+ int rows;
+ if ((bytes.length == 1024 + 6 && Atari8BitUtility
+ .getLengthFromBinaryHeader(bytes, 0) == 1024)) {
+ data.getParameters().getSourceFile(CharSetConverter.CHAR_SET_FILE)
+ .setOffset(6);
+
+ rows = (bytes.length - 6 + lineSize - 1) / lineSize;
+ } else if (bytes.length % 0x100 == 2) {
+ data.getParameters().getSourceFile(CharSetConverter.CHAR_SET_FILE)
+ .setOffset(2);
+ rows = (bytes.length - 2 + lineSize - 1) / lineSize;
+
+ } else {
+ rows = (bytes.length + lineSize - 1) / lineSize;
+ }
+
+ RGB[] paletteColors;
+ paletteColors = PaletteUtility.getPaletteColors(
+ PaletteType.ATARI_DEFAULT, Palette.HIRES_1, null);
+ setImageSizeAndPalette(data, columns, rows, Palette.HIRES_1,
+ paletteColors);
+ }
+
+ @Override
+ public void convertToImageDataSize(FilesConverterData data) {
+ data.setImageDataWidth((data.getParameters().getColumns())
+ * (16 + data.getParameters().getSpacingWidth()));
+ data.setImageDataHeight((data.getParameters().getRows())
+ * (16 + data.getParameters().getSpacingWidth()));
+ }
+
+ @Override
+ public boolean convertToImageData(FilesConverterData data) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+
+ int offset = 0;
+ int xpixels = 16 + data.getParameters().getSpacingWidth();
+ int ypixels = 16 + data.getParameters().getSpacingWidth();
+
+ for (int y1 = 0; y1 < data.getParameters().getRows(); y1++) {
+ for (int x1 = 0; x1 < data.getParameters().getColumns(); x1++) {
+ for (int cy = 0; cy < 2; cy++) {
+ for (int cx = 0; cx < 2; cx++) {
+ for (int y2 = 0; y2 < 8; y2++) {
+ int b = data.getSourceFileByte(CHAR_SET_FILE,
+ offset++);
+ if (b < 0) {
+ return true;
+ }
+ int y = y1 * ypixels + cy * 8 + y2;
+ for (int x2 = 0; x2 < 8; x2++) {
+ int x = x1 * xpixels + cx * 8 + x2;
+ int color = (b & mask_1bit[x2]) >>> shift_1bit[x2];
+ data.setPalettePixel(x, y, color);
+ }
+ }
+ }
+ }
+ }
+ }
+ return true;
+ }
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/CharSet2x2MultiColorConverter.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/CharSet2x2MultiColorConverter.java
new file mode 100644
index 00000000..7b5eb17f
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/CharSet2x2MultiColorConverter.java
@@ -0,0 +1,72 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.generic;
+
+import com.wudsn.ide.gfx.converter.FilesConverterData;
+
+public class CharSet2x2MultiColorConverter extends CharSetConverter {
+
+ public CharSet2x2MultiColorConverter() {
+
+ }
+
+ @Override
+ public void convertToImageDataSize(FilesConverterData data) {
+ data.setImageDataWidth((data.getParameters().getColumns())
+ * (8 + data.getParameters().getSpacingWidth()));
+ data.setImageDataHeight((data.getParameters().getRows())
+ * (16 + data.getParameters().getSpacingWidth()));
+ }
+
+ @Override
+ public boolean convertToImageData(FilesConverterData data) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+
+ int offset = 0;
+ int xpixels = 8 + data.getParameters().getSpacingWidth();
+ int ypixels = 16 + data.getParameters().getSpacingWidth();
+
+ for (int y1 = 0; y1 < data.getParameters().getRows() ; y1++) {
+ for (int x1 = 0; x1 < data.getParameters().getColumns() ; x1++) {
+ for (int cy = 0; cy < 2; cy++) {
+ for (int cx = 0; cx < 2; cx++) {
+ for (int y2 = 0; y2 < 8; y2++) {
+ int b = data.getSourceFileByte(CHAR_SET_FILE,
+ offset++);
+ if (b < 0) {
+ return true;
+ }
+ int y = y1 * ypixels + cy * 8 + y2;
+ for (int x2 = 0; x2 < 4; x2++) {
+ int x = x1 * xpixels + cx * 4 + x2;
+ int color = (b & mask_2bit[x2]) >>> shift_2bit[x2];
+ data.setPalettePixel(x, y, color);
+ }
+ }
+ }
+ }
+ }
+ }
+ return true;
+ }
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/CharSetConverter.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/CharSetConverter.java
new file mode 100644
index 00000000..85c292f2
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/CharSetConverter.java
@@ -0,0 +1,33 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.generic;
+
+import com.wudsn.ide.gfx.converter.Converter;
+
+public abstract class CharSetConverter extends Converter {
+
+ /**
+ * Source file ids.
+ */
+ public static final int CHAR_SET_FILE = 0;
+
+ public CharSetConverter() {
+ }
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/LinearBitMapConverter.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/LinearBitMapConverter.java
new file mode 100644
index 00000000..274fe60c
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/LinearBitMapConverter.java
@@ -0,0 +1,31 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.generic;
+
+
+public abstract class LinearBitMapConverter extends BitMapConverter {
+
+
+
+ protected LinearBitMapConverter() {
+
+ }
+
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/TiledBitMap2x2MultiColorConverter.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/TiledBitMap2x2MultiColorConverter.java
new file mode 100644
index 00000000..bad74331
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/TiledBitMap2x2MultiColorConverter.java
@@ -0,0 +1,121 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.generic;
+
+import org.eclipse.swt.graphics.RGB;
+
+import com.wudsn.ide.gfx.converter.FilesConverterData;
+import com.wudsn.ide.gfx.converter.c64.C64Utility;
+
+public class TiledBitMap2x2MultiColorConverter extends TiledBitMapConverter {
+
+ public TiledBitMap2x2MultiColorConverter() {
+
+ }
+
+ @Override
+ public void convertToImageDataSize(FilesConverterData data) {
+ data.setImageDataWidth(data.getParameters().getColumns()
+ * (8 + data.getParameters().getSpacingWidth()));
+ data.setImageDataHeight(data.getParameters().getRows()
+ * (16 + data.getParameters().getSpacingWidth()));
+ }
+
+ @Override
+ public boolean convertToImageData(FilesConverterData data) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+ int[] colors = new int[] { 0x191d19, 0xfcf9fc, 0x933a4c, 0xb6fafa,
+ 0xd27ded, 0x6acf6f, 0x4f44d8, 0xfbfb8b, 0xd89c5b, 0x7f5307,
+ 0xef839f, 0x575753, 0xa3a7a7, 0xb7ffbbf, 0xa397ff, 0xefe9e7 };
+
+ for (int i = 0; i < 16; i++) {
+ int r = (colors[i] >> 16) & 0xff;
+ int g = (colors[i] >> 8) & 0xff;
+ int b = (colors[i] >> 0) & 0xff;
+ data.getImageData().palette.colors[i] = new RGB(r, g, b);
+ }
+
+ int tile = 0;
+ int bitmap_offset = 0;
+ int video_ram_offset = 0;
+ int color_ram_offset = 0;
+ int xpixels = 8 + data.getParameters().getSpacingWidth();
+ int ypixels = 16 + data.getParameters().getSpacingWidth();
+ int rows = data.getParameters().getRows();
+ int columns = data.getParameters().getColumns();
+
+ int[] cell_colors = new int[] { 0, 1, 2, 3 };
+
+ for (int y1 = 0; y1 < rows; y1++) {
+ for (int x1 = 0; x1 < columns; x1++) {
+ video_ram_offset = tile * 4;
+ color_ram_offset = tile * 2;
+ for (int y2 = 0; y2 < 2; y2++) {
+ for (int x2 = 0; x2 < 2; x2++) {
+ int v = data.getSourceFileByte(VIDEO_RAM_FILE,
+ video_ram_offset + y2 * 2 + x2);
+ int c = data.getSourceFileByte(COLOR_RAM_FILE,
+ color_ram_offset + y2);
+ if (v >= 0 && c >= 0) {
+ cell_colors[1] = (v >> 4) & 0xf;
+ cell_colors[2] = (v >> 0) & 0xf;
+ if (x2 == 0) {
+ cell_colors[3] = (c >> 4) & 0xf;
+ } else {
+ cell_colors[3] = (c >> 0) & 0xf;
+
+ }
+
+ } else {
+ cell_colors[1] = C64Utility.RED.intValue();
+ cell_colors[2] = C64Utility.LIGHT_RED.intValue();
+ cell_colors[3] = C64Utility.WHITE.intValue();
+ }
+
+ for (int y3 = 0; y3 < 8; y3++) {
+ int b = data.getSourceFileByte(BIT_MAP_FILE,
+ bitmap_offset++);
+ if (b < 0) {
+ return true;
+ }
+
+ int y = y1 * ypixels + y2 * 8 + y3;
+ for (int x3 = 0; x3 < 4; x3++) {
+ int x = x1 * xpixels + x2 * 4 + x3;
+
+ int color = (b & mask_2bit[x3]) >>> shift_2bit[x3];
+ data.setPalettePixel(x, y, cell_colors[color]);
+ }
+ }
+
+ }
+ }
+ color_ram_offset += 4;
+ video_ram_offset += 4;
+ tile++;
+
+ }
+ }
+ return true;
+ }
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/TiledBitMapConverter.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/TiledBitMapConverter.java
new file mode 100644
index 00000000..62e71964
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/TiledBitMapConverter.java
@@ -0,0 +1,35 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.generic;
+
+
+public abstract class TiledBitMapConverter extends BitMapConverter {
+
+ /**
+ * Source file ids.
+ */
+ public static final int VIDEO_RAM_FILE = 1;
+ public static final int COLOR_RAM_FILE = 2;
+
+ protected TiledBitMapConverter() {
+
+ }
+
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/TiledBitMapHiresConverter.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/TiledBitMapHiresConverter.java
new file mode 100644
index 00000000..78a8ffdc
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/TiledBitMapHiresConverter.java
@@ -0,0 +1,67 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.generic;
+
+import com.wudsn.ide.gfx.converter.FilesConverterData;
+
+public class TiledBitMapHiresConverter extends TiledBitMapConverter {
+
+ public TiledBitMapHiresConverter() {
+
+ }
+
+ @Override
+ public void convertToImageDataSize(FilesConverterData data) {
+ data.setImageDataWidth(data.getParameters().getColumns()
+ * (8 + data.getParameters().getSpacingWidth()));
+ data.setImageDataHeight(data.getParameters().getRows()
+ * (8 + data.getParameters().getSpacingWidth()));
+ }
+
+ @Override
+ public boolean convertToImageData(FilesConverterData data) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+
+ int offset = 0;
+ int xpixels = 8 + data.getParameters().getSpacingWidth();
+ int ypixels = 8 + data.getParameters().getSpacingWidth();
+
+ for (int y1 = 0; y1 < data.getParameters().getRows(); y1++) {
+ for (int x1 = 0; x1 < data.getParameters().getColumns(); x1++) {
+ for (int y2 = 0; y2 < 8; y2++) {
+ int b = data.getSourceFileByte(BIT_MAP_FILE, offset++);
+ if (b < 0) {
+ return true;
+ }
+ int y = y1 * ypixels + y2;
+ for (int x2 = 0; x2 < 8; x2++) {
+ int x = x1 * xpixels + x2;
+ int color = (b & mask_1bit[x2]) >>> shift_1bit[x2];
+ data.setPalettePixel(x, y, color);
+ }
+ }
+ }
+ }
+ return true;
+ }
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/TiledBitMapMultiColorConverter.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/TiledBitMapMultiColorConverter.java
new file mode 100644
index 00000000..a2f7be8e
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/converter/generic/TiledBitMapMultiColorConverter.java
@@ -0,0 +1,68 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.converter.generic;
+
+import com.wudsn.ide.gfx.converter.FilesConverterData;
+
+public class TiledBitMapMultiColorConverter extends TiledBitMapConverter {
+
+ public TiledBitMapMultiColorConverter() {
+
+ }
+
+ @Override
+ public void convertToImageDataSize(FilesConverterData data) {
+ data.setImageDataWidth(data.getParameters().getColumns()
+ * (4 + data.getParameters().getSpacingWidth()));
+ data.setImageDataHeight(data.getParameters().getRows()
+ * (8 + data.getParameters().getSpacingWidth()));
+ }
+
+ @Override
+ public boolean convertToImageData(FilesConverterData data) {
+ if (data == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'data' must not be null.");
+ }
+
+ int offset = 0;
+ int xpixels = 4 + data.getParameters().getSpacingWidth();
+ int ypixels = 8 + data.getParameters().getSpacingWidth();
+
+ for (int y1 = 0; y1 < data.getParameters().getRows(); y1++) {
+ for (int x1 = 0; x1 < data.getParameters().getColumns(); x1++) {
+ for (int y2 = 0; y2 < 8; y2++) {
+ int b = data.getSourceFileByte(BIT_MAP_FILE, offset++);
+ if (b < 0) {
+ return true;
+ }
+ int y = y1 * ypixels + y2;
+ for (int x2 = 0; x2 < 4; x2++) {
+ int x = x1 * xpixels + x2;
+
+ int color = (b & mask_2bit[x2]) >>> shift_2bit[x2];
+ data.setPalettePixel(x, y, color);
+ }
+ }
+ }
+ }
+ return true;
+ }
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/editor/FilesConverterDataView.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/editor/FilesConverterDataView.java
new file mode 100644
index 00000000..d38aa200
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/editor/FilesConverterDataView.java
@@ -0,0 +1,327 @@
+/**
+ * Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.editor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jface.preference.ColorSelector;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.TraverseEvent;
+import org.eclipse.swt.events.TraverseListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.ToolItem;
+
+import com.wudsn.ide.base.common.NumberUtility;
+import com.wudsn.ide.base.gui.Action;
+import com.wudsn.ide.base.gui.FilePathField;
+import com.wudsn.ide.base.gui.IntegerField;
+import com.wudsn.ide.base.gui.MessageManager;
+import com.wudsn.ide.base.gui.SWTFactory;
+import com.wudsn.ide.gfx.Texts;
+import com.wudsn.ide.gfx.converter.Converter;
+import com.wudsn.ide.gfx.converter.ConverterCommonParameters;
+import com.wudsn.ide.gfx.converter.ConverterSourceFileDefinition;
+import com.wudsn.ide.gfx.converter.FilesConverterData;
+import com.wudsn.ide.gfx.converter.FilesConverterParameters;
+import com.wudsn.ide.gfx.converter.FilesConverterParameters.SourceFile;
+import com.wudsn.ide.gfx.gui.AspectField;
+import com.wudsn.ide.gfx.gui.ConverterIdField;
+import com.wudsn.ide.gfx.gui.SourceFileView;
+import com.wudsn.ide.gfx.model.ConverterDirection;
+
+final class FilesConverterDataView {
+
+ public final class Actions {
+
+ /**
+ * Creation is private.
+ */
+ private Actions() {
+ }
+
+ public static final int FIND_DEFAULT_FILE_CONVERTER = 999;
+ public static final int CREATE_CONVERSION = 1000;
+ public static final int REFRESH = 1001;
+ public static final int SAVE_IMAGE = 1002;
+ public static final int CONVERTER_ID_CHANGED = 1003;
+ public static final int PARAMETER_CHANGED = 1100;
+ public static final int PALETTE_COLORS_CHANGED = 1101;
+ }
+
+ private FilesConverterData filesConverterData;
+ private FilesConverterParameters filesConverterParameters;
+
+ private Composite composite;
+
+ private ConverterIdField converterIdField;
+
+ private ToolItem findDefaultFileConverterButton;
+ private ToolItem createConversionButton;
+ private ToolItem refreshButton;
+ private ToolItem saveImageButton;
+
+ private static final int SOURCE_FILES = 3;
+ private List sourceFileViews;
+
+ private IntegerField columnsField;
+ private IntegerField rowsField;
+
+ private Label spacingColorSelectorLabel;
+ private ColorSelector spacingColorSelector;
+ private IntegerField spacingWidthField;
+
+ private FilePathField imageFilePathField;
+ private AspectField imageAspectField;
+ private IntegerField imageDataWidthField;
+ private IntegerField imageDataHeightField;
+
+ public FilesConverterDataView(final GraphicsEditor editor, Composite parent, FilesConverterData filesConverterData) {
+ if (parent == null) {
+ throw new IllegalArgumentException("Parameter 'parent' must not be null.");
+ }
+
+ if (filesConverterData == null) {
+ throw new IllegalArgumentException("Parameter 'filesConverterData' must not be null.");
+ }
+ this.filesConverterData = filesConverterData;
+ this.filesConverterParameters = this.filesConverterData.getParameters();
+
+ MessageManager messageManager = editor.getMessageManager();
+
+ GridData gd = new GridData();
+
+ composite = SWTFactory.createComposite(parent, 9, 1, SWT.HORIZONTAL);
+
+ converterIdField = new ConverterIdField(composite, Texts.CONVERTER_PARAMETERS_CONVERTER_ID_LABEL,
+ ConverterDirection.FILES_TO_IMAGE);
+ converterIdField.addSelectionListener(new Action(Actions.CONVERTER_ID_CHANGED, editor));
+ messageManager.registerField(converterIdField, ConverterCommonParameters.MessageIds.CONVERTER_ID);
+
+ Composite toolBarcomposite = SWTFactory.createComposite(composite, 3, 7, GridData.FILL_HORIZONTAL);
+ ToolBar toolbar = new ToolBar(toolBarcomposite, SWT.HORIZONTAL);
+
+ findDefaultFileConverterButton = new ToolItem(toolbar, SWT.PUSH);
+ findDefaultFileConverterButton.setImage(Icons.FIND_DEFAULT_CONVERTER);
+ findDefaultFileConverterButton.setToolTipText(Texts.FIND_DEFAULT_FILE_CONVERTER_BUTTON_TOOLTIP);
+ findDefaultFileConverterButton.addSelectionListener(new Action(Actions.FIND_DEFAULT_FILE_CONVERTER, editor));
+
+ createConversionButton = new ToolItem(toolbar, SWT.PUSH);
+ createConversionButton.setImage(Icons.CREATE_CONVERSION);
+ createConversionButton.setToolTipText(Texts.CREATE_CONVERSION_BUTTON_TOOLTIP);
+ createConversionButton.addSelectionListener(new Action(Actions.CREATE_CONVERSION, editor));
+
+ final Action refreshAction = new Action(Actions.REFRESH, editor);
+ refreshButton = new ToolItem(toolbar, SWT.PUSH);
+ refreshButton.setImage(Icons.REFRESH);
+ refreshButton.setToolTipText(Texts.REFRESH_BUTTON_TOOLTIP);
+ refreshButton.addSelectionListener(refreshAction);
+
+ // Press
+ composite.addTraverseListener(new TraverseListener() {
+
+ @Override
+ public void keyTraversed(TraverseEvent event) {
+ if (event.detail == SWT.TRAVERSE_RETURN) {
+ // The user pressed Enter
+ refreshAction.widgetDefaultSelected(null);
+ }
+
+ }
+ });
+
+ saveImageButton = new ToolItem(toolbar, SWT.NONE);
+ saveImageButton.setImage(Icons.SAVE_IMAGE);
+ saveImageButton.setToolTipText(Texts.SAVE_IMAGE_BUTTON_TOOLTIP);
+ saveImageButton.addSelectionListener(new Action(Actions.SAVE_IMAGE, editor));
+
+ sourceFileViews = new ArrayList(SOURCE_FILES);
+ for (int i = 0; i < SOURCE_FILES; i++) {
+ SourceFileView sourceFileView;
+
+ sourceFileView = new SourceFileView(composite, "", SWT.OPEN);
+ sourceFileView.addChangeListener(editor);
+ sourceFileView.getFileOffsetField().addSelectionAction(refreshAction);
+ messageManager.registerField(sourceFileView.getFilePathField(),
+ FilesConverterParameters.MessageIds.SOURCE_FILE_PATH + i);
+ messageManager.registerField(sourceFileView.getFileOffsetField(),
+ FilesConverterParameters.MessageIds.SOURCE_FILE_OFFSET + i);
+ sourceFileViews.add(sourceFileView);
+ SWTFactory.createLabels(composite, 1);
+
+ }
+
+ SWTFactory.createLabels(composite, 1);
+
+ spacingColorSelectorLabel = new Label(composite, SWT.NONE);
+ spacingColorSelectorLabel.setText(Texts.CONVERTER_PARAMETERS_SPACING_COLOR_LABEL);
+ spacingColorSelector = new ColorSelector(composite);
+ Button spacingColorButton = spacingColorSelector.getButton();
+ gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
+ spacingColorButton.setLayoutData(gd);
+ spacingColorButton.addSelectionListener(new Action(Actions.PARAMETER_CHANGED, editor));
+ // messageManager.registerField(rowsField,
+ // FilesConverterParameters.MessageIds.SPACING_COLOR);
+ // TODO Requires a ColorSelectorField
+
+ spacingWidthField = new IntegerField(composite, Texts.CONVERTER_PARAMETERS_SPACING_WIDTH_LABEL, new int[] { 0,
+ 1, 2, 4, 8 }, false, NumberUtility.AUTOMATIC_LENGTH, SWT.NONE);
+ spacingWidthField.addSelectionAction(new Action(Actions.PARAMETER_CHANGED, editor));
+ messageManager.registerField(spacingWidthField, FilesConverterParameters.MessageIds.SPACING_WIDTH);
+
+ columnsField = new IntegerField(composite, Texts.CONVERTER_PARAMETERS_COLUMNS_LABEL, new int[] { 1, 2, 3, 4, 8,
+ 16, 32, 40, 48, 64, 128, 256 }, false, NumberUtility.AUTOMATIC_LENGTH, SWT.NONE);
+ columnsField.addChangeListener(editor);
+ columnsField.addSelectionAction(new Action(Actions.PARAMETER_CHANGED, editor));
+ messageManager.registerField(columnsField, FilesConverterParameters.MessageIds.COLUMNS);
+
+ rowsField = new IntegerField(composite, Texts.CONVERTER_PARAMETERS_ROWS_LABEL,
+ new int[] { 1, 2, 3, 4, 24, 25 }, false, NumberUtility.AUTOMATIC_LENGTH, SWT.NONE);
+ rowsField.addChangeListener(editor);
+ rowsField.addSelectionAction(new Action(Actions.PARAMETER_CHANGED, editor));
+ messageManager.registerField(rowsField, FilesConverterParameters.MessageIds.ROWS);
+
+ imageFilePathField = new FilePathField(composite, Texts.CONVERTER_PARAMETERS_IMAGE_FILE_PATH_LABEL, SWT.SAVE);
+ imageFilePathField.addChangeListener(editor);
+ imageFilePathField.addChangeListener(editor);
+ messageManager.registerField(imageFilePathField, FilesConverterParameters.MessageIds.IMAGE_FILE_PATH);
+
+ imageAspectField = new AspectField(composite, Texts.CONVERTER_PARAMETERS_IMAGE_ASPECT_LABEL);
+ imageAspectField.addSelectionAction(new Action(Actions.PARAMETER_CHANGED, editor));
+ imageFilePathField.addChangeListener(editor);
+ messageManager.registerField(imageAspectField, ConverterCommonParameters.MessageIds.IMAGE_ASPECT);
+
+ // Read only fields.
+ imageDataWidthField = new IntegerField(composite, Texts.CONVERTER_DATA_IMAGE_DATA_WIDTH_LABEL, null, false,
+ NumberUtility.AUTOMATIC_LENGTH, SWT.READ_ONLY);
+ imageDataHeightField = new IntegerField(composite, Texts.CONVERTER_DATA_IMAGE_DATA_HEIGHT_LABEL, null, false,
+ NumberUtility.AUTOMATIC_LENGTH, SWT.READ_ONLY);
+ }
+
+ public Composite getComposite() {
+ return composite;
+ }
+
+ public void dataFromUI() {
+
+ // Copy the file paths and offsets before setting the new converter.
+ Converter converter = filesConverterData.getConverter();
+ for (int i = 0; i < sourceFileViews.size(); i++) {
+ SourceFileView sourceFileView = sourceFileViews.get(i);
+ if (converter == null) {
+
+ } else {
+ List sourceFileDefinitions = converter.getDefinition()
+ .getSourceFileDefinitions();
+ if (i < sourceFileDefinitions.size()) {
+ SourceFile sourceFile = filesConverterParameters.getSourceFile(i);
+ sourceFile.setPath(sourceFileView.getFilePath());
+ sourceFile.setOffset(sourceFileView.getFileOffset());
+ }
+ }
+ }
+
+ filesConverterParameters.setImageFilePath(imageFilePathField.getValue());
+
+ filesConverterParameters.setConverterId(converterIdField.getValue());
+
+ filesConverterParameters.setColumns(columnsField.getValue());
+ filesConverterParameters.setRows(rowsField.getValue());
+
+ filesConverterParameters.setSpacingColor(spacingColorSelector.getColorValue());
+ filesConverterParameters.setSpacingWidth(spacingWidthField.getValue());
+
+ filesConverterParameters.setImageAspect(imageAspectField.getValue());
+ }
+
+ public void dataToUI() {
+
+ findDefaultFileConverterButton.setEnabled(filesConverterData.isValid());
+ createConversionButton.setEnabled(filesConverterData.isCreateConversionEnabled());
+ refreshButton.setEnabled(filesConverterData.isRefreshEnabled());
+ saveImageButton.setEnabled(filesConverterData.isSaveImageEnabled());
+
+ converterIdField.setValue(filesConverterParameters.getConverterId());
+ converterIdField.setEnabled(filesConverterData.isValid());
+
+ Converter converter = filesConverterData.getConverter();
+ for (int i = 0; i < sourceFileViews.size(); i++) {
+ SourceFileView sourceFileView = sourceFileViews.get(i);
+ sourceFileView.setFilePathPrefix(filesConverterData.getFilePathPrefix());
+ if (converter == null) {
+ sourceFileView.getFilePathField().setLabelText("Not used");
+ sourceFileView.setFilePath("");
+ sourceFileView.setFileBytes(null);
+ sourceFileView.setFileOffset(0);
+ sourceFileView.setVisible(true);
+ sourceFileView.setEnabled(false);
+ } else {
+ List sourceFileDefinitions = converter.getDefinition()
+ .getSourceFileDefinitions();
+ if (i < sourceFileDefinitions.size()) {
+ sourceFileView.getFilePathField().setLabelText(sourceFileDefinitions.get(i).getLabel());
+ SourceFile sourceFile = filesConverterParameters.getSourceFile(i);
+ sourceFileView.setFilePath(sourceFile.getPath());
+ sourceFileView.setFileBytes(filesConverterData.getSourceFileBytes(sourceFile.getId()));
+ sourceFileView.setFileOffset(sourceFile.getOffset());
+ sourceFileView.setVisible(true);
+ sourceFileView.setEnabled(true);
+ } else {
+ sourceFileView.getFilePathField().setLabelText("Not used");
+ sourceFileView.setFilePath("");
+ sourceFileView.setFileBytes(null);
+ sourceFileView.setFileOffset(0);
+ sourceFileView.setVisible(true);
+ sourceFileView.setEnabled(false);
+ }
+ }
+
+ }
+
+ imageFilePathField.setFilePathPrefix(filesConverterData.getFilePathPrefix());
+ imageFilePathField.setValue(filesConverterParameters.getImageFilePath());
+ imageFilePathField.setEnabled(filesConverterData.isValid());
+ imageFilePathField.setEditable(true);
+
+ columnsField.setValue(filesConverterParameters.getColumns());
+ columnsField.setEnabled(filesConverterData.isValid());
+ rowsField.setValue(filesConverterParameters.getRows());
+ rowsField.setEnabled(filesConverterData.isValid());
+
+ spacingColorSelector.setColorValue(filesConverterParameters.getSpacingColor());
+ spacingColorSelectorLabel.setEnabled(filesConverterData.isValid());
+ spacingColorSelector.setEnabled(filesConverterData.isValid());
+ spacingWidthField.setValue(filesConverterParameters.getSpacingWidth());
+ spacingWidthField.setEnabled(filesConverterData.isValid());
+
+ imageAspectField.setValue(filesConverterParameters.getImageAspect());
+ imageAspectField.setEnabled(filesConverterData.isValid());
+ imageDataWidthField.setValue(filesConverterData.getImageDataWidth());
+ imageDataWidthField.setEnabled(filesConverterData.isImageDataValid());
+ imageDataHeightField.setValue(filesConverterData.getImageDataHeight());
+ imageDataHeightField.setEnabled(filesConverterData.isImageDataValid());
+
+ composite.pack();
+ }
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/editor/GraphicsEditor.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/editor/GraphicsEditor.java
new file mode 100644
index 00000000..81243168
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/editor/GraphicsEditor.java
@@ -0,0 +1,729 @@
+/**
+ * Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.editor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.TabFolder;
+import org.eclipse.swt.widgets.TabItem;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorSite;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.IViewPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.dialogs.SaveAsDialog;
+import org.eclipse.ui.ide.IDE;
+import org.eclipse.ui.part.EditorPart;
+
+import com.wudsn.ide.base.BasePlugin;
+import com.wudsn.ide.base.common.NumberUtility;
+import com.wudsn.ide.base.gui.Action;
+import com.wudsn.ide.base.gui.Application;
+import com.wudsn.ide.base.gui.MessageManager;
+import com.wudsn.ide.gfx.GraphicsPlugin;
+import com.wudsn.ide.gfx.Texts;
+import com.wudsn.ide.gfx.converter.ConverterData;
+import com.wudsn.ide.gfx.converter.ConverterDataLogic;
+import com.wudsn.ide.gfx.converter.FilesConverterParameters;
+import com.wudsn.ide.gfx.converter.ImageColorHistogram;
+import com.wudsn.ide.gfx.converter.ImageConverterParameters;
+import com.wudsn.ide.gfx.model.Aspect;
+import com.wudsn.ide.gfx.model.ConverterDirection;
+import com.wudsn.ide.gfx.model.ConverterMode;
+
+
+public final class GraphicsEditor extends EditorPart implements Application, ISelectionProvider, ChangeListener {
+
+ public final class Actions {
+
+ /**
+ * Creation is private.
+ */
+ private Actions() {
+ }
+
+ public static final int TAB_CHANGED = 900;
+ }
+
+ /**
+ * Encapsulation of the external image views.
+ */
+ private final class MyImageProvider implements ImageProvider {
+
+ private ImageData displayImageData;
+ private ImageColorHistogram displayImageColorHistogram;
+
+ private ImageView imageView;
+ private ImagePaletteView imagePaletteView;
+
+ MyImageProvider() {
+
+ }
+
+ @Override
+ public void setImageView(ImageView imageView) {
+ this.imageView = imageView;
+ }
+
+ @Override
+ public void setImagePaletteView(ImagePaletteView imagePaletteView) {
+ this.imagePaletteView = imagePaletteView;
+ }
+
+ @Override
+ public Aspect getAspect() {
+ return converterData.getParameters().getConverterCommonParameters().getDisplayAspect();
+ }
+
+ @Override
+ public void setAspect(Aspect value) {
+ dataFromUI();
+ converterData.getParameters().getConverterCommonParameters().setDisplayAspect(value);
+ dataToUI();
+ }
+
+ @Override
+ public boolean isShrinkToFit() {
+ return converterData.getParameters().getConverterCommonParameters().isDisplayShrinkToFit();
+ }
+
+ @Override
+ public void setShrinkToFit(boolean value) {
+ dataFromUI();
+ converterData.getParameters().getConverterCommonParameters().setDisplayShrinkToFit(value);
+ dataToUI();
+ }
+
+ @Override
+ public boolean isZoomToFit() {
+ return converterData.getParameters().getConverterCommonParameters().isDisplayZoomToFit();
+ }
+
+ @Override
+ public void setZoomToFit(boolean value) {
+ dataFromUI();
+ converterData.getParameters().getConverterCommonParameters().setDisplayZoomToFit(value);
+ dataToUI();
+ }
+
+ @Override
+ public ImageData getImageData() {
+ return displayImageData;
+ }
+
+ @Override
+ public ImageColorHistogram getImageColorHistogram() {
+ return displayImageColorHistogram;
+ }
+
+ @Override
+ public boolean isPaletteChangeable() {
+ return converterData.getConverterDirection() == ConverterDirection.FILES_TO_IMAGE
+ && displayImageData != null && !displayImageData.palette.isDirect;
+ }
+
+ @Override
+ public void setPaletteRGBs(RGB[] rgbs) {
+ if (rgbs == null) {
+ throw new IllegalArgumentException("Parameter 'rgbs' must not be null.");
+ }
+ dataFromUI();
+ FilesConverterParameters parameters;
+ parameters = converterData.getParameters().getFilesConverterParameters();
+ RGB[] currentRGBs = parameters.getPaletteRGBs();
+ for (int i = 0; i < rgbs.length && i < currentRGBs.length; i++) {
+ currentRGBs[i] = rgbs[i];
+ }
+ parameters.setPaletteManual();
+ parameters.setPaletteRGBs(currentRGBs);
+ convert();
+ dataToUi();
+ }
+
+ @Override
+ public void setPaletteRGB(int pixelColor, RGB rgb) {
+ if (rgb == null) {
+ throw new IllegalArgumentException("Parameter 'rgb' must not be null.");
+ }
+ dataFromUI();
+ FilesConverterParameters parameters;
+ parameters = converterData.getParameters().getFilesConverterParameters();
+ RGB[] rgbs = parameters.getPaletteRGBs();
+ rgbs[pixelColor] = rgb;
+ parameters.setPaletteManual();
+ parameters.setPaletteRGBs(rgbs);
+ convert();
+ dataToUi();
+ }
+
+ final void dataToUi() {
+ IWorkbenchPage workbenchPage = getSite().getPage();
+
+ // If there is no perspective active yet, we are in the phase of
+ // starting while launching the IDE.
+ // In this situation, the additional views cannot be opened yet.
+ if (workbenchPage.getOpenPerspectives().length == 0) {
+ return;
+ }
+
+ displayImageData = converterData.getConverterCommonData().getImageData();
+ displayImageColorHistogram = converterData.getConverterCommonData().getImageColorHistogram();
+
+ // Ensure that there is an open image palette view.
+ if (imagePaletteView == null) {
+ try {
+ IViewPart viewPart = getSite().getPage().showView(ImagePaletteView.ID);
+ if (viewPart instanceof ImagePaletteView) {
+ ((ImagePaletteView) viewPart).setImageProvider(this);
+ }
+ } catch (PartInitException ex) {
+ imagePaletteView = null;
+ BasePlugin.getInstance().logError("Cannot open image palette view.", null, ex.getCause());
+ }
+ }
+ if (imagePaletteView != null) {
+ imagePaletteView.dataToUI();
+ }
+
+ // Ensure that there is an open image view.
+ if (imageView == null) {
+ try {
+ IViewPart viewPart = getSite().getPage().showView(ImageView.ID);
+ if (viewPart instanceof ImageView) {
+ ((ImageView) viewPart).setImageProvider(this);
+ }
+ } catch (PartInitException ex) {
+ imageView = null;
+ BasePlugin.getInstance().logError("Cannot open image view.", null, ex);
+ }
+ }
+ if (imageView != null) {
+ imageView.dataToUI();
+ }
+ }
+
+ final void dispose() {
+ if (imageView != null) {
+ imageView.setImageProvider(null);
+ }
+ if (imagePaletteView != null) {
+ imagePaletteView.setImageProvider(null);
+ }
+ }
+ }
+
+ private static final class MySaveAsDialog extends SaveAsDialog {
+ private String title;
+ private String message;
+
+ public MySaveAsDialog(Shell parentShell, String title, String message) {
+ super(parentShell);
+ this.title = title;
+ this.message = message;
+ }
+
+ @Override
+ protected Control createContents(Composite parent) {
+ if (parent == null) {
+ throw new IllegalArgumentException("Parameter 'parent' must not be null.");
+ }
+ Control result;
+ result = super.createContents(parent);
+ setTitle(title);
+ setMessage(message);
+ return result;
+ }
+
+ }
+
+ // ID of the editor in the plugin manifest.
+ public static final String ID = "com.wudsn.ide.gfx.editor.GraphicsEditor";
+
+ private MessageManager messageManager;
+ private boolean processing;
+ private boolean closeEditor;
+
+ // All data and parameters.
+ private ConverterDataLogic converterDataLogic;
+ final ConverterData converterData;
+
+ // UI state.
+ private boolean partControlCreated;
+ private TabFolder tabFolder;
+ private TabItem filesConverterDataViewTabItem;
+ private FilesConverterDataView filesConverterDataView;
+ private TabItem imageConverterDataViewTabItem;
+ private ImageConverterDataView imageConverterDataView;
+
+ // UI state in external views.
+ private List selectionChangedListeners;
+ private MyImageProvider imageProvider;
+
+ public GraphicsEditor() {
+ messageManager = new MessageManager(this);
+
+ converterDataLogic = new ConverterDataLogic(messageManager);
+ converterData = converterDataLogic.createData();
+
+ selectionChangedListeners = new ArrayList();
+ imageProvider = new MyImageProvider();
+ }
+
+ @Override
+ public MessageManager getMessageManager() {
+ return messageManager;
+ }
+
+ @Override
+ public void dispose() {
+ imageProvider.dispose();
+ messageManager.dispose();
+ super.dispose();
+ }
+
+ @Override
+ public void doSave(IProgressMonitor monitor) {
+ dataFromUI();
+ if (!converterData.isValid()) {
+ throw new IllegalStateException("Converter data is not valid.");
+ }
+ if (converterData.getConverterMode() != ConverterMode.CNV) {
+ throw new IllegalStateException("Converter data is not in mode CNV.");
+ }
+ messageManager.clearMessages();
+ IFile saveFile = converterDataLogic.saveConversion(converterData, monitor);
+ if (saveFile != null) {
+ firePropertyChange(PROP_INPUT);
+ messageManager.sendMessage(0, IStatus.INFO, "Conversion {0} saved", saveFile.getFullPath().toString());
+ } else if (monitor != null) {
+ monitor.setCanceled(true);
+
+ }
+ dataToUI();
+ }
+
+ @Override
+ public void doSaveAs() {
+ dataFromUI();
+ if (!converterData.isValid()) {
+ throw new IllegalStateException("Converter data is not valid.");
+ }
+ if (converterData.getConverterMode() != ConverterMode.CNV) {
+ throw new IllegalStateException("Converter data is not in mode CNV.");
+ }
+ IFile saveAsFile = saveConversionAs(converterData, Texts.SAVE_AS_DIALOG_TITLE, Texts.SAVE_AS_DIALOG_MESSAGE,
+ null);
+ if (saveAsFile != null) {
+ firePropertyChange(PROP_INPUT);
+ messageManager.sendMessage(0, IStatus.INFO, "Conversion {0} saved", saveAsFile.getFullPath().toString());
+ }
+ dataToUI();
+ }
+
+ @Override
+ public void init(IEditorSite site, IEditorInput input) throws PartInitException {
+ if (site == null) {
+ throw new IllegalArgumentException("Parameter 'site' must not be null.");
+ }
+ setSite(site);
+ setInput(input);
+
+ if (input != null) {
+ setPartName(input.getName());
+ } else {
+ setPartName("");
+ }
+
+ messageManager.clearMessages();
+ converterData.clear();
+ try {
+ if (input instanceof IFileEditorInput) {
+ IFileEditorInput fileEditorInput = (IFileEditorInput) input;
+ IFile file = fileEditorInput.getFile();
+ converterData.setFile(file);
+ converterDataLogic.load(converterData);
+ }
+ } catch (Exception ex) {
+ BasePlugin.getInstance().logError("Cannot open file.", null, ex);
+ }
+ convert();
+ if (partControlCreated) {
+ dataToUI();
+ }
+
+ }
+
+ /**
+ * Opens another file a new editor instance.
+ *
+ * @param file
+ * The file, not null
.
+ * @return true
if the editor was opened, false
+ * otherwise.
+ */
+ private boolean openEditor(IFile file) {
+ if (file == null) {
+ throw new IllegalArgumentException("Parameter 'file' must not be null.");
+ }
+
+ boolean result;
+
+ result = false;
+ try {
+
+ IDE.openEditor(getSite().getPage(), file, ID);
+ result = true;
+
+ } catch (PartInitException ex) {
+ GraphicsPlugin.getInstance().logError("Cannot open default editor for {0}'.", new Object[] { file }, ex);
+ }
+ return result;
+ }
+
+ /**
+ * Closes the current editor instance.
+ */
+ private void closeEditor() {
+ getSite().getPage().closeEditor(this, false);
+ }
+
+ @Override
+ public boolean isDirty() {
+ boolean result;
+ dataFromUI();
+ result = converterData.isValidConversion() && converterData.isChanged();
+ return result;
+ }
+
+ @Override
+ public boolean isSaveAsAllowed() {
+ boolean result;
+ result = converterData.isValidConversion();
+ return result;
+ }
+
+ @Override
+ public void createPartControl(Composite parent) {
+
+ getSite().setSelectionProvider(this);
+
+ Composite composite = parent;
+ composite.setLayout(new FillLayout(SWT.VERTICAL));
+ tabFolder = new TabFolder(composite, SWT.TOP);
+
+ filesConverterDataViewTabItem = new TabItem(tabFolder, SWT.NONE);
+ filesConverterDataViewTabItem.setText(Texts.FILES_CONVERTER_DATA_VIEW_TAB);
+ filesConverterDataView = new FilesConverterDataView(this, tabFolder, converterData.getFilesConverterData());
+ filesConverterDataViewTabItem.setControl(filesConverterDataView.getComposite());
+
+ imageConverterDataViewTabItem = new TabItem(tabFolder, SWT.NONE);
+ imageConverterDataViewTabItem.setText(Texts.IMAGE_CONVERTER_DATA_VIEW_TAB);
+ imageConverterDataView = new ImageConverterDataView(this, tabFolder, converterData.getImageConverterData());
+ imageConverterDataViewTabItem.setControl(imageConverterDataView.getComposite());
+
+ // Add selection listener only after all tabs have been added.
+ tabFolder.addSelectionListener(new Action(Actions.TAB_CHANGED, this));
+
+ partControlCreated = true;
+
+ dataToUI();
+
+ }
+
+ @Override
+ public void performAction(Action action) {
+ if (action == null) {
+ throw new IllegalArgumentException("Parameter 'action' must not be null.");
+ }
+ if (!processing) {
+ processing = true;
+
+ try {
+
+ messageManager.clearMessages();
+ dataFromUI();
+
+ switch (action.getId()) {
+ case Actions.TAB_CHANGED:
+ loadSources(false, true);
+ break;
+
+ case FilesConverterDataView.Actions.FIND_DEFAULT_FILE_CONVERTER:
+ converterDataLogic.findDefaultFileConverter(converterData);
+ convert();
+ break;
+
+ case FilesConverterDataView.Actions.CREATE_CONVERSION:
+ createConversion();
+ break;
+
+ case FilesConverterDataView.Actions.REFRESH:
+ loadSources(false, true);
+ break;
+
+ case FilesConverterDataView.Actions.SAVE_IMAGE:
+ saveTargets();
+ break;
+
+ case FilesConverterDataView.Actions.CONVERTER_ID_CHANGED:
+ loadSources(true, true);
+ break;
+
+ case FilesConverterDataView.Actions.PARAMETER_CHANGED:
+ convert();
+ break;
+
+ case FilesConverterDataView.Actions.PALETTE_COLORS_CHANGED:
+ converterData.getFilesConverterData().getParameters().setPaletteManual();
+ convert();
+ break;
+
+ case ImageConverterDataView.Actions.CREATE_CONVERSION:
+ createConversion();
+ break;
+
+ case ImageConverterDataView.Actions.REFRESH:
+ loadSources(false, true);
+ break;
+
+ case ImageConverterDataView.Actions.SAVE_FILES:
+ saveTargets();
+ break;
+
+ case ImageConverterDataView.Actions.CONVERTER_ID_CHANGED:
+ loadSources(true, true);
+ break;
+
+ case ImageConverterDataView.Actions.PARAMETER_CHANGED:
+ convert();
+ }
+
+ dataToUI();
+ } catch (Exception ex) {
+ GraphicsPlugin.getInstance().showError(getSite().getShell(), "Error in update()", ex);
+ }
+
+ processing = false;
+ if (closeEditor) {
+ closeEditor();
+ }
+ }
+
+ }
+
+ private void loadSources(boolean applyDefaults, boolean convert) {
+ if (applyDefaults) {
+ converterDataLogic.applyDefaults(converterData);
+ }
+ long startTimeMillis = System.currentTimeMillis();
+ if (converterDataLogic.loadSources(converterData, false)) {
+ if (convert) {
+ converterDataLogic.convert(converterData);
+ long duration = System.currentTimeMillis() - startTimeMillis;
+ String durationString = NumberUtility.getLongValueDecimalString(duration);
+ switch (converterData.getConverterDirection()) {
+ case FILES_TO_IMAGE:
+ messageManager.sendMessage(ImageConverterParameters.MessageIds.IMAGE_FILE_PATH, IStatus.OK,
+ Texts.MESSAGE_S100, durationString);
+ break;
+ case IMAGE_TO_FILES:
+ messageManager.sendMessage(ImageConverterParameters.MessageIds.IMAGE_FILE_PATH, IStatus.OK,
+ "Image file loaded and converted in {0} ms", durationString);
+ break;
+ }
+ } else {
+ switch (converterData.getConverterDirection()) {
+ case FILES_TO_IMAGE:
+ messageManager.sendMessage(ImageConverterParameters.MessageIds.IMAGE_FILE_PATH, IStatus.OK,
+ "Source files loaded");
+ break;
+ case IMAGE_TO_FILES:
+ messageManager.sendMessage(ImageConverterParameters.MessageIds.IMAGE_FILE_PATH, IStatus.OK,
+ "Image file loaded");
+ break;
+ }
+ }
+ }
+ }
+
+ final void convert() {
+ converterDataLogic.convert(converterData);
+ }
+
+ private void saveTargets() {
+ converterDataLogic.saveTargets(converterData);
+
+ }
+
+ private void createConversion() {
+
+ ConverterData newConverterData;
+ IFile saveAsFile;
+
+ newConverterData = converterDataLogic.createConversion(converterData);
+
+ saveAsFile = saveConversionAs(newConverterData, Texts.CREATE_CONVERSION_DIALOG_TITLE,
+ Texts.CREATE_CONVERSION_DIALOG_MESSAGE, null);
+ if (saveAsFile != null) {
+ messageManager.sendMessage(0, IStatus.INFO, "Conversion {0} saved", saveAsFile.getFullPath().toString());
+ closeEditor = openEditor(saveAsFile);
+
+ }
+ }
+
+ private IFile saveConversionAs(ConverterData data, String title, String message, IProgressMonitor monitor) {
+ if (data == null) {
+ throw new IllegalArgumentException("Parameter 'data' must not be null.");
+ }
+
+ if (title == null) {
+ throw new IllegalArgumentException("Parameter 'title' must not be null.");
+ }
+ if (message == null) {
+ throw new IllegalArgumentException("Parameter 'message' must not be null.");
+ }
+ IFile saveAsFile;
+ IPath saveAsPath;
+ SaveAsDialog saveAsDialog = new MySaveAsDialog(getSite().getShell(), title, message);
+ saveAsDialog.setBlockOnOpen(true);
+ saveAsDialog.setOriginalFile(data.getFile());
+ saveAsDialog.open();
+ saveAsPath = saveAsDialog.getResult();
+ if (saveAsPath != null) {
+
+ IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
+ saveAsFile = workspaceRoot.getFile(saveAsPath);
+ converterData.setFile(saveAsFile);
+ converterDataLogic.saveConversion(data, monitor);
+
+ } else {
+ saveAsFile = null;
+ }
+ return saveAsFile;
+ }
+
+ final void dataFromUI() {
+
+ TabItem[] tabItems = tabFolder.getSelection();
+ if (tabItems == null || tabItems.length == 0 || tabItems[0] == filesConverterDataViewTabItem) {
+ converterData.getParameters().setConverterDirection(ConverterDirection.FILES_TO_IMAGE);
+ } else {
+ converterData.getParameters().setConverterDirection(ConverterDirection.IMAGE_TO_FILES);
+ }
+
+ filesConverterDataView.dataFromUI();
+ imageConverterDataView.dataFromUI();
+
+ }
+
+ final void dataToUI() {
+
+ firePropertyChange(PROP_DIRTY);
+
+ switch (converterData.getConverterDirection()) {
+ case FILES_TO_IMAGE:
+ tabFolder.setSelection(filesConverterDataViewTabItem);
+ break;
+ case IMAGE_TO_FILES:
+ tabFolder.setSelection(imageConverterDataViewTabItem);
+ break;
+ default:
+ throw new IllegalStateException("Unknown converter direction '" + converterData.getConverterDirection()
+ + "'.");
+ }
+
+ filesConverterDataView.dataToUI();
+ imageConverterDataView.dataToUI();
+
+ if (partControlCreated) {
+ imageProvider.dataToUi();
+ }
+
+ messageManager.displayMessages();
+
+ }
+
+ @Override
+ public void setFocus() {
+ tabFolder.setFocus();
+ // dataToUI(); Do not use here. Causes a recursion due to the image view
+ // trying to come to front.
+ }
+
+ @Override
+ public void addSelectionChangedListener(ISelectionChangedListener listener) {
+ selectionChangedListeners.add(listener);
+ }
+
+ @Override
+ public void removeSelectionChangedListener(ISelectionChangedListener listener) {
+ selectionChangedListeners.remove(listener);
+ }
+
+ @Override
+ public ISelection getSelection() {
+ return new StructuredSelection();
+ }
+
+ @Override
+ public void setSelection(ISelection selection) {
+ for (ISelectionChangedListener listener : selectionChangedListeners) {
+ listener.selectionChanged(new SelectionChangedEvent(this, selection));
+ }
+ }
+
+ @Override
+ public void stateChanged(ChangeEvent event) {
+ firePropertyChange(PROP_DIRTY);
+ }
+
+ /**
+ * Gets the image provider for this editor.
+ *
+ * @return The image provider, not null
.
+ */
+ public ImageProvider getImageProvider() {
+ return imageProvider;
+ }
+
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/editor/GraphicsEditorOpenCommandHandler.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/editor/GraphicsEditorOpenCommandHandler.java
new file mode 100644
index 00000000..b3115a86
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/editor/GraphicsEditorOpenCommandHandler.java
@@ -0,0 +1,39 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.editor;
+
+import com.wudsn.ide.base.editor.CommonOpenEditorCommandHandler;
+
+/**
+ * The action to open the graphics editor from the context menu.
+ *
+ * @author Peter Dell
+ */
+public final class GraphicsEditorOpenCommandHandler extends CommonOpenEditorCommandHandler {
+
+ /**
+ * Creation is public. Called by extension "org.eclipse.ui.popupMenus".
+ */
+ public GraphicsEditorOpenCommandHandler() {
+ super(GraphicsEditor.ID);
+ }
+
+
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/editor/Icons.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/editor/Icons.java
new file mode 100644
index 00000000..d209856d
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/editor/Icons.java
@@ -0,0 +1,43 @@
+/**
+ * Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.editor;
+
+import org.eclipse.swt.graphics.Image;
+
+import com.wudsn.ide.base.common.AbstractIDEPlugin;
+import com.wudsn.ide.gfx.GraphicsPlugin;
+
+final class Icons {
+
+ public static final Image FIND_DEFAULT_CONVERTER;
+ public static final Image CREATE_CONVERSION;
+ public static final Image REFRESH;
+ public static final Image SAVE_IMAGE;
+ public static final Image SAVE_FILES;
+
+ static {
+ AbstractIDEPlugin plugin = GraphicsPlugin.getInstance();
+ FIND_DEFAULT_CONVERTER = plugin.getImage("searchm_obj.gif");
+ CREATE_CONVERSION = plugin.getImage("graphics-editor-16x16.gif");
+ REFRESH = plugin.getImage("refresh.gif");
+ SAVE_IMAGE = plugin.getImage("save_edit.gif");
+ SAVE_FILES = plugin.getImage("save_edit.gif");
+ }
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/editor/ImageConverterDataView.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/editor/ImageConverterDataView.java
new file mode 100644
index 00000000..7233c590
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/editor/ImageConverterDataView.java
@@ -0,0 +1,297 @@
+/**
+ * Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+package com.wudsn.ide.gfx.editor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.ToolItem;
+
+import com.wudsn.ide.base.common.NumberUtility;
+import com.wudsn.ide.base.gui.Action;
+import com.wudsn.ide.base.gui.CheckBoxField;
+import com.wudsn.ide.base.gui.FilePathField;
+import com.wudsn.ide.base.gui.IntegerField;
+import com.wudsn.ide.base.gui.MessageManager;
+import com.wudsn.ide.base.gui.MultiLineTextField;
+import com.wudsn.ide.base.gui.SWTFactory;
+import com.wudsn.ide.gfx.Texts;
+import com.wudsn.ide.gfx.converter.Converter;
+import com.wudsn.ide.gfx.converter.ConverterCommonParameters;
+import com.wudsn.ide.gfx.converter.ConverterTargetFileDefinition;
+import com.wudsn.ide.gfx.converter.ImageConverterData;
+import com.wudsn.ide.gfx.converter.ImageConverterParameters;
+import com.wudsn.ide.gfx.converter.ImageConverterParameters.TargetFile;
+import com.wudsn.ide.gfx.gui.AspectField;
+import com.wudsn.ide.gfx.gui.ConverterIdField;
+import com.wudsn.ide.gfx.gui.TargetFileView;
+import com.wudsn.ide.gfx.model.ConverterDirection;
+
+final class ImageConverterDataView {
+
+ public final class Actions {
+
+ /**
+ * Creation is private.
+ */
+ private Actions() {
+ }
+
+ public static final int CREATE_CONVERSION = 2000;
+ public static final int REFRESH = 2001;
+ public static final int SAVE_FILES = 2002;
+ public static final int CONVERTER_ID_CHANGED = 2003;
+
+ public static final int PARAMETER_CHANGED = 2100;
+ public static final int PALETTE_COLORS_CHANGED = 2101;
+ }
+
+ private ImageConverterData imageConverterData;
+ private ImageConverterParameters imageConverterParameters;
+
+ private Composite composite;
+
+ private ConverterIdField converterIdField;
+
+ private ToolItem createConversionButton;
+ private ToolItem refreshButton;
+ private ToolItem saveFilesButton;
+
+ private FilePathField imageFilePathField;
+ private AspectField imageAspectField;
+ private IntegerField imageDataWidthField;
+ private IntegerField imageDataHeightField;
+
+ private static final int TARGET_FILES = 3;
+ private List targetFileViews;
+
+ private CheckBoxField useDefaultScriptField;
+ private MultiLineTextField scriptField;
+
+ public ImageConverterDataView(GraphicsEditor editor, Composite parent, ImageConverterData imageConverterData) {
+ if (editor == null) {
+ throw new IllegalArgumentException("Parameter 'editor' must not be null.");
+ }
+ if (parent == null) {
+ throw new IllegalArgumentException("Parameter 'parent' must not be null.");
+ }
+ if (imageConverterData == null) {
+ throw new IllegalArgumentException("Parameter 'imageConverterData' must not be null.");
+ }
+ this.imageConverterData = imageConverterData;
+ this.imageConverterParameters = this.imageConverterData.getParameters();
+
+ MessageManager messageManager = editor.getMessageManager();
+
+ // Create visual elements.
+ composite = new Composite(parent, SWT.NONE);
+ composite.setLayout(new GridLayout(1, false));
+ GridData gd = new GridData();
+ gd.grabExcessHorizontalSpace = false;
+ gd.grabExcessVerticalSpace = false;
+ composite.setLayoutData(gd);
+
+ Composite topComposite = SWTFactory.createComposite(composite, 9, 1, SWT.HORIZONTAL);
+
+ converterIdField = new ConverterIdField(topComposite, Texts.CONVERTER_PARAMETERS_CONVERTER_ID_LABEL,
+ ConverterDirection.IMAGE_TO_FILES);
+ converterIdField.addSelectionListener(new Action(Actions.CONVERTER_ID_CHANGED, editor));
+ messageManager.registerField(converterIdField, ConverterCommonParameters.MessageIds.CONVERTER_ID);
+
+ Composite toolBarcomposite = SWTFactory.createComposite(topComposite, 3, 7, GridData.FILL_HORIZONTAL);
+ ToolBar toolbar = new ToolBar(toolBarcomposite, SWT.HORIZONTAL);
+
+ createConversionButton = new ToolItem(toolbar, SWT.PUSH);
+ createConversionButton.setImage(Icons.CREATE_CONVERSION);
+ createConversionButton.setToolTipText(Texts.CREATE_CONVERSION_BUTTON_TOOLTIP);
+ createConversionButton.addSelectionListener(new Action(Actions.CREATE_CONVERSION, editor));
+
+ refreshButton = new ToolItem(toolbar, SWT.PUSH);
+ refreshButton.setImage(Icons.REFRESH);
+ refreshButton.setToolTipText(Texts.REFRESH_BUTTON_TOOLTIP);
+ refreshButton.addSelectionListener(new Action(Actions.REFRESH, editor));
+
+ saveFilesButton = new ToolItem(toolbar, SWT.NONE);
+ saveFilesButton.setImage(Icons.SAVE_FILES);
+ saveFilesButton.setToolTipText(Texts.SAVE_FILES_BUTTON_TOOLTIP);
+ saveFilesButton.addSelectionListener(new Action(Actions.SAVE_FILES, editor));
+
+ imageFilePathField = new FilePathField(topComposite, Texts.CONVERTER_PARAMETERS_IMAGE_FILE_PATH_LABEL, SWT.OPEN);
+ imageFilePathField.addChangeListener(editor);
+ messageManager.registerField(imageFilePathField, ImageConverterParameters.MessageIds.IMAGE_FILE_PATH);
+
+ //
+ imageAspectField = new AspectField(topComposite, Texts.CONVERTER_PARAMETERS_IMAGE_ASPECT_LABEL);
+ imageAspectField.addSelectionAction(new Action(Actions.PARAMETER_CHANGED, editor));
+ messageManager.registerField(imageAspectField, ConverterCommonParameters.MessageIds.IMAGE_ASPECT);
+
+ imageDataWidthField = new IntegerField(topComposite, Texts.CONVERTER_DATA_IMAGE_DATA_WIDTH_LABEL, null, false,
+ NumberUtility.AUTOMATIC_LENGTH, SWT.READ_ONLY);
+ imageDataHeightField = new IntegerField(topComposite, Texts.CONVERTER_DATA_IMAGE_DATA_HEIGHT_LABEL, null,
+ false, NumberUtility.AUTOMATIC_LENGTH, SWT.READ_ONLY);
+
+ targetFileViews = new ArrayList(TARGET_FILES);
+ for (int i = 0; i < TARGET_FILES; i++) {
+ TargetFileView targetFileView;
+
+ targetFileView = new TargetFileView(topComposite, "", SWT.SAVE);
+ targetFileView.addChangeListener(editor);
+ messageManager.registerField(targetFileView.getFilePathField(),
+ ImageConverterParameters.MessageIds.TARGET_FILE_PATH + i);
+ targetFileViews.add(targetFileView);
+ SWTFactory.createLabels(topComposite, 4);
+
+ }
+
+ useDefaultScriptField = new CheckBoxField(topComposite, Texts.CONVERTER_PARAMETERS_USE_DEFAULT_SCRIPT_LABEL,
+ SWT.NONE);
+ useDefaultScriptField.addSelectionAction(new Action(Actions.PARAMETER_CHANGED, editor));
+ messageManager.registerField(useDefaultScriptField, ImageConverterParameters.MessageIds.USE_DEFAULT_SCRIPT);
+ SWTFactory.createLabels(topComposite, 6);
+
+ scriptField = new MultiLineTextField(composite, SWT.H_SCROLL | SWT.V_SCROLL);
+ scriptField.addChangeListener(editor);
+ messageManager.registerField(scriptField, ImageConverterParameters.MessageIds.SCRIPT);
+ gd = new GridData();
+ gd.horizontalSpan = 1;
+ gd.verticalSpan = 1;
+ gd.grabExcessHorizontalSpace = true;
+ gd.grabExcessVerticalSpace = true;
+ Rectangle clientArea = Display.getCurrent().getClientArea();
+ gd.heightHint = clientArea.width;
+ gd.widthHint = clientArea.height;
+ StyledText styledText = scriptField.getText();
+ styledText.setLayoutData(gd);
+ styledText.setFont(JFaceResources.getTextFont());
+ styledText.setTabs(4);
+
+ }
+
+ public Composite getComposite() {
+ return composite;
+ }
+
+ public void dataFromUI() {
+
+ imageConverterParameters.setImageFilePath(imageFilePathField.getValue());
+ imageConverterParameters.setImageAspect(imageAspectField.getValue());
+
+ // Copy the file paths before setting the new converter.
+ Converter converter = imageConverterData.getConverter();
+ for (int i = 0; i < targetFileViews.size(); i++) {
+ TargetFileView targetFileView = targetFileViews.get(i);
+ if (converter == null) {
+
+ } else {
+ List targetFileDefinitions = converter.getDefinition()
+ .getTargetFileDefinitions();
+ if (i < targetFileDefinitions.size()) {
+ TargetFile targetFile = imageConverterParameters.getTargetFile(i);
+ targetFile.setPath(targetFileView.getFilePath());
+ }
+ }
+ }
+
+ imageConverterParameters.setConverterId(converterIdField.getValue());
+
+ imageConverterParameters.setUseDefaultScript(useDefaultScriptField.getValue());
+ if (!imageConverterParameters.isUseDefaultScript()) {
+ imageConverterParameters.setScript(scriptField.getValue());
+ }
+ }
+
+ public void dataToUI() {
+
+ createConversionButton.setEnabled(imageConverterData.isCreateConversionEnabled());
+ refreshButton.setEnabled(imageConverterData.isRefreshEnabled());
+ saveFilesButton.setEnabled(imageConverterData.isSaveFilesEnabled());
+
+ converterIdField.setValue(imageConverterParameters.getConverterId());
+ converterIdField.setEnabled(imageConverterData.isValid());
+
+ imageFilePathField.setFilePathPrefix(imageConverterData.getFilePathPrefix());
+ imageFilePathField.setValue(imageConverterParameters.getImageFilePath());
+ imageFilePathField.setEnabled(imageConverterData.isValid());
+ imageFilePathField.setEditable(true);
+
+ imageAspectField.setValue(imageConverterParameters.getImageAspect());
+ imageAspectField.setEnabled(imageConverterData.isValid());
+ imageDataWidthField.setValue(imageConverterData.getImageDataWidth());
+ imageDataWidthField.setEnabled(imageConverterData.isValid());
+ imageDataHeightField.setValue(imageConverterData.getImageDataHeight());
+ imageDataHeightField.setEnabled(imageConverterData.isValid());
+
+ Converter converter = imageConverterData.getConverter();
+ for (int i = 0; i < targetFileViews.size(); i++) {
+ TargetFileView targetFileView = targetFileViews.get(i);
+ targetFileView.setFilePathPrefix(imageConverterData.getFilePathPrefix());
+ if (converter == null) {
+ targetFileView.getFilePathField().setLabelText("Not used");
+ targetFileView.setFilePath("");
+ targetFileView.setFileBytes(null);
+ targetFileView.setVisible(true);
+ targetFileView.setEnabled(false);
+ } else {
+ List targetFileDefinitions = converter.getDefinition()
+ .getTargetFileDefinitions();
+ if (i < targetFileDefinitions.size()) {
+ targetFileView.getFilePathField().setLabelText(targetFileDefinitions.get(i).getLabel());
+ TargetFile targetFile = imageConverterParameters.getTargetFile(i);
+ targetFileView.setFilePath(targetFile.getPath());
+ targetFileView.setFileBytes(imageConverterData.getTargetFileBytes(targetFile.getId()));
+ targetFileView.setVisible(true);
+ targetFileView.setEnabled(imageConverterData.isValidConversion());
+ } else {
+ targetFileView.getFilePathField().setLabelText("Not used");
+ targetFileView.setFilePath("");
+ targetFileView.setFileBytes(null);
+ targetFileView.setVisible(true);
+ targetFileView.setEnabled(false);
+ }
+ }
+
+ }
+
+ useDefaultScriptField.setValue(imageConverterParameters.isUseDefaultScript());
+ useDefaultScriptField.setEnabled(imageConverterData.isValid());
+ useDefaultScriptField.setEditable(imageConverterData.isValidConversion());
+
+ String script = imageConverterParameters.getScript();
+ scriptField.setValue(script);
+ scriptField.setEnabled(imageConverterData.isValid());
+ scriptField.setEditable(!imageConverterParameters.isUseDefaultScript());
+
+ int lineNumber = imageConverterData.getConverterScriptData().geErrorLineNumber();
+ if (lineNumber > 0) {
+ int offset = scriptField.getText().getOffsetAtLine(lineNumber - 1);
+ scriptField.setSelection(offset);
+ }
+ imageConverterData.getConverterScriptData().setErrorLineNumber(-1);
+
+ }
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/editor/ImagePaletteView.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/editor/ImagePaletteView.java
new file mode 100644
index 00000000..3948bf32
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/editor/ImagePaletteView.java
@@ -0,0 +1,829 @@
+/**
+ * Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.editor;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IMenuCreator;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.PaletteData;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.graphics.Region;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.ColorDialog;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.ui.ISelectionListener;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.part.ViewPart;
+
+import com.wudsn.ide.base.common.HexUtility;
+import com.wudsn.ide.base.common.NumberUtility;
+import com.wudsn.ide.base.common.TextUtility;
+import com.wudsn.ide.gfx.Texts;
+import com.wudsn.ide.gfx.converter.ImageColorHistogram;
+import com.wudsn.ide.gfx.gui.ImageCanvas;
+import com.wudsn.ide.gfx.model.Palette;
+import com.wudsn.ide.gfx.model.PaletteType;
+import com.wudsn.ide.gfx.model.PaletteUtility;
+
+/**
+ * This class displays the palette of the image from a {@link ImageProvider}.
+ *
+ * @author Peter Dell
+ * @see ImageCanvas
+ */
+
+public final class ImagePaletteView extends ViewPart implements
+ ISelectionListener {
+
+ private final class PaletteMenuCreator implements IMenuCreator,
+ SelectionListener {
+ private Menu menu;
+ private Map images;
+
+ public PaletteMenuCreator() {
+ images = new HashMap(10);
+ }
+
+ @Override
+ public Menu getMenu(Menu parent) {
+ return null;
+ }
+
+ @Override
+ public Menu getMenu(Control parent) {
+ if (menu != null) {
+ menu.dispose();
+ menu = null;
+ }
+ menu = new Menu(parent);
+ createMenuItem("Hires-1", PaletteUtility.getPaletteColors(
+ PaletteType.ATARI_DEFAULT, Palette.HIRES_1, null));
+ createMenuItem("Hires-2", PaletteUtility.getPaletteColors(
+ PaletteType.ATARI_DEFAULT, Palette.HIRES_2, null));
+
+ createMenuItem("Multi-1", PaletteUtility.getPaletteColors(
+ PaletteType.ATARI_DEFAULT, Palette.MULTI_1, null));
+ createMenuItem("Multi-2", PaletteUtility.getPaletteColors(
+ PaletteType.ATARI_DEFAULT, Palette.MULTI_2, null));
+ createMenuItem("Multi-3", PaletteUtility.getPaletteColors(
+ PaletteType.ATARI_DEFAULT, Palette.MULTI_3, null));
+ createMenuItem("Multi-4", PaletteUtility.getPaletteColors(
+ PaletteType.ATARI_DEFAULT, Palette.MULTI_4, null));
+ createMenuItem("Multi-5", PaletteUtility.getPaletteColors(
+ PaletteType.ATARI_DEFAULT, Palette.MULTI_5, null));
+ createMenuItem("Multi-6", PaletteUtility.getPaletteColors(
+ PaletteType.ATARI_DEFAULT, Palette.MULTI_6, null));
+ return menu;
+ }
+
+ private void createMenuItem(String text, RGB[] rgbs) {
+ MenuItem item = new MenuItem(menu, SWT.NONE);
+ Image image = images.get(text);
+ if (image == null) {
+ int size = 16;
+ int width = rgbs.length * size;
+ int height = size;
+ PaletteData paletteData = new PaletteData(rgbs);
+ ImageData imageData = new ImageData(width, height, 8,
+ paletteData);
+ for (int i = 0; i < rgbs.length; i++) {
+ for (int y = 0; y < size; y++) {
+ for (int x = 0; x < size; x++) {
+ imageData.setPixel(i * size + x, y, i);
+ }
+ }
+ }
+ image = new Image(Display.getCurrent(), imageData);
+ images.put(text, image);
+ }
+ item.setImage(image);
+ item.setData(rgbs);
+ item.addSelectionListener(this);
+ }
+
+ @Override
+ public void dispose() {
+ if (menu != null) {
+ menu.dispose();
+ }
+ menu = null;
+ if (images != null) {
+ for (Image image : images.values()) {
+ image.dispose();
+ }
+ images = null;
+ }
+ }
+
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ MenuItem item = (MenuItem) e.widget;
+ imageProvider.setPaletteRGBs((RGB[]) item.getData());
+ }
+
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e) {
+
+ }
+ }
+
+ /**
+ *
+ * @author Peter Dell
+ *
+ */
+ private static final class TableView {
+
+ /**
+ * Data container for a row in the table view.
+ *
+ * @author Peter Dell
+ *
+ */
+ private static final class Data {
+ private int index;
+ private int pixelColor;
+ private RGB rgb;
+ private int pixelColorCount;
+ private int pixelColorCountPercent;
+
+ public Data(int index, Integer pixelColor, RGB rgb,
+ int pixelColorCount, int pixelColorCountPercent) {
+ if (pixelColor == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'pixelColor' must not be null.");
+ }
+ if (rgb == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'rgb' must not be null.");
+ }
+ this.index = index;
+ this.pixelColor = pixelColor.intValue();
+ this.rgb = rgb;
+ this.pixelColorCount = pixelColorCount;
+ this.pixelColorCountPercent = pixelColorCountPercent;
+ }
+
+ public int getIndex() {
+ return index;
+ }
+
+ public int getPixelColor() {
+ return pixelColor;
+ }
+
+ public RGB getRGB() {
+ return rgb;
+ }
+
+ public int getPixelColorCount() {
+ return pixelColorCount;
+ }
+
+ public int getPixelColorCountPercent() {
+ return pixelColorCountPercent;
+ }
+ }
+
+ /**
+ * Comparator to sort lists of {@link Data}.
+ *
+ * @author Peter Dell
+ *
+ */
+ private class DataComparator implements Comparator {
+
+ private TableColumn sortColumn;
+ private int sortDirection;
+
+ /**
+ * Creates a new comparator.
+ *
+ * @param sortColumn
+ * The column to sort by, not null
.
+ * @param direction
+ * The direction to sort by, see {@link SWT#UP} or
+ * {@link SWT#DOWN}.
+ */
+ public DataComparator(TableColumn sortColumn, int direction) {
+ if (sortColumn == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'sortColumn' must not be null.");
+ }
+ this.sortColumn = sortColumn;
+ this.sortDirection = direction == SWT.UP ? 1 : -1;
+ }
+
+ @Override
+ public int compare(Data o1, Data o2) {
+ if (sortColumn == indexColumn) {
+ return (o1.getIndex() - o2.getIndex()) * sortDirection;
+ } else if (sortColumn == pixelColorHexColumn
+ || sortColumn == pixelColorBinaryColumn) {
+ return (o1.getPixelColor() - o2.getPixelColor())
+ * sortDirection;
+ } else if (sortColumn == rgbColorColumn) {
+ // Sort by brightness
+ float b1 = o1.getRGB().getHSB()[2];
+ float b2 = o2.getRGB().getHSB()[2];
+ if (b1 > b2) {
+ return sortDirection;
+ } else if (b1 < b2) {
+ return -sortDirection;
+ }
+ return 0;
+ } else if (sortColumn == pixelColorCountColumn
+ || sortColumn == pixelColorCountPercentColumn) {
+ return (o1.getPixelColorCount() - o2.getPixelColorCount())
+ * sortDirection;
+ }
+ return 0;
+ }
+
+ }
+
+ // Standard width of a column.
+ private static final int WIDTH = 47;
+
+ // Objects created in the constructor.
+ private final ImagePaletteView owner;
+ private final Table table;
+ private final Listener defaultSelectionListener;
+ final TableColumn indexColumn;
+ final TableColumn pixelColorHexColumn;
+ final TableColumn pixelColorBinaryColumn;
+ final TableColumn rgbColorColumn;
+ final TableColumn pixelColorCountColumn;
+ final TableColumn pixelColorCountPercentColumn;
+
+ // The image cache map.
+ private Map images;
+
+ // The image color histogram containing the original data.
+ private ImageColorHistogram imageColorHistogram;
+
+ // The data list containing the converted image color histogram data.
+ private List dataList;
+
+ public TableView(Composite parent, final ImagePaletteView owner) {
+ if (parent == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'parent' must not be null.");
+ }
+ if (owner == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'owner' must not be null.");
+ }
+ this.owner = owner;
+
+ table = new Table(parent, SWT.VIRTUAL | SWT.BORDER | SWT.SINGLE
+ | SWT.FULL_SELECTION);
+ table.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ table.setHeaderVisible(true);
+
+ /*
+ * NOTE: MeasureItem, PaintItem and EraseItem are called repeatedly.
+ * Therefore, it is critical for performance that these methods be
+ * as efficient as possible.
+ */
+ table.addListener(SWT.EraseItem, new Listener() {
+ @Override
+ public void handleEvent(Event event) {
+ eraseItem(event);
+ }
+ });
+
+ defaultSelectionListener = new Listener() {
+ @Override
+ public void handleEvent(Event e) {
+ editColor();
+ }
+ };
+
+ // The first column is always left aligned in SWT due to a
+ // restriction in windows.
+ // This is a trick to come round this restriction.
+ TableColumn dummyColumn;
+ dummyColumn = new TableColumn(table, SWT.LEFT);
+ dummyColumn.setWidth(0);
+
+ indexColumn = new TableColumn(table, SWT.RIGHT);
+ indexColumn.setText("Index");
+ indexColumn.setText(Texts.IMAGE_PALETTE_VIEW_COLUMN_INDEX_TEXT);
+ pixelColorHexColumn = new TableColumn(table, SWT.RIGHT);
+ pixelColorHexColumn.setText("Hex");
+ pixelColorHexColumn
+ .setText(Texts.IMAGE_PALETTE_VIEW_COLUMN_COLOR_HEX_TEXT);
+ pixelColorBinaryColumn = new TableColumn(table, SWT.RIGHT);
+ pixelColorBinaryColumn
+ .setText(Texts.IMAGE_PALETTE_VIEW_COLUMN_COLOR_BINARY_TEXT);
+ rgbColorColumn = new TableColumn(table, SWT.RIGHT);
+ rgbColorColumn
+ .setText(Texts.IMAGE_PALETTE_VIEW_COLUMN_RGB_COLOR_TEXT);
+ pixelColorCountColumn = new TableColumn(table, SWT.RIGHT);
+ pixelColorCountColumn
+ .setText(Texts.IMAGE_PALETTE_VIEW_COLUMN_COLOR_COUNT_TEXT);
+ pixelColorCountPercentColumn = new TableColumn(table, SWT.RIGHT);
+ pixelColorCountPercentColumn
+ .setText(Texts.IMAGE_PALETTE_VIEW_COLUMN_COLOR_COUNT_PERCENT_TEXT);
+
+ indexColumn.setWidth(WIDTH);
+ pixelColorHexColumn.setWidth(WIDTH);
+ pixelColorBinaryColumn.setWidth(WIDTH);
+ rgbColorColumn.setWidth(90);
+ pixelColorCountColumn.setWidth(WIDTH);
+ pixelColorCountPercentColumn.setWidth(WIDTH);
+
+ table.addListener(SWT.SetData, new Listener() {
+ @Override
+ public void handleEvent(Event event) {
+
+ updateTableItem(event);
+ }
+ });
+
+ // Add sort indicator and sort data when column selected
+ Listener sortListener = new Listener() {
+ @Override
+ public void handleEvent(Event event) {
+ sortTableColumn(event);
+ }
+ };
+ indexColumn.addListener(SWT.Selection, sortListener);
+ pixelColorHexColumn.addListener(SWT.Selection, sortListener);
+ pixelColorBinaryColumn.addListener(SWT.Selection, sortListener);
+ rgbColorColumn.addListener(SWT.Selection, sortListener);
+ pixelColorCountColumn.addListener(SWT.Selection, sortListener);
+ pixelColorCountPercentColumn.addListener(SWT.Selection,
+ sortListener);
+
+ table.setSortColumn(indexColumn);
+ table.setSortDirection(SWT.UP);
+
+ images = new HashMap();
+ imageColorHistogram = null;
+ dataList = new ArrayList();
+ }
+
+ public void clear() {
+ if (!table.isDisposed()) {
+ table.setItemCount(0);
+ table.clearAll();
+ }
+
+ for (Image image : images.values()) {
+ image.dispose();
+ }
+ images.clear();
+
+ imageColorHistogram = null;
+ dataList.clear();
+ }
+
+ public void setFocus() {
+ table.setFocus();
+ }
+
+ void updateTableItem(Event event) {
+ if (event == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'event' must not be null.");
+ }
+ TableItem item = (TableItem) event.item;
+ Font font = JFaceResources.getTextFont();
+ int i = table.indexOf(item);
+ Data data = dataList.get(i);
+ item.setData(data);
+ item.setText(1,
+ NumberUtility.getLongValueDecimalString(data.getIndex()));
+
+ // Pixel color values are uninteresting for direct palettes.
+ if (!imageColorHistogram.isDirectPalette()) {
+ item.setText(2,
+ HexUtility.getLongValueHexString(data.getPixelColor()));
+ item.setFont(2, font);
+ item.setText(3, Integer.toBinaryString(data.getPixelColor()));
+ item.setFont(3, font);
+ }
+ RGB rgb = data.getRGB();
+
+ // Images are resources which have to be disposed, so handle
+ Image image = images.get(rgb);
+ if (image == null) {
+ PaletteData paletteData = new PaletteData(new RGB[] { rgb });
+ ImageData imageData = new ImageData(32, 16, 1, paletteData);
+ image = new Image(table.getDisplay(), imageData);
+ images.put(rgb, image);
+ }
+ item.setImage(4, image);
+ item.setText(4, PaletteUtility.getPaletteColorText(rgb));
+ item.setFont(4, font);
+ item.setText(5, NumberUtility.getLongValueDecimalString(data
+ .getPixelColorCount()));
+ item.setText(6, NumberUtility.getLongValueDecimalString(data
+ .getPixelColorCountPercent()));
+
+ }
+
+ void eraseItem(Event event) {
+ if (event == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'event' must not be null.");
+ }
+ event.detail &= ~SWT.HOT;
+ if ((event.detail & SWT.SELECTED) != 0) {
+ GC gc = event.gc;
+ Rectangle area = table.getClientArea();
+ /*
+ * If you wish to paint the selection beyond the end of last
+ * column, you must change the clipping region.
+ */
+ int columnCount = table.getColumnCount();
+ if (event.index == columnCount - 1 || columnCount == 0) {
+ int width = area.x + area.width - event.x;
+ if (width > 0) {
+ Region region = new Region();
+ gc.getClipping(region);
+ region.add(event.x, event.y, width, event.height);
+ gc.setClipping(region);
+ region.dispose();
+ }
+ }
+ gc.setAdvanced(true);
+ if (gc.getAdvanced()) {
+ gc.setAlpha(127);
+ }
+ Rectangle rect = event.getBounds();
+ Color foreground = gc.getForeground();
+
+ gc.setForeground(table.getDisplay().getSystemColor(
+ SWT.COLOR_RED));
+ gc.fillRectangle(0, rect.y, 500, rect.height - 1);
+
+ // Restore colors for subsequent drawing
+ gc.setForeground(foreground);
+ // Mark event as handled
+ event.detail &= ~SWT.SELECTED;
+ }
+ }
+
+ void sortTableColumn(Event event) {
+ if (event == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'event' must not be null.");
+ }
+ // determine new sort column and direction
+ TableColumn sortColumn = table.getSortColumn();
+ TableColumn currentColumn = (TableColumn) event.widget;
+ int direction = table.getSortDirection();
+ if (sortColumn == currentColumn) {
+ direction = direction == SWT.UP ? SWT.DOWN : SWT.UP;
+ } else {
+ table.setSortColumn(currentColumn);
+ direction = SWT.UP;
+ }
+ table.setSortDirection(direction);
+
+ Collections.sort(dataList, new DataComparator(
+ table.getSortColumn(), table.getSortDirection()));
+ // Update data displayed in table
+ table.clearAll();
+ }
+
+ void editColor() {
+ TableItem[] selection = table.getSelection();
+ if (selection.length == 1) {
+ Data data = (Data) selection[0].getData();
+ ColorDialog colorDialog = new ColorDialog(table.getShell());
+ colorDialog.setRGB(data.getRGB());
+ RGB newRGB = colorDialog.open();
+
+ if (newRGB != null) {
+ owner.imageProvider.setPaletteRGB(data.getPixelColor(),
+ newRGB);
+ }
+ }
+ }
+
+ public void setImageColorHistogram(
+ ImageColorHistogram imageColorHistogram,
+ boolean paletteChangeable, boolean showUnusedColors,
+ boolean force) {
+ if (imageColorHistogram == null) {
+ clear();
+ } else if (this.imageColorHistogram != imageColorHistogram || force) {
+ clear();
+ this.imageColorHistogram = imageColorHistogram;
+
+ // Register double click only if palette is changeable.
+ table.removeListener(SWT.DefaultSelection,
+ defaultSelectionListener);
+ if (paletteChangeable) {
+ table.addListener(SWT.DefaultSelection,
+ defaultSelectionListener);
+ }
+
+ // For direct palette, display only used pixel colors.
+ // For indexed palette, display either all pixel colors or only
+ // used pixel colors.
+ List pixelColors;
+ if (imageColorHistogram.isDirectPalette()) {
+ pixelColors = imageColorHistogram.getUsedPixelColors();
+ } else {
+ if (showUnusedColors) {
+ pixelColors = imageColorHistogram
+ .getPalettePixelColors();
+ } else {
+ pixelColors = imageColorHistogram.getUsedPixelColors();
+ }
+ }
+
+ // Hide unused column in direct palette mode.
+ if (imageColorHistogram.isDirectPalette()) {
+ pixelColorHexColumn.setWidth(0);
+ pixelColorBinaryColumn.setWidth(0);
+ } else {
+ pixelColorHexColumn.setWidth(WIDTH);
+ pixelColorBinaryColumn.setWidth(WIDTH);
+ }
+
+ // Create data list.
+ int size = pixelColors.size();
+ int pixelCount = imageColorHistogram.getPixelCount();
+ for (int i = 0; i < size; i++) {
+ Integer pixelColor = pixelColors.get(i);
+ int pixelColorCount = imageColorHistogram
+ .getPixelColorCount(pixelColor);
+ int pixelColorCountPercent = ((pixelColorCount * 100) / pixelCount);
+ RGB rgb = imageColorHistogram.getRGB(pixelColor);
+ Data data = new Data(i, pixelColor, rgb, pixelColorCount,
+ pixelColorCountPercent);
+ dataList.add(data);
+ }
+
+ Collections.sort(
+ dataList,
+ new DataComparator(table.getSortColumn(), table
+ .getSortDirection()));
+ table.setItemCount(dataList.size());
+ table.setSelection(0);
+ }
+
+ }
+ }
+
+ // ID of this view in the plugin manifest.
+ public static final String ID = ImagePaletteView.class.getName();
+
+ // UI components, not final because they are created outside of the
+ // constructor.
+ private IAction editColorAction;
+ private IAction showUnusedColorsAction;
+ private Label infoLabel;
+ private TableView tableView;
+
+ // The currently active image provider or null.
+ ImageProvider imageProvider;
+
+ /**
+ * Creation is private.
+ */
+ public ImagePaletteView() {
+ }
+
+ @Override
+ public void createPartControl(Composite parent) {
+
+ IToolBarManager toolBarManager = getViewSite().getActionBars()
+ .getToolBarManager();
+
+ editColorAction = new Action(
+ Texts.IMAGE_PALETTE_VIEW_EDIT_COLOR_ACTION_LABEL,
+ IAction.AS_DROP_DOWN_MENU) {
+ @Override
+ public void run() {
+ editColor();
+ }
+ };
+ editColorAction
+ .setToolTipText(Texts.IMAGE_PALETTE_VIEW_EDIT_COLOR_ACTION_TOOLTIP);
+ editColorAction.setMenuCreator(new PaletteMenuCreator());
+
+ showUnusedColorsAction = new Action(
+ Texts.IMAGE_PALETTE_VIEW_UNUSED_COLORS_ACTION_LABEL,
+ IAction.AS_CHECK_BOX) {
+ @Override
+ public void run() {
+ showUnusedColors();
+ }
+ };
+ showUnusedColorsAction
+ .setToolTipText(Texts.IMAGE_PALETTE_VIEW_UNUSED_COLORS_ACTION_TOOLTIP);
+
+ toolBarManager.add(editColorAction);
+ toolBarManager.add(showUnusedColorsAction);
+
+ // presetColorsAction.setText("Test");
+
+ GridLayout gridLayout = new GridLayout();
+ gridLayout.marginWidth = 0;
+ gridLayout.marginHeight = 0;
+ parent.setLayout(gridLayout);
+
+ Composite infoComposite = new Composite(parent, SWT.NONE);
+ gridLayout = new GridLayout(1, false);
+ gridLayout.marginHeight = 0;
+ infoComposite.setLayout(gridLayout);
+ GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+ infoComposite.setLayoutData(gd);
+ infoLabel = new Label(infoComposite, SWT.NONE);
+ infoLabel.setLayoutData(gd);
+
+ tableView = new TableView(parent, this);
+
+ // Add this as a global selection listener
+ getSite().getPage().addSelectionListener(this);
+
+ // Preset based on current selection
+ selectionChanged(null, getSite().getPage().getSelection());
+
+ }
+
+ void editColor() {
+ tableView.editColor();
+ }
+
+ void showUnusedColors() {
+ ImageColorHistogram imageColorHistogram = imageProvider
+ .getImageColorHistogram();
+ boolean paletteChangeable = imageProvider.isPaletteChangeable();
+ tableView.setImageColorHistogram(imageColorHistogram,
+ paletteChangeable, showUnusedColorsAction.isChecked(), true);
+ }
+
+ @Override
+ public void setFocus() {
+ tableView.setFocus();
+ }
+
+ @Override
+ public void dispose() {
+
+ if (tableView != null) {
+ tableView.clear();
+ }
+
+ if (imageProvider != null) {
+ imageProvider.setImagePaletteView(null);
+ imageProvider = null;
+ }
+
+ editColorAction.getMenuCreator().dispose();
+ getSite().getPage().removeSelectionListener(this);
+ super.dispose();
+ }
+
+ @Override
+ public void selectionChanged(IWorkbenchPart part, ISelection selection) {
+
+ if (part == null) {
+ setImageProvider(null);
+ } else {
+ if (part instanceof GraphicsEditor) {
+ GraphicsEditor graphicsEditor = ((GraphicsEditor) part);
+ setImageProvider(graphicsEditor.getImageProvider());
+ }
+ }
+ }
+
+ /**
+ * Sets the image provider.
+ *
+ * @param imageProvider
+ * The image provider or null
.
+ */
+ public void setImageProvider(ImageProvider imageProvider) {
+ if (imageProvider != this.imageProvider) {
+ // Unregister from old provider
+ if (this.imageProvider != null) {
+ this.imageProvider.setImagePaletteView(null);
+ this.imageProvider = null;
+ }
+
+ // Register with new provider
+ if (imageProvider != null) {
+ this.imageProvider = imageProvider;
+ this.imageProvider.setImagePaletteView(this);
+ }
+ }
+ dataToUI();
+ }
+
+ /**
+ * Retrieve the current status from the image provider and display it.
+ *
+ */
+ public void dataToUI() {
+ boolean enabled;
+
+ if (imageProvider != null) {
+ ImageColorHistogram imageColorHistogram = imageProvider
+ .getImageColorHistogram();
+ boolean paletteChangeable = imageProvider.isPaletteChangeable();
+ editColorAction.setEnabled(paletteChangeable);
+
+ enabled = (imageColorHistogram != null)
+ && !imageColorHistogram.isDirectPalette();
+ showUnusedColorsAction.setEnabled(enabled);
+
+ String text;
+ if (imageColorHistogram != null) {
+ int palettBits = imageColorHistogram.getPaletteBits();
+ if (imageColorHistogram.isDirectPalette()) {
+ text = TextUtility
+ .format(Texts.IMAGE_PALETTE_VIEW_INFO_DIRECT_PALETTE_IMAGE,
+ NumberUtility
+ .getLongValueDecimalString(palettBits),
+ NumberUtility
+ .getLongValueDecimalString(imageColorHistogram
+ .getUsedPixelColors()
+ .size()));
+ } else {
+ text = TextUtility
+ .format(Texts.IMAGE_PALETTE_VIEW_INFO_INDEXED_PALETTE_IMAGE,
+ NumberUtility
+ .getLongValueDecimalString(palettBits),
+
+ NumberUtility
+ .getLongValueDecimalString(imageColorHistogram
+ .getUsedPixelColors()
+ .size()),
+ NumberUtility
+ .getLongValueDecimalString(1 << palettBits));
+ }
+ } else {
+ text = Texts.IMAGE_PALETTE_VIEW_INFO_NO_IMAGE;
+ }
+ infoLabel.setText(text);
+
+ tableView.setImageColorHistogram(imageColorHistogram,
+ paletteChangeable, showUnusedColorsAction.isChecked(),
+ false);
+ } else {
+ editColorAction.setEnabled(false);
+ showUnusedColorsAction.setEnabled(false);
+ infoLabel.setText(Texts.IMAGE_PALETTE_VIEW_INFO_NO_IMAGE);
+ tableView.clear();
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/editor/ImageProvider.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/editor/ImageProvider.java
new file mode 100644
index 00000000..7cfaf7ff
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/editor/ImageProvider.java
@@ -0,0 +1,57 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.editor;
+
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.RGB;
+
+import com.wudsn.ide.gfx.converter.ImageColorHistogram;
+import com.wudsn.ide.gfx.model.Aspect;
+
+public interface ImageProvider {
+
+ public void setImageView(ImageView imageView);
+
+ public void setImagePaletteView(ImagePaletteView imagePaletteView);
+
+ public Aspect getAspect();
+
+ public void setAspect(Aspect value);
+
+ public boolean isShrinkToFit();
+
+ public void setShrinkToFit(boolean value);
+
+ public boolean isZoomToFit();
+
+ public void setZoomToFit(boolean value);
+
+ public ImageData getImageData();
+
+ public ImageColorHistogram getImageColorHistogram();
+
+ public boolean isPaletteChangeable();
+
+ public void setPaletteRGBs(RGB[] rgbs);
+
+ public void setPaletteRGB(int pixelColor, RGB rgb);
+
+
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/editor/ImageView.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/editor/ImageView.java
new file mode 100644
index 00000000..ab76ed9c
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/editor/ImageView.java
@@ -0,0 +1,288 @@
+/**
+ * Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.editor;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.action.ControlContribution;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.ISelectionListener;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.part.ViewPart;
+
+import com.wudsn.ide.base.gui.Action;
+import com.wudsn.ide.base.gui.ActionListener;
+import com.wudsn.ide.base.gui.MessageManager;
+import com.wudsn.ide.base.gui.SWTFactory;
+import com.wudsn.ide.gfx.Texts;
+import com.wudsn.ide.gfx.converter.ConverterCommonParameters;
+import com.wudsn.ide.gfx.gui.AspectField;
+import com.wudsn.ide.gfx.gui.ImageCanvas;
+import com.wudsn.ide.gfx.model.Aspect;
+
+/**
+ * This ImageView class shows the image from an {@link ImageProvider} in an
+ * {@link ImageCanvas}.
+ *
+ * @author Peter Dell
+ * @author Chengdong Li: cli4@uky.edu
+ *
+ * @see ImageCanvas
+ */
+
+public final class ImageView extends ViewPart implements ISelectionListener {
+
+ private final class AspectControlContribution extends ControlContribution implements ActionListener {
+
+ private boolean enabled;
+ private Aspect value;
+ private AspectField aspectField;
+ private Action action;
+
+ public AspectControlContribution() {
+ super("com.wudsn.ide.gfx.editor.ImageViewAspect");
+ enabled = false;
+ value = new Aspect(1, 1);
+ }
+
+ @Override
+ protected Control createControl(Composite parent) {
+ Composite composite = SWTFactory.createComposite(parent, 2, 1, GridData.FILL_HORIZONTAL);
+ GridLayout gridLayout = (GridLayout) composite.getLayout();
+ gridLayout.marginHeight = 0;
+ aspectField = new AspectField(composite, Texts.IMAGE_VIEW_ASPECT_LABEL);
+ aspectField.setEnabled(enabled);
+ aspectField.setValue(value);
+ action = new Action(1, this);
+ aspectField.addSelectionAction(action);
+
+ messageManager.registerField(aspectField, ConverterCommonParameters.MessageIds.DISPLAY_ASPECT);
+ return composite;
+ }
+
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ if (aspectField != null) {
+ aspectField.setEnabled(enabled);
+ }
+ }
+
+ public void setValue(Aspect value) {
+ this.value = value;
+ if (aspectField != null) {
+ aspectField.setValue(value);
+ }
+ }
+
+ @Override
+ public void performAction(Action action) {
+ imageProvider.setAspect(aspectField.getValue());
+ }
+ }
+
+ public static final String ID = ImageView.class.getName();
+ MessageManager messageManager;
+
+ private AspectControlContribution aspectControlContribution;
+ IAction shrinkToFitAction;
+ IAction zoomToFitAction;
+ private ImageCanvas imageCanvas;
+
+ ImageProvider imageProvider;
+
+ /**
+ * Creation is private.
+ */
+ public ImageView() {
+ messageManager = new MessageManager(this);
+ }
+
+ @Override
+ public void createPartControl(Composite parent) {
+
+ IToolBarManager toolBarManager = getViewSite().getActionBars().getToolBarManager();
+
+ aspectControlContribution = new AspectControlContribution();
+
+ shrinkToFitAction = new org.eclipse.jface.action.Action("Shrink", IAction.AS_CHECK_BOX) {
+ @Override
+ public void run() {
+ imageProvider.setShrinkToFit(shrinkToFitAction.isChecked());
+ }
+ };
+ zoomToFitAction = new org.eclipse.jface.action.Action("Zoom", IAction.AS_CHECK_BOX) {
+ @Override
+ public void run() {
+ imageProvider.setZoomToFit(zoomToFitAction.isChecked());
+ }
+ };
+
+ toolBarManager.add(aspectControlContribution);
+ toolBarManager.add(shrinkToFitAction);
+ toolBarManager.add(zoomToFitAction);
+
+ imageCanvas = new ImageCanvas(parent, SWT.NONE);
+
+ // Currently there's no use-case for reacting on the mouse position.
+ // imageCanvas.addMouseMoveListener(new MouseMoveListener() {
+ // public void mouseMove(MouseEvent event) {
+ // Point point;
+ // messageManager.clearMessages();
+ //
+ // point = imageCanvas.getPoint(event);
+ // messageManager.sendMessage(
+ // 0,
+ // IStatus.INFO,
+ // "x={0} y={1}",
+ // new String[] {
+ // NumberUtility
+ // .getLongValueDecimalString(point.x),
+ //
+ // NumberUtility
+ // .getLongValueDecimalString(point.y) });
+ // messageManager.displayMessages();
+ //
+ // }
+ // });
+
+ // Add this as a global selection listener
+ getSite().getPage().addSelectionListener(this);
+
+ // Preset based on current selection
+ selectionChanged(null, getSite().getPage().getSelection());
+ }
+
+ @Override
+ public void setFocus() {
+ imageCanvas.setFocus();
+ }
+
+ @Override
+ public void dispose() {
+
+ if (imageProvider != null) {
+ imageProvider.setImageView(null);
+ imageProvider = null;
+ }
+
+ getSite().getPage().removeSelectionListener(this);
+ imageCanvas.dispose();
+ super.dispose();
+ }
+
+ @Override
+ public void selectionChanged(IWorkbenchPart part, ISelection selection) {
+
+ if (part == null) {
+ setImageProvider(null);
+ } else {
+ if (part instanceof GraphicsEditor) {
+ GraphicsEditor graphicsEditor = ((GraphicsEditor) part);
+ setImageProvider(graphicsEditor.getImageProvider());
+ System.out.println(this + "" + part + "" + selection);
+ }
+ }
+ }
+
+ /**
+ * Sets the image provider.
+ *
+ * @param imageProvider
+ * The image provider or null
.
+ */
+ public void setImageProvider(ImageProvider imageProvider) {
+ if (imageProvider != this.imageProvider) {
+ // Unregister from old provider
+ if (this.imageProvider != null) {
+ this.imageProvider.setImageView(null);
+ this.imageProvider = null;
+ }
+
+ // Register with new provider
+ if (imageProvider != null) {
+ this.imageProvider = imageProvider;
+ this.imageProvider.setImageView(this);
+ }
+ }
+ dataToUI();
+
+ }
+
+ /**
+ * Retrieve the current status from the image provider and display it.
+ *
+ */
+ public void dataToUI() {
+ ImageData imageData;
+ boolean enabled;
+
+ messageManager.clearMessages();
+ if (imageProvider != null) {
+ imageData = imageProvider.getImageData();
+ enabled = (imageData != null);
+
+ aspectControlContribution.setEnabled(enabled);
+ aspectControlContribution.setValue(imageProvider.getAspect());
+ shrinkToFitAction.setEnabled(false);
+ shrinkToFitAction.setChecked(imageProvider.isShrinkToFit());
+ shrinkToFitAction.setEnabled(enabled);
+ zoomToFitAction.setEnabled(false);
+ zoomToFitAction.setChecked(imageProvider.isZoomToFit());
+ zoomToFitAction.setEnabled(enabled);
+ imageCanvas.setShrinkToFit(imageProvider.isShrinkToFit());
+ imageCanvas.setZoomToFit(imageProvider.isZoomToFit());
+
+ boolean valid;
+ ImageData displayImageData;
+
+ Aspect aspect = imageProvider.getAspect();
+ if (aspect.isValid()) {
+ valid = true;
+ } else {
+ messageManager.sendMessage(ConverterCommonParameters.MessageIds.DISPLAY_ASPECT, IStatus.ERROR,
+ "Invalid display aspect");
+ valid = false;
+ }
+ if (valid && imageData != null) {
+ int width = imageData.width;
+ int height = imageData.height;
+ displayImageData = imageData.scaledTo(width * aspect.getValidFactorX(),
+ height * aspect.getValidFactorY());
+ } else {
+ displayImageData = null;
+ }
+
+ imageCanvas.setImageData(displayImageData);
+ } else {
+ aspectControlContribution.setEnabled(false);
+ shrinkToFitAction.setEnabled(false);
+ zoomToFitAction.setEnabled(false);
+ imageCanvas.setImageData(null);
+ }
+ messageManager.displayMessages();
+ }
+}
\ No newline at end of file
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/gui/AspectField.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/gui/AspectField.java
new file mode 100644
index 00000000..23e1dc0d
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/gui/AspectField.java
@@ -0,0 +1,134 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.gui;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+
+import com.wudsn.ide.base.common.StringUtility;
+import com.wudsn.ide.base.gui.Action;
+import com.wudsn.ide.base.gui.Field;
+import com.wudsn.ide.gfx.model.Aspect;
+import com.wudsn.ide.gfx.model.AspectUtility;
+
+public final class AspectField extends Field {
+
+ private Label label;
+ private Combo combo;
+ private List selectionActions;
+
+ public AspectField(Composite parent, String labelText) {
+ if (parent == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'parent' must not be null.");
+ }
+ if (labelText == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'labelText' must not be null.");
+ }
+
+ label = new Label(parent, SWT.NONE);
+ label.setText(labelText);
+ combo = new Combo(parent, SWT.DROP_DOWN);
+
+ combo.add("1x1");
+ combo.add("2x1");
+ combo.add("2x2");
+ combo.add("4x2");
+ combo.add("4x4");
+
+ combo.select(0);
+
+ selectionActions = new ArrayList(1);
+ }
+
+ public void setValue(Aspect value) {
+ if (value == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'value' must not be null.");
+ }
+ for (Action action : selectionActions) {
+ action.setEnabled(false);
+ }
+ combo.setText(AspectUtility.toString(value));
+ for (Action action : selectionActions) {
+ action.setEnabled(true);
+ }
+ }
+
+ public Aspect getValue() {
+ Aspect result;
+ String text = combo.getText().toLowerCase();
+ if (StringUtility.isEmpty(text)) {
+ result = new Aspect(1, 1);
+ } else {
+ result = AspectUtility.fromString(text);
+ }
+ return result;
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Control getControl() {
+ return combo;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setEnabled(boolean enabled) {
+ label.setEnabled(enabled);
+ combo.setEnabled(enabled);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setEditable(boolean editable) {
+ // There is only a style SWT#READ_ONLY, but no changeable property
+ }
+
+ /**
+ * Adds a selection action which is fire when the field content changes.
+ *
+ * @param action
+ * The selection action, not null
.
+ */
+ public void addSelectionAction(Action action) {
+ if (action == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'action' must not be null.");
+ }
+ selectionActions.add(action);
+ combo.addSelectionListener(action);
+ }
+
+}
\ No newline at end of file
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/gui/ConverterIdField.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/gui/ConverterIdField.java
new file mode 100644
index 00000000..cba855f0
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/gui/ConverterIdField.java
@@ -0,0 +1,128 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.gui;
+
+import java.util.List;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+
+import com.wudsn.ide.base.gui.Field;
+import com.wudsn.ide.gfx.GraphicsPlugin;
+import com.wudsn.ide.gfx.converter.ConverterDefinition;
+import com.wudsn.ide.gfx.converter.ConverterRegistry;
+import com.wudsn.ide.gfx.model.ConverterDirection;
+
+public final class ConverterIdField extends Field {
+
+ private Label label;
+ private Combo combo;
+ private List converterDefinitions;
+
+ public ConverterIdField(Composite parent, String labelText,
+ ConverterDirection converterDirection) {
+ if (parent == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'parent' must not be null.");
+ }
+ if (labelText == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'labelText' must not be null.");
+ }
+ if (converterDirection == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'converterDirection' must not be null.");
+ }
+ label = new Label(parent, SWT.NONE);
+ label.setText(labelText);
+ combo = new Combo(parent, SWT.DROP_DOWN);
+
+ GraphicsPlugin plugin = GraphicsPlugin.getInstance();
+ ConverterRegistry converterRegistry = plugin.getConverterRegistry();
+ converterDefinitions = converterRegistry
+ .getDefinitions(converterDirection);
+
+ combo.add("");
+ for (ConverterDefinition converterDefinition : converterDefinitions) {
+ combo.add(converterDefinition.getName());
+ }
+ combo.select(0);
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Control getControl() {
+ return combo;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setEnabled(boolean enabled) {
+ label.setEnabled(enabled);
+ combo.setEnabled(enabled);
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setEditable(boolean editable) {
+ // There is only an SWT.READ_ONLY style but not property
+ }
+
+ public void setValue(String value) {
+ if (value == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'value' must not be null.");
+ }
+ for (int i = 0; i < converterDefinitions.size(); i++) {
+ if (value.equals(converterDefinitions.get(i).getId())) {
+ combo.select(i + 1);
+ return;
+ }
+ }
+ combo.select(0);
+ }
+
+ public String getValue() {
+ int index;
+ index = combo.getSelectionIndex();
+ if (index == -1 || index == 0) {
+ return "";
+ }
+ String result = converterDefinitions.get(index - 1).getId();
+ return result;
+ }
+
+ public void addSelectionListener(SelectionListener selectionListener) {
+ combo.addSelectionListener(selectionListener);
+
+ }
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/gui/ImageCanvas.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/gui/ImageCanvas.java
new file mode 100644
index 00000000..ae315690
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/gui/ImageCanvas.java
@@ -0,0 +1,369 @@
+package com.wudsn.ide.gfx.gui;
+
+import java.awt.geom.AffineTransform;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ControlAdapter;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.ScrollBar;
+
+/**
+ * A scrollable SWT image canvas that extends org.eclipse.swt.graphics.Canvas.
+ *
+ * @author Peter Dell
+ * @author Chengdong Li: cli4@uky.edu
+ */
+public final class ImageCanvas extends Canvas {
+
+ // Zoom settings
+ private boolean shrinkToFit;
+ private boolean zoomToFit;
+
+ // Original image
+ private Image sourceImage;
+
+ // Affine transform applied to the source image.
+ private AffineTransform transform;
+
+ // Screen image
+ private Image screenImage;
+
+ /**
+ * Constructor for ScrollableCanvas.
+ *
+ * @param parent
+ * The parent of this control, not null
.
+ * @param style
+ * The style of this control.
+ */
+ public ImageCanvas(final Composite parent, int style) {
+ super(parent, style | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL
+ | SWT.NO_BACKGROUND);
+
+ // Register a resize listener
+ addControlListener(new ControlAdapter() {
+ @Override
+ public void controlResized(ControlEvent event) {
+ updateSize();
+ }
+ });
+ // Register a paint listener
+ addPaintListener(new PaintListener() {
+ @Override
+ public void paintControl(final PaintEvent event) {
+ paint(event.gc);
+ }
+ });
+
+ // Start with the identity transformation.
+ transform = new AffineTransform();
+ initScrollBars();
+ }
+
+ /**
+ * Dispose the garbage here
+ */
+ @Override
+ public void dispose() {
+ if (sourceImage != null && !sourceImage.isDisposed()) {
+ sourceImage.dispose();
+ sourceImage = null;
+ }
+ if (screenImage != null && !screenImage.isDisposed()) {
+ screenImage.dispose();
+ screenImage = null;
+ }
+ }
+
+ /* Paint function */
+ void paint(GC gc) {
+ // Canvas' painting area
+ Rectangle clientRectangle = getClientArea();
+
+ if (sourceImage != null) {
+ Rectangle imageRectangle = ImageCanvasUtility
+ .inverseTransformRectangle(transform, clientRectangle);
+ // Find a better start point to render
+ int gap = 2;
+ imageRectangle.x -= gap;
+ imageRectangle.y -= gap;
+ imageRectangle.width += 2 * gap;
+ imageRectangle.height += 2 * gap;
+
+ Rectangle imageBounds = sourceImage.getBounds();
+ imageRectangle = imageRectangle.intersection(imageBounds);
+ Rectangle destRect = ImageCanvasUtility.transformRectangle(
+ transform, imageRectangle);
+
+ if (screenImage != null) {
+ screenImage.dispose();
+ }
+ screenImage = new Image(getDisplay(), clientRectangle.width,
+ clientRectangle.height);
+ GC newGC = new GC(screenImage);
+ newGC.setBackground(getBackground());
+ newGC.fillRectangle(clientRectangle);
+ newGC.setClipping(clientRectangle);
+ newGC.drawImage(sourceImage, imageRectangle.x, imageRectangle.y,
+ imageRectangle.width, imageRectangle.height, destRect.x,
+ destRect.y, destRect.width, destRect.height);
+ newGC.dispose();
+
+ gc.drawImage(screenImage, 0, 0);
+ } else {
+ gc.setClipping(clientRectangle);
+ gc.fillRectangle(clientRectangle);
+ initScrollBars();
+ }
+ }
+
+ /**
+ * Initializes the scrollbars and registers the listeners.
+ */
+ private void initScrollBars() {
+ ScrollBar horizontal = getHorizontalBar();
+ horizontal.setEnabled(false);
+ horizontal.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent event) {
+ scrollHorizontally((ScrollBar) event.widget);
+ }
+ });
+ ScrollBar vertical = getVerticalBar();
+ vertical.setEnabled(false);
+ vertical.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent event) {
+ scrollVertically((ScrollBar) event.widget);
+ }
+ });
+ }
+
+ /* Scroll horizontally */
+ void scrollHorizontally(ScrollBar scrollBar) {
+ if (sourceImage == null)
+ return;
+
+ AffineTransform af = transform;
+ double tx = af.getTranslateX();
+ double select = -scrollBar.getSelection();
+ af.preConcatenate(AffineTransform.getTranslateInstance(select - tx, 0));
+ transform = af;
+ synchronizeScrollBars();
+ }
+
+ /* Scroll vertically */
+ void scrollVertically(ScrollBar scrollBar) {
+ if (sourceImage == null)
+ return;
+
+ AffineTransform af = transform;
+ double ty = af.getTranslateY();
+ double select = -scrollBar.getSelection();
+ af.preConcatenate(AffineTransform.getTranslateInstance(0, select - ty));
+ transform = af;
+ synchronizeScrollBars();
+ }
+
+ /**
+ * Synchronize the scrollbars with the image. If the transform is out of
+ * range, this method will correct it. This function considers only
+ * following factors : transform, image size, client area size.
+ */
+ void synchronizeScrollBars() {
+ if (sourceImage == null) {
+ redraw();
+ return;
+ }
+
+ AffineTransform af = transform;
+ double sx = af.getScaleX(), sy = af.getScaleY();
+ double tx = af.getTranslateX(), ty = af.getTranslateY();
+ if (tx > 0) {
+ tx = 0;
+ }
+ if (ty > 0) {
+ ty = 0;
+ }
+
+ Rectangle clientArea = getClientArea();
+
+ ScrollBar horizontal = getHorizontalBar();
+ horizontal.setIncrement((clientArea.width / 100));
+ horizontal.setPageIncrement(clientArea.width);
+ Rectangle imageBound = sourceImage.getBounds();
+ if (imageBound.width * sx > clientArea.width) {
+ // Image is wider than client area
+ horizontal.setMaximum((int) (imageBound.width * sx));
+ horizontal.setEnabled(true);
+ if (((int) -tx) > horizontal.getMaximum() - clientArea.width) {
+ tx = -horizontal.getMaximum() + clientArea.width;
+ }
+ } else {
+ // Image is narrower than client area
+ horizontal.setEnabled(false);
+ // Center if too small.
+ tx = (clientArea.width - imageBound.width * sx) / 2;
+ }
+ horizontal.setSelection((int) (-tx));
+ horizontal.setThumb(clientArea.width);
+
+ ScrollBar vertical = getVerticalBar();
+ vertical.setIncrement(clientArea.height / 100);
+ vertical.setPageIncrement(clientArea.height);
+ if (imageBound.height * sy > clientArea.height) {
+ // Image is higher than client area
+ vertical.setMaximum((int) (imageBound.height * sy));
+ vertical.setEnabled(true);
+ if (((int) -ty) > vertical.getMaximum() - clientArea.height) {
+ ty = -vertical.getMaximum() + clientArea.height;
+ }
+ } else {
+ // Image is not as high as the client area
+ vertical.setEnabled(false);
+ // Center if too small
+ ty = (clientArea.height - imageBound.height * sy) / 2;
+ }
+ vertical.setSelection((int) (-ty));
+ vertical.setThumb(clientArea.height);
+
+ // Update transform using concatenation
+ af = AffineTransform.getScaleInstance(sx, sy);
+ af.preConcatenate(AffineTransform.getTranslateInstance(tx, ty));
+ transform = af;
+
+ redraw();
+ }
+
+ /**
+ * Sets the shrink to fit property. This will no update the image.
+ *
+ * @param shrinkToFit
+ * true
to activate the automatic shrinking.
+ */
+ public void setShrinkToFit(boolean shrinkToFit) {
+ this.shrinkToFit = shrinkToFit;
+ updateSize();
+ }
+
+ /**
+ * Sets the zoom to fit property. This will no update the image.
+ *
+ * @param zoomToFit
+ * true
to activate the automatic zooming.
+ */
+ public void setZoomToFit(boolean zoomToFit) {
+ this.zoomToFit = zoomToFit;
+ updateSize();
+ }
+
+ /**
+ * Reset the image data and update the image
+ *
+ * @param data
+ * image data to be set
+ */
+ public void setImageData(ImageData data) {
+ Rectangle oldBounds = new Rectangle(-1, -1, -1, -1);
+
+ if (sourceImage != null) {
+ oldBounds = sourceImage.getBounds();
+ sourceImage.dispose();
+ sourceImage = null;
+ }
+
+ if (data != null) {
+ sourceImage = new Image(getDisplay(), data);
+
+ if (!sourceImage.getBounds().equals(oldBounds)) {
+ updateSize();
+ } else {
+ redraw();
+ }
+ } else {
+ redraw();
+ }
+ }
+
+ public Image getImage() {
+ return sourceImage;
+ }
+
+ /**
+ * Translates the x,y coordinates from a mouse event to the point
+ * coordinates in the original unscaled image.
+ *
+ * @param event
+ * The event, not null
.
+ * @return The point or null
.
+ */
+ public Point getPoint(MouseEvent event) {
+ if (event == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'event' must not be null.");
+ }
+ return new Point(event.x, event.y);
+ }
+
+ /**
+ * Update the image size and scrollbar positions.
+ */
+ void updateSize() {
+ if (sourceImage == null) {
+ redraw();
+ return;
+ }
+ Rectangle imageBounds = sourceImage.getBounds();
+ Rectangle clientArea = getClientArea();
+ double sx = (double) clientArea.width / (double) imageBounds.width;
+ double sy = (double) clientArea.height / (double) imageBounds.height;
+
+ if (!shrinkToFit) {
+ sx = Math.max(sx, 1.0);
+ sy = Math.max(sy, 1.0);
+ }
+ if (!zoomToFit) {
+ sx = Math.min(sx, 1.0);
+ sy = Math.min(sy, 1.0);
+ }
+ double s = Math.min(sx, sy);
+ double dx = 0.5 * clientArea.width;
+ double dy = 0.5 * clientArea.height;
+ zoom(dx, dy, s, new AffineTransform());
+ }
+
+ /**
+ * Perform a zooming operation centered on the given point (dx, dy) and
+ * using the given scale factor. The given AffineTransform instance is
+ * preconcatenated.
+ *
+ * @param dx
+ * center x
+ * @param dy
+ * center y
+ * @param scale
+ * zoom rate
+ * @param af
+ * original affinetransform
+ */
+ private void zoom(double dx, double dy, double scale, AffineTransform af) {
+ af.preConcatenate(AffineTransform.getTranslateInstance(-dx, -dy));
+ af.preConcatenate(AffineTransform.getScaleInstance(scale, scale));
+ af.preConcatenate(AffineTransform.getTranslateInstance(dx, dy));
+ transform = af;
+ synchronizeScrollBars();
+ }
+
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/gui/ImageCanvasUtility.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/gui/ImageCanvasUtility.java
new file mode 100644
index 00000000..9e75a6fb
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/gui/ImageCanvasUtility.java
@@ -0,0 +1,202 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.gui;
+
+import java.awt.geom.AffineTransform;
+import java.awt.geom.NoninvertibleTransformException;
+import java.awt.geom.Point2D;
+
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+
+/**
+ * Utility for Java2d transform used by{@link ImageCanvas}.
+ *
+ * @author Peter Dell
+ * @author Chengdong Li: cli4@uky.edu
+ *
+ */
+final class ImageCanvasUtility {
+
+ /**
+ * Creation is private.
+ */
+ private ImageCanvasUtility() {
+ }
+
+ /**
+ * Apply an affine transform to an SWT rectangle. The resulting SWT
+ * rectangle will have positive width and positive height.
+ *
+ * @param affineTransform
+ * The affine transform, not null
.
+ * @param sourceRectangle
+ * The SWT source rectangle, not null
.
+ * @return The SWT rectangle after transform with positive width and height,
+ * not null
.
+ */
+ public static Rectangle transformRectangle(AffineTransform affineTransform,
+ Rectangle sourceRectangle) {
+ if (affineTransform == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'transform' must not be null.");
+ }
+ if (sourceRectangle == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'sourceRectangle' must not be null.");
+ }
+ Rectangle result = new Rectangle(0, 0, 0, 0);
+ sourceRectangle = absoluteRectangle(sourceRectangle);
+ Point point = new Point(sourceRectangle.x, sourceRectangle.y);
+ point = transformPoint(affineTransform, point);
+ result.x = point.x;
+ result.y = point.y;
+ result.width = (int) (sourceRectangle.width * affineTransform
+ .getScaleX());
+ result.height = (int) (sourceRectangle.height * affineTransform
+ .getScaleY());
+ return result;
+ }
+
+ /**
+ * Apply the inverse of an affine transform to an SWT rectangle. The
+ * resulting SWT rectangle will have positive width and positive height.
+ *
+ * @param affineTransform
+ * The affine transform, not null
.
+ * @param sourceRectangle
+ * The SWT source rectangle, not null
.
+ * @return The SWT rectangle after transform with positive width and height,
+ * not null
.
+ */
+ public static Rectangle inverseTransformRectangle(
+ AffineTransform affineTransform, Rectangle sourceRectangle) {
+ if (affineTransform == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'transform' must not be null.");
+ }
+ if (sourceRectangle == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'sourceRectangle' must not be null.");
+ }
+ Rectangle result = new Rectangle(0, 0, 0, 0);
+ sourceRectangle = absoluteRectangle(sourceRectangle);
+ Point p1 = new Point(sourceRectangle.x, sourceRectangle.y);
+ p1 = inverseTransformPoint(affineTransform, p1);
+ result.x = p1.x;
+ result.y = p1.y;
+ result.width = (int) (sourceRectangle.width / affineTransform
+ .getScaleX());
+ result.height = (int) (sourceRectangle.height / affineTransform
+ .getScaleY());
+ return result;
+ }
+
+ /**
+ * Apply an affine transform to an SWT point.
+ *
+ * @param affineTransform
+ * The affine transform, not null
.
+ * @param sourcePoint
+ * The SWT source point, not null
.
+ * @return The SWT point after transform, not null
.
+ */
+ public static Point transformPoint(AffineTransform affineTransform,
+ Point sourcePoint) {
+ if (affineTransform == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'affineTransform' must not be null.");
+ }
+ if (sourcePoint == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'sourcePoint' must not be null.");
+ }
+ Point2D src = new Point2D.Float(sourcePoint.x, sourcePoint.y);
+ Point2D dest = affineTransform.transform(src, null);
+ Point result = new Point((int) Math.floor(dest.getX()), (int) Math
+ .floor(dest.getY()));
+ return result;
+ }
+
+ /**
+ * Apply the inverse of an affine transform to an SWT point.
+ *
+ * @param affineTransform
+ * The affine transform, not null
.
+ * @param sourcePoint
+ * The SWT source point, not null
.
+ * @return The SWT point after transform, not null
.
+ */
+ public static Point inverseTransformPoint(AffineTransform affineTransform,
+ Point sourcePoint) {
+
+ if (affineTransform == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'affineTransform' must not be null.");
+ }
+ if (sourcePoint == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'sourcePoint' must not be null.");
+ }
+ Point2D src = new Point2D.Float(sourcePoint.x, sourcePoint.y);
+
+ Point2D dest;
+ try {
+ dest = affineTransform.inverseTransform(src, null);
+ } catch (NoninvertibleTransformException ex) {
+ throw new RuntimeException("Invalid transformation", ex);
+ }
+ Point result = new Point((int) Math.floor(dest.getX()), (int) Math
+ .floor(dest.getY()));
+ return result;
+ }
+
+ /**
+ * Given arbitrary SWT rectangle, return a rectangle with upper-left start
+ * and positive width and height.
+ *
+ * @param sourceRectangle
+ * The SWT source rectangle, not null
.
+ * @return result The equivalent SWT rectangle with positive width and
+ * height, not null
.
+ */
+ private static Rectangle absoluteRectangle(Rectangle sourceRectangle) {
+ if (sourceRectangle == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'sourceRectangle' must not be null.");
+ }
+ Rectangle result = new Rectangle(0, 0, 0, 0);
+ if (sourceRectangle.width < 0) {
+ result.x = sourceRectangle.x + sourceRectangle.width + 1;
+ result.width = -sourceRectangle.width;
+ } else {
+ result.x = sourceRectangle.x;
+ result.width = sourceRectangle.width;
+ }
+ if (sourceRectangle.height < 0) {
+ result.y = sourceRectangle.y + sourceRectangle.height + 1;
+ result.height = -sourceRectangle.height;
+ } else {
+ result.y = sourceRectangle.y;
+ result.height = sourceRectangle.height;
+ }
+ return result;
+ }
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/gui/SourceFileView.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/gui/SourceFileView.java
new file mode 100644
index 00000000..490c3a7c
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/gui/SourceFileView.java
@@ -0,0 +1,147 @@
+/**
+ * Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.gui;
+
+import javax.swing.event.ChangeListener;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+
+import com.wudsn.ide.base.common.HexUtility;
+import com.wudsn.ide.base.gui.FilePathField;
+import com.wudsn.ide.base.gui.IntegerField;
+import com.wudsn.ide.base.gui.TextField;
+import com.wudsn.ide.gfx.Texts;
+
+public final class SourceFileView {
+
+ private static final int[] EMPTY_DEFAULT_VALUES = new int[] { 0, 65535 };
+
+ private final FilePathField filePathField;
+ private final TextField fileSizeField;
+ private final IntegerField fileOffsetField;
+ private final Label dummyLabel;
+
+ public SourceFileView(Composite parent, String labelText, int dialogMode) {
+ if (parent == null) {
+ throw new IllegalArgumentException("Parameter 'parent' must not be null.");
+ }
+ if (dialogMode != SWT.OPEN && dialogMode != SWT.SAVE) {
+ throw new IllegalArgumentException(
+ "Parameter 'dialogMode' must be 'SWT.OPEN' or 'SWT.SAVE'. Specified value is " + dialogMode + "-");
+ }
+
+ filePathField = new FilePathField(parent, labelText, dialogMode);
+
+ fileSizeField = new TextField(parent, Texts.FILE_SECTION_FIELD_SIZE_LABEL, SWT.READ_ONLY);
+
+ fileOffsetField = new IntegerField(parent, Texts.FILE_SECTION_FIELD_OFFSET_LABEL, EMPTY_DEFAULT_VALUES, true,
+ 4, SWT.NONE);
+
+ dummyLabel = new Label(parent, SWT.NONE);
+ }
+
+ public FilePathField getFilePathField() {
+ return filePathField;
+ }
+
+ public IntegerField getFileOffsetField() {
+ return fileOffsetField;
+ }
+
+ /**
+ * Sets the path prefix which will be stripped automatically if it is the
+ * prefix of the user input.
+ *
+ * @param filePathPrefix
+ * The file path prefix, may be empty, not null
.
+ */
+ public void setFilePathPrefix(IPath filePathPrefix) {
+ if (filePathPrefix == null) {
+ throw new IllegalArgumentException("Parameter 'filePathPrefix' must not be null.");
+ }
+ filePathField.setFilePathPrefix(filePathPrefix);
+ }
+
+ public void setFilePath(String filePath) {
+ filePathField.setValue(filePath);
+ }
+
+ public String getFilePath() {
+ return filePathField.getValue();
+ }
+
+ public void setFileBytes(byte[] bytes) {
+ if (bytes == null) {
+ fileSizeField.setValue(Texts.FILE_SECTION_FIELD_SIZE_NO_DATA);
+ fileOffsetField.setDefaultValues(EMPTY_DEFAULT_VALUES);
+ } else {
+ fileSizeField.setValue(HexUtility.getLongValueHexString(bytes.length));
+
+ int step = (bytes.length + 15) / 16;
+ int[] defaultValues = new int[16];
+
+ for (int i = 0; i < 16; i++) {
+ defaultValues[i] = i * step;
+ }
+
+ fileOffsetField.setDefaultValues(defaultValues);
+ }
+ }
+
+ public void setFileOffset(int fileOffset) {
+ fileOffsetField.setValue(fileOffset);
+ }
+
+ public int getFileOffset() {
+ return fileOffsetField.getValue();
+ }
+
+ public void setVisible(boolean visible) {
+ filePathField.setVisible(visible);
+ fileSizeField.setVisible(visible);
+ fileOffsetField.setVisible(visible);
+ dummyLabel.setVisible(visible);
+ }
+
+ public void setEnabled(boolean enabled) {
+ filePathField.setEnabled(enabled);
+ fileSizeField.setEnabled(enabled);
+ fileOffsetField.setEnabled(enabled);
+ dummyLabel.setEnabled(enabled);
+ }
+
+ /**
+ * Adds a change listener.
+ *
+ * @param changeListener
+ * The change listener , not null
.
+ */
+ public void addChangeListener(ChangeListener changeListener) {
+ if (changeListener == null) {
+ throw new IllegalArgumentException("Parameter 'changeListener' must not be null.");
+ }
+ filePathField.addChangeListener(changeListener);
+ fileOffsetField.addChangeListener(changeListener);
+
+ }
+}
\ No newline at end of file
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/gui/TargetFileView.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/gui/TargetFileView.java
new file mode 100644
index 00000000..a0c93466
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/gui/TargetFileView.java
@@ -0,0 +1,119 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+package com.wudsn.ide.gfx.gui;
+
+import javax.swing.event.ChangeListener;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+
+import com.wudsn.ide.base.common.HexUtility;
+import com.wudsn.ide.base.gui.FilePathField;
+import com.wudsn.ide.base.gui.TextField;
+import com.wudsn.ide.gfx.Texts;
+
+public final class TargetFileView {
+
+ private final FilePathField filePathField;
+ private final TextField fileSizeField;
+
+ public TargetFileView(Composite parent, String labelText, int dialogMode) {
+ if (parent == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'parent' must not be null.");
+ }
+ if (dialogMode != SWT.OPEN && dialogMode != SWT.SAVE) {
+ throw new IllegalArgumentException(
+ "Parameter 'dialogMode' must be 'SWT.OPEN' or 'SWT.SAVE'. Specified value is "
+ + dialogMode + "-");
+ }
+
+ filePathField = new FilePathField(parent, labelText, dialogMode);
+
+ fileSizeField = new TextField(parent,
+ Texts.FILE_SECTION_FIELD_SIZE_LABEL, SWT.READ_ONLY);
+ }
+
+ public FilePathField getFilePathField() {
+ return filePathField;
+ }
+
+ /**
+ * Sets the path prefix which will be stripped automatically if it is the
+ * prefix of the user input.
+ *
+ * @param filePathPrefix
+ * The file path prefix, may be empty, not null
.
+ */
+ public void setFilePathPrefix(IPath filePathPrefix) {
+ if (filePathPrefix == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'filePathPrefix' must not be null.");
+ }
+ filePathField.setFilePathPrefix(filePathPrefix);
+ }
+
+ public void setFilePath(String filePath) {
+ filePathField.setValue(filePath);
+ }
+
+ public String getFilePath() {
+ return filePathField.getValue();
+ }
+
+ public void setFileBytes(byte[] bytes) {
+ if (bytes == null) {
+ fileSizeField.setValue(Texts.FILE_SECTION_FIELD_SIZE_NO_DATA);
+ } else {
+ fileSizeField.setValue(HexUtility
+ .getLongValueHexString(bytes.length));
+
+ int step = (bytes.length + 15) / 16;
+ int[] defaultValues = new int[16];
+
+ for (int i = 0; i < 16; i++) {
+ defaultValues[i] = i * step;
+ }
+ }
+ }
+
+ public void setVisible(boolean visible) {
+ filePathField.setVisible(visible);
+ fileSizeField.setVisible(visible);
+ }
+
+ public void setEnabled(boolean enabled) {
+ filePathField.setEnabled(enabled);
+ fileSizeField.setEnabled(enabled);
+ }
+
+ /**
+ * Adds a change listener.
+ *
+ * @param changeListener
+ * The change listener , not null
.
+ */
+ public void addChangeListener(ChangeListener changeListener) {
+ if (changeListener == null) {
+ throw new IllegalArgumentException("Parameter 'changeListener' must not be null.");
+ }
+ filePathField.addChangeListener(changeListener);
+ }
+}
\ No newline at end of file
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/model/Aspect.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/model/Aspect.java
new file mode 100644
index 00000000..bc387ff4
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/model/Aspect.java
@@ -0,0 +1,82 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+package com.wudsn.ide.gfx.model;
+
+public final class Aspect {
+
+ private int factorX;
+ private int factorY;
+
+ public Aspect(int factorX, int factorY) {
+ this.factorX = factorX;
+ this.factorY = factorY;
+ }
+
+ public int getFactorX() {
+ return factorX;
+ }
+
+ public int getFactorY() {
+ return factorY;
+ }
+
+ public int getValidFactorX() {
+ if (isValid()) {
+ return factorX;
+ }
+ return 1;
+ }
+
+ public int getValidFactorY() {
+ if (isValid()) {
+ return factorY;
+ }
+ return 1;
+ }
+
+ public boolean isValid() {
+ return factorX > 0 && factorX < 32 && factorY > 0 && factorY < 32;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+
+ if (obj instanceof Aspect) {
+ Aspect aspect;
+ aspect = (Aspect) obj;
+ if (aspect.getFactorX() == factorX
+ && aspect.getFactorY() == factorY) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+
+ return factorX+17*factorY;
+ }
+
+ @Override
+ public String toString() {
+ return factorX + "x" + factorY;
+ }
+
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/model/AspectUtility.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/model/AspectUtility.java
new file mode 100644
index 00000000..0716ca8f
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/model/AspectUtility.java
@@ -0,0 +1,93 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+package com.wudsn.ide.gfx.model;
+
+import com.wudsn.ide.base.common.StringUtility;
+
+public final class AspectUtility {
+
+ /**
+ * Creation is private.
+ */
+ private AspectUtility() {
+ }
+
+ /**
+ * Gets the language independent string representation of an aspect.
+ *
+ * @param value
+ * The aspect or nullnull
.
+ */
+ public static String toString(Aspect value) {
+ String result;
+ if (value == null) {
+ result = "";
+ } else {
+ result = value.getFactorX() + "x" + value.getFactorY();
+ }
+ return result;
+ }
+
+ /**
+ * Gets the aspect for a language independent string representation.
+ *
+ * @param value
+ * The language independent string representation, may be empty,
+ * not null
.
+ * @return The XYFactor or null
in case the value was empty.
+ */
+ public static Aspect fromString(String value) {
+ if (value == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'value' must not be null.");
+ }
+
+ Aspect result;
+ int factorX;
+ int factorY;
+
+ if (StringUtility.isEmpty(value)) {
+ result = null;
+ } else {
+ int index = value.indexOf('x');
+ if (index > 0) {
+ String intValue = value.substring(0, index);
+ try {
+ factorX = Integer.parseInt(intValue);
+ } catch (NumberFormatException ex) {
+ factorX = -1;
+ }
+ intValue = value.substring(index + 1, value.length());
+ try {
+ factorY = Integer.parseInt(intValue);
+ } catch (NumberFormatException ex) {
+ factorY = -1;
+ }
+ } else {
+ factorX = -1;
+ factorY = -1;
+ }
+ result = new Aspect(factorX, factorY);
+ }
+ return result;
+ }
+
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/model/ConverterDirection.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/model/ConverterDirection.java
new file mode 100644
index 00000000..d060cd1d
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/model/ConverterDirection.java
@@ -0,0 +1,24 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.model;
+
+public enum ConverterDirection {
+ FILES_TO_IMAGE, IMAGE_TO_FILES
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/model/ConverterMode.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/model/ConverterMode.java
new file mode 100644
index 00000000..347dc690
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/model/ConverterMode.java
@@ -0,0 +1,24 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.model;
+
+public enum ConverterMode {
+ NONE, RAW_FILE, RAW_IMAGE, CNV
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/model/GraphicsPropertiesSerializer.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/model/GraphicsPropertiesSerializer.java
new file mode 100644
index 00000000..5abf5e05
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/model/GraphicsPropertiesSerializer.java
@@ -0,0 +1,151 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.model;
+
+import org.eclipse.swt.graphics.RGB;
+
+import com.wudsn.ide.base.common.PropertiesSerializer;
+
+public final class GraphicsPropertiesSerializer extends PropertiesSerializer {
+
+ /**
+ * Creation is public.
+ */
+ public GraphicsPropertiesSerializer() {
+
+
+ }
+
+ public final RGB readRGB(String key, RGB defaultValue) {
+
+ if (key == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'key' must not be null.");
+ }
+ if (defaultValue == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'defaultValue' must not be null.");
+ }
+
+ RGB result;
+
+ int red = readInteger(key + ".red", 0);
+ int green = readInteger(key + ".green", 0);
+ int blue = readInteger(key + ".blue", 0);
+
+ result = new RGB(red, green, blue);
+
+ return result;
+ }
+
+ public final void writeRGB(String key, RGB value) {
+
+ if (key == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'key' must not be null.");
+ }
+ if (value == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'value' must not be null.");
+ }
+
+ writeInteger(key + ".red", value.red);
+ writeInteger(key + ".green", value.green);
+ writeInteger(key + ".blue", value.blue);
+ }
+
+ public final Aspect readXYFactor(String key, Aspect defaultValue) {
+
+ if (key == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'key' must not be null.");
+ }
+ if (defaultValue == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'defaultValue' must not be null.");
+ }
+ Aspect result;
+
+ int factorX = readInteger(key + ".factorX", 1);
+ int factorY = readInteger(key + ".factorY", 1);
+
+ result = new Aspect(factorX, factorY);
+ return result;
+ }
+
+ public final void writeAspect(String key, Aspect value) {
+
+ if (key == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'key' must not be null.");
+ }
+ if (value == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'value' must not be null.");
+ }
+ setProperty(key + ".factorX", String.valueOf(value.getFactorX()));
+ setProperty(key + ".factorY", String.valueOf(value.getFactorY()));
+ }
+
+
+ public final RGB[] readRGBArray(String key, RGB[] defaultValue) {
+ if (key == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'key' must not be null.");
+ }
+ if (defaultValue == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'defaultValue' must not be null.");
+ }
+ RGB[] result;
+
+ if (properties.containsKey(key)) {
+ int length = readInteger(key, 0);
+ result = new RGB[length];
+ String prefix = key + ".";
+ RGB black = new RGB(0, 0, 0);
+ for (int i = 0; i < length; i++) {
+ String valueKey = prefix + i;
+ result[i] = readRGB(valueKey, black);
+ }
+ } else {
+ result = defaultValue;
+ }
+ return result;
+
+ }
+
+ public final void writeRGBArray(String key, RGB[] value) {
+ if (key == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'key' must not be null.");
+ }
+ if (value == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'value' must not be null.");
+ }
+ writeInteger(key, value.length);
+ String prefix = key + ".";
+ for (int i = 0; i < value.length; i++) {
+ String valueKey = prefix + i;
+ writeRGB(valueKey, value[i]);
+ }
+ }
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/model/Palette.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/model/Palette.java
new file mode 100644
index 00000000..af89456e
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/model/Palette.java
@@ -0,0 +1,24 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.model;
+
+public enum Palette {
+ TRUE_COLOR, HIRES_1, HIRES_2, HIRES_MANUAL, MULTI_1, MULTI_2, MULTI_3, MULTI_4, MULTI_5, MULTI_6, MULTI_MANUAL, GTIA_GREY_1, GTIA_GREY_2, GTIA_GREY_MANUAL
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/model/PaletteType.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/model/PaletteType.java
new file mode 100644
index 00000000..980826bb
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/model/PaletteType.java
@@ -0,0 +1,25 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.model;
+
+
+public enum PaletteType {
+ TRUE_COLOR, ATARI_DEFAULT, ATARI_REAL, ATARI_XFORMER, C64_NORMAL, C64_PAL,
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/model/PaletteUtility.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/model/PaletteUtility.java
new file mode 100644
index 00000000..6238642c
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/model/PaletteUtility.java
@@ -0,0 +1,156 @@
+/**
+* Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.model;
+
+import org.eclipse.swt.graphics.RGB;
+
+import com.wudsn.ide.base.common.HexUtility;
+
+public final class PaletteUtility {
+
+ public static final RGB BLACK = new RGB(0, 0, 0);
+ public static final RGB GREY1 = new RGB(85, 85, 85);
+ public static final RGB GREY2 = new RGB(170, 170, 170);
+ public static final RGB WHITE = new RGB(255, 255, 255);
+
+ /**
+ * Creation is private.
+ */
+ private PaletteUtility() {
+ }
+
+ public static RGB[] getPaletteColors(PaletteType paletteType,
+ Palette palette, RGB[] manualPaletteColors) {
+ if (paletteType == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'paletteType' must not be null.");
+ }
+ if (palette == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'palette' must not be null.");
+ }
+
+ RGB[] result;
+
+ switch (palette) {
+ case TRUE_COLOR:
+ result = new RGB[0];
+ break;
+
+ case HIRES_1:
+ result = new RGB[] { BLACK, WHITE };
+ break;
+ case HIRES_2:
+ result = new RGB[] { WHITE, BLACK };
+ break;
+
+ case HIRES_MANUAL:
+ result = getPaletteColorsCopy(manualPaletteColors, 2);
+ break;
+
+ case MULTI_1:
+ result = new RGB[] { BLACK, GREY1, GREY2, WHITE };
+ break;
+ case MULTI_2:
+ result = new RGB[] { BLACK, GREY1, WHITE, GREY2 };
+ break;
+ case MULTI_3:
+ result = new RGB[] { BLACK, GREY2, GREY1, WHITE };
+ break;
+ case MULTI_4:
+ result = new RGB[] { BLACK, GREY2, WHITE, GREY1 };
+ break;
+ case MULTI_5:
+ result = new RGB[] { BLACK, WHITE, GREY1, GREY2 };
+ break;
+ case MULTI_6:
+ result = new RGB[] { BLACK, WHITE, GREY2, GREY1 };
+ break;
+ case MULTI_MANUAL:
+ result = getPaletteColorsCopy(manualPaletteColors,
+ manualPaletteColors.length);
+ break;
+
+ case GTIA_GREY_1:
+ result = new RGB[16];
+ for (int i = 0; i < 16; i++) {
+ int c = 0x11 * i;
+ result[i] = new RGB(c, c, c);
+ }
+ break;
+ case GTIA_GREY_2:
+ result = new RGB[16];
+ for (int i = 0; i < 16; i++) {
+ int c = 255 - 0x11 * i;
+ result[i] = new RGB(c, c, c);
+ }
+ break;
+ case GTIA_GREY_MANUAL:
+ result = getPaletteColorsCopy(manualPaletteColors, 16);
+ break;
+
+ default:
+ throw new IllegalStateException("Unknown palette '" + palette
+ + "'.");
+ }
+ return result;
+ }
+
+ /**
+ * Gets an array of colors with the given size based on the current palette
+ * colors.
+ *
+ * @param paletteColors
+ * The original palette colors or null
.
+ * @param size
+ * The size of the palette, a positive integer.
+ * @return The new array with palette colors of the given size.
+ *
+ */
+ private static RGB[] getPaletteColorsCopy(RGB[] paletteColors, int size) {
+
+ if (size < 1) {
+ throw new IllegalArgumentException(
+ "Parameter 'size' must be positive. Specified value is "
+ + size + ".");
+ }
+
+ RGB[] result;
+ result = new RGB[size];
+ for (int i = 0; i < size; i++) {
+ if (paletteColors != null && i < paletteColors.length) {
+ result[i] = paletteColors[i];
+ } else {
+ result[i] = new RGB(0, 0, 0);
+ }
+ }
+ return result;
+ }
+
+ public static String getPaletteColorText(RGB rgb) {
+ if (rgb == null) {
+ throw new IllegalArgumentException(
+ "Parameter 'rgb' must not be null.");
+ }
+ return HexUtility.getByteValueHexString(rgb.red)
+ + HexUtility.getByteValueHexString(rgb.green)
+ + HexUtility.getByteValueHexString(rgb.blue);
+ }
+}
diff --git a/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/model/RBGUtility.java b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/model/RBGUtility.java
new file mode 100644
index 00000000..dc300180
--- /dev/null
+++ b/com.wudsn.ide.gfx/src/com/wudsn/ide/gfx/model/RBGUtility.java
@@ -0,0 +1,63 @@
+/**
+ * Copyright (C) 2009 - 2014 Peter Dell
+ *
+ * This file is part of WUDSN IDE.
+ *
+ * WUDSN IDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * WUDSN IDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WUDSN IDE. If not, see .
+ */
+
+package com.wudsn.ide.gfx.model;
+
+import org.eclipse.swt.graphics.RGB;
+
+public final class RBGUtility {
+
+ /**
+ * Creation is private.
+ */
+ private RBGUtility() {
+ }
+
+ /**
+ * Combines to RBG color values to a mixed color value.
+ *
+ * @param color1
+ * The first color, not null
.
+ * @param color2
+ * The second color, not null
.
+ * @return The mixed color, not null
.
+ */
+ public static RGB combineRGB(RGB color1, RGB color2) {
+ return new RGB((color1.red + color2.red) >>> 1, (color1.green + color2.green) >>> 1,
+ (color1.blue + color2.blue) >>> 1);
+ }
+
+ /**
+ * Combines to RBG color values to a mixed color value.
+ *
+ * @param color1
+ * The first color.
+ * @param color2
+ * The second color.
+ * @return The mixed color.
+ */
+ public static int combineRGBColor(int color1, int color2) {
+ int r = (((color1 >>> 16) & 0xff) + ((color2 >>> 16) & 0xff)) >>> 1;
+ int g = (((color1 >>> 8) & 0xff) + ((color2 >>> 8) & 0xff)) >>> 1;
+ int b = (((color1 >>> 0) & 0xff) + ((color2 >>> 0) & 0xff)) >>> 1;
+ return r << 16 | g << 8 | b;
+
+ }
+
+}