I need to replicate the image - java

So this program needs to do a few things with the image. I started writing method called replicate and what it needs to do is to take in num1 and num2, and then duplicate the image left-right num1 times, and then replicate the picture num2 times top to bottom. So like the same a small image would act as desktop wallpaper, it's repeat itself. I am not allowed to use image buffer. thank you
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.*;
import javax.imageio.ImageIO;
public class ImageTool {
// THIS METHOD MAY BE CALLED, BUT MUST NOT BE MODIFIED!
//
public static int[][] readGrayscaleImage(String filename) {
int [][] result = null;
try {
File imageFile = new File(filename);
BufferedImage image = ImageIO.read(imageFile);
int height = image.getHeight();
int width = image.getWidth();
result = new int[height][width];
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int rgb = image.getRGB(x, y);
result[y][x] = rgb & 0xff;
}
}
}
catch (IOException ioe) {
System.err.println("Problems reading file named " + filename);
System.exit(1);
}
return result;
}
// THIS METHOD MAY BE CALLED, BUT MUST NOT BE MODIFIED!
//
public static void writeGrayscaleImage(String filename, int[][] array) {
int width = array[0].length;
int height = array.length;
try {
BufferedImage image = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int rgb = array[y][x];
rgb |= rgb << 8;
rgb |= rgb << 16;
image.setRGB(x, y, rgb);
}
}
File imageFile = new File(filename);
ImageIO.write(image, "jpg", imageFile);
}
catch (IOException ioe) {
System.err.println("Problems writing file named " + filename);
System.exit(1);
}
}
public static void main (String [] args) {
if (args.length < 1) {
System.out.println("Invalid program execution");
System.out.println("Please provide command");
System.exit(-1);
}
if (args[0].equals("--dump")){
String fileName = args[1];
int [][] image = readGrayscaleImage(fileName);
print2dArray(image);
} else if (args[0].equals("--reflectV")){
String fileName = args[1];
int [][] image = readGrayscaleImage(fileName);
int [][] reflected = reflectV(image);
String outputFilename = args[2];
writeGrayscaleImage(outputFilename, reflected);
} else if (args[0].equals("--reflectH")){
String fileName = args[1];
int [][] image = readGrayscaleImage(fileName);
int [][] reflected = reflectH(image);
String outputFilename = args[2];
writeGrayscaleImage(outputFilename, reflected);
} else if (args[0].equals("--ascii")){
String fileName=args[1];
int [][] image = readGrayscaleImage(fileName);
ascii(image);
} else if (args[0].equals("--replicate")) {
String fileName = args[2];
int [][] image = readGrayscaleImage(fileName);
double factor = args[0];
String outputFilename = args[3];
writeGrayscaleImage(outputFilename, reflected);
}
}
public static void replicate(double num1, double num2, int[][]arr) {
double length = num1 * arr.length;
double height = num2 * arr[0].length;
int[][]newArr = new int[length][height];
for(int i = 0; i <= newArr.length; i++){
for(int j = 0; j <= arr.length; j++){
newArr[i][j]=arr[i][j];
}
}
}
public static void ascii (int[][]arr) {
int rows = arr.length;
int cols = arr[0].length;
for(int i = 0; i < rows; i++){
for(int j = 0; j < cols; j++){
if(arr[i][j] >= 0 && arr[i][j] <= 25){
System.out.print("M");
} else if(arr[i][j]>=26 && arr[i][j] <=50){
System.out.print("$");
} else if(arr[i][j]>=51 && arr[i][j] <= 76){
System.out.print("0");
} else if(arr[i][j]>=77 && arr[i][j] <=102){
System.out.print("|");
} else if(arr[i][j]>=103 && arr[i][j]<=127){
System.out.print("*");
} else if (arr[i][j]>=128 && arr[i][j]<=152){
System.out.print(":");
} else if (arr[i][j]>=153 && arr[i][j]<=178){
System.out.print("=");
} else if (arr[i][j]>=179 && arr[i][j]<=204){
System.out.print("\'");
} else if (arr[i][j]>=205 && arr[i][j]<=230){
System.out.print(".");
} else if (arr[i][j]>=231 && arr[i][j]<=255){
System.out.print(" ");
}
}
System.out.println();
}
}
public static void print2dArray(int[][] arr) {
for (int i = 0; i <arr.length; i++){
//System.out.println(Arrays.toString(arr[i]));
for (int j = 0; j< arr[i].length; j++){
System.out.format("%3d, " , arr[i][j]);
}
System.out.println();
}
}
public static int [][] reflectV (int [][] arr) {
int rows = arr.length;
int cols = arr[0].length;
int [][] reflected = new int[rows][cols];
for (int i = 0; i < rows; i++){
for(int j = 0; j < cols; j++) {
reflected [i][j] = arr[i][cols-j-1];
}
}
//go through arr and reverse values in each row
return reflected;
}
public static int [][] reflectH (int [][] arr) {
int rows = arr.length;
int cols = arr[0].length;
int [][] reflected = new int[rows][cols];
for (int i = 0; i < cols; i++){
for(int j = 0; j < rows; j++) {
reflected [j][i] = arr[cols-j-1][i];
}
}
//go through arr and reverse values in each row
return reflected;
}
}

This should be the solution:
public static int[][] replicate(double num1, double num2, int[][]arr) {
double length = num1 * arr.length;
double height = num2 * arr[0].length;
int[][]newArr = new int[(int) length][(int) height];
for(int i = 0; i < newArr.length; i++){
for(int j = 0; j < newArr[i].length; j++){
newArr[i][j]=arr[i % arr.length][j % arr[0].length];
}
}
return newArr;
}
Test input:
1 2 3
4 5 6
7 8 9
The method calculates the output array as follows (num1=1.8d and num2=1.8d):
1 2 3 1 2
4 5 6 4 5
7 8 9 7 8
1 2 3 1 2
4 5 6 4 5
Please note that I have changed the signature of the method. It now returns the resulting array.

Related

I'm getting Runtime Error when submitting answer to online judge. What could be the cause?

Link to the problem : https://vjudge.net/problem/UVA-1665
This is my code so far it works on my end with the sample input provided by the problem statement, i already tried to change the class name from class problemb to public class Main as someone else did with a similar issue but no luck. Any help would be appreciated.
import java.io.BufferedReader;
import java.io.InputStreamReader;
class problemb {
static int dx[] = {-1, 0, 1, 0};
static int dy[] = {0, 1, 0, -1};
static int[][] map;
static boolean[][] visited;
static int n, m;
static int t;
static int[] years;
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int z = Integer.parseInt(br.readLine());
for (int i = 0; i < z; i++) {
String[] nm = br.readLine().split(" ");
n = Integer.parseInt(nm[0]);
m = Integer.parseInt(nm[1]);
map = new int[n][m];
visited = new boolean[n][m];
for (int j = 0; j < n; j++) {
String[] row = br.readLine().split(" ");
for (int k = 0; k < m; k++) {
map[j][k] = Integer.parseInt(row[k]);
}
}
t = Integer.parseInt(br.readLine());
years = new int[t];
String[] tValues = br.readLine().split(" ");
for (int j = 0; j < t; j++) {
years[j] = Integer.parseInt(tValues[j]);
}
br.close();
int[] results = new int[t];
for (int j = 0; j < t; j++) {
int year = years[j];
int areas = 0;
// Reset the visited array for the current year
visited = new boolean[n][m];
for (int y = 0; y < n; y++) {
for (int x = 0; x < m; x++) {
if (!visited[y][x] && map[y][x] > year) {
areas++;
bfs(y, x, year);
}
}
}
results[j] = areas;
}
for (int j = 0; j < results.length; j++) {
System.out.print(results[j]);
if (j < results.length - 1) {
System.out.print(" ");
}
}
System.out.println();
}
}
static void bfs(int y, int x, int year) {
int[][] queue = new int[n * m][2];
int head = 0, tail = 0;
queue[tail][0] = y;
queue[tail][1] = x;
tail++;
visited[y][x] = true;
while (head < tail) {
int yy = queue[head][0];
int xx = queue[head][1];
head++;
for (int i = 0; i < 4; i++) {
int ny = yy + dy[i];
int nx = xx + dx[i];
if (ny < 0 || ny >= n || nx < 0 || nx >= m || visited[ny][nx] || map[ny][nx] <= year) {
continue;
}
visited[ny][nx] = true;
queue[tail][0] = ny;
queue[tail][1] = nx;
tail++;
}
}
}
}

Java 2D Array; Variable Row & Column Length from File Input

For this intro-level assignment, I have to set up a 2D multidimensional array from a file and from a double[][] a and apply several methods to them. For now, I'm mostly concerned with simply initializing the arrays. I'm trying to figure out a way to take a test file, read the first int as the number of rows, the first integer of each line as the number of columns per row, and each double as a member of the array.
public class MDArray
{
static int rowCount;
static int columnCount;
private static double[][] mdarray = new double[rowCount][columnCount];
public MDArray(double[][] a)
{
mdarray = a;
}
public MDArray(String file)
{
Scanner input = null;
try
{
input = new Scanner(new FileInputStream("ragged.txt"));
}
catch (FileNotFoundException e)
{
System.out.println("File Not Found.");
System.exit(0);
}
while(input.hasNextDouble())
{
rowCount = input.nextInt();
for(int i = 0; i < rowCount; i++)
{
columnCount = input.nextInt();
for(int j = 0; j < columnCount; j++)
{
double value = input.nextDouble();
mdarray[i][j] = value;
}
}
}
}
public static boolean isRagged()
{
for(int i = 0; i < mdarray.length; i++)
{
int rowLength1 = mdarray.length;
for(int j = i + 1; j < mdarray.length; j++)
{
int rowLength2 = mdarray.length;
if(rowLength1 != rowLength2)
{
return true;
}
}
}
return false;
}
public static int getNumberOfRows()
{
int numRows = 0;
for(int i = 0; i < mdarray.length; i++)
{
numRows++;
}
return numRows;
}
public static int getNumberOfCols()
{
int numCols = 0;
for(int i = 0, j = i + 1; i < mdarray.length; i++)
{
for(int k = 0; k < mdarray[i].length; k++)
{
if(mdarray[i].length > mdarray[j].length)
{
numCols++;
}
}
}
return numCols;
}
public static double getValAt(int i, int j)
{
if(i > mdarray.length || j > mdarray[i].length)
{
double invalid = Double.NaN;
return invalid;
}
double valAt = mdarray[i][j];
return valAt;
}
public static void sort(boolean byColumn)
{
if(isRagged() == true)
{
System.out.println("Ragged arrays cannot be sorted by column.");
}
else{
for(int i = 0; i < mdarray.length; i++)
{
for(int j = 0; j < mdarray[i].length; j++)
{
for(int k = j + 1; k < mdarray[i].length; k++)
{
if(mdarray[i][j] < mdarray[i][k])
{
double temp = mdarray[i][j];
mdarray[i][k] = mdarray[i][j];
mdarray[i][j] = temp;
}
}
}
}
}
}
public static int hamming(boolean byColumn)
{
int hamVal = 0;
if(isRagged() == true)
{
System.out.println("Ragged arrays cannot be sorted by column.");
}
else{
for(int i = 0; i < mdarray.length; i++)
{
for(int j = 0; j < mdarray[i].length; j++)
{
for(int k = j + 1; k < mdarray[i].length; k++)
{
if(mdarray[i][j] < mdarray[i][k])
{
double temp = mdarray[i][j];
mdarray[i][k] = mdarray[i][j];
mdarray[i][j] = temp;
hamVal++;
}
}
}
}
}
return hamVal;
}
public static double[] max()
{
double[] maxVal = new double[mdarray.length];
for(int i = 0, j = i + 1; i < maxVal.length; i++)
{
for(int k = 0; k < mdarray[i].length; k++)
{
if(mdarray[i][k] > mdarray[j][k])
{
maxVal = mdarray[i];
}
}
}
return maxVal;
}
public String toString()
{
String arrayString = "";
for(int i = 0; i < mdarray.length; i++)
{
for(int j = 0; j < mdarray[i].length; j++)
{
arrayString += ", " + mdarray[i][j];
}
arrayString = arrayString + "/n";
}
return arrayString;
}
}
This was the file I was testing the MDArray(String file) with:
3
2 4.1 8.9
5 9.5 2.0 7.3 2.1 8.9
3 1.3 5.2 3.4
I think the problem is that the rowCount and columnCount integers are not initialized, but I'm not sure how to initialize them to a variable length with basic array skills. This is also affecting the other constructor as well. Being an intro-level course, I am not supposed to use more advanced techniques such as ArrayList. In addition, I can't verify if the methods are correct, since I don't have an array to test them with.
EDIT: While I did implement many of the suggestions in the answers, such as changing everything to non-static and other changes, I'm still getting a NullPointerException for the line mdarray[i][j] = input.nextDouble();. I assume it has to do with the private double[][] mdarray, which is required in the assignment specifications. Now I'm trying to find a way to initialize it such that it can be overridden in the later methods.
You have to initialize the array in your constructor, since that's when you know the dimensions :
public MDArray(String file)
{
Scanner input = null;
try {
input = new Scanner(new FileInputStream("ragged.txt"));
}
catch (FileNotFoundException e) {
System.out.println("File Not Found.");
System.exit(0);
}
rowCount = input.nextInt();
mdarray = new double[rowCount][]; // init the array
for(int i = 0; i < rowCount; i++) {
columnCount = input.nextInt();
mdarray[i] = new double[columnCount]; // init the current row
for(int j = 0; j < columnCount; j++) {
mdarray[i][j] = input.nextDouble();
}
}
}
You could initialize your arrays by putting the amount of rows and columns on the first 2 lines of your multidimensional array, if i had 10 rows and 12 columns i could do something like this:
public void arrayStuff() {
File fileToRead = new File("YOUR LINK HERE");
String[][] data;
try (BufferedReader reader = new BufferedReader(new FileReader(fileToRead))) {
String line;
data = new String[Integer.parseInt(reader.readLine())][Integer.parseInt(reader.readLine())];
while((line = reader.readLine()) != null) {
// read the rest here..
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I am using an AutoCloseable (which is why the try is between these ()'s, but this is so that i don't have to close it afterwards.
Basically, first i read the amount of rows there are and then the amount of columns there are, so if i had this file:
10
12
a b c d e f g h i j
a b c d e f g h i j
a b c d e f g h i j
a b c d e f g h i j
a b c d e f g h i j
a b c d e f g h i j
a b c d e f g h i j
a b c d e f g h i j
a b c d e f g h i j
a b c d e f g h i j
a b c d e f g h i j
a b c d e f g h i j
It'd be able to read all of this, because the amount of rows and columns were defined in the file.
You don't use the fields rowCount and columnCount: you can remove them
The mdarray field should be non-static, so should be the methods that use them (if it was a utility class, you wouldn't have any constructor)
The arrays can be created while reading the file:
Scanner input = null;
try
{
input = new Scanner(new FileInputStream("ragged.txt"));
}
catch (FileNotFoundException e)
{
System.out.println("File Not Found.");
System.exit(0);
}
int rowCount = input.nextInt();
mdarray = new double[rowCount][];
for(int i = 0; i < rowCount; i++)
{
int columnCount = input.nextInt();
mdarray[i] = new double[columnCount];
for(int j = 0; j < columnCount; j++)
{
double value = input.nextDouble();
mdarray[i][j] = value;
}
}
methods getNumberOfRows() and getNumberOfCols() count be much simpler:
public int getNumberOfRows()
{
return mdarray.length;
}
public int getNumberOfCols() {
int result = 0;
for (double[] col: mdarray) {
if (col.length > result) {
result = col.length;
}
}
return result;
}
In getValueAt(), the test is wrong; it should be:
if(i >= mdarray.length || j >= mdarray[i].length)

Make a Grid from a string in a text file

I have three run arguments that are min width, max width and the text file name. The text files are filled with one long string of random characters. I want to put each character into a grid spot. But all I get back is the string itself from the file. How do I make the grid?
class GridCipher{
static int minGridWidth;
static int maxGridWidth;
static File inputFile;
public static void main(String[] args) throws FileNotFoundException {
if (handleArguments(args))
processInput();
}
static final String usage = "Usage: GridWriter min_width max_width input_file_name";
static boolean handleArguments(String[] args) {
// Check for correct number of arguments
if (args.length != 3) {
System.out.println("Wrong number of command line arguments.");
System.out.println(usage);
return false;
}
try {
minGridWidth = Integer.parseInt(args[0]);
maxGridWidth = Integer.parseInt(args[1]);
} catch (NumberFormatException ex) {
System.out.println("min_width and max_width must be integers.");
System.out.println(usage);
return false;
}
inputFile = new File(args[2]);
if (!inputFile.canRead()) {
System.out.println("The file " + args[2] + " cannot be opened for input.");
return false;
}
return true;
}
static void processInput() throws FileNotFoundException {
Scanner input = new Scanner(inputFile);
String line = input.nextLine();
int length = line.length(); // number of characters.
// Try each width in the appropriate range
for (int width = minGridWidth; width <= maxGridWidth; width++) {
// Determine heigth of grid
int height = line.length() / width;
// Add one to height if there's a partial last row
if (line.length() % width != 0)
height += 1;
loadUnloadGrid(line, width, height);
}
}
static void loadUnloadGrid(String line, int width, int height) {
char grid[][] = new char[height][width];
// Determine number long columns
int longColumn = line.length() % width;
if (longColumn == 0)
longColumn = width;
//Load the input data into the grid by column
int charCount = 0;
for (int c = 0; c < width; c++) {
for (int r = 0; r < height; r++) {
if (r < height - 1 || c < longColumn) {
grid[r][c] = line.charAt(charCount);
charCount += 1;
}
}
}
// Output data from the grid by rows
for (int r = 0; r < height - 1; r++) {
for (int c = 0; c < width; c++) {
System.out.print(grid[r][c]);
}
}
// Special handling for last row
for (int c = 0; c < longColumn; c++) {
System.out.print(grid[height - 1][c]);
}
System.out.println("\"");
}
}
If the text file has ABCDE, I just get back ABCDE. I would like the characters in a grid determined by my min and max width.
If I understand you correctly you want ABCDEFG into
A B C
D E F
G
but in the fragment writing it on screen you miss new line character
// Output data from the grid by rows
for (int r = 0; r < height - 1; r++) {
for (int c = 0; c < width; c++) {
System.out.print(grid[r][c]);
}
}
should be
// Output data from the grid by rows
for (int r = 0; r < height - 1; r++) {
for (int c = 0; c < width; c++) {
System.out.print(grid[r][c]);
}
System.out.println();
}
Printing grid is not correct in your program.
Change below to
// Output data from the grid by rows
for (int r = 0; r < height - 1; r++) {
for (int c = 0; c < width; c++) {
System.out.print(grid[r][c]);
}
}
this code
for(char[] arr : grid) {
System.out.println(Arrays.toString(arr));
}

Java code - compile time optimisation

I am new to programming and have programmed a java program that calculates the voronoi diagram for random points and draws it on a picture - 1080 x 1920 pixels. Here you can see the result
The problem is that it takes nearly four minutes to compile the code. Please help me with code optimization. Below you can find the code:
class Voronoi {
private static Random r;
private static KDTree<Integer> kd;
private static double[][] keys;
private static int counter;
private static int x;
public static void main(String[] args) throws IOException,
KeySizeException, KeyDuplicateException {
BufferedImage img = null;
Scanner sc = new Scanner(System.in);
x = sc.nextInt();
// input an image
img = ImageIO.read(new File("input.jpg"));
// get image Height and Width
int w = img.getWidth();
int h = img.getHeight();
// make array with equal size like the image and populate it with the 0
// make an empty array and populate it
int[][] empty = new int[h][w];
for (int row = 0; row < h; row++) {
for (int col = 0; col < w; col++) {
empty[row][col] = 0;
}
}
// make a D-dimensional KD-tree
keys = new double[x][2];
kd = new KDTree<Integer>(2);
ArrayList<Color> b = new ArrayList<Color>();
int[] totalBlue = new int[x];
int[] totalGreen = new int[x];
int[] totalRed = new int[x];
int[] counter_sec = new int[x];
// Generate random centers and populate them with 1
for (int i = 0; i < x; i++) {
generateCentre(empty, h, w);
// b.add(new Color(r.nextInt(256),r.nextInt(256),r.nextInt(256)));
}
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
double[] array = new double[2];
array[0] = i;
array[1] = j;
Color c = new Color(img.getRGB(j, i));
totalBlue[kd.nearest(array)] = totalBlue[kd.nearest(array)]
+ c.getBlue();
totalRed[kd.nearest(array)] = totalRed[kd.nearest(array)]
+ c.getRed();
totalGreen[kd.nearest(array)] = totalGreen[kd.nearest(array)]
+ c.getGreen();
// img.setRGB(j, i, b.get(kd.nearest(array)).getRGB());
counter_sec[kd.nearest(array)] = counter_sec[kd.nearest(array)] + 1;
}
}
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
double[] array = new double[2];
array[0] = i;
array[1] = j;
Color c = new Color(img.getRGB(j, i));
// img.setRGB(j, i, b.get(kd.nearest(array)).getRGB());
Color color = new Color(totalRed[kd.nearest(array)]/counter_sec[kd.nearest(array)], totalGreen[kd.nearest(array)]/counter_sec[kd.nearest(array)],totalBlue[kd.nearest(array)]/counter_sec[kd.nearest(array)]);
img.setRGB(j, i, color.getRGB());
}
}
File outputfile = new File("image.jpg");
ImageIO.write(img, "jpg", outputfile);
System.out.println(totalRed[0]/counter_sec[0]+" "+totalGreen[0]/counter_sec[0]+" "+totalBlue[0]/counter_sec[0]);
}
public static void generateCentre(int[][] empty, int h, int w)
throws KeySizeException, KeyDuplicateException {
r = new Random();
int height = r.nextInt(h);
int width = r.nextInt(w);
for (int row = 0; row < h; row++) {
for (int col = 0; col < w; col++) {
if (row == height && col == width && empty[height][width] == 0) {
empty[height][width] = 1;
keys[counter][0] = row;
keys[counter][2] = col;
kd.insert(keys[counter], counter);
}/*else if (row == height && col == width
&& empty[height][width] != 0) {
generateCentre(empty, h, w);
}*/
}
}
System.out.println(kd.search(keys[counter]));
if (counter < x) {
counter++;
}
}
}
Although I don't claim a full understanding of your code, I see one potentially large cause of slowdown:
totalBlue[kd.nearest(array)] = totalBlue[kd.nearest(array)]
+ c.getBlue();
totalRed[kd.nearest(array)] = totalRed[kd.nearest(array)]
+ c.getRed();
totalGreen[kd.nearest(array)] = totalGreen[kd.nearest(array)]
+ c.getGreen();
// img.setRGB(j, i, b.get(kd.nearest(array)).getRGB());
counter_sec[kd.nearest(array)] = counter_sec[kd.nearest(array)] + 1;
You seem to be repeatedly calling kd.nearest(array), which is probably not a very cheap operation. You should call that once and store it in a local variable. I would rewrite your key loop as follows:
double[] coords = new double[2];
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
coords[0] = i;
coords[1] = j;
final int nearest = kd.nearest(coords);
final Color c = new Color(img.getRGB(j, i));
totalBlue[nearest] += c.getBlue();
totalRed[nearest] += c.getRed();
totalGreen[nearest] += c.getGreen();
counter_sec[nearest]++;
}
}
Here I have utilized the += and ++ operators to make things shorter and more readable. I have also hoisted your coordinates array outside the loop because it can be safely reused at each iteration. This reduces GC time, but more importantly it helps CPU caches.
Apply the same changes to your second loop, where you generate the output image.

Image Processing: averaging filter on a grayscale image

I am working on an assignment that asking us to Develop a program that perform averaging filter on a grayscale image with different filter sizes 3x3, 5x5...11x11
First I developed a matrix class in Java:
final public class Matrix {
private final int M; // number of rows
private final int N; // number of columns
private final double[][] data; // M-by-N array
// create M-by-N matrix of 0's
public Matrix(int M, int N) {
this.M = M;
this.N = N;
data = new double[M][N];
}
// create matrix based on 2d array
public Matrix(double [][] data) {
M = data.length;
N = data[0].length;
this.data = new double[M][N];
for (int i = 0; i < M; i++)
for (int j = 0; j < N; j++)
this.data[i][j] = data[i][j];
}
public static Matrix filter(int M, int N) {
Matrix A = new Matrix(M, N);
for (int i = 0; i < M; i++)
for (int j = 0; j < N; j++)
A.data[i][j] = (1.0/9.0);
return A;
}
// copy constructor
private Matrix(Matrix A) { this(A.data); }
// return C = A + B
public Matrix plus(Matrix B) {
Matrix A = this;
if (B.M != A.M || B.N != A.N) throw new RuntimeException("Illegal matrix dimensions.");
Matrix C = new Matrix(M, N);
for (int i = 0; i < M; i++)
for (int j = 0; j < N; j++)
C.data[i][j] = A.data[i][j] + B.data[i][j];
return C;
}
// return C = A - B
public Matrix minus(Matrix B) {
Matrix A = this;
if (B.M != A.M || B.N != A.N) throw new RuntimeException("Illegal matrix dimensions.");
Matrix C = new Matrix(M, N);
for (int i = 0; i < M; i++)
for (int j = 0; j < N; j++)
C.data[i][j] = A.data[i][j] - B.data[i][j];
return C;
}
public boolean eq(Matrix B) {
Matrix A = this;
if (B.M != A.M || B.N != A.N) throw new RuntimeException("Illegal matrix dimensions.");
for (int i = 0; i < M; i++)
for (int j = 0; j < N; j++)
if (A.data[i][j] != B.data[i][j]) return false;
return true;
}
// return C = A * B
public Matrix multiply(Matrix B) {
Matrix A = this;
if (A.N != B.M) throw new RuntimeException("Illegal matrix dimensions.");
Matrix C = new Matrix(A.M, B.N);
for (int i = 0; i < C.M; i++)
for (int j = 0; j < C.N; j++)
for (int k = 0; k < A.N; k++)
C.data[i][j] += (A.data[i][k] * B.data[k][j]);
return C;
}
public double average (){
double sum=0.0;
for (int i = 0; i < M; i++) {
for (int j = 0; j < N; j++) {
sum = sum + data[i][j];
}
}
return sum;
}
public void show() {
for (int i = 0; i < M; i++) {
for (int j = 0; j < N; j++)
System.out.printf("%9.4f ", data[i][j]);
System.out.println();
}
}
}
Then I developed my Image filtering application as follows:
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
/**
*
* #author Yousra
*/
public class ImgfilterApplication {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
System.out.println("Please Enter Your Image Path Here ...");
Scanner myscanner = new Scanner(System.in);
String path = myscanner.next();
BufferedImage img = getImage(path);
int filtersize = 3;
BufferedImage outimg = TDfilter(img, filtersize);
JFrame frame = new JFrame();
JLabel image = new JLabel(new ImageIcon("imageName.png"));
frame.getContentPane().setLayout(new FlowLayout());
frame.getContentPane().add(new JLabel(new ImageIcon(img)));
frame.getContentPane().add(new JLabel(new ImageIcon(outimg)));
frame.pack();
frame.setVisible(true);
}
public static BufferedImage TDfilter (BufferedImage img, int filtersize){
int w = img.getWidth();
int h = img.getHeight();
WritableRaster cr=img.getRaster();
WritableRaster wr=img.copyData(null);
double[][] imgarray = Img2D(img);
double[][] x = new double[filtersize][filtersize];
Matrix filter = Matrix.filter(filtersize, filtersize);
filter.show();
Matrix imgm = new Matrix(w,h);;
Matrix result;
for (int ii = 0; ii < w; ii++)
for (int jj = 0; jj < h; jj++) {
for (int i = ii; i < filtersize + ii; i++) {
for (int j = jj; j < filtersize + jj; j++) {
if (i - filtersize / 2 < 0 || i - filtersize / 2 >= w || j- filtersize / 2 < 0 || j- filtersize / 2 >= h) {
x[i-ii][j-jj] = 0;
// imgm = new Matrix(x);
} else {
x[i-ii][j-jj] = imgarray[i - filtersize / 2][j - filtersize / 2];
};
}
}
imgm = new Matrix(x);
result = imgm.multiply(filter);
double value = result.average();
wr.setSample(ii, jj, 0, value);
}
BufferedImage img2= new BufferedImage(w, h, img.getType());
img2.setData(wr);
return img2;
}
public static double [][] Img2D(BufferedImage img) {
int w = img.getWidth();
int h = img.getHeight();
double[][] imgarray = new double[w][h] ;
Raster raster = img.getData();
for (int i = 0; i < w; i++) {
for (int j = 0; j < h; j++) {
imgarray[i][j] = raster.getSample(i, j, 0);
}
}
return imgarray;
}
public static BufferedImage getImage(String imageName) {
try {
File input = new File(imageName);
BufferedImage image = ImageIO.read(input);
return image;
} catch (IOException ie) {
System.out.println("Error:" + ie.getMessage());
}
return null;
}
}
This suppose to make the image more blurry, yet it makes it blurry in parts and negative in others in a random pattern. Can You please help :(
I didn't bother digging through you code. Better post pseudo representation of you algorithm.
Well to address the issue with negative parts of image, this happens when there is an number overflow; e.g. you are trying to make pixel with value 256 depending on used data structures and language, it might happen that the byte roll over 256 and instead the pixel gets value 0.
You need to check that all values you are assigning to image are in range <0-255> for 8-bit grayscale.
I figured out what was wrong. I made the filter a matrix and I multiplied the filter matrix by the image filter then I got the average of the resulting matrix.
To correct this is to pass the filter over the whole image and multiply each pixel by the number that is inside the filter then add it all up.

Categories