Fixes from cyclone test with Seth

This commit is contained in:
Brendan Robert
2014-09-28 12:15:08 -05:00
parent f43c642875
commit f5eda11edd
3 changed files with 48 additions and 35 deletions

View File

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

View File

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

View File

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