diff --git a/konvolucija1.p2 b/konvolucija1.p2 new file mode 100644 index 0000000..d5a0b34 --- /dev/null +++ b/konvolucija1.p2 @@ -0,0 +1,2 @@ +P2: 4 x 4 +0 64 128 255 255 128 64 0 0 0 1 1 255 255 37 5 \ No newline at end of file diff --git a/slika.p2 b/slika.p2 new file mode 100644 index 0000000..af0a2af --- /dev/null +++ b/slika.p2 @@ -0,0 +1,2 @@ +P2: 15 x 10 +0 0 128 128 128 164 164 164 164 164 128 128 128 0 0 0 255 255 255 0 0 255 255 255 255 255 255 255 255 0 128 255 255 0 255 255 0 255 255 255 16 255 16 255 128 128 255 0 255 255 255 255 0 255 255 255 16 255 255 128 164 255 0 255 255 255 255 0 255 255 16 255 16 255 164 164 255 255 0 255 255 0 255 255 244 255 255 244 255 164 128 255 255 255 0 0 255 255 255 255 244 244 255 255 128 128 255 144 255 255 255 255 144 255 255 244 244 255 255 128 0 255 255 255 255 255 255 255 255 244 255 255 244 255 0 0 0 128 128 128 164 164 164 164 164 128 128 128 0 0 diff --git a/slikaB.p2 b/slikaB.p2 new file mode 100644 index 0000000..3476b39 --- /dev/null +++ b/slikaB.p2 @@ -0,0 +1,2 @@ +P2B: 4 x 3 +1072693248 1072693248 1073741823 672794241 1073741823 1047552 1047552 1073741823 0 1073741823 1023 1023 \ No newline at end of file diff --git a/src/DN05.java b/src/DN05.java new file mode 100644 index 0000000..56d1dc6 --- /dev/null +++ b/src/DN05.java @@ -0,0 +1,523 @@ +import java.io.File; +import java.io.FileNotFoundException; +import java.util.Arrays; +import java.util.Scanner; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + + +public class DN05 { + + public static void main(String[] args) { + if (args[0].equals("barvna") || args[0].equals("sivinska")) { + int[][][] barvnaSlika = preberiBarvnoSliko(args[1]); + if (barvnaSlika == null) return; + + switch (args[0]) { + case "barvna": + izpisiBarvnoSliko(barvnaSlika); + return; + case "sivinska": + izpisiSliko(pretvoriVSivinsko(barvnaSlika)); + return; + } + } + + int[][] slika = preberiSliko(args[1]); + if (slika == null) return; + + switch (args[0]) { + case "izpisi": + izpisiSliko(slika); + break; + case "histogram": + izpisiHistogram(slika); + break; + case "svetlost": + System.out.printf("Srednja vrednost sivine na sliki %s je: %.2f\n", args[1], svetlostSlike(slika)); + break; + case "zmanjsaj": + izpisiSliko(zmanjsajSliko(slika)); + break; + case "rotiraj": + izpisiSliko(rotirajSliko(slika)); + break; + case "zrcali": + izpisiSliko(zrcaliSliko(slika)); + break; + case "vrstica": + System.out.printf("Max razlika svetlo - temno je v %d. vrstici.\n", poisciMaxVrstico(slika)); + break; + case "uredi": + preberiVseInIzpisi(Arrays.stream(args).skip(1).toArray(String[]::new)); + break; + case "jedro": + konvolucijaJedro(slika); + break; + case "glajenje": + konvolucijaGlajenje(slika); + break; + case "robovi": + konvolucijaRobovi(slika); + break; + + default: + System.out.println("Napaka: Neveljaven argument."); + } + } + + static int[][] preberiSliko(String ime) { + File file = new File(ime); + + Scanner scanner; + try { + scanner = new Scanner(file); + } catch (FileNotFoundException e) { + System.out.printf("Napaka: datoteka %s ne obstaja.\n", ime); + return null; + } + + if (!scanner.hasNextLine()) { + System.out.printf("Napaka: Datoteka %s je prazna.\n", ime); + return null; + } + + String format = scanner.nextLine(); + + Pattern pattern = Pattern.compile("^P2: (.+) x (.+)$"); + Matcher matcher = pattern.matcher(format); + + if (!matcher.matches()) { + System.out.printf("Napaka: datoteka %s ni v formatu P2.\n", ime); + return null; + } + + int width, height; + try { + width = Integer.parseInt(matcher.group(1)); + height = Integer.parseInt(matcher.group(2)); + } catch (NumberFormatException e) { + System.out.printf("Napaka: datoteka %s ni v formatu P2 (velikost slike ni pravilna).\n", ime); + return null; + } + + if (width <= 0 || height <= 0) { + System.out.printf("Napaka: datoteka %s ni v formatu P2 (velikost slike je 0 ali negativna).\n", ime); + return null; + } + + if (!scanner.hasNextLine()) { + System.out.printf("Napaka: datoteka %s vsebuje premalo podatkov.\n", ime); + return null; + } + + String[] data = scanner.nextLine().split(" "); + + if (data.length < width * height) { + System.out.printf("Napaka: datoteka %s vsebuje premalo podatkov.\n", ime); + return null; + } + + int[][] image = new int[height][width]; + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { + int p = Integer.parseInt(data[i * width + j]); + if (p < 0 || p > 255) { + System.out.printf("Napaka: datoteka %s vsebuje podatke izven obsega 0 do 255.\n", ime); + return null; + } + image[i][j] = p; + } + } + + return image; + } + + static void izpisiSliko(int[][] slika) { + System.out.printf("velikost slike: %d x %d\n", slika[0].length, slika.length); + + for (int[] row : slika) { + for (int p : row) { + System.out.printf("%3d ", p); + } + System.out.println(); + } + } + + static void izpisiHistogram(int[][] slika) { + int[] histogram = new int[256]; + + for (int[] row : slika) { + for (int p : row) { + histogram[p]++; + } + } + + System.out.println("sivina : # pojavitev"); + for (int i = 0; i < 256; i++) { + if (histogram[i] == 0) continue; + System.out.printf(" %3d : %d\n", i, histogram[i]); + } + } + + static double svetlostSlike(int[][] slika) { + double sum = 0; + for (int[] row : slika) { + for (int p : row) { + sum += p; + } + } + return sum / (slika.length * slika[0].length); + } + + static int[][] zmanjsajSliko(int[][] slika) { + int width = slika[0].length; + int height = slika.length; + if (width < 3 || height < 3) { + return slika; + } + + int newWidth = width / 2; + int newHeight = height / 2; + + int[][] newImage = new int[newHeight][newWidth]; + + for (int i = 0; i < newHeight; i++) { + for (int j = 0; j < newWidth; j++) { + newImage[i][j] = (slika[i * 2][j * 2] + slika[i * 2][j * 2 + 1] + slika[i * 2 + 1][j * 2] + slika[i * 2 + 1][j * 2 + 1]) / 4; + } + } + + return newImage; + } + + static int[][] rotirajSliko(int[][] slika) { + int width = slika[0].length; + int height = slika.length; + + int[][] newImage = new int[width][height]; + + for (int i = 0; i < width; i++) { + for (int j = 0; j < height; j++) { + newImage[i][j] = slika[height - j - 1][i]; + } + } + + return newImage; + } + + static int[][] zrcaliSliko(int[][] slika) { + int width = slika[0].length; + int height = slika.length; + + int[][] newImage = new int[height][width]; + + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { + newImage[i][j] = slika[i][width - j - 1]; + } + } + + return newImage; + } + + static int poisciMaxVrstico(int[][] slika) { + int maxDiff = 0; + int maxDiffIndex = 0; + + for (int i = 0; i < slika.length; i++) { + int min = slika[i][0]; + int max = slika[i][0]; + + for (int j = 1; j < slika[i].length; j++) { + if (slika[i][j] < min) { + min = slika[i][j]; + } + if (slika[i][j] > max) { + max = slika[i][j]; + } + } + + int diff = max - min; + if (diff > maxDiff) { + maxDiff = diff; + maxDiffIndex = i; + } + } + + return maxDiffIndex + 1; + } + + static int[][][] preberiBarvnoSliko(String ime) { + File file = new File(ime); + + Scanner scanner; + try { + scanner = new Scanner(file); + } catch (FileNotFoundException e) { + System.out.printf("Napaka: datoteka %s ne obstaja.\n", ime); + return null; + } + + if (!scanner.hasNextLine()) { + System.out.printf("Napaka: Datoteka %s je prazna.\n", ime); + return null; + } + + String format = scanner.nextLine(); + + Pattern pattern = Pattern.compile("^P2B: (.+) x (.+)$"); + Matcher matcher = pattern.matcher(format); + + if (!matcher.matches()) { + System.out.printf("Napaka: datoteka %s ni v formatu P2B.\n", ime); + return null; + } + + int width, height; + try { + width = Integer.parseInt(matcher.group(1)); + height = Integer.parseInt(matcher.group(2)); + } catch (NumberFormatException e) { + System.out.printf("Napaka: datoteka %s ni v formatu P2B (velikost slike ni pravilna).\n", ime); + return null; + } + + if (width <= 0 || height <= 0) { + System.out.printf("Napaka: datoteka %s ni v formatu P2B (velikost slike je 0 ali negativna).\n", ime); + return null; + } + + if (!scanner.hasNextLine()) { + System.out.printf("Napaka: datoteka %s vsebuje premalo podatkov.\n", ime); + return null; + } + + String[] data = scanner.nextLine().split(" "); + + if (data.length < width * height) { + System.out.printf("Napaka: datoteka %s vsebuje premalo podatkov.\n", ime); + return null; + } + + int[][][] image = new int[height][width][3]; + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { + int p = Integer.parseInt(data[i * width + j]); + int mask = 0b1111111111; + image[i][j][2] = p & mask; + image[i][j][1] = (p >> 10) & mask; + image[i][j][0] = (p >> 20) & mask; + } + } + + return image; + } + + static void izpisiBarvnoSliko(int[][][] slika) { + System.out.println("velikost slike: " + slika[0].length + " x " + slika.length); + + for (int[][] row : slika) { + for (int[] p : row) { + System.out.printf("(%4d, %4d, %4d) ", p[0], p[1], p[2]); + } + System.out.println(); + } + } + + static int[][] pretvoriVSivinsko(int[][][] slika) { + int width = slika[0].length; + int height = slika.length; + + int[][] newImage = new int[height][width]; + + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { + newImage[i][j] = (slika[i][j][0] + slika[i][j][1] + slika[i][j][2]) / 3 * 255 / 1023; + } + } + + return newImage; + } + + static void preberiVseInIzpisi(String[] imenaSlik) { + int[][] map = new int[imenaSlik.length][2]; + + for (int i = 0; i < imenaSlik.length; i++) { + int[][] slika = preberiSliko(imenaSlik[i]); + if (slika == null) continue; + int svetlost = (int) Math.round(svetlostSlike(slika)); + map[i][0] = svetlost; + map[i][1] = i; + } + + for (int i = 0; i < map.length; i++) { + for (int j = 0; j < map.length - i - 1; j++) { + if (map[j][0] < map[j + 1][0] || (map[j][0] == map[j + 1][0] && imenaSlik[map[j][1]].compareToIgnoreCase(imenaSlik[map[j + 1][1]]) > 0)) { + int[] temp = map[j]; + map[j] = map[j + 1]; + map[j + 1] = temp; + } + } + } + + for (int[] pair : map) { + System.out.printf("%s (%d)\n", imenaSlik[pair[1]], pair[0]); + } + } + + static void konvolucijaJedro(int[][] slika) { + int[][] jedro = { + {1, 1, 1}, + {1, 1, 1}, + {1, 1, 1} + }; + + int width = slika[0].length; + int height = slika.length; + + int[][] novaSlika = new int[height - 2][width - 2]; + + for (int i = 1; i < height - 1; i++) { + for (int j = 1; j < width - 1; j++) { + int sum = 0; + for (int k = -1; k <= 1; k++) { + for (int l = -1; l <= 1; l++) { + sum += slika[i + k][j + l] * jedro[k + 1][l + 1]; + } + } + novaSlika[i - 1][j - 1] = sum; + } + } + + izpisiSliko(novaSlika); + } + + static int[][] razsiriSliko(int[][] slika) { + int w = slika[0].length; + int h = slika.length; + + int[][] razsirjena = new int[h + 2][w + 2]; + for (int i = 0; i < razsirjena.length; i++) { + for (int j = 0; j < razsirjena[i].length; j++) { + if (i == 0 && j == 0) { + razsirjena[i][j] = slika[0][0]; + } else if (i == 0 && j == w + 1) { + razsirjena[i][j] = slika[0][w - 1]; + } else if (i == h + 1 && j == 0) { + razsirjena[i][j] = slika[h - 1][0]; + } else if (i == h + 1 && j == w + 1) { + razsirjena[i][j] = slika[h - 1][w - 1]; + } else if (i == 0) { + razsirjena[i][j] = slika[0][j - 1]; + } else if (i == h + 1) { + razsirjena[i][j] = slika[h - 1][j - 1]; + } else if (j == 0) { + razsirjena[i][j] = slika[i - 1][0]; + } else if (j == w + 1) { + razsirjena[i][j] = slika[i - 1][w - 1]; + } else { + razsirjena[i][j] = slika[i - 1][j - 1]; + } + } + } + + return razsirjena; + } + + static void konvolucijaGlajenje(int[][] slika) { + double[][] jedro = { + {16, 8, 16}, + {8, 4, 8}, + {16, 8, 16}, + }; + + int width = slika[0].length; + int height = slika.length; + + int[][] razsirjenaSlika = razsiriSliko(slika); + + int[][] novaSlika = new int[height][width]; + + for (int i = 1; i <= height; i++) { + for (int j = 1; j <= width; j++) { + int sum = 0; + for (int k = -1; k <= 1; k++) { + for (int l = -1; l <= 1; l++) { + sum += (int) Math.round(razsirjenaSlika[i + k][j + l] / jedro[k + 1][l + 1]); + } + } + novaSlika[i - 1][j - 1] = sum; + } + } + + izpisiSliko(novaSlika); + } + + static void konvolucijaRobovi(int[][] slika) { + int width = slika[0].length; + int height = slika.length; + + int[][] razsirjenaSlika = razsiriSliko(slika); + + int[][] navpicni = { + {1, 0, -1}, + {2, 0, -2}, + {1, 0, -1} + }; + int[][] roboviNavpicno = new int[height][width]; + for (int i = 1; i <= height; i++) { + for (int j = 1; j <= width; j++) { + int sum = 0; + for (int k = -1; k <= 1; k++) { + for (int l = -1; l <= 1; l++) { + sum += razsirjenaSlika[i + k][j + l] * navpicni[k + 1][l + 1]; + } + } + roboviNavpicno[i - 1][j - 1] = sum; + } + } + + int[][] vodoravni = { + {1, 2, 1}, + {0, 0, 0}, + {-1, -2, -1} + }; + int[][] roboviVodoravno = new int[height][width]; + for (int i = 1; i <= height; i++) { + for (int j = 1; j <= width; j++) { + int sum = 0; + for (int k = -1; k <= 1; k++) { + for (int l = -1; l <= 1; l++) { + sum += razsirjenaSlika[i + k][j + l] * vodoravni[k + 1][l + 1]; + } + } + roboviVodoravno[i - 1][j - 1] = sum; + } + } + + int[][] roboviSkupaj = new int[height][width]; + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { + roboviSkupaj[i][j] = (int) Math.round(Math.sqrt(roboviNavpicno[i][j] * roboviNavpicno[i][j] + roboviVodoravno[i][j] * roboviVodoravno[i][j])); + } + } + + int max = 0; + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { + max = Math.max(max, roboviSkupaj[i][j]); + } + } + + int[][] roboviKoncni = new int[height][width]; + + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { + roboviKoncni[i][j] = (int) Math.round(roboviSkupaj[i][j] * 255.0 / max); + } + } + + izpisiSliko(roboviKoncni); + } +}