This question already has answers here:
What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it?
(26 answers)
Closed 5 years ago.
Here is the code:
// Java program for implementation of Ford Fulkerson algorithm
import java.util.*;
import java.lang.*;
import java.io.*;
import java.util.LinkedList;
class MaxFlow
{
static final int V = 8; //Number of vertices in graph
/* Returns true if there is a path from source 's' to sink
't' in residual graph. Also fills parent[] to store the
path */
boolean bfs(int rGraph[][], int s, int t, int parent[])
{
// Create a visited array and mark all vertices as not
// visited
boolean visited[] = new boolean[V];
for(int i=0; i<V; ++i)
visited[i]=false;
// Create a queue, enqueue source vertex and mark
// source vertex as visited
LinkedList<Integer> queue = new LinkedList<Integer>();
queue.add(s);
visited[s] = true;
parent[s]=-1;
// Standard BFS Loop
while (queue.size()!=0)
{
int u = queue.poll();
for (int v=0; v<V; v++)
{
if (visited[v]==false && rGraph[u][v] > 0)
{
queue.add(v);
parent[v] = u;
visited[v] = true;
}
}
}
// If we reached sink in BFS starting from source, then
// return true, else false
return (visited[t] == true);
}
// Returns tne maximum flow from s to t in the given graph
int fordFulkerson(int graph[][], int s, int t)
{
int u, v;
// Create a residual graph and fill the residual graph
// with given capacities in the original graph as
// residual capacities in residual graph
// Residual graph where rGraph[i][j] indicates
// residual capacity of edge from i to j (if there
// is an edge. If rGraph[i][j] is 0, then there is
// not)
int rGraph[][] = new int[V][V];
for (u = 0; u < V; u++)
for (v = 0; v < V; v++)
rGraph[u][v] = graph[u][v];
// This array is filled by BFS and to store path
int parent[] = new int[V];
int max_flow = 0; // There is no flow initially
// Augment the flow while tere is path from source
// to sink
while (bfs(rGraph, s, t, parent))
{
// Find minimum residual capacity of the edhes
// along the path filled by BFS. Or we can say
// find the maximum flow through the path found.
int path_flow = Integer.MAX_VALUE;
for (v=t; v!=s; v=parent[v])
{
u = parent[v];
path_flow = Math.min(path_flow, rGraph[u][v]);
}
// update residual capacities of the edges and
// reverse edges along the path
for (v=t; v != s; v=parent[v])
{
u = parent[v];
rGraph[u][v] -= path_flow;
rGraph[v][u] += path_flow;
}
// Add path flow to overall flow
max_flow += path_flow;
}
// Return the overall flow
return max_flow;
}
// Driver program to test above functions
public static void main (String[] args) throws java.lang.Exception
{
int graph[][] =new int[][] { {0, 14, 0, 10, 0, 18, 0, 0},
{0, 0, 18, 0, 14, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 10},
{0, 0, 10, 0, 8, 0, 0, 0},
{0, 0, 14, 0, 8, 0, 20},
{0, 0, 0, 6, 0, 0, 16},
{0, 0, 16, 0, 0, 0, 0, 6},
{0,0,0,0,0,0,0,0} };
MaxFlow m = new MaxFlow();
System.out.println("The maximum possible flow is " +
m.fordFulkerson(graph, 0, 7));
}
}
I'd like to modify it to output the path and the weight of each edge but I'm not sure how. I would like to know the path taken so i can see whats going on graphically
edit: The error as someone has pointed out was that I was missing two elements when i created my matrix. Still unsure how to output the path used.
ArrayIndexOutOfBoundsException is thrown when an array is accessed at an invalid index.
for (u = 0; u < V; u++)
for (v = 0; v < V; v++)
rGraph[u][v] = graph[u][v];
tries to access 8 indexes in 8 one-dimensional arrays in graph and rgraph. But in line# 113, {0, 0, 14, 0, 8, 0, 20}, has 7 elements, which is the 6th one-dimensional array in graph. So accessing graph[5][7] is causing the out of bound error.
Related
I have a simple 2D polygon with 4 points.
int[] x = {38, 100, 80, 18};
int[] y = {50, 50, 100, 100};
Polygon poly = new Polygon(x, y, 4);
The above polygon is just an example. The polygon above could really be anything as long as the polygon is always convex, always has 4 points, and is a parallelogram. I need to split it into any number of even parts, all proportional to the bigger polygon, as long as the number is a square number. Is there any simple way I can do this? I am using Graphics on a Jframe if that's important at all.
The code below works for any convex 4-sided polygon. When the initial polygon is a parallelogram, the resultant sub-polygons are by nature all parallelograms too, all with the same size, i.e. they are even-sized.
Since the desired number of parts must be a square number, it means we can simply split the 4-sided polygon horizontally and vertically into partsPerSide = sqrt(parts).
When we split a 4-sided polygon into multiple parts, we may end up with coordinates that are not exact integers. We can simply round the value to an integer, but then the pieces wouldn't be exactly even in size. Whether that is acceptable is a matter of choice. Visually, the rounding can be noticed, since the lines won't be 100% straight.
In the code below, we assume that rounding is not acceptable, i.e. we want exact even sizes. If rounding is ok, simply comment out the if (rounded != delta) throw new ArithmeticException() code at the end, then call splitFourSided() with the desired number of partsPerSide.
Enough talk, here is the code:
private static Polygon[][] splitFourSided(Polygon poly, int partsPerSide) {
if (poly.npoints != 4)
throw new IllegalArgumentException("Polygon must be 4-sided");
if (partsPerSide <= 0)
throw new IllegalArgumentException("There must be a positive number of parts per side");
int[][] x = splitFourSided(poly.xpoints, partsPerSide);
int[][] y = splitFourSided(poly.ypoints, partsPerSide);
Polygon[][] pieces = new Polygon[partsPerSide][partsPerSide];
for (int row = 0; row < partsPerSide; row++) {
for (int col = 0; col < partsPerSide; col++) {
pieces[row][col] = new Polygon(
new int[] { x[row][col], x[row][col+1], x[row+1][col+1], x[row+1][col] },
new int[] { y[row][col], y[row][col+1], y[row+1][col+1], y[row+1][col] },
4);
}
}
return pieces;
}
private static int[][] splitFourSided(int[] xy, int parts) {
// To visualize, assume values are [topLeft, topRight, bottomRight, bottomLeft].
// The 'xy' array is either the x-coordinates or the y-coordinates.
// First we split left and right sides, e.g. for 3 parts:
// From: ┌ To: ┐
// ├ ┤
// ├ ┤
// └ ┘
// Then we split between those:
// ┌─┬─┬─┐
// ├─┼─┼─┤
// ├─┼─┼─┤
// └─┴─┴─┘
int[] from = splitRange(xy[0], xy[3], parts);
int[] to = splitRange(xy[1], xy[2], parts);
int[][] grid = new int[parts + 1][];
for (int i = 0; i <= parts; i++)
grid[i] = splitRange(from[i], to[i], parts);
return grid;
}
private static int[] splitRange(int from, int to, int parts) {
int[] prorated = new int[parts + 1];
for (int i = 0; i <= parts; i++)
prorated[i] = prorate(from, to, i, parts);
return prorated;
}
private static int prorate(int from, int to, int index, int parts) {
if (index == 0)
return from;
if (index == parts)
return to;
double delta = (to - (double) from) * index / parts;
int rounded = (int) Math.round(delta);
if (rounded != delta)
throw new ArithmeticException("Cannot prorate to integer value");
return from + rounded;
}
Test
int[] x = {38, 100, 80, 18};
int[] y = {50, 50, 100, 100};
Polygon poly = new Polygon(x, y, 4);
splitAndDrawFourSided(g, poly, 2);
private static void splitAndDrawFourSided(Graphics g, Polygon poly, int partsPerSide) {
Polygon[][] pieces = splitFourSided(poly, partsPerSide);
for (int row = 0; row < partsPerSide; row++)
for (int col = 0; col < partsPerSide; col++)
g.drawPolygon(pieces[row][col]);
Graphics gMain = g.create();
try {
gMain.setColor(Color.RED);
gMain.drawPolygon(poly);
} finally {
gMain.dispose();
}
}
Result
To search for a valid number of parts, we can add a search loop, and change the coordinates so they are only divisible by 7.
int[] x = {37, 100, 79, 16};
int[] y = {50, 50, 99, 99};
Polygon poly = new Polygon(x, y, 4);
for (int partsPerSide : new int[] { 2, 3, 5, 7, 11, 13, 17, 19 }) {
try {
splitAndDrawFourSided(g, poly, partsPerSide);
break; // stop when successful
} catch (#SuppressWarnings("unused") ArithmeticException ignored) {
continue; // try next number of parts
}
}
Result
If we remove the rounding check, that code will of course always just split by 2 parts per side, i.e. into 4 parts. This shows the effect of rounding, e.g. in this case the center row coordinates ended up a bit to the right, causing the black and red lines to not match up. Even without the red line depicting the input parallelogram, the rounding can be noticed. Anti-aliasing helps, but it can still be noticed that the vertical lines aren't 100% straight.
There are some similar threads and I have tried some solutions but none are working to how my result is intended to be.
I have a 2d array (Which is a game board).
If i want to move a playerID to a position in the board I want to check if that position has an adjacent cell that is equal to the player ID. Otherwise it wont place it.
For example if i have a board:
[0, 0, 0, 0, 0, 0, 0, 1, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 2, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
If i try 1 in position [0][0] it should reject it but if i try put it in either: [0][7], [0][9], [1][6], [1][7],[1][8] (this includes diagonals).
My current code was a starting attempt I guess? But im not sure how I could do the clientID check:
public void move(int client, int x, int y) {
int startPosX = (x - 1 < MIN_X) ? x : x-1;
int startPosY = (y - 1 < MIN_Y) ? y : y-1;
int endPosX = (x + 1 > MAX_X) ? x : x+1;
int endPosY = (y + 1 > MAX_Y) ? y : y+1;
for (int rowNum=startPosX; rowNum<=endPosX; rowNum++) {
for (int colNum=startPosY; colNum<=endPosY; colNum++) {
if (storeArray[x][y] == EMPTY && client <= 5 && client >= 1) {
storeArray[x][y] = client;
int count = totals.containsKey(client) ? totals.get(client) : 1;
totals.put(client, count + 1);
}
}
}
So it goes through the rows and columns and if it's in any of the surrounding cells, it should place it. But I can still place it anywhere.
Is my code even close to doing what it's supposed to do?
What sort of things am i missing to match my criteria and can this code be modified to make it work?
If you can't store the coordinates of clients you can modify your if statement to the following. If you can store the coordinates I would definitely use Leo Leontev's answer.
/*I removed check for client to be between 1-5, can be re-added.
I would add the checks for the desired spot being empty and the client
being within 1-5 to the top of the method.
For loop iterates over the possible spaces where the client would be in range
check if client is in a space*/
if (storeArray[rowNum][colNum]==client) {
//storeArray[rowNum][colNum]=0;
storeArray[x][y] = client;
//unchanged
int count = totals.containsKey(client) ? totals.get(client) : 1;
totals.put(client, count + 1);
}
You can also simplify your startX,Y, endX,Y by using Math.min and Math.max to avoid any indexOutOfBounds errors that may be caused by trying to move the client outside of the board.
int startPosX = Math.max(x-1,0);
int startPosY = Math.max(y-1,0;
int endPosX = Math.min(x+1,storeArray.length-1);
int endPosY = Math.min(y+1,storeArray[0].length-1);
If you're not doing anything after the totals.put(client,count+1); call you can add a return; statement to exit the method. If you still need to do more work you can add a label to the outer for loop and then break out of the label. Either way will stop your count from counting more than once per move.
outerloop:
for(int rowNum=startPosX;rowNum<=endPosX;rowNum++){
for(int colNum=startPosY;colNum<=endPosY;colNum++){
if(...){
//code
totals.put(client, count+1);
break outerloop;
}
}
}
Here is the method as it is in my editor
public static move(int client, int x, int y){
if(storeArray[x][y]==client)
return;
int startPosX = Math.max(x-1,0), startPosY=Math.max(y-1,0);
int endPosX = Math.min(x+1,storeArray.length-1), endPosY = Math.min(y+1,storeArray[0].length-1);
outerloop:
for(int rowNum=startPosX;rowNum<=endPosX;rowNum++)
{
for(int colNum=startPosY;colNum<=endPosY;colNum++){
if(storeArray[rowNum][colNum]==client)
{
storeArray[x][y]=client;
System.out.println("Successful move");
int count = totals.getOrDefault(client, 1);
totals.put(client, count + 1);
break outerloop;
//could set colNum=endPosY+1 and rowNum=endPosX+1 if you don't want to use label/break
}
}
}
}
You can use an array to store the coordinates of clients:
ArrayList<int[]> clientCoords = new ArrayList<>;
And so the move method will look like that:
public void move(int client, int x, int y) {
int[] coords = clientCoords.get(client);
int old_x = coords[0], old_y = coords[1]; // previous coordinates of the client
// check that the new cell is adjacent
if(Math.abs(x - old_x) <= 1 && Math.abs(y - old_y) <= 1){
clientCoords.set(client, new int[2]{x, y});
// your code
int count = totals.containsKey(client) ? totals.get(client) : 1;
totals.put(client, count + 1);
}
}
I need to find the best fitting regression line for a set of points.
For example for this matrix:
int b [][] = { { 3, 1, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 2, 3, 1, 0, 1, 0, 0, 0 },
{ 0, 1, 2, 1, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 3, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 1, 3, 0, 0 },
{ 0, 0, 0, 0, 0, 1, 2, 3, 1 },
{ 0, 0, 0, 0, 0, 1, 1, 1, 2 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 1 } };
Every number represents the amount of data points (weight I suppose) at that location (where rows are the X axis and Columns are for the Y).
I have attempted to use the SimpleRegression class from the apache mathematics library and am having some issues.
First, it doesn't appear to support weights. Second I believe that I'm doing something wrong, even for a matrix that is nothing but 1's on the main diagonal the slope/intercept results make no sense.
public static void main(String[] args) {
double a[][] = new double[9][9];
for (int i = 0; i < 9; i++)
a[i][i] = 1;
SimpleRegression r = new SimpleRegression(true);
r.addData(a);
System.out.println("Slope = " + r.getSlope());
System.out.println("Intercept = " + r.getIntercept());
}
This gives me results that are incorrect. I would assume that this matrix represents the function f(x) = x yet the slope I'm getting is -0.12499..
Could anyone point me at what I'm doing wrong?
I have a feeling I'm not only misusing the code but also the mathematics.
As the comments say, addData() expects a 2xN matrix of x y positions or individual x y positions. The following example returns a slope of 1 for a diagonal matrix as expected:
public static void main(String[] args) {
double a[][] = new double[9][9];
for (int i = 0; i < 9; i++)
a[i][i] = 1;
SimpleRegression r = new SimpleRegression(true);
addData(r, a);
System.out.println("Slope = " + r.getSlope());
System.out.println("Intercept = " + r.getIntercept());
}
public static void addData(SimpleRegression r, double[][] data) {
for(int x=0; x<data.length; x++) {
for(int y=0; y<data[0].length; y++) {
for(int i=0; i<data[x][y]; i++) {
r.addData(x, y);
}
}
}
}
The example assumes that index 0 corresponds to a position of 0, index 1 corresponds to a position of 1 and so on. If this is not the case you need to add a function to transform index to position.
I am attempting to iterate through a 2D array of integers to generate a tiled map using Java's Graphics2D.
int[][] mapArray = {{1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1}};
public void draw(Graphics2D g2d){
for(int y = 0; y < mapArray.length; y++){
for(int x = 0; x < mapArray[0].length; x++){
if(mapArray[x][y] == 1){
ImageIcon ic = new ImageIcon("/Textures/stone.jpg");
g2d.drawImage(ic.getImage(), x, y, null);
}
else if(mapArray[x][y] == 0){
ImageIcon ic = new ImageIcon("/Textures/water.jpg");
g2d.drawImage(ic.getImage(), x, y, null);
}
I just can't seem to wrap my head around the logic of iterating a 2D array. Ideally, each 0 would represent a water tile while each 1 would represent a stone tile. Every time I run this I get a NullPointerException.
x and y are wrong way around
public void draw(Graphics2D g2d){
for(int y = 0; y < mapArray.length; y++){
for(int x = 0; x < mapArray[y].length; x++){ //you want to use y here not 0
if(mapArray[y][x] == 1){ //first box is outer array second is inner one
ImageIcon ic = new ImageIcon("/Textures/stone.jpg");
g2d.drawImage(ic.getImage(), x, y, null);
} else if(mapArray[y][x] == 0){
ImageIcon ic = new ImageIcon("/Textures/water.jpg");
g2d.drawImage(ic.getImage(), x, y, null);
}
}
}
}
I could see potentially two big issues in your code, in your code "y" represents rows and "x" represents columns but in your if statement you are picking [column][row] and while having a dry run you are probabily counting [row][column] and secondly you are always counting columns that are present in first row. if your data structure is always nXn in such case it will work but in any other case you would have different results and you might encounter ArrayIndexOutofBound exception.
I am developing a steganography program for a computer programming class. It appears to gives random ascii symbols. The output is supposed to be BINARY. The encode message method was given to us by my teacher. We just have to program the decode part.
import java.awt.*;
class HideMessage {
public void encodeMessage(Picture stegoObject, int[] binaryArray) {
Pixel pixelTarget = new Pixel(stegoObject, 0, 0);
Pixel[] pixelArray = stegoObject.getPixels();
Color pixelColor = null;
int redValue = 0;
for (int x = 0; x < binaryArray.length; x++) {
redValue = binaryArray[x];
pixelTarget = pixelArray[x];
pixelTarget.setRed(redValue);
}
pixelTarget = pixelArray[binaryArray.length];
pixelTarget.setRed(255);
System.out.println("FinishedPic");
stegoObject.write("SecretMessage.bmp");
stegoObject.explore();
}
public void decodeMessage(Picture decodepic) {
int redValue = 0;
Pixel targetPixel = null;
Color pixelColor = null;
int sum = 0;
for (int x = 0; redValue < 2; x++) {
//inside nested loop to traverse the image from left to right
for (int count = 1; count < 9; count++) {
targetPixel =
decodepic.getPixel(count + (8 * x), 0);
//gets the x,y coordinate of the target pixel
pixelColor = targetPixel.getColor();
//gets the color of the target pixel
redValue = pixelColor.getRed();
if (redValue == 1) {
if (count == 1) {
sum = sum + 128;
}
if (count == 2) {
sum = sum + 64;
}
if (count == 3) {
sum = sum + 32;
}
if (count == 4) {
sum = sum + 16;
}
if (count == 5) {
sum = sum + 8;
}
if (count == 6) {
sum = sum + 4;
}
if (count == 7) {
sum = sum + 2;
}
if (count == 8) {
sum = sum + 1;
}
}
System.out.println(sum);
}
System.out.println((char)sum);
sum = 0;
} //end of the inner for loop
}
}
public class HideMessageTester {
public static void main(String[] args) {
int[] bitArray =
{ 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1,
0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0,
1, 1, 1, 1, 0, 0, 1 };
//int[] bitArray =
{ 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1,
0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1,
1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0,
0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1,
0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1,
0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1,
0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1,
0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1,
1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0,
0, 1, 0, 0, 0, 0, 1};
Picture stegoObject = new Picture("Earth.bmp");
HideMessage stego = new HideMessage();
stego.encodeMessage(stegoObject, bitArray);
Picture decodeObject = new Picture("SecretMessage.bmp");
System.out.println("Now Decoding");
stego.decodeMessage(decodeObject);
}
}
First, some general pieces of advice: I think your program is overly complicated because the functions are commingling their responsibilities:
Picture stegoObject = new Picture("Earth.bmp");
HideMessage stego = new HideMessage();
stego.encodeMessage(stegoObject, bitArray);
Picture decodeObject = new Picture("SecretMessage.bmp");
System.out.println("Now Decoding");
stego.decodeMessage(decodeObject);
I was very surprised to see SecretMessage.bmp; it wasn't at all obvious that were trying to decode the object you had just created. Sure, upon reading the encodeMessage() method it was easy enough to determine where it came from, but I think this flow would have been easier:
/* encode */
Picture pic_to_steg = new Picture("foo.bmp");
HideMessage stego = new HideMessage();
Picture secret = stego.encodeMessage(pic_to_steg, bitArray);
secret.write("SecretMessage.bmp");
/* decode */
Picture pic_with_message = new Picture("SecretMessage.bmp");
int[] hidden = stego.decodeMessage(pic_with_message);
/* output `hidden` and compare against `bitArray` */
In other words: leave the file IO entirely up to the main flow of the program. Perhaps your routines will be called from a network server in the future, and the pictures will never be saved to disk. That modification will be far easier if the routines operate on Pictures and return amended Pictures and int[].
Can you test your encodeMessage() method in isolation? Perhaps look at the differences in what it does between an input file and an output file. This section looks troublesome:
public void encodeMessage(Picture stegoObject, int[] binaryArray) {
Pixel pixelTarget = new Pixel(stegoObject, 0, 0);
Pixel[] pixelArray = stegoObject.getPixels();
Color pixelColor = null;
int redValue = 0;
for (int x = 0; x < binaryArray.length; x++) {
redValue = binaryArray[x];
pixelTarget = pixelArray[x];
pixelTarget.setRed(redValue);
}
pixelTarget = pixelArray[binaryArray.length];
pixelTarget.setRed(255);
Is the pixelArray really a reference into the image that can be updated through simple assignment? I'd really expect the design to look more like this pseudo-code:
pixel p = image.getPixel(x, y);
p.setred(binaryArray[i]);
image.setPixel(x, y, p);
The decoding has some strange loops:
for (int x = 0; redValue < 2; x++) {
//inside nested loop to traverse the image from left to right
for (int count = 1; count < 9; count++) {
This loop might work exactly as you designed it, but upon a first reading, it feels very wrong: You start with x=0, you increment x each time through the loop, but you use redValue < 2 as your loop termination rule.
I would so much rather see the loop written like this:
int x = 0;
while (redValue < 2) {
/* stuff */
x++;
}
(It isn't identical; x is still valid outside the loop, which can be dangerous. However, I think this is much more clear.)
There are cases where the termination clause of a for loop isn't related to the setup or increment clauses -- in my experience, they are very rare.
In this case though, it feels like a mistake; the condition redValue < 2 a loop invariant, but the inner loop assumes it will only happen on pixels that are multiples of 8, which is an assumption that is not enforced in the encodeMessage() method.
Trying to compute an integer value from your redValues as you read them is needlessly complicating your decode routine. I suggest removing the inner loop and return an array exactly like the array passed into the encodeMessage() routine. This will be (a) easier (b) easier to debug (c) easier to test (d) a thousand times easier to handle writing bit arrays that aren't evenly divisible by 8.
Then write a second method that turns the bit array output into the sum, or ASCII characters, or EBCDIC characters, or RSA key parameters, or whatever it is that's being encoded. Don't try to do too much at once. Writing a separate method to decode the array of bits will be (a) easier (b) easier to debug (c) easier to test (d) thousand time easier to handle arbitrary output modifications.
I hope these hints help.