From ba891e380f06305f4504def0f97ca4d6a3fdfa57 Mon Sep 17 00:00:00 2001 From: Brendan Robert Date: Tue, 10 Sep 2013 21:38:25 -0500 Subject: [PATCH] Big changes to image editors to support resizing. Also fixed that annoying rectangle drawing bug! --- .../badvision/outlaweditor/ImageEditor.java | 12 ++ .../badvision/outlaweditor/ImageRenderer.java | 11 +- .../org/badvision/outlaweditor/MapEditor.java | 4 +- .../org/badvision/outlaweditor/Platform.java | 12 +- .../outlaweditor/apple/AppleImageEditor.java | 136 ++++++++++++------ .../apple/AppleImageRenderer.java | 63 ++++---- .../outlaweditor/apple/FillPattern.java | 4 +- .../apple/FloydSteinbergDither.java | 36 ++--- .../apple/dhgr/AppleDHGRImageEditor.java | 26 +++- .../apple/dhgr/AppleDHGRImageRenderer.java | 35 +++-- 10 files changed, 210 insertions(+), 129 deletions(-) diff --git a/OutlawEditor/src/main/java/org/badvision/outlaweditor/ImageEditor.java b/OutlawEditor/src/main/java/org/badvision/outlaweditor/ImageEditor.java index 508044af..c35d695d 100644 --- a/OutlawEditor/src/main/java/org/badvision/outlaweditor/ImageEditor.java +++ b/OutlawEditor/src/main/java/org/badvision/outlaweditor/ImageEditor.java @@ -6,6 +6,7 @@ package org.badvision.outlaweditor; import javafx.scene.control.Menu; import org.badvision.outlaweditor.data.xml.Image; +import org.badvision.outlaweditor.data.xml.PlatformData; /** * @@ -29,4 +30,15 @@ public abstract class ImageEditor extends Editor { public abstract void zoomOut(); public abstract void exportImage(); + + public abstract void resize(int newWidth, int newHeight); + + public PlatformData getPlatformData(Platform p) { + for (PlatformData data : getEntity().getDisplayData()) { + if (data.getPlatform().equalsIgnoreCase(p.name())) { + return data; + } + } + return null; + } } diff --git a/OutlawEditor/src/main/java/org/badvision/outlaweditor/ImageRenderer.java b/OutlawEditor/src/main/java/org/badvision/outlaweditor/ImageRenderer.java index 1a7f932f..27ac2501 100644 --- a/OutlawEditor/src/main/java/org/badvision/outlaweditor/ImageRenderer.java +++ b/OutlawEditor/src/main/java/org/badvision/outlaweditor/ImageRenderer.java @@ -15,13 +15,12 @@ import org.badvision.outlaweditor.data.xml.Map; */ public abstract class ImageRenderer { - public abstract WritableImage renderImage(WritableImage img, byte[] rawImage); + public abstract WritableImage renderImage(WritableImage img, byte[] rawImage, int width, int height); - public abstract byte[] createImageBuffer(); + public abstract byte[] createImageBuffer(int width, int height); - public abstract WritableImage renderPreview(TileMap map, int startX, int startY); + public abstract byte[] renderPreview(TileMap map, int startX, int startY, int width, int height); - public abstract WritableImage renderScanline(WritableImage currentImage, int y, byte[] imageData); - - public abstract byte[] generatePreview(TileMap map, int x1, int y1); + public abstract WritableImage renderScanline(WritableImage currentImage, int y, int width, byte[] imageData); + } diff --git a/OutlawEditor/src/main/java/org/badvision/outlaweditor/MapEditor.java b/OutlawEditor/src/main/java/org/badvision/outlaweditor/MapEditor.java index 8f43cc3d..5f2f6d3f 100644 --- a/OutlawEditor/src/main/java/org/badvision/outlaweditor/MapEditor.java +++ b/OutlawEditor/src/main/java/org/badvision/outlaweditor/MapEditor.java @@ -256,7 +256,7 @@ public class MapEditor extends Editor implements EventH } public void showPreview() { - WritableImage img = currentPlatform.imageRenderer.renderPreview(currentMap, posX, posY); + WritableImage img = currentPlatform.imageRenderer.renderPreview(currentMap, posX, posY, currentPlatform.maxImageWidth, currentPlatform.maxImageHeight); Stage stage = new Stage(); stage.setTitle("Preview"); ImageView imgView = new ImageView(img); @@ -267,7 +267,7 @@ public class MapEditor extends Editor implements EventH @Override public void copy() { - WritableImage img = currentPlatform.imageRenderer.renderPreview(currentMap, posX, posY); + WritableImage img = currentPlatform.imageRenderer.renderPreview(currentMap, posX, posY, currentPlatform.maxImageWidth, currentPlatform.maxImageHeight); java.util.Map clip = new HashMap<>(); clip.put(DataFormat.IMAGE, img); clip.put(DataFormat.PLAIN_TEXT, "selection/map/"+Application.gameData.getMap().indexOf(getEntity())+"/"+getSelectionInfo()); diff --git a/OutlawEditor/src/main/java/org/badvision/outlaweditor/Platform.java b/OutlawEditor/src/main/java/org/badvision/outlaweditor/Platform.java index 9ac454f2..9e4faa43 100644 --- a/OutlawEditor/src/main/java/org/badvision/outlaweditor/Platform.java +++ b/OutlawEditor/src/main/java/org/badvision/outlaweditor/Platform.java @@ -14,9 +14,9 @@ import org.badvision.outlaweditor.apple.dhgr.AppleDHGRTileRenderer; * @author brobert */ public enum Platform { - AppleII(AppleTileEditor.class, AppleImageEditor.class, new AppleTileRenderer(), new AppleImageRenderer(),2, 16), - AppleII_DHGR(AppleDHGRTileEditor.class, AppleDHGRImageEditor.class, new AppleDHGRTileRenderer(), new AppleDHGRImageRenderer(),4, 16), - C64(null, null, null, null, 16, 16); + AppleII(AppleTileEditor.class, AppleImageEditor.class, new AppleTileRenderer(), new AppleImageRenderer(),2, 16, 40, 192), + AppleII_DHGR(AppleDHGRTileEditor.class, AppleDHGRImageEditor.class, new AppleDHGRTileRenderer(), new AppleDHGRImageRenderer(),4, 16, 80, 192), + C64(null, null, null, null, 16, 16, 40, 200); public Class tileEditor; public Class imageEditor; @@ -24,13 +24,17 @@ public enum Platform { public ImageRenderer imageRenderer; public int dataWidth; public int dataHeight; + public int maxImageWidth; + public int maxImageHeight; - Platform(Class ed, Class imged, TileRenderer ren, ImageRenderer img, int w, int h) { + Platform(Class ed, Class imged, TileRenderer ren, ImageRenderer img, int w, int h, int maxW, int maxH) { tileEditor = ed; imageEditor = imged; tileRenderer = ren; imageRenderer = img; dataWidth = w; dataHeight = h; + maxImageWidth = maxW; + maxImageHeight = maxH; } } diff --git a/OutlawEditor/src/main/java/org/badvision/outlaweditor/apple/AppleImageEditor.java b/OutlawEditor/src/main/java/org/badvision/outlaweditor/apple/AppleImageEditor.java index 1067e2fd..42503c5f 100644 --- a/OutlawEditor/src/main/java/org/badvision/outlaweditor/apple/AppleImageEditor.java +++ b/OutlawEditor/src/main/java/org/badvision/outlaweditor/apple/AppleImageEditor.java @@ -1,11 +1,6 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ package org.badvision.outlaweditor.apple; import java.io.File; -import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.HashMap; @@ -27,6 +22,7 @@ import org.badvision.outlaweditor.Application; import org.badvision.outlaweditor.FileUtils; import org.badvision.outlaweditor.ImageEditor; import org.badvision.outlaweditor.Platform; +import org.badvision.outlaweditor.UIAction; import org.badvision.outlaweditor.data.DataObserver; import org.badvision.outlaweditor.data.TileMap; import org.badvision.outlaweditor.data.xml.Image; @@ -60,6 +56,7 @@ public class AppleImageEditor extends ImageEditor implements EventHandler 0) ? b1 | 0x0100 : b1][b2]; extraHalfBit = (i & 0x10000000) != 0; scanline[x / 2] = i & 0xfffffff; } - renderScanline(img.getPixelWriter(), y * 2, scanline, true, false); - renderScanline(img.getPixelWriter(), y * 2 + 1, scanline, true, false); + renderScanline(img.getPixelWriter(), y * 2, scanline, true, false, width); + renderScanline(img.getPixelWriter(), y * 2 + 1, scanline, true, false, width); return img; } - public static void renderScanline(PixelWriter img, int y, int[] scanline, boolean hiresMode, boolean mixedMode, boolean... useColor) { + public static void renderScanline(PixelWriter img, int y, int[] scanline, boolean hiresMode, boolean mixedMode, int width, boolean... useColor) { + int scanlineLength = Math.min(width/2, scanline.length); int[][] activePalette = AppleTileRenderer.useSolidPalette ? solidPalette : textPalette; int byteCounter = 0; int x = 0; - for (int s = 0; s < scanline.length; s++) { + for (int s = 0; s < scanlineLength; s++) { int add = 0; int bits = 0; if (hiresMode) { diff --git a/OutlawEditor/src/main/java/org/badvision/outlaweditor/apple/FillPattern.java b/OutlawEditor/src/main/java/org/badvision/outlaweditor/apple/FillPattern.java index 121ac26c..12f19d6e 100644 --- a/OutlawEditor/src/main/java/org/badvision/outlaweditor/apple/FillPattern.java +++ b/OutlawEditor/src/main/java/org/badvision/outlaweditor/apple/FillPattern.java @@ -231,8 +231,8 @@ public enum FillPattern { b2 = pattern[y * 4 + 3] & 255; i = hgrToDhgr[(extraHalfBit) ? b1 | 0x0100 : b1][b2]; scan[1] = i & 0xfffffff; - AppleImageRenderer.renderScanline(img.getPixelWriter(), y * 2, scan, true, false); - AppleImageRenderer.renderScanline(img.getPixelWriter(), y * 2 + 1, scan, true, false); + AppleImageRenderer.renderScanline(img.getPixelWriter(), y * 2, scan, true, false, 4); + AppleImageRenderer.renderScanline(img.getPixelWriter(), y * 2 + 1, scan, true, false, 4); } return img; } diff --git a/OutlawEditor/src/main/java/org/badvision/outlaweditor/apple/FloydSteinbergDither.java b/OutlawEditor/src/main/java/org/badvision/outlaweditor/apple/FloydSteinbergDither.java index 161f9463..d53828f6 100644 --- a/OutlawEditor/src/main/java/org/badvision/outlaweditor/apple/FloydSteinbergDither.java +++ b/OutlawEditor/src/main/java/org/badvision/outlaweditor/apple/FloydSteinbergDither.java @@ -70,12 +70,15 @@ public class FloydSteinbergDither { final int startY, final int width, final int height, + final byte[] screen, + final int bufferWidth, final DitherCallback callback) { final AppleImageRenderer renderer = (AppleImageRenderer) platform.imageRenderer; final int errorWindow = 6; final int overlap = 2; final int pixelShift = -2; - final WritableImage source = getScaledImage(img, 560, 192); + int byteRenderWidth = platform == org.badvision.outlaweditor.Platform.AppleII_DHGR ? 7 : 14; + final WritableImage source = getScaledImage(img, width * byteRenderWidth, height); AnchorPane pane = new AnchorPane(); Scene s = new Scene(pane); final ImageView previewImage = new ImageView(source); @@ -98,7 +101,6 @@ public class FloydSteinbergDither { public void run() { final WritableImage keepScaled = new WritableImage(source.getPixelReader(), 560, 192); WritableImage tmpScaled = new WritableImage(source.getPixelReader(), 560, 192); - final byte[] screen = renderer.createImageBuffer(); for (int i = 0; i < screen.length; i++) { screen[i] = (byte) Math.max(255, Math.random() * 256.0); } @@ -129,8 +131,8 @@ public class FloydSteinbergDither { } }); System.out.println("Image type: " + platform.name()); - for (int y = startY; y < height + startY; y++) { - for (int x = startX; x < startX + width; x += 2) { + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x += 2) { Thread.yield(); switch (platform) { case AppleII: @@ -153,15 +155,15 @@ public class FloydSteinbergDither { } void hiresDither(final byte[] screen, int y, int x, int[] scanline, List pixels, WritableImage tmpScaled, int pass, final WritableImage keepScaled) { - int bb1 = screen[y * 40 + x] & 255; - int bb2 = screen[y * 40 + x + 1] & 255; + int bb1 = screen[(y+startY) * bufferWidth + startX + x] & 255; + int bb2 = screen[(y+startY) * bufferWidth + startX + x + 1] & 255; int next = bb2 & 127; // Preserve hi-bit so last pixel stays solid, it is a very minor detail int prev = 0; - if (x > 0) { - prev = screen[y * 40 + x - 1] & 255; + if ((x+startX) > 0) { + prev = screen[(y+startY) * bufferWidth + startX + x - 1] & 255; } - if (x < 38) { - next = screen[y * 40 + x + 2] & 255; + if ((x+startX) < 38) { + next = screen[(y+startY) * bufferWidth + startX + x + 2] & 255; } // First byte, compared with a sliding window encompassing the previous byte, if any. int leastError = Integer.MAX_VALUE; @@ -265,8 +267,8 @@ public class FloydSteinbergDither { tmpScaled.getPixelWriter().setPixels(0, y, 560, (y < 191) ? 2 : 1, keepScaled.getPixelReader(), 0, y); } } - screen[y * 40 + x] = (byte) bb1; - screen[y * 40 + x + 1] = (byte) bb2; + screen[(y+startY) * bufferWidth + startX + x] = (byte) bb1; + screen[(y+startY) * bufferWidth + startX + x + 1] = (byte) bb2; } void doubleHiresDither(final byte[] screen, int y, int x, int[] scanline, List pixels, WritableImage tmpScaled, int pass, final WritableImage keepScaled) { @@ -339,10 +341,10 @@ public class FloydSteinbergDither { // } else { // tmpScaled.getPixelWriter().setPixels(0, y, 560, (y < 191) ? 2 : 1, keepScaled.getPixelReader(), 0, y); } - screen[y * 80 + x] = (byte) bytes[0]; - screen[y * 80 + x + 1] = (byte) bytes[1]; - screen[y * 80 + x + 2] = (byte) bytes[2]; - screen[y * 80 + x + 3] = (byte) bytes[3]; + screen[(y+startY) * bufferWidth + startX + x] = (byte) bytes[0]; + screen[(y+startY) * bufferWidth + startX + x + 1] = (byte) bytes[1]; + screen[(y+startY) * bufferWidth + startX + x + 2] = (byte) bytes[2]; + screen[(y+startY) * bufferWidth + startX + x + 3] = (byte) bytes[3]; } }); t.start(); @@ -411,7 +413,7 @@ public class FloydSteinbergDither { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } }; - AppleImageRenderer.renderScanline(fakeWriter, 0, scanline, true, false); + AppleImageRenderer.renderScanline(fakeWriter, 0, scanline, true, false, 20); double max = 0; double min = Double.MAX_VALUE; double total = 0; diff --git a/OutlawEditor/src/main/java/org/badvision/outlaweditor/apple/dhgr/AppleDHGRImageEditor.java b/OutlawEditor/src/main/java/org/badvision/outlaweditor/apple/dhgr/AppleDHGRImageEditor.java index e6deaf34..38765817 100644 --- a/OutlawEditor/src/main/java/org/badvision/outlaweditor/apple/dhgr/AppleDHGRImageEditor.java +++ b/OutlawEditor/src/main/java/org/badvision/outlaweditor/apple/dhgr/AppleDHGRImageEditor.java @@ -10,7 +10,6 @@ import javafx.scene.control.Menu; import javafx.scene.input.MouseEvent; import org.badvision.outlaweditor.Platform; import org.badvision.outlaweditor.data.DataObserver; -import org.badvision.outlaweditor.data.xml.PlatformData; /** * @@ -49,11 +48,28 @@ public class AppleDHGRImageEditor extends AppleImageEditor implements EventHandl @Override public void redrawScanline(int y) { - currentImage = Platform.AppleII_DHGR.imageRenderer.renderScanline(currentImage, y, getImageData()); + currentImage = Platform.AppleII_DHGR.imageRenderer.renderScanline(currentImage, y, getWidth(), getImageData()); } - + + /** + * This takes the current image and dithers it to match the new image dimensions + * Most likely it will result in a really bad looking resized copy + * but in some cases might look okay + * @param newWidth + * @param newHeight + */ @Override - public int getWidth() { - return 80; + public void rescale(int newWidth, int newHeight) { + } + + /** + * Crops the image (if necessary) or resizes the image leaving the extra space + * blank (black) + * @param newWidth + * @param newHeight + */ + @Override + public void crop(int newWidth, int newHeight) { + } } \ No newline at end of file diff --git a/OutlawEditor/src/main/java/org/badvision/outlaweditor/apple/dhgr/AppleDHGRImageRenderer.java b/OutlawEditor/src/main/java/org/badvision/outlaweditor/apple/dhgr/AppleDHGRImageRenderer.java index 8d2e5ca5..b9e89a88 100644 --- a/OutlawEditor/src/main/java/org/badvision/outlaweditor/apple/dhgr/AppleDHGRImageRenderer.java +++ b/OutlawEditor/src/main/java/org/badvision/outlaweditor/apple/dhgr/AppleDHGRImageRenderer.java @@ -23,17 +23,14 @@ public class AppleDHGRImageRenderer extends AppleImageRenderer { // If mixed-mode is used then useColor needs to be an 80-boolean array indicating which bytes are supposed to be BW @Override - public byte[] createImageBuffer() { - return new byte[80 * 192]; - } - - @Override - public WritableImage renderPreview(TileMap map, int startX, int startY) { - byte[] buffer = createImageBuffer(); + public WritableImage renderPreview(TileMap map, int startX, int startY, int width, int height) { + byte[] buffer = createImageBuffer(width, height); int pos = 0; - for (int y = 0; y < 12; y++) { + int numRows = height / 16; + int numCols = width / 4; + for (int y = 0; y < numRows; y++) { for (int yy = 0; yy < 16; yy++) { - for (int x = 0; x < 20; x++) { + for (int x = 0; x < numCols; x++) { Tile t = map.get(x + startX, y + startY); if (t == null) { buffer[pos++] = 0; @@ -50,7 +47,7 @@ public class AppleDHGRImageRenderer extends AppleImageRenderer { } } } - return renderImage(null, buffer); + return renderImage(null, buffer, width, height); } // @Override @@ -65,21 +62,21 @@ public class AppleDHGRImageRenderer extends AppleImageRenderer { // } @Override - public WritableImage renderScanline(WritableImage img, int y, byte[] rawImage) { + public WritableImage renderScanline(WritableImage img, int y, int width, byte[] rawImage) { if (y < 0) return img; - int[] scanline = new int[20]; - for (int x = 0; x < 80; x += 4) { - int scan = rawImage[y * 80 + x + 3] & 255; + int[] scanline = new int[width/4]; + for (int x = 0; x < width; x += 4) { + int scan = rawImage[y * width + x + 3] & 255; scan <<=7; - scan |= rawImage[y * 80 + x + 2] & 255; + scan |= rawImage[y * width + x + 2] & 255; scan <<=7; - scan |= rawImage[y * 80 + x + 1] & 255; + scan |= rawImage[y * width + x + 1] & 255; scan <<=7; - scan |= rawImage[y * 80 + x] & 255; + scan |= rawImage[y * width + x] & 255; scanline[x / 4] = scan; } - renderScanline(img.getPixelWriter(), y * 2, scanline, true, false); - renderScanline(img.getPixelWriter(), y * 2 + 1, scanline, true, false); + renderScanline(img.getPixelWriter(), y * 2, scanline, true, false, width); + renderScanline(img.getPixelWriter(), y * 2 + 1, scanline, true, false, width); return img; } //