mirror of
https://github.com/badvision/lawless-legends.git
synced 2025-01-13 03:30:28 +00:00
Fixes from cyclone test with Seth
This commit is contained in:
parent
f43c642875
commit
f5eda11edd
@ -5,7 +5,6 @@ import java.nio.ByteBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.SnapshotParameters;
|
||||
import javafx.scene.canvas.Canvas;
|
||||
import javafx.scene.image.Image;
|
||||
@ -14,7 +13,6 @@ import javafx.scene.image.PixelReader;
|
||||
import javafx.scene.image.PixelWriter;
|
||||
import javafx.scene.image.WritableImage;
|
||||
import javafx.scene.paint.Color;
|
||||
import javax.swing.Renderer;
|
||||
import org.badvision.outlaweditor.Platform;
|
||||
import static org.badvision.outlaweditor.apple.AppleNTSCGraphics.hgrToDhgr;
|
||||
|
||||
@ -79,9 +77,9 @@ public class FloydSteinbergDither {
|
||||
c.snapshot(sp, newImg);
|
||||
return newImg;
|
||||
}
|
||||
|
||||
|
||||
public WritableImage getPreviewImage() {
|
||||
return new WritableImage(bufferWidth * byteRenderWidth, height*2);
|
||||
return new WritableImage(bufferWidth * byteRenderWidth, height * 2);
|
||||
}
|
||||
|
||||
public void setOutputDimensions(int width, int height) {
|
||||
@ -90,7 +88,7 @@ public class FloydSteinbergDither {
|
||||
screen = platform.imageRenderer.createImageBuffer(width, height);
|
||||
resetOutput = true;
|
||||
}
|
||||
|
||||
|
||||
public void setDivisor(int divisor) {
|
||||
this.divisor = divisor;
|
||||
}
|
||||
@ -111,21 +109,25 @@ public class FloydSteinbergDither {
|
||||
WritableImage tmpScaled;
|
||||
int[] scanline;
|
||||
List<Integer> pixels;
|
||||
|
||||
public void restartDither() {
|
||||
|
||||
public byte[] restartDither(int value) {
|
||||
keepScaled = new WritableImage(source.getPixelReader(), 560, 192);
|
||||
tmpScaled = new WritableImage(source.getPixelReader(), 560, 192);
|
||||
for (int i = 0; i < screen.length; i++) {
|
||||
screen[i]=(byte) 255;
|
||||
// screen[i] = (byte) Math.max(255, Math.random() * 256.0);
|
||||
screen[i] = (byte) (value >= 0 ? value : (int) Math.floor(Math.random() * 256.0));
|
||||
}
|
||||
scanline = new int[3];
|
||||
pixels = new ArrayList<>();
|
||||
return screen;
|
||||
}
|
||||
|
||||
public Image getScratchBuffer() {
|
||||
return keepScaled;
|
||||
}
|
||||
|
||||
public byte[] dither(boolean propagateError) {
|
||||
if (resetOutput) {
|
||||
restartDither();
|
||||
restartDither(0);
|
||||
resetOutput = false;
|
||||
}
|
||||
keepScaled.getPixelWriter().setPixels(0, 0, 560, 192, source.getPixelReader(), 0, 0);
|
||||
@ -153,7 +155,7 @@ public class FloydSteinbergDither {
|
||||
if ((x + startX) > 0) {
|
||||
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;
|
||||
}
|
||||
// First byte, compared with a sliding window encompassing the previous byte, if any.
|
||||
@ -167,7 +169,7 @@ public class FloydSteinbergDither {
|
||||
int off = on ^ (1 << c);
|
||||
// get values for "off"
|
||||
int i = hgrToDhgr[0][prev];
|
||||
scanline[0] = i & 0x0fffffff;
|
||||
scanline[0] = i & 0x0fffffff;
|
||||
i = hgrToDhgr[(i & 0x10000000) != 0 ? off | 0x0100 : off][bb2];
|
||||
scanline[1] = i & 0x0fffffff;
|
||||
// scanline[2] = hgrToDhgr[(i & 0x10000000) != 0 ? next | 0x0100 : next][0] & 0x0fffffff;
|
||||
@ -202,11 +204,11 @@ public class FloydSteinbergDither {
|
||||
}
|
||||
}
|
||||
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;
|
||||
bb1 = b1;
|
||||
} 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.
|
||||
@ -251,11 +253,11 @@ public class FloydSteinbergDither {
|
||||
}
|
||||
}
|
||||
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;
|
||||
bb2 = b2;
|
||||
} 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;
|
||||
@ -313,11 +315,9 @@ public class FloydSteinbergDither {
|
||||
|
||||
int[] col1;
|
||||
if (errorOff < errorOn) {
|
||||
// totalError += errorOff;
|
||||
b1 = off;
|
||||
col1 = Palette.parseIntColor(off1);
|
||||
} else {
|
||||
// totalError += errorOn;
|
||||
b1 = on;
|
||||
col1 = Palette.parseIntColor(on1);
|
||||
}
|
||||
@ -325,19 +325,15 @@ public class FloydSteinbergDither {
|
||||
propagateError((x + byteOffset) * 7 + bit, y, tmpScaled, col1);
|
||||
}
|
||||
}
|
||||
// if (totalError < leastError) {
|
||||
keepScaled.getPixelWriter().setPixels(0, y, 560, (y < 191) ? 2 : 1, tmpScaled.getPixelReader(), 0, y);
|
||||
// leastError = totalError;
|
||||
keepScaled.getPixelWriter().setPixels(0, y, 560, (y < 190) ? 3 : (y < 191) ? 2 : 1, tmpScaled.getPixelReader(), 0, y);
|
||||
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 + 1] = (byte) bytes[1];
|
||||
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] = (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];
|
||||
}
|
||||
|
||||
|
||||
public static int ALPHA_SOLID = 255 << 24;
|
||||
|
||||
private void propagateError(int x, int y, WritableImage img, int[] newColor) {
|
||||
@ -349,7 +345,7 @@ public class FloydSteinbergDither {
|
||||
continue;
|
||||
}
|
||||
int c = img.getPixelReader().getArgb(x + xx, y + yy);
|
||||
int errorAmount = ((error * coefficients[xx+2][yy]) / divisor);
|
||||
int errorAmount = ((error * coefficients[xx + 2][yy]) / divisor);
|
||||
img.getPixelWriter().setArgb(x + xx, y + yy, ALPHA_SOLID | Palette.addError(c, i, errorAmount));
|
||||
}
|
||||
}
|
||||
|
@ -85,6 +85,8 @@ public class ImageConversionWizardController implements Initializable {
|
||||
private ImageView sourceImageView;
|
||||
@FXML
|
||||
private ImageView convertedImageView;
|
||||
@FXML
|
||||
private TextField fillValue;
|
||||
/**
|
||||
* Initializes the controller class.
|
||||
*/
|
||||
@ -96,7 +98,7 @@ public class ImageConversionWizardController implements Initializable {
|
||||
coefficientValue01, coefficientValue02, coefficientValue11, coefficientValue12,
|
||||
coefficientValue21, coefficientValue22, coefficientValue30, coefficientValue31,
|
||||
coefficientValue32, coefficientValue40, coefficientValue41, coefficientValue41,
|
||||
coefficientValue42, divisorValue, outputHeightValue, outputWidthValue
|
||||
coefficientValue42, divisorValue, outputHeightValue, outputWidthValue, fillValue
|
||||
}) {
|
||||
configureNumberValidation(field, "0");
|
||||
}
|
||||
@ -165,6 +167,16 @@ public class ImageConversionWizardController implements Initializable {
|
||||
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
|
||||
private void performQuantizePass(ActionEvent event) {
|
||||
@ -179,6 +191,7 @@ public class ImageConversionWizardController implements Initializable {
|
||||
ditherEngine.setCoefficients(getCoefficients());
|
||||
ditherEngine.setDivisor(getDivisor());
|
||||
byte[] out = ditherEngine.dither(true);
|
||||
sourceImageView.setImage(ditherEngine.getScratchBuffer());
|
||||
updateConvertedImageWithData(out);
|
||||
}
|
||||
|
||||
|
@ -196,7 +196,7 @@
|
||||
</AnchorPane>
|
||||
</content>
|
||||
</Tab>
|
||||
<Tab text="Output Settings">
|
||||
<Tab text="Output">
|
||||
<content>
|
||||
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
|
||||
<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" />
|
||||
<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>
|
||||
</AnchorPane>
|
||||
</content>
|
||||
</Tab>
|
||||
</tabs>
|
||||
</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 onAction="#performDiffusionPass" layoutX="159.0" layoutY="412.0" mnemonicParsing="false" text="Error Diffusion Pass" AnchorPane.bottomAnchor="14.0" AnchorPane.leftAnchor="162.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" />
|
||||
<Button layoutX="482.0" layoutY="412.0" mnemonicParsing="false" onAction="#performOK" text="OK" AnchorPane.bottomAnchor="14.0" AnchorPane.rightAnchor="81.0" />
|
||||
<Button layoutX="526.0" layoutY="412.0" mnemonicParsing="false" onAction="#performCancel" text="Cancel" AnchorPane.bottomAnchor="14.0" AnchorPane.rightAnchor="14.0" />
|
||||
</children>
|
||||
</AnchorPane>
|
||||
|
Loading…
x
Reference in New Issue
Block a user