Переделай код, чтобы private void sawtooth1Image() делал пилу по направлению в вверх, private void sawtooth2Image() делал пилу по направлению в вниз, private void sawtooth3Image() делал 2 пилы в разные стороны, private void sawtooth4Image() делал 3 пилы.
// Гистограмма для sawtoottImage()
private void sawtooth1Image() {
if (image != null) {
// Запрос значения порогов в цикле до тех пор, пока пользователь не введет правильные значения
float t1 = 0, t2 = 0;
boolean valid = false;
while (!valid) {
t1 = userInput("Введите значение порога 1: ", 0, 1);
t2 = userInput("Введите значение порога 2: ", 0, 1);
if (t2 > t1) {
valid = true;
} else {
JOptionPane.showMessageDialog(null, “Значение порога 2 должно быть больше порога 1”);
}
}

BufferedImage sawtoothContrastImage = sawtoothContrast(image, t1, t2);

setImageIcon(sawtoothContrastImage);
saveImage(sawtoothContrastImage);

int[] originalHistogram = getHistogram(image);
int[] sawtoothHistogram = getHistogram(sawtoothContrastImage);

JFrame histogramFrame = new JFrame(“Гистограммы”);
histogramFrame.setLayout(new GridLayout(1, 2, 10, 10));

JPanel originalHistogramPanel = createHistogramPanel(originalHistogram, “Гистограмма исходного изображения”);

JPanel sawtoothHistogramPanel = createHistogramPanel(sawtoothHistogram, “Гистограмма после контрастирования”);

histogramFrame.add(originalHistogramPanel);
histogramFrame.add(sawtoothHistogramPanel);
histogramFrame.pack();
histogramFrame.setLocationRelativeTo(null);
histogramFrame.setVisible(true);
}
}
// Функция для создания панели с гистограммой
private JPanel createHistogramPanel(int[] histogram, String label) {
JPanel histogramPanel = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int max = Arrays.stream(histogram).max().getAsInt();
for (int i = 0; i < 256; i++) {
int height = (int) (300.0 * histogram[i] / max);
g.fillRect(i, 300 - height, 1, height);
}
}
};
histogramPanel.setPreferredSize(new Dimension(256, 300));
histogramPanel.setBorder(BorderFactory.createTitledBorder(label));
return histogramPanel;
}

// Функция для получения гистограммы изображения
private int[] getHistogram(BufferedImage image) {
int[] histogram = new int[256];
for (int i = 0; i < image.getWidth(); i++) {
for (int j = 0; j < image.getHeight(); j++) {
int pixel = image.getRGB(i, j);
int red = (pixel >> 16) & 0xff;
int green = (pixel >> 8) & 0xff;
int blue = pixel & 0xff;
int brightness = (int) (0.2126 * red + 0.7152 * green + 0.0722 * blue);
if (brightness >= 0 && brightness < 256) {
histogram[brightness]++;
}
}
}
return histogram;
}


private void sawtooth2Image() {
if (image != null) {
// Запрос значения порогов в цикле до тех пор, пока пользователь не введет правильные значения
float t1 = 0, t2 = 0;
boolean valid = false;
while (!valid) {
t1 = userInput("Введите значение порога 1: ", 0, 1);
t2 = userInput("Введите значение порога 2: ", 0, 1);
if (t2 > t1) {
valid = true;
} else {
JOptionPane.showMessageDialog(null, “Значение порога 2 должно быть больше порога 1”);
}
}

BufferedImage sawtoothContrastImage = sawtoothContrast(image, t1, t2);

setImageIcon(sawtoothContrastImage);
saveImage(sawtoothContrastImage);

int[] originalHistogram = getHistogram(image);
int[] sawtoothHistogram = getHistogram(sawtoothContrastImage);

JFrame histogramFrame = new JFrame(“Гистограммы”);
histogramFrame.setLayout(new GridLayout(1, 2, 10, 10));

JPanel originalHistogramPanel = createHistogramPanel(originalHistogram, “Гистограмма исходного изображения”);

JPanel sawtoothHistogramPanel = createHistogramPanel(sawtoothHistogram, “Гистограмма после контрастирования”);

histogramFrame.add(originalHistogramPanel);
histogramFrame.add(sawtoothHistogramPanel);
histogramFrame.pack();
histogramFrame.setLocationRelativeTo(null);
histogramFrame.setVisible(true);
}
}

private void sawtooth3Image() {
if (image != null) {
// Запрос значения порогов в цикле до тех пор, пока пользователь не введет правильные значения
float t1 = 0, t2 = 0;
boolean valid = false;
while (!valid) {
t1 = userInput("Введите значение порога 1: ", 0, 1);
t2 = userInput("Введите значение порога 2: ", 0, 1);
if (t2 > t1) {
valid = true;
} else {
JOptionPane.showMessageDialog(null, “Значение порога 2 должно быть больше порога 1”);
}
}

BufferedImage sawtoothContrastImage = sawtoothContrast(image, t1, t2);

setImageIcon(sawtoothContrastImage);
saveImage(sawtoothContrastImage);

int[] originalHistogram = getHistogram(image);
int[] sawtoothHistogram = getHistogram(sawtoothContrastImage);

JFrame histogramFrame = new JFrame(“Гистограммы”);
histogramFrame.setLayout(new GridLayout(1, 2, 10, 10));

JPanel originalHistogramPanel = createHistogramPanel(originalHistogram, “Гистограмма исходного изображения”);

JPanel sawtoothHistogramPanel = createHistogramPanel(sawtoothHistogram, “Гистограмма после контрастирования”);

histogramFrame.add(originalHistogramPanel);
histogramFrame.add(sawtoothHistogramPanel);
histogramFrame.pack();
histogramFrame.setLocationRelativeTo(null);
histogramFrame.setVisible(true);
}
}

private void sawtooth4Image() {
if (image != null) {
// Запрос значения порогов в цикле до тех пор, пока пользователь не введет правильные значения
float t1 = 0, t2 = 0;
boolean valid = false;
while (!valid) {
t1 = userInput("Введите значение порога 1: ", 0, 1);
t2 = userInput("Введите значение порога 2: ", 0, 1);
if (t2 > t1) {
valid = true;
} else {
JOptionPane.showMessageDialog(null, “Значение порога 2 должно быть больше порога 1”);
}
}

BufferedImage sawtoothContrastImage = sawtoothContrast(image, t1, t2);

setImageIcon(sawtoothContrastImage);
saveImage(sawtoothContrastImage);

int[] originalHistogram = getHistogram(image);
int[] sawtoothHistogram = getHistogram(sawtoothContrastImage);

JFrame histogramFrame = new JFrame(“Гистограммы”);
histogramFrame.setLayout(new GridLayout(1, 2, 10, 10));

JPanel originalHistogramPanel = createHistogramPanel(originalHistogram, “Гистограмма исходного изображения”);

JPanel sawtoothHistogramPanel = createHistogramPanel(sawtoothHistogram, “Гистограмма после контрастирования”);

histogramFrame.add(originalHistogramPanel);
histogramFrame.add(sawtoothHistogramPanel);
histogramFrame.pack();
histogramFrame.setLocationRelativeTo(null);
histogramFrame.setVisible(true);
}
}

/// Функция пилообразного контрастирования с порогами
private BufferedImage sawtoothContrast(BufferedImage image, float t1, float t2) {
BufferedImage output = new BufferedImage(image.getWidth(), image.getHeight(), image.getType());
for (int i = 0; i < image.getWidth(); i++) {
for (int j = 0; j < image.getHeight(); j++) {
int pixel = image.getRGB(i, j);
int red = (pixel >> 16) & 0xff;
int green = (pixel >> 8) & 0xff;
int blue = pixel & 0xff;
int brightness = (int) (0.2126 * red + 0.7152 * green + 0.0722 * blue);
if (brightness < t1) {
output.setRGB(i, j, new Color(0, 0, 0).getRGB());
} else if (brightness >= t1 && brightness < t2) {
int value = (int) (255 * (brightness - t1) / (t2 - t1));
output.setRGB(i, j, new Color(value, value, value).getRGB());
} else if (brightness >= t2) {
output.setRGB(i, j, new Color(255, 255, 255).getRGB());
}
}
}
return output;
}

private float userInput(String message, float lowerBound, float upperBound) {
boolean valid = false;
float value = 0;
while (!valid) {
String input = JOptionPane.showInputDialog(message);
try {
value = Float.parseFloat(input);
if (value >= lowerBound && value <= upperBound) {
valid = true;
} else {
JOptionPane.showMessageDialog(null, "Значение должно быть от " + lowerBound + " до " + upperBound);
}
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(null, “Ошибка ввода. Попробуйте еще раз.”);
} catch (NullPointerException e) {
System.exit(1);
}
}
return value;
}