The problem seems to be to tile an image onto another image. You have width and height for the target image's dimensions, so let's say sourceWidth and sourceHeight are the source image's dimensions (100 by 100, in your example).
To tile an image, you want k == i % sourceWidth and l == j % sourceHeight, so that the pixel you read from the source image "wraps around" the boundaries. These should be invariant conditions. The simplest way to satisfy them is to declare them that way directly:
for(int i = 0; i < width; ++i) {
int k = i % sourceWidth;
for(int j = 0; j < height; ++j) {
int l = j % sourceHeight;
set(i, j, pixel(k, l));
}
}
This does a lot of % operations, which could be quite inefficient, but it gives us a correct piece of code to transform. If we are incrementing k and l, then there are two properties needed to maintain the invariants:
k and i are incremented in unison; and l and j are incremented in unison.
- When
k reaches sourceWidth it must wrap back to 0, likewise for l and sourceHeight.
for(int i = 0, k = 0; i < width; ++i, ++k) {
if(k == sourceWidth) { k = 0; }
for(int j = 0, l = 0; j < height; ++j, ++l) {
if(l == sourceHeight) { l = 0; }
set(i, j, pixel(k, l));
}
}
Note that the for loop initialiser and stepper now declare and update two variables, for both loops. This is allowed in Java.
This is likely to be faster than doing a lot of % operations, but note that branching with if statements can also slow down an algorithm, so you may want to benchmark it to be sure.
In the special case where source image's dimensions are powers of two, we can achieve the same result with a fast bitwise operation: i % sourceWidth will be equivalent to i & (sourceWidth - 1):
// special case: sourceWidth and sourceHeight are powers of 2
int wMask = sourceWidth - 1, hMask = sourceHeight - 1;
for(int i = 0, k = 0; i < width; ++i, ++k) {
for(int j = 0, l = 0; j < height; ++j, ++l) {
set(i, j, pixel(i & wMask, j & hMask));
}
}