Tek Renk Resim basma Algoritması

Başlatan Mucit23, 13 Nisan 2019, 16:17:50

Mucit23

Selamlar

Tek Renk resim basma ile ilgili bir yerde takıldım

Normalde Monochrome yada tek renk resimler hafızada byte byte tutuluyor. Örnek olarak aşağıdaki gibi bir hafıza yapısı var.
const unsigned char Horn_24x24[] = {
  0x00,0x00,0x00, // ........................
  0x00,0x00,0x00, // ........................
  0x00,0x00,0x00, // ........................
  0x00,0x00,0x00, // ........................
  0x00,0x00,0x00, // ........................
  0x00,0x00,0x01, // .......................#
  0x00,0x00,0x03, // ......................##
  0x00,0x00,0x0F, // ....................####
  0x1C,0x00,0x1D, // ...###.............###.#
  0x37,0x00,0xF1, // ..##.###........####...#
  0x63,0x3F,0xC1, // .##...##..########.....#
  0xC1,0xF8,0x0F, // ##.....######.......####
  0xC1,0xC7,0xFF, // ##.....###...###########
  0xCD,0xFF,0xFF, // ##..##.#################
  0x63,0x1F,0xFF, // .##...##...#############
  0x37,0x00,0xFF, // ..##.###........########
  0x1C,0x00,0x1F, // ...###.............#####
  0x00,0x00,0x0F, // ....................####
  0x00,0x00,0x03, // ......................##
  0x00,0x00,0x01, // .......................#
  0x00,0x00,0x00, // ........................
  0x00,0x00,0x00, // ........................
  0x00,0x00,0x00, // ........................
  0x00,0x00,0x00  // ........................
};

Bu resimde genişlik 24 pixel yani 8'in katı ve 3 byte ile temsil edilebiliyor. Aşağıdaki gibi bir yapı ile LCD ekranıma bu resmi gönderebiliyorum.
void LCD_DrawMonoImage(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t *pdata, uint16_t size)
{
  uint16_t i=0, j=0;
	uint8_t temp=0;

  LCD_SetDisplayWindow(x,y,x+w,y+h);//Ilk önce uygun boyutta penceremizi açiyoruz. 
	
	for(i=0;i<size;i++)
  {
	   temp=pdata[i];
		
		 for(j=0;j<8;j++)
		 {
		   if((temp>>j)&0x01) 
			 {
			 	ST7735_WriteData(TextColor  >> 8);
	      ST7735_WriteData(TextColor);
			 }
			 else
			 {
			 	ST7735_WriteData(BackColor >> 8);
	      ST7735_WriteData(BackColor);
			 }
		 }
	}	
}

Resim genişliği 8'in tam katı ise sorun yok. Fakat 8'in tam katı değilse yukarıdaki algoritma düzgün çalışmıyor.
Örneğin aşağıdaki gibi bir resim olsun.
const unsigned char charging[] = {
  0x07,0x80, // .....####.......
  0x0F,0x80, // ....#####.......
  0x1F,0x00, // ...#####........
  0x1F,0x00, // ...#####........
  0x3E,0x00, // ..#####.........
  0x3F,0xC0, // ..########......
  0x7F,0xC0, // .#########......
  0xFF,0x80, // #########.......
  0x0F,0x00, // ....####........
  0x0E,0x00, // ....###.........
  0x1C,0x00, // ...###..........
  0x1C,0x00, // ...###..........
  0x18,0x00, // ...##...........
  0x30,0x00  // ..##............
};
Bu resmin genişliği 10 pixel Dolayısıyla her bir satırdaki 2. byte'in sadece en yüksek 2 biti kullanılıyor. Yazacağım algoritmaya resim genişlik ve yüksekliğini pixel olarak gönderiyorum fakat hafızadan veriyi düzgün çekecek bir algoritma yazamadım.

Nasıl yapabilirim bu dediğimi fikir verebilecek olan varmı?

devrecii

Ekranın ramina ulaşman gerekir yada tüm ekranın hafızasını mcu hafızasında tutman gerekir.

Ekranın raminden o yerdeki 1 bayt bilgiyi aldın  , elindeki pixel değerini and or işlemi kullanarak bu ilgili pixelleri değere verip ekrana gönderdin.


Mucit23

@iboibo Yok hocam Ekran Ramiyle işim yok. Sabit Bir resmi ekrana basacak bir algoritma sadece. Arkadaki resmin üzerine basacağı için ram ile işim yok.

Aslında ben bir algoritma yazdım Fakat pek aklıma yatmadı.

void LCD_DrawByte(uint8_t data, uint8_t width)
{
	uint8_t j=0;
					 for(j=0;j<width;j++)
					 {
							if((data<<j)&0x80) 
							{
								ST7735_WriteData(TextColor  >> 8);
								ST7735_WriteData(TextColor);
							}
							else
							{
								ST7735_WriteData(BackColor >> 8);
								ST7735_WriteData(BackColor);
							}
					 }
}

void LCD_DrawMonoImage(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t *pdata, uint16_t size)
{
  uint16_t i=0;
  uint8_t temp=0;
  uint8_t wbyte=w/8;  
  uint8_t wmod=w%8;   
  uint8_t byte_count=0;

  LCD_SetDisplayWindow(x,y,x+w-1,y+h-1);//Ilk önce uygun boyutta penceremizi açiyoruz. 
	
  while(i<size)
	{
	   temp=pdata[i];
		
		 if(wmod!=0)
		 {
		    if(byte_count==wbyte)
		    {
			byte_count=0;
                        LCD_DrawByte(temp,wmod);
		    }
		    else 
		    {
                       LCD_DrawByte(temp,8);
		       byte_count++;
		    }
		}
		else
		{
	           LCD_DrawByte(temp,8);
		}
        i++;
	}
}

Resim dönüştürme yazılımını değiştirdim. Aşağıdaki program ile resim dönüşümü yapıyorum.
https://www.riuson.com/lcd-image-converter
Resim genişliğinin modunu alıp aynı zamanda 8'e bölerek kaç tane tam byte ve kaç pixel kalan olduğunu buldum. Ona göre tam byte'ları sayıp resmi basmaya çalıştım. Çalışıyor ama kesinlikle daha iyi yazılabilir. Sanki kulağı tersten tutmuş gibi oldum.

Şunu sorayım bari. Fonksiyonun içine bir dizi gönderiyorum. Tabiki pointer olarak gönderiyorum. Bu pointer'in boyutunu dizi içinde nasıl tespi ederim. Yani N byte'dan oluşan bir diziyi fonksiyon içine gönderdik diyelim. Fonksiyon için yazacağım bir makro ile bu pointer'in kaç elemandan oluştuğunu nasıl bulurum?

RaMu

Resim genişlik ve yüksekliğini her zaman 8 in katı olarak gir,
zaten olmayan bitler boşluk olarak basılacak.
Dediğin 10 bitlik resim datası zaten mcu da 16 bit olarak tutulmuş,
ekrana basarkende bu 16 bit resimdir dersin.
Böyle olmuyor mu?
Sorularınıza hızlı cevap alın: http://www.picproje.org/index.php/topic,57135.0.html

Mucit23

Olmuyor. Eğer dediğin gibi yaparsam 9 Pixel genişliğe sahip bir resim ekrana basılırken 16 pixel genişliğinde bir alan kaplar

yas

Örnek kodlar şu an elimde yok ama şöyle bir yöntem kullanmıştım. Resim datasının ilk iki byte ına resmin en boy piksel sayısını girip (örneğin;32x24 piksel gibi), sonraki dataları buna göre işleyecek bir algoritma kullanmıştım.
Paintte çizimini tek renkli bmp formatında kaydedip hex editör ile açıp incelersen. Resim datasının Hexemal 3D adresinden sonra başladığını, hexemal 12. byte adreste yatay piksel sayısını, hexemal 16. byte adreste ise dikey piksel sayısının olduğunu göreceksiniz. Umarım işinize yarar.

kantirici

Tek renk veya çoklu renklere ait font, resim v.b datalara ait metadata bulunmak zorunda. Aksi halde her farklı durum için ayrı bir fonksiyon veya parametre gerekir ki buda pek iyi bir yöntem sayılmaz.

Elinizde bir resime ait ham (piksel) verisinin yanında o resime ait gerekli olan bilgileri içeren ayrı bir veri olmalıdır(metadata). Genellikle bu veri diziye ilk olarak yerleştirilir ve her zaman uzunluğu sabittir. Sizin durumda genişlik ve yükseklik bilgisi yeterli ve 2 byte ile ifade edilebilir. Son durumda dizi aşağıdaki gibi olacak ve asıl veri 2 byte offset ile başlayacak.

const unsigned char Horn_24x24[] = {
  yukseklik, genislik,
  0x00,0x00,0x00, // ........................
  0x00,0x00,0x00, // ........................
  0x00,0x00,0x00, // ........................
  0x00,0x00,0x00, // ........................
  0x00,0x00,0x00, // ........................
  0x00,0x00,0x01, // .......................#
  0x00,0x00,0x03, // ......................##
  0x00,0x00,0x0F, // ....................####
  0x1C,0x00,0x1D, // ...###.............###.#
  0x37,0x00,0xF1, // ..##.###........####...#
  0x63,0x3F,0xC1, // .##...##..########.....#
  0xC1,0xF8,0x0F, // ##.....######.......####
  0xC1,0xC7,0xFF, // ##.....###...###########
  0xCD,0xFF,0xFF, // ##..##.#################
  0x63,0x1F,0xFF, // .##...##...#############
  0x37,0x00,0xFF, // ..##.###........########
  0x1C,0x00,0x1F, // ...###.............#####
  0x00,0x00,0x0F, // ....................####
  0x00,0x00,0x03, // ......................##
  0x00,0x00,0x01, // .......................#
  0x00,0x00,0x00, // ........................
  0x00,0x00,0x00, // ........................
  0x00,0x00,0x00, // ........................
  0x00,0x00,0x00  // ........................
};

Artık elinizde her resme ait yükseklik ve genişlik bilgisi var. Buradan bu datayı alıp ona gore islem yapabilirsiniz.




RaMu

Alıntı yapılan: Mucit23 - 13 Nisan 2019, 19:45:36Olmuyor. Eğer dediğin gibi yaparsam 9 Pixel genişliğe sahip bir resim ekrana basılırken 16 pixel genişliğinde bir alan kaplar
Evet @iboibo nun dediğinide yaparsan o problemde çözülüyor.

Benzer bir şeyi program memory den arkaplan resmi basarken
üzerine çizgi harf rakam yazabilmek için yapmıştım.

https://rmtulay.wordpress.com/2018/07/10/ccsc-ssd1306-oled-lless-than-80bayt-ram-code-and-proteus-isis-simulation/

Sorularınıza hızlı cevap alın: http://www.picproje.org/index.php/topic,57135.0.html