Вопрос о хранении данных - графики и

whoim
Offline
Зарегистрирован: 03.11.2011

 И дискуссия как оптимизировать их.

Сейчас я научился хранит и выводить графику (спрайты) из "битовых" картинок. Выглядит это так:

static prog_char uaz1_logo[] PROGMEM = {
	1,1,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,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,0,0,0,0,0,0,0,0,0,0,0,0,	0,0,
.......
0,1
}

И вот мы получаем, что один экран (и даже не полный) и функция вывода занимают у нас 8Кб данных, что, простите, полный пэ.

Я так понимаю, что  prog_char - массив, в котором элемент может представлять собой число от 0 до 255 (то есть символ), в то время как у меня будет достаточно бита (0 или 1). 

Однако вот тут мы видим возможные типы данных PROGMEM:

prog_char      - a signed char (1 byte) -127 to 128
 prog_uchar     - an unsigned char (1 byte) 0 to 255
 prog_int16_t   - a signed int (2 bytes) -32,767 to 32,768
 prog_uint16_t  - an unsigned int (2 bytes) 0 to 65,535
 prog_int32_t   - a signed long (4 bytes) -2,147,483,648 to * 2,147,483,647.
 prog_uint32_t  - an unsigned long (4 bytes) 0 to 4,294,967,295

И это меня не радует совершенно - нет там более экономного типа данных.. Кто как выкручивается? Или, мб, у кого есть какие мысли?

whoim
Offline
Зарегистрирован: 03.11.2011

  0 до 255 (

сорри, a signed char (1 byte) -127 to 128

whoim
Offline
Зарегистрирован: 03.11.2011

 И вот какие у меня мысли. Можно объединить группы из 8 битов в байты и хранить их в prog_char, а в функции вывода на экран (вот она кстати)

void LCD12864::DrawSprite(uint8_t xPos, uint8_t yPos, uint8_t swidth, uint8_t sheight, prog_char* header_data) {
int count = 0;
for (int j = 0; j < sheight; j++) {
for (int i = 0; i < swidth; i++) {
if (pgm_read_byte_near(header_data + count) == 1)
this->DrawScreenBuffer(xPos+i,yPos+128+j);
count++;
}
}
}

делать наоборот - переводить байт в биты, 8 раз их выводить и счетчик увеличивать на 8 вместо одного. Подскажите, как попробовать реализовать это? Интересуют варианты перевода такого массива в байты (ну это я решу на делфи или php на худой конец), а вот как перевести байт в биты и использовать их на си?

step962
Offline
Зарегистрирован: 23.05.2011

А у вас память дисплея имеет битовую организацию? Или все-таки байтовую?

Если хотите организовать оптимальное хранение и вывод спрайтов - отходите от стандартных библиотек и создавайте свои собственные процедуры вывода хранящихся в памяти изображений на дисплей. Иначе данные будут проходить несколько уровней абстракции, многократно увеличивая время вывода на дисплей. 

И в EEPROM храните не изображение, а его образ, учитывающий физическую организацию памяти конкретного дисплея. В идеальном случае вывод спрайта должен представлять собой простое копирование информации из одного участка памяти (EEPROM) в другой (DDRAM).

whoim
Offline
Зарегистрирован: 03.11.2011

 Когда то на ZX так и делал :)

Я ориентируюсь на работу функции, которая выводит данные на дисплей (из библиотеки).  Если ей верить, то данные все же правильно ложить побитово, где высокий бит - пиксель горит. 

void LCD12864::DrawScreenBuffer(uint8_t X, uint8_t Y) {

int xpos = X/8;
int ypos = (Y-128);

int leftX = X%8;
int orit = checkAND[leftX];

ScreenBuffer[xpos][ypos] |= orit;

}

и

void LCD12864::RenderScreenBuffer(uint8_t screen) {

for (int k = 0; k < 32; k++) {
VectorConverter(k+128); // Starting Y Position
setPins(0,0,this->temp[0],this->temp[1],this->temp[2],this->temp[3],this->temp[4],this->temp[5],this->temp[6],this->temp[7]); // SET DDRAM Y
setPins(0,0,1,0,0,0,0,0,0,0); // SET DDRAM X at start again


if (screen == 2) {
for (int i = 0; i < 16; i++) {
setPins(1,0,0,0,0,0,0,0,0,0); // draw remaining pixels =D

}
}

for (int i = 0; i < 16; i++) {

// Check if a pixel exists
for (int j = 0; j < 8; j++) {
int res = ScreenBuffer[i][k] & checkAND[j];

if (res > 0) { // Looks like we found a 1
temp[j] = 1;
}
else
temp[j] = 0;
} // end j
setPins(1,0,this->temp[0],this->temp[1],this->temp[2],this->temp[3],this->temp[4],this->temp[5],this->temp[6],this->temp[7]); // draw remaining pixels =D
} // end i


} // end k

}

 

whoim
Offline
Зарегистрирован: 03.11.2011

 Попробую пока что виртуально доработать функцию чтения изображени и вывода его на дисплей (реально проверю вечером, может до этого поправите меня


void LCD12864::DrawSprite(uint8_t xPos, uint8_t yPos, uint8_t swidth, uint8_t sheight, prog_char* header_data) {
int count = 0;
for (int j = 0; j < sheight; j++) {
 for (int i = 0; i < swidth; i++) {
  for (int b = 7; b > 0; b--) { //цикл по байту
   if (bitRead(pgm_read_byte_near(header_data + count),b) == 1)
        this->DrawScreenBuffer(xPos+i,yPos+128+j);
  }
  count=count+8;
 }
}
}

 Задача функции - прочитать байт (в котором содержаться 8 бит графической инфы), разложить его на биты и вывести все единички в пикселы.

Данные теперь надо преобразовать - каждые 8 байт сложить как биты в байт и записать его взамен этих 8 байт. Изменить тип данных на uchar

whoim
Offline
Зарегистрирован: 03.11.2011

 мм и вообще - где лучше хранить графику с точки зрения экономности памяти для работы программы?