Big changes to image editors to support resizing. Also fixed that annoying rectangle drawing bug!

This commit is contained in:
Brendan Robert 2013-09-10 21:38:25 -05:00
parent 3b55e1a336
commit ba891e380f
10 changed files with 210 additions and 129 deletions

View File

@ -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<Image, ImageEditor.DrawMode> {
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;
}
}

View File

@ -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);
}

View File

@ -256,7 +256,7 @@ public class MapEditor extends Editor<Map, MapEditor.DrawMode> 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<Map, MapEditor.DrawMode> 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<DataFormat,Object> clip = new HashMap<>();
clip.put(DataFormat.IMAGE, img);
clip.put(DataFormat.PLAIN_TEXT, "selection/map/"+Application.gameData.getMap().indexOf(getEntity())+"/"+getSelectionInfo());

View File

@ -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<? extends TileEditor> tileEditor;
public Class<? extends ImageEditor> 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;
}
}

View File

@ -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<MouseE
redraw();
screen = new ImageView(currentImage);
anchorPane.getChildren().add(0, screen);
screen.setOnMousePressed(this);
screen.setOnMouseClicked(this);
screen.setOnMouseReleased(this);
screen.setOnMouseDragged(this);
@ -106,13 +103,13 @@ public class AppleImageEditor extends ImageEditor implements EventHandler<MouseE
}
public void redrawScanline(int y) {
currentImage = getPlatform().imageRenderer.renderScanline(currentImage, y, getImageData());
currentImage = getPlatform().imageRenderer.renderScanline(currentImage, y, getWidth(), getImageData());
}
@Override
public void redraw() {
System.out.println("Redraw " + getPlatform().name());
currentImage = getPlatform().imageRenderer.renderImage(currentImage, getImageData());
currentImage = getPlatform().imageRenderer.renderImage(currentImage, getImageData(), getWidth(), getHeight());
anchorPane.getChildren().get(1).setLayoutX((anchorPane.getWidth() - 30) / 2);
anchorPane.getChildren().get(2).setLayoutY((anchorPane.getHeight() - 30) / 2);
anchorPane.getChildren().get(3).setLayoutX((anchorPane.getWidth() - 30) / 2);
@ -122,19 +119,13 @@ public class AppleImageEditor extends ImageEditor implements EventHandler<MouseE
public byte[] getImageData() {
if (imageData == null) {
PlatformData data = null;
for (PlatformData d : getEntity().getDisplayData()) {
if (d.getPlatform().equalsIgnoreCase(getPlatform().name())) {
data = d;
break;
}
}
PlatformData data = getPlatformData(getPlatform());
if (data == null) {
data = new PlatformData();
data.setWidth(40);
data.setHeight(192);
data.setWidth(getPlatform().maxImageWidth);
data.setHeight(getPlatform().maxImageHeight);
data.setPlatform(getPlatform().name());
data.setValue(getPlatform().imageRenderer.createImageBuffer());
data.setValue(getPlatform().imageRenderer.createImageBuffer(getPlatform().maxImageWidth, getPlatform().maxImageHeight));
getEntity().getDisplayData().add(data);
}
imageData = data.getValue();
@ -208,13 +199,25 @@ public class AppleImageEditor extends ImageEditor implements EventHandler<MouseE
@Override
public void handle(MouseEvent t) {
performAction(t.isShiftDown() || t.isSecondaryButtonDown(), t.getEventType().equals(MouseEvent.MOUSE_RELEASED), (int) t.getX() / xScale, (int) t.getY() / yScale);
if (performAction(t.isShiftDown() || t.isSecondaryButtonDown(), t.getEventType().equals(MouseEvent.MOUSE_RELEASED), (int) t.getX() / xScale, (int) t.getY() / yScale)) {
t.consume();
}
}
protected int lastActionX = -1;
protected int lastActionY = -1;
protected long debounce = -1;
public static long DEBOUNCE_THRESHOLD = 50;
public void performAction(boolean alt, boolean released, int x, int y) {
y = Math.min(Math.max(y, 0), 191);
public boolean performAction(boolean alt, boolean released, int x, int y) {
if (debounce != -1) {
long ellapsed = System.currentTimeMillis() - debounce;
if (ellapsed <= DEBOUNCE_THRESHOLD) {
return false;
}
debounce = -1;
}
y = Math.min(Math.max(y, 0), getHeight() - 1);
x = Math.min(Math.max(x, 0), (getWidth() * 7) - 1);
boolean canSkip = false;
if (lastActionX == x && lastActionY == y) {
@ -225,8 +228,8 @@ public class AppleImageEditor extends ImageEditor implements EventHandler<MouseE
switch (currentDrawMode) {
case Toggle:
if (canSkip) {
return;
}
return false;
}
if (alt) {
toggleHiBit(x, y);
} else {
@ -236,36 +239,39 @@ public class AppleImageEditor extends ImageEditor implements EventHandler<MouseE
break;
case Pencil1px:
if (canSkip) {
return;
}
return false;
}
plot(x, y, currentFillPattern, hiBitMatters);
redrawScanline(y);
break;
case Pencil3px:
if (canSkip) {
return;
}
return false;
}
drawBrush(x, y, 3, currentFillPattern, hiBitMatters);
break;
case Pencil5px:
if (canSkip) {
return;
}
return false;
}
drawBrush(x, y, 5, currentFillPattern, hiBitMatters);
break;
case Rectangle:
if (released) {
fillSelection(x, y);
redraw();
} else {
updateSelection(x, y);
}
fillSelection(x, y);
redraw();
debounce = System.currentTimeMillis();
} else {
updateSelection(x, y);
}
break;
}
return true;
// observedObjectChanged(getEntity());
}
public static Rectangle selectRect = null;
public int selectStartX = 0;
public int selectStartY = 0;
public int selectStartX = -1;
public int selectStartY = -1;
private void startSelection(int x, int y) {
selectRect = new Rectangle(1, 1, Color.NAVY);
@ -293,6 +299,9 @@ public class AppleImageEditor extends ImageEditor implements EventHandler<MouseE
}
private void fillSelection(int x, int y) {
if (selectRect == null) {
return;
}
anchorPane.getChildren().remove(selectRect);
selectRect = null;
@ -358,11 +367,11 @@ public class AppleImageEditor extends ImageEditor implements EventHandler<MouseE
}
public int getWidth() {
return 40;
return getPlatformData(getPlatform()).getWidth();
}
public int getHeight() {
return 192;
return getPlatformData(getPlatform()).getHeight();
}
@Override
@ -397,10 +406,12 @@ public class AppleImageEditor extends ImageEditor implements EventHandler<MouseE
details.put(bufferDetails[i], Integer.parseInt(bufferDetails[i + 1]));
}
TileMap map = new TileMap(Application.gameData.getMap().get(mapNumber));
byte[] buf = getPlatform().imageRenderer.generatePreview(
byte[] buf = getPlatform().imageRenderer.renderPreview(
map,
details.get("x1"),
details.get("y1"));
details.get("y1"),
getWidth(),
getHeight());
setData(buf);
redraw();
return true;
@ -419,7 +430,7 @@ public class AppleImageEditor extends ImageEditor implements EventHandler<MouseE
}
private void importImage(javafx.scene.image.Image image) {
FloydSteinbergDither.floydSteinbergDither(image, getPlatform(), 0, 0, getWidth(), getHeight(), new FloydSteinbergDither.DitherCallback() {
FloydSteinbergDither.floydSteinbergDither(image, getPlatform(), 0, 0, getWidth(), getHeight(), getImageData(), getWidth(), new FloydSteinbergDither.DitherCallback() {
@Override
public void ditherCompleted(byte[] data) {
setData(data);
@ -447,14 +458,53 @@ public class AppleImageEditor extends ImageEditor implements EventHandler<MouseE
}
}
File out = FileUtils.getFile(null, "Export image", true, FileUtils.Extension.BINARY, FileUtils.Extension.ALL);
if (out == null) return;
if (out == null) {
return;
}
try {
FileOutputStream outStream = new FileOutputStream(out);
outStream.write(output);
outStream.flush();
outStream.close();
} catch (IOException ex) {
} catch (IOException ex) {
Logger.getLogger(AppleImageEditor.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
@Override
public void resize(final int newWidth, final int newHeight) {
UIAction.confirm("Do you want to scale the image? If you select no, the image will be cropped as needed.",
new Runnable() {
@Override
public void run() {
rescale(newWidth, newHeight);
}
}, new Runnable() {
@Override
public void run() {
crop(newWidth, newHeight);
}
});
}
/**
* 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
*/
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
*/
public void crop(int newWidth, int newHeight) {
}
}

View File

@ -11,7 +11,6 @@ import org.badvision.outlaweditor.ImageRenderer;
import org.badvision.outlaweditor.Platform;
import org.badvision.outlaweditor.data.TileMap;
import org.badvision.outlaweditor.data.TileUtils;
import org.badvision.outlaweditor.data.xml.Map;
import org.badvision.outlaweditor.data.xml.Tile;
/**
@ -25,26 +24,32 @@ public class AppleImageRenderer extends ImageRenderer {
// scanline is 20 16-bit words
// If mixed-mode is used then useColor needs to be an 80-boolean array indicating which bytes are supposed to be BW
public byte[] createImageBuffer(int width, int height) {
return new byte[width * height];
}
@Override
public byte[] createImageBuffer() {
return new byte[40 * 192];
}
@Override
public byte[] generatePreview(TileMap map, int x1, int y1) {
byte[] buffer = createImageBuffer();
public byte[] 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 / 2;
boolean isOdd = (width) % 2 == 1;
for (int y = 0; y < numRows; y++) {
for (int yy = 0; yy < 16; yy++) {
for (int x = 0; x < 20; x++) {
Tile t = map.get(x + x1, y + y1);
for (int x = 0; x < numCols; x++) {
Tile t = map.get(x + startX, y + startY);
if (t == null) {
buffer[pos++] = 0;
buffer[pos++] = 0;
if (!isOdd) {
buffer[pos++] = 0;
}
} else {
byte[] tileData = TileUtils.getPlatformData(t, Platform.AppleII);
buffer[pos++] = tileData[yy * 2];
buffer[pos++] = tileData[yy * 2 + 1];
if (!isOdd) {
buffer[pos++] = tileData[yy * 2 + 1];
}
}
}
}
@ -53,42 +58,38 @@ public class AppleImageRenderer extends ImageRenderer {
}
@Override
public WritableImage renderPreview(TileMap map, int startX, int startY) {
return renderImage(null, generatePreview(map, startX, startY));
}
@Override
public WritableImage renderImage(WritableImage img, byte[] rawImage) {
public WritableImage renderImage(WritableImage img, byte[] rawImage, int width, int height) {
if (img == null) {
img = new WritableImage(560, 384);
img = new WritableImage(width * 14, height * 2);
}
for (int y = 0; y < 192; y++) {
renderScanline(img, y, rawImage);
for (int y = 0; y < height; y++) {
renderScanline(img, y, width, rawImage);
}
return img;
}
@Override
public WritableImage renderScanline(WritableImage img, int y, byte[] rawImage) {
int[] scanline = new int[20];
public WritableImage renderScanline(WritableImage img, int y, int width, byte[] rawImage) {
int[] scanline = new int[width/2 + 1];
boolean extraHalfBit = false;
for (int x = 0; x < 40; x += 2) {
int b1 = rawImage[y * 40 + x] & 255;
int b2 = rawImage[y * 40 + x + 1] & 255;
for (int x = 0; x < width; x += 2) {
int b1 = rawImage[y * width + x] & 255;
int b2 = rawImage[y * width + x + 1] & 255;
int i = hgrToDhgr[(extraHalfBit && x > 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) {

View File

@ -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;
}

View File

@ -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<Integer> 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<Integer> 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;

View File

@ -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) {
}
}

View File

@ -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;
}
//