在AVR中,我使用八个字节的数组来存储显示在8x8 LED矩阵上的图像。图片需要不时旋转。因此,图片┘
定义为:
uint8_t rows[8] = {
0b00000001,
0b00000001,
0b00000001,
0b00000001,
0b00000001,
0b00000001,
0b00000001,
0b11111111
};
我想逆时针“旋转”以获得┐
:
uint8_t rows2[8] = {
0b11111111,
0b00000001,
0b00000001,
0b00000001,
0b00000001,
0b00000001,
0b00000001,
0b00000001
};
如果按顺时针方向完成,└
:
uint8_t rows3[8] = {
0b10000000,
0b10000000,
0b10000000,
0b10000000,
0b10000000,
0b10000000,
0b10000000,
0b11111111
};
如何在直接C中执行此操作?
答案 0 :(得分:2)
一些按位操作可以解决问题。
#include <inttypes.h>
int main(){
uint8_t rows[8] = {
0b11111111,
0b00000001,
0b00000001,
0b00111111,
0b00000001,
0b00000001,
0b00000001,
0b11111111
};
uint8_t rows2[8] = {0, 0, 0, 0, 0, 0, 0, 0};
uint8_t rows3[8] = {0, 0, 0, 0, 0, 0, 0, 0};
int i, j;
// rotate clockwise
for(i=0; i<8; ++i){
for(j=0; j<8; ++j){
rows3[i] = ( ( (rows[j] & (1 << (7-i) ) ) >> (7-i) ) << j ) | rows3[i];
}
}
// rotate anti-clockwise
for(i=0; i<8; ++i){
for(j=0; j<8; ++j){
rows2[i] = ( ( (rows[j] & (1 << i ) ) >> i ) << (7-j) ) | rows2[i];
}
}
}
在顺时针方式的情况下,用(rows[j] & (1 << (7-i) ) ) >> (7-i)
得到第j个原始字节的每个第(7-i)位,然后将其移到第j个位置。通过对字节本身执行“或”(|
)来收集所有位,因此使用0初始化数组非常重要。
逆时针的情况类似,改变了索引。
我用另一封信来测试它,让你确定旋转是否正常工作。如果您需要进一步说明,请询问。
如果您想查看结果,我正在使用此SO问题中的函数:Is there a printf converter to print in binary format?
答案 1 :(得分:1)
uint8_t rows[8] = {
0b00000001,
0b00000001,
0b00000001,
0b00000001,
0b00000001,
0b00000001,
0b00000001,
0b11111111
};
uint8_t temp[8];
void anti()
{
int i, j;
for(i = 0; i < 8; ++i) temp[i] = 0;
for(i = 0; i < 8; ++i)
for(j = 0; j < 8; ++j)
if(rows[j] & 1<<i) temp[i] |= 1<<(7-j);
for(i = 0; i < 8; ++i) row[i] = temp[i];
}
答案 2 :(得分:1)
这是一个简单/标准的[方形]矩阵旋转。我使用方格纸手工制作并物理旋转它。
对于逆时针(向左旋转),等式为:
out[7-x][y] = inp[y][x];
对于顺时针(向右旋转),等式为:
out[x][7-y] = inp[y][x];
...除了我们必须在X维度中提取位,所以我们需要一些模拟位的矩阵访问的函数。
这是一个具有必要功能的测试程序:
#include <stdio.h>
typedef unsigned char byte;
typedef void (*rot_p)(byte *dst,const byte *src);
#define MSK(_shf) (1 << (7 - (_shf)))
byte result[8];
// original matrix
byte rows[8] = {
0b00000001,
0b00000001,
0b00000001,
0b00000001,
0b00000001,
0b00000001,
0b00000001,
0b11111111
};
// counterclockwise (rotate left)
byte rows2[8] = {
0b11111111,
0b00000001,
0b00000001,
0b00000001,
0b00000001,
0b00000001,
0b00000001,
0b00000001
};
// clockwise (rotate right)
byte rows3[8] = {
0b10000000,
0b10000000,
0b10000000,
0b10000000,
0b10000000,
0b10000000,
0b10000000,
0b11111111
};
// bitget -- get bit from matrix
byte
bitget(const byte *rows,int y,int x)
{
byte val;
rows += y;
val = *rows;
val &= MSK(x);
return val;
}
// bitget -- set bit in matrix
void
bitset(byte *rows,int y,int x,byte val)
{
byte msk;
rows += y;
msk = MSK(x);
if (val)
*rows |= msk;
else
*rows &= ~msk;
}
// rotright -- rotate matrix right (clockwise)
void
rotright(byte *dst,const byte *src)
{
int x;
int y;
byte val;
for (y = 0; y < 8; ++y) {
for (x = 0; x < 8; ++x) {
val = bitget(src,y,x);
bitset(dst,x,7 - y,val);
}
}
}
// rotleft -- rotate matrix left (counterclockwise)
void
rotleft(byte *dst,const byte *src)
{
int x;
int y;
byte val;
for (y = 0; y < 8; ++y) {
for (x = 0; x < 8; ++x) {
val = bitget(src,y,x);
bitset(dst,7 - x,y,val);
}
}
}
// mtxshow -- print matrix
void
mtxshow(const byte *mtx,const char *sym,const char *tag)
{
int y;
int x;
byte val;
printf("%s/%s:\n",sym,tag);
for (y = 0; y < 8; ++y) {
printf(" ");
for (x = 0; x < 8; ++x) {
val = bitget(mtx,y,x);
val = val ? '1' : '0';
fputc(val,stdout);
}
fputc('\n',stdout);
}
}
// test -- perform test
void
test(const byte *exp,rot_p fnc,const char *tag)
{
printf("\n");
mtxshow(exp,tag,"expected");
fnc(result,rows);
mtxshow(result,tag,"actual");
}
int
main(void)
{
mtxshow(rows,"rows","orig");
test(rows2,rotleft,"rotleft");
test(rows3,rotright,"rotright");
return 0;
}
这是程序输出:
rows/orig:
00000001
00000001
00000001
00000001
00000001
00000001
00000001
11111111
rotleft/expected:
11111111
00000001
00000001
00000001
00000001
00000001
00000001
00000001
rotleft/actual:
11111111
00000001
00000001
00000001
00000001
00000001
00000001
00000001
rotright/expected:
10000000
10000000
10000000
10000000
10000000
10000000
10000000
11111111
rotright/actual:
10000000
10000000
10000000
10000000
10000000
10000000
10000000
11111111
答案 3 :(得分:-1)
您可以使用数组索引来执行此操作,但使用string.h
提供的工具(例如memcpy
和memmove
)来完成旋转要容易得多。例如,如果您的数组为r
且sz
个元素要按n
个位置旋转,那么顺时针旋转就是:
uint8_t i = 0, tmp[n];
...
memcpy (tmp, &r[sz-n], n);
memmove (&r[n], r, sz-n);
memcpy (r, tmp, n);
for (; i < sz; i++)
if (i != n-1 && r[i] != 0x80)
r[i] ^= 0x81;
您的逆时针旋转是:
memcpy (tmp, r, n);
memmove (r, &r[n], sz-n);
memcpy (&r[sz-n], tmp, n);
for (; i < sz; i++)
if (i != sz-n+1 && r[i] != 0xff)
r[i] ^= 0x81;
(n == 0 || n == sz)
无需执行任何操作,您必须选择(n > sz)
时的操作(例如,抛出错误或旋转n % sz
位置)。看起来你只关心在任一方向旋转1。将所有部分放在一起,一个简短的例子就是:
更新了轮播次数
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
void rotcw (uint8_t *r, uint8_t sz, uint8_t n);
void rotccw (uint8_t *r, uint8_t sz, uint8_t n);
void prnrows (uint8_t *r, uint8_t sz);
int main (void) {
uint8_t rows[] = {0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0xff};
uint8_t sz = sizeof rows / sizeof *rows;
printf ("\n original array :");
prnrows (rows, sz);
rotcw (rows, sz, 1);
printf ("\n rotate cw by 1 :");
prnrows (rows, sz);
rotccw (rows, sz, 1);
printf ("\n rotate ccw by 1 :");
prnrows (rows, sz);
return 0;
}
void rotcw (uint8_t *r, uint8_t sz, uint8_t n)
{
if (n == sz ) return; /* nothing to do */
if (n > sz) n %= sz; /* rotate 'n % sz' positions */
uint8_t i = 0, tmp[n];
memcpy (tmp, &r[sz-n], n);
memmove (&r[n], r, sz-n);
memcpy (r, tmp, n);
for (; i < sz; i++)
if (i != n-1 && r[i] != 0x80)
r[i] ^= 0x81;
}
void rotccw (uint8_t *r, uint8_t sz, uint8_t n)
{
if (n == sz ) return; /* nothing to do */
if (n > sz) n %= sz; /* rotate 'n % sz' positions */
uint8_t i = 0, tmp[n];
memcpy (tmp, r, n);
memmove (r, &r[n], sz-n);
memcpy (&r[sz-n], tmp, n);
for (; i < sz; i++)
if (i != sz-n+1 && r[i] != 0xff)
r[i] ^= 0x81;
}
void prnrows (uint8_t *r, uint8_t sz)
{
uint8_t i;
for (i = 0; i < sz; i++)
printf (" 0x%02" PRIx8, r[i]);
putchar ('\n');
}
<强>输出强>
$ ./bin/bytes_rotate
original array : 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0xff
rotate cw by 1 : 0xff 0x80 0x80 0x80 0x80 0x80 0x80 0x80
rotate ccw by 1 : 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0xff