mirror of
https://github.com/badvision/lawless-legends.git
synced 2025-08-15 06:27:24 +00:00
Fixes from cyclone test with Seth
This commit is contained in:
@@ -5,7 +5,6 @@ import java.nio.ByteBuffer;
|
|||||||
import java.nio.IntBuffer;
|
import java.nio.IntBuffer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javafx.scene.Scene;
|
|
||||||
import javafx.scene.SnapshotParameters;
|
import javafx.scene.SnapshotParameters;
|
||||||
import javafx.scene.canvas.Canvas;
|
import javafx.scene.canvas.Canvas;
|
||||||
import javafx.scene.image.Image;
|
import javafx.scene.image.Image;
|
||||||
@@ -14,7 +13,6 @@ import javafx.scene.image.PixelReader;
|
|||||||
import javafx.scene.image.PixelWriter;
|
import javafx.scene.image.PixelWriter;
|
||||||
import javafx.scene.image.WritableImage;
|
import javafx.scene.image.WritableImage;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
import javax.swing.Renderer;
|
|
||||||
import org.badvision.outlaweditor.Platform;
|
import org.badvision.outlaweditor.Platform;
|
||||||
import static org.badvision.outlaweditor.apple.AppleNTSCGraphics.hgrToDhgr;
|
import static org.badvision.outlaweditor.apple.AppleNTSCGraphics.hgrToDhgr;
|
||||||
|
|
||||||
@@ -112,20 +110,24 @@ public class FloydSteinbergDither {
|
|||||||
int[] scanline;
|
int[] scanline;
|
||||||
List<Integer> pixels;
|
List<Integer> pixels;
|
||||||
|
|
||||||
public void restartDither() {
|
public byte[] restartDither(int value) {
|
||||||
keepScaled = new WritableImage(source.getPixelReader(), 560, 192);
|
keepScaled = new WritableImage(source.getPixelReader(), 560, 192);
|
||||||
tmpScaled = new WritableImage(source.getPixelReader(), 560, 192);
|
tmpScaled = new WritableImage(source.getPixelReader(), 560, 192);
|
||||||
for (int i = 0; i < screen.length; i++) {
|
for (int i = 0; i < screen.length; i++) {
|
||||||
screen[i]=(byte) 255;
|
screen[i] = (byte) (value >= 0 ? value : (int) Math.floor(Math.random() * 256.0));
|
||||||
// screen[i] = (byte) Math.max(255, Math.random() * 256.0);
|
|
||||||
}
|
}
|
||||||
scanline = new int[3];
|
scanline = new int[3];
|
||||||
pixels = new ArrayList<>();
|
pixels = new ArrayList<>();
|
||||||
|
return screen;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Image getScratchBuffer() {
|
||||||
|
return keepScaled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] dither(boolean propagateError) {
|
public byte[] dither(boolean propagateError) {
|
||||||
if (resetOutput) {
|
if (resetOutput) {
|
||||||
restartDither();
|
restartDither(0);
|
||||||
resetOutput = false;
|
resetOutput = false;
|
||||||
}
|
}
|
||||||
keepScaled.getPixelWriter().setPixels(0, 0, 560, 192, source.getPixelReader(), 0, 0);
|
keepScaled.getPixelWriter().setPixels(0, 0, 560, 192, source.getPixelReader(), 0, 0);
|
||||||
@@ -153,7 +155,7 @@ public class FloydSteinbergDither {
|
|||||||
if ((x + startX) > 0) {
|
if ((x + startX) > 0) {
|
||||||
prev = screen[(y + startY) * bufferWidth + startX + x - 1] & 255;
|
prev = screen[(y + startY) * bufferWidth + startX + x - 1] & 255;
|
||||||
}
|
}
|
||||||
if ((x + startX) < 38) {
|
if ((x + startX) < (bufferWidth-2)) {
|
||||||
next = screen[(y + startY) * bufferWidth + startX + x + 2] & 255;
|
next = screen[(y + startY) * bufferWidth + startX + x + 2] & 255;
|
||||||
}
|
}
|
||||||
// First byte, compared with a sliding window encompassing the previous byte, if any.
|
// First byte, compared with a sliding window encompassing the previous byte, if any.
|
||||||
@@ -202,11 +204,11 @@ public class FloydSteinbergDither {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (totalError < leastError) {
|
if (totalError < leastError) {
|
||||||
keepScaled.getPixelWriter().setPixels(0, y, 560, (y < 191) ? 2 : 1, tmpScaled.getPixelReader(), 0, y);
|
keepScaled.getPixelWriter().setPixels(0, y, 560, (y < 190) ? 3 : (y < 191) ? 2 : 1, tmpScaled.getPixelReader(), 0, y);
|
||||||
leastError = totalError;
|
leastError = totalError;
|
||||||
bb1 = b1;
|
bb1 = b1;
|
||||||
} else {
|
} else {
|
||||||
tmpScaled.getPixelWriter().setPixels(0, y, 560, (y < 191) ? 2 : 1, keepScaled.getPixelReader(), 0, y);
|
tmpScaled.getPixelWriter().setPixels(0, y, 560, (y < 190) ? 3 : (y < 191) ? 2 : 1, keepScaled.getPixelReader(), 0, y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Second byte, compared with a sliding window encompassing the next byte, if any.
|
// Second byte, compared with a sliding window encompassing the next byte, if any.
|
||||||
@@ -251,11 +253,11 @@ public class FloydSteinbergDither {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (totalError < leastError) {
|
if (totalError < leastError) {
|
||||||
keepScaled.getPixelWriter().setPixels(0, y, 560, (y < 191) ? 2 : 1, tmpScaled.getPixelReader(), 0, y);
|
keepScaled.getPixelWriter().setPixels(0, y, 560, (y < 190) ? 3 : (y < 191) ? 2 : 1, tmpScaled.getPixelReader(), 0, y);
|
||||||
leastError = totalError;
|
leastError = totalError;
|
||||||
bb2 = b2;
|
bb2 = b2;
|
||||||
} else {
|
} else {
|
||||||
tmpScaled.getPixelWriter().setPixels(0, y, 560, (y < 191) ? 2 : 1, keepScaled.getPixelReader(), 0, y);
|
tmpScaled.getPixelWriter().setPixels(0, y, 560, (y < 190) ? 3 : (y < 191) ? 2 : 1, keepScaled.getPixelReader(), 0, y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
screen[(y + startY) * bufferWidth + startX + x] = (byte) bb1;
|
screen[(y + startY) * bufferWidth + startX + x] = (byte) bb1;
|
||||||
@@ -313,11 +315,9 @@ public class FloydSteinbergDither {
|
|||||||
|
|
||||||
int[] col1;
|
int[] col1;
|
||||||
if (errorOff < errorOn) {
|
if (errorOff < errorOn) {
|
||||||
// totalError += errorOff;
|
|
||||||
b1 = off;
|
b1 = off;
|
||||||
col1 = Palette.parseIntColor(off1);
|
col1 = Palette.parseIntColor(off1);
|
||||||
} else {
|
} else {
|
||||||
// totalError += errorOn;
|
|
||||||
b1 = on;
|
b1 = on;
|
||||||
col1 = Palette.parseIntColor(on1);
|
col1 = Palette.parseIntColor(on1);
|
||||||
}
|
}
|
||||||
@@ -325,18 +325,14 @@ public class FloydSteinbergDither {
|
|||||||
propagateError((x + byteOffset) * 7 + bit, y, tmpScaled, col1);
|
propagateError((x + byteOffset) * 7 + bit, y, tmpScaled, col1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if (totalError < leastError) {
|
keepScaled.getPixelWriter().setPixels(0, y, 560, (y < 190) ? 3 : (y < 191) ? 2 : 1, tmpScaled.getPixelReader(), 0, y);
|
||||||
keepScaled.getPixelWriter().setPixels(0, y, 560, (y < 191) ? 2 : 1, tmpScaled.getPixelReader(), 0, y);
|
|
||||||
// leastError = totalError;
|
|
||||||
bytes[byteOffset] = b1;
|
bytes[byteOffset] = b1;
|
||||||
// } else {
|
|
||||||
// tmpScaled.getPixelWriter().setPixels(0, y, 560, (y < 191) ? 2 : 1, keepScaled.getPixelReader(), 0, y);
|
|
||||||
}
|
|
||||||
screen[(y + startY) * bufferWidth + startX + x] = (byte) bytes[0];
|
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 + 1] = (byte) bytes[1];
|
||||||
screen[(y + startY) * bufferWidth + startX + x + 2] = (byte) bytes[2];
|
screen[(y + startY) * bufferWidth + startX + x + 2] = (byte) bytes[2];
|
||||||
screen[(y + startY) * bufferWidth + startX + x + 3] = (byte) bytes[3];
|
screen[(y + startY) * bufferWidth + startX + x + 3] = (byte) bytes[3];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static int ALPHA_SOLID = 255 << 24;
|
public static int ALPHA_SOLID = 255 << 24;
|
||||||
|
|
||||||
|
@@ -85,6 +85,8 @@ public class ImageConversionWizardController implements Initializable {
|
|||||||
private ImageView sourceImageView;
|
private ImageView sourceImageView;
|
||||||
@FXML
|
@FXML
|
||||||
private ImageView convertedImageView;
|
private ImageView convertedImageView;
|
||||||
|
@FXML
|
||||||
|
private TextField fillValue;
|
||||||
/**
|
/**
|
||||||
* Initializes the controller class.
|
* Initializes the controller class.
|
||||||
*/
|
*/
|
||||||
@@ -96,7 +98,7 @@ public class ImageConversionWizardController implements Initializable {
|
|||||||
coefficientValue01, coefficientValue02, coefficientValue11, coefficientValue12,
|
coefficientValue01, coefficientValue02, coefficientValue11, coefficientValue12,
|
||||||
coefficientValue21, coefficientValue22, coefficientValue30, coefficientValue31,
|
coefficientValue21, coefficientValue22, coefficientValue30, coefficientValue31,
|
||||||
coefficientValue32, coefficientValue40, coefficientValue41, coefficientValue41,
|
coefficientValue32, coefficientValue40, coefficientValue41, coefficientValue41,
|
||||||
coefficientValue42, divisorValue, outputHeightValue, outputWidthValue
|
coefficientValue42, divisorValue, outputHeightValue, outputWidthValue, fillValue
|
||||||
}) {
|
}) {
|
||||||
configureNumberValidation(field, "0");
|
configureNumberValidation(field, "0");
|
||||||
}
|
}
|
||||||
@@ -165,6 +167,16 @@ public class ImageConversionWizardController implements Initializable {
|
|||||||
cropBottomValue.setText(String.valueOf(height));
|
cropBottomValue.setText(String.valueOf(height));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private void fillOutput(ActionEvent event) {
|
||||||
|
int fill = Integer.parseInt(fillValue.getText());
|
||||||
|
updateConvertedImageWithData(ditherEngine.restartDither(fill));
|
||||||
|
}
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private void randomizeOutput(ActionEvent event) {
|
||||||
|
updateConvertedImageWithData(ditherEngine.restartDither(-1));
|
||||||
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private void performQuantizePass(ActionEvent event) {
|
private void performQuantizePass(ActionEvent event) {
|
||||||
@@ -179,6 +191,7 @@ public class ImageConversionWizardController implements Initializable {
|
|||||||
ditherEngine.setCoefficients(getCoefficients());
|
ditherEngine.setCoefficients(getCoefficients());
|
||||||
ditherEngine.setDivisor(getDivisor());
|
ditherEngine.setDivisor(getDivisor());
|
||||||
byte[] out = ditherEngine.dither(true);
|
byte[] out = ditherEngine.dither(true);
|
||||||
|
sourceImageView.setImage(ditherEngine.getScratchBuffer());
|
||||||
updateConvertedImageWithData(out);
|
updateConvertedImageWithData(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -196,7 +196,7 @@
|
|||||||
</AnchorPane>
|
</AnchorPane>
|
||||||
</content>
|
</content>
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab text="Output Settings">
|
<Tab text="Output">
|
||||||
<content>
|
<content>
|
||||||
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
|
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
|
||||||
<children>
|
<children>
|
||||||
@@ -205,15 +205,19 @@
|
|||||||
|
|
||||||
<Label alignment="CENTER_RIGHT" layoutX="14.0" layoutY="44.0" prefHeight="16.0" prefWidth="53.0" text="Height" textAlignment="RIGHT" />
|
<Label alignment="CENTER_RIGHT" layoutX="14.0" layoutY="44.0" prefHeight="16.0" prefWidth="53.0" text="Height" textAlignment="RIGHT" />
|
||||||
<TextField fx:id="outputHeightValue" layoutX="69.0" layoutY="39.0" prefHeight="16.0" prefWidth="122.0" promptText="Height (in pixels)" />
|
<TextField fx:id="outputHeightValue" layoutX="69.0" layoutY="39.0" prefHeight="16.0" prefWidth="122.0" promptText="Height (in pixels)" />
|
||||||
|
<Button layoutX="432.0" layoutY="70.0" mnemonicParsing="false" onAction="#performQuantizePass" prefHeight="26.0" prefWidth="141.0" text="Quantize Pass" AnchorPane.rightAnchor="9.0" />
|
||||||
|
<Button layoutX="432.0" layoutY="101.0" mnemonicParsing="false" onAction="#performDiffusionPass" text="Error Diffusion Pass" AnchorPane.rightAnchor="9.0" />
|
||||||
|
<Label layoutX="434.0" layoutY="13.0" text="Fill with" AnchorPane.rightAnchor="98.0" />
|
||||||
|
<TextField fx:id="fillValue" layoutX="484.0" layoutY="8.0" prefHeight="26.0" prefWidth="44.0" text="0" AnchorPane.rightAnchor="54.0" />
|
||||||
|
<Button layoutX="531.0" layoutY="8.0" mnemonicParsing="false" onAction="#fillOutput" text="Fill!" AnchorPane.rightAnchor="9.0" />
|
||||||
|
<Button layoutX="513.0" layoutY="39.0" mnemonicParsing="false" onAction="#randomizeOutput" prefHeight="26.0" prefWidth="140.0" text="Randomize" AnchorPane.rightAnchor="9.0" />
|
||||||
</children>
|
</children>
|
||||||
</AnchorPane>
|
</AnchorPane>
|
||||||
</content>
|
</content>
|
||||||
</Tab>
|
</Tab>
|
||||||
</tabs>
|
</tabs>
|
||||||
</TabPane>
|
</TabPane>
|
||||||
<Button onAction="#performQuantizePass" layoutX="14.0" layoutY="412.0" mnemonicParsing="false" prefHeight="26.0" prefWidth="141.0" text="Quantize Pass" AnchorPane.bottomAnchor="14.0" AnchorPane.leftAnchor="14.0" />
|
<Button layoutX="482.0" layoutY="412.0" mnemonicParsing="false" onAction="#performOK" text="OK" AnchorPane.bottomAnchor="14.0" AnchorPane.rightAnchor="81.0" />
|
||||||
<Button onAction="#performDiffusionPass" layoutX="159.0" layoutY="412.0" mnemonicParsing="false" text="Error Diffusion Pass" AnchorPane.bottomAnchor="14.0" AnchorPane.leftAnchor="162.0" />
|
<Button layoutX="526.0" layoutY="412.0" mnemonicParsing="false" onAction="#performCancel" text="Cancel" AnchorPane.bottomAnchor="14.0" AnchorPane.rightAnchor="14.0" />
|
||||||
<Button onAction="#performOK" layoutX="482.0" layoutY="412.0" mnemonicParsing="false" text="OK" AnchorPane.bottomAnchor="14.0" AnchorPane.rightAnchor="81.0" />
|
|
||||||
<Button onAction="#performCancel" layoutX="526.0" layoutY="412.0" mnemonicParsing="false" text="Cancel" AnchorPane.bottomAnchor="14.0" AnchorPane.rightAnchor="14.0" />
|
|
||||||
</children>
|
</children>
|
||||||
</AnchorPane>
|
</AnchorPane>
|
||||||
|
Reference in New Issue
Block a user