Используйте более качественную структуру данных
В данный момент вы используете многомерные массивы, у которых есть определенные достоинства и недостатки, слегка затронутые в других местах SO .Поскольку то, что вы делаете, - это обработка изображений, производительность может быть критической для вас, а разыменование многомерных массивов не совсем оптимально по ряду причин (т. Е. Вы, скорее всего, потеряете производительность из-за непоследовательного чтения).
Существует несколько способов как повысить производительность, так и упростив вашу жизнь:
Чередующийся одномерный массив
То есть вы должны использовать один массив unsigned char img[WIDTH * HEIGHT * COLORS]
,Это дает то преимущество, что ваш код также легче поддерживать, поскольку вы можете обрабатывать изображения RGB, B & W и RGBA с изменением на постоянную COLORS
.Чтобы получить доступ к данному цвету одного пикселя, вы можете иметь img[y * width * COLORS + x * COLORS + color]
.Вы также можете написать макрос, чтобы помочь с этим, например,
#define INDEX_XYZ(x,y,color) ((y) * WIDTH * COLORS + (x) * COLORS + (color))
Для дальнейшего улучшения удобства использования функции, рассматривая возможность передачи ей размера каждого измерения вместе с количеством цветов.Например, вы можете изменить подпись на ...
void Shuffle(unsigned char image[], int height, int width, int colors);
, которая позволит вам использовать одну и ту же функцию для изображений любого размера (при условии, что оба измерения делятся на четыре) и любого цвета,Возможно, вы также захотите передать аргумент, указывающий количество подразделений, чтобы вы могли иметь сегментацию 3 на 3 или 8 на 8, если хотите, и без необходимости изменять функцию или повторять код.
Разделить изображение на сегменты
Один из способов сделать это - создать массивы для сегментов ...
unsigned char segments[SEG_HORI * SEG_VERT][WIDTH / SEG_HORI * HEIGHT / SEG_VERT * COLOR];
Обратите внимание на многомерность - здесь все хорошо,поскольку для нас желательно иметь несколько отдельных сегментов для хранения данных.
После чего мы копируем данные из оригинала:
// Calculate the height/width for the segments; you could do this as a macro too.
int seg_height = HEIGHT / SEG_VERT;
int seg_width = WIDTH / SEG_HORI;
// Iterate through the rows in the picture
for (int y = 0; y < HEIGHT; y++)
{
// Obtain the Y-coordinate of the segment.
int segy = y / seg_height;
// Iterate through the columns in the picture
for (int x = 0; x < WIDTH; x++)
{
// Calculate the X-coordinate of the segment.
int segx = x / seg_width,
// Then calculate its index, using the X and Y coordinates.
seg = segy * SEG_HORI + segx,
// Then, calculate the source index (from the image).
src_idx = y * WIDTH * COLORS + x * COLORS,
// Then, map the coordinates to the segment; notice that we take
// modulos on the coordinates to get them to correctly map.
dst_idx = y % seg_height * seg_width * COLORS + x % seg_width * COLORS;
// Then copy the colors. You could also use memcpy(),
// but the below should be more educational.
for (int c = 0; c < COLORS; c++)
segments[seg][dst_idx + c] = img[src_idx + c];
}
}
Теперь изображение скопированов сегменты, и вы можете изменить их порядок, как вы хотите, так как «сегменты» просто указатели.Например, нижеприведенный список поменяет местами верхний левый и нижний правый сегменты.
unsigned char seg_temp[] = segments[0];
segments[0] = segments[15];
segments[15] = seg_temp;
Наконец, чтобы завершить процесс и объединить сегменты вместе, необходимо повторить процесс выше в обратном порядке;это должно быть довольно тривиально, поэтому я оставлю это вам в качестве упражнения.
Заключительные замечания
Если вы еще этого не сделали, вам следует ознакомиться с malloc()
и free()
функций, а также memset()
и memcpy()
.Они должны оказаться очень полезными в будущем, а также улучшат производительность, так как тогда вы можете скопировать все в целевой массив (вместе с shuffle) в операциях n
вместо изменения оригинала в 2n
.
Отказ от ответственности 1: Я не запускал код через компилятор.Нет гарантий, что он будет работать "из коробки".
Отказ от ответственности 2: Я также не утверждаю, что код был хорошо оптимизирован.Надо что-то оставить для вас.