Skip to content

Commit

Permalink
Multi-color pattern support
Browse files Browse the repository at this point in the history
  • Loading branch information
stg committed Jun 14, 2012
1 parent b4c3eb4 commit a408f96
Show file tree
Hide file tree
Showing 21 changed files with 186 additions and 178 deletions.
Binary file modified bin-linux/cli
Binary file not shown.
Binary file modified bin-linux/gui
Binary file not shown.
Binary file modified bin-linux/gui_sdl12
Binary file not shown.
Binary file added bin-linux/libSDL2.so
Binary file not shown.
Binary file modified bin-win/gui.exe
Binary file not shown.
8 changes: 6 additions & 2 deletions cli/src/knit.c → cli/src/main.c
Expand Up @@ -138,11 +138,15 @@ static void cmd_track() {
// print image to screen
static void image_print(uint8_t *p_img,uint16_t w,uint16_t h) {
uint16_t x,y;
uint8_t sample,memo;
for(y=0;y<h;y++) {
memo=0;
for(x=0;x<w;x++) {
putchar(image_sample(p_img,w,x,y)?'X':'-');
sample=image_sample(p_img,w,x,y);
if(memo==0&&sample!=0xFF) memo=sample&0xF;
putchar(sample!=0xFF?'X':'-');
}
printf("\n");
printf(" %01X\n",memo);
}
}

Expand Down
36 changes: 24 additions & 12 deletions doc/rawimage_format.txt
Expand Up @@ -5,20 +5,32 @@ All values are big-endian where appropriate.
Offset Bytes Content
0x0000 2 Width in pixels/stitches
0x0002 2 Height in pixels/rows
0x0008 width*height Greyscale pixel data - top-down, left-right
0x0008 width*height Pixel data - top-down, left-right

Pixels will output as a stitch when < 50% brightness (0x80).

Example, letter P, 6x9 pixels, 58 bytes, hexadecimal:

00 06
00 09
FF FF FF FF FF FF
FF 00 00 00 FF FF
FF 00 FF FF 00 FF
FF 00 FF FF 00 FF
FF 00 00 00 FF FF
FF 00 FF FF FF FF
FF 00 FF FF FF FF
FF 00 FF FF FF FF
FF FF FF FF FF FF
00 06
00 09
FF FF FF FF FF FF
FF 00 00 00 FF FF
FF 00 FF FF 00 FF
FF 00 FF FF 00 FF
FF 00 00 00 FF FF
FF 00 FF FF FF FF
FF 00 FF FF FF FF
FF 00 FF FF FF FF
FF FF FF FF FF FF

Pixel values for single color patterns:

00 contrast yarn
FF main yarn

Pixel values for multi-color patterns:

01 contrast yarn 1
02 contrast yarn 2
03 contrast yarn 3
FF main yarn
71 changes: 69 additions & 2 deletions gui/loader.c
Expand Up @@ -3,13 +3,47 @@
#include <stdbool.h>
#include <FreeImage.h>
#include "loader.h"
#include <stdio.h> // todo remove
#include <string.h> // todo remove

#define ABS(n) (((n)<0)?(-(n)):((n)))

// byte order access fixes bug in FreeImage
#define RED(q) (q->rgbBlue)
#define GREEN(q) (q->rgbGreen)
#define BLUE(q) (q->rgbRed)

static FIBITMAP *dib=NULL;
static uint16_t w,h;
static RGBQUAD colors[16] = {
{.rgbRed=0x00,.rgbGreen=0x00,.rgbBlue=0x00}, // 0 black
{.rgbRed=0x00,.rgbGreen=0x00,.rgbBlue=0x7F}, // 1 dark blue
{.rgbRed=0x00,.rgbGreen=0x7F,.rgbBlue=0x00}, // 2 dark green
{.rgbRed=0x7F,.rgbGreen=0x00,.rgbBlue=0x00}, // 3 dark red
{.rgbRed=0x00,.rgbGreen=0x00,.rgbBlue=0x00},
{.rgbRed=0x00,.rgbGreen=0x00,.rgbBlue=0x00},
{.rgbRed=0x00,.rgbGreen=0x00,.rgbBlue=0x00},
{.rgbRed=0x00,.rgbGreen=0x00,.rgbBlue=0x00},
{.rgbRed=0x00,.rgbGreen=0x00,.rgbBlue=0x00},
{.rgbRed=0x00,.rgbGreen=0x00,.rgbBlue=0x00},
{.rgbRed=0x00,.rgbGreen=0x00,.rgbBlue=0x00},
{.rgbRed=0x00,.rgbGreen=0x00,.rgbBlue=0x00},
{.rgbRed=0x00,.rgbGreen=0x00,.rgbBlue=0x00},
{.rgbRed=0x00,.rgbGreen=0x00,.rgbBlue=0x00},
{.rgbRed=0x00,.rgbGreen=0x00,.rgbBlue=0x00},
{.rgbRed=0xFF,.rgbGreen=0xFF,.rgbBlue=0xFF} // F white
};

bool image_loadpicture(const char* filename) {
FREE_IMAGE_FORMAT fif=FIF_UNKNOWN;
int flag=0;
/*
int n;
for(n=0;n<strlen(filename);n++) {
printf("%02X ",filename[n]);
}
printf("\n");
*/
fif=FreeImage_GetFileType(filename,0);
if(fif==FIF_UNKNOWN) {
fif=FreeImage_GetFIFFromFilename(filename);
Expand Down Expand Up @@ -38,15 +72,48 @@ uint16_t image_height() {
return h;
}

static uint8_t match_color(RGBQUAD *p_quad) {
uint16_t diff,best=0xFFFF;
uint8_t n,i=0x0F;
// printf("%02X%02X%02X ",p_quad->rgbRed,p_quad->rgbGreen,p_quad->rgbBlue);
for(n=0;n<16;n++) {
diff = ABS((RED(p_quad)) -((int16_t)colors[n].rgbRed ))
+ ABS((GREEN(p_quad))-((int16_t)colors[n].rgbGreen))
+ ABS((BLUE(p_quad)) -((int16_t)colors[n].rgbBlue ));
if(diff<best) {
best=diff;
i=n;
}
}
// printf("%02X ",i);
return i==0x0F?0xFF:i;
}

static void image_print(uint8_t *p_img,uint16_t w,uint16_t h) {
uint16_t x,y;
uint8_t sample,memo;
for(y=0;y<h;y++) {
memo=0;
for(x=0;x<w;x++) {
sample=image_sample(p_img,w,x,y);
if(memo==0&&sample!=0xFF) memo=sample&0xF;
// printf("%c",sample!=0xFF?'X':'-');
}
// printf(" %01X\n",memo);
}
}

void image_convert(uint8_t *p_data) {
uint16_t x,y;
RGBQUAD quad;
for(y=0;y<h;y++) {
for(x=0;x<w;x++) {
FreeImage_GetPixelColor(dib,x,y,&quad);
p_data[y*w+x]=((uint16_t)quad.rgbRed+(uint16_t)quad.rgbGreen+(uint16_t)quad.rgbBlue)/3;
p_data[y*w+x]=match_color(&quad);
}
}
// printf("\n");
}
image_print(p_data,w,h);
}

void image_free() {
Expand Down
16 changes: 15 additions & 1 deletion gui/renderer.c
Expand Up @@ -210,6 +210,7 @@ void r_init( SDL_Surface *scr ) {
void r_draw() {
unsigned char x, y;
unsigned char i, j;
Uint32 SDL_color;
SDL_BlitSurface(bg,NULL,screen,NULL);
write_index = 0;
SDL_Rect srcrect;
Expand All @@ -231,7 +232,20 @@ void r_draw() {
srcrect.x = TERM( x, y ).cchar << 4;
srcrect.y = ( TERM( x, y ).tick >= 0 ? TERM( x, y ).tick << 4 : 240 ) + TERM( x, y ).cfont * 256;
if( TERM( x, y ).bgc ) {
SDL_FillRect( screen, &dstrect, 0 );

switch(0xF-TERM( x, y ).bgc) {
case 0x0: SDL_color = SDL_MapRGB(screen->format,0x00,0x00,0x00);
break;
case 0x1: SDL_color = SDL_MapRGB(screen->format,0x00,0x00,0x7F);
break;
case 0x2: SDL_color = SDL_MapRGB(screen->format,0x00,0x7F,0x00);
break;
case 0x3: SDL_color = SDL_MapRGB(screen->format,0x7F,0x00,0x00);
break;
default : SDL_color = SDL_MapRGB(screen->format,0x7F,0x7F,0x7F);
}

SDL_FillRect( screen, &dstrect, SDL_color );
}
SDL_BlitSurface( font, &srcrect, screen, &dstrect );
}
Expand Down
150 changes: 18 additions & 132 deletions gui/ui.c
Expand Up @@ -138,12 +138,6 @@ static bool grid_cset(uiobj_t *p_ui,int16_t x,int16_t y,char c,uint8_t bg) {
}

static void grid_focus(uiobj_t *p_ui) {
/* grid_t *p_grid=p_ui->obj;
view_t *p_view=p_ui->view;
if(p_grid->data) {
r_cins(p_ui->x+p_view->x-p_grid->l+p_grid->x*3+2,p_ui->y+p_view->y-p_grid->t+p_grid->y*3+2);
}
*/
grid_t *p_grid=p_ui->obj;
view_t *p_view=p_ui->view;
if(p_grid->data) {
Expand All @@ -153,77 +147,6 @@ static void grid_focus(uiobj_t *p_ui) {
}

static void grid_draw(uiobj_t *p_ui) {
/* grid_t *p_grid=p_ui->obj;
view_t *p_view=p_ui->view;
uint16_t x,y;
uint8_t bg;
if(p_ui->state&9) {
r_white(p_ui->x+p_view->x-1,p_ui->y+p_view->y-1,p_ui->w+2,p_ui->h+2);
if(p_grid->data) {
for(y=1;y<3*p_grid->h+1;y++) {
grid_cset(p_ui,0,y,'h',0);
grid_cset(p_ui,p_grid->w*3+1,y,'g',0);
if(((y-1)%15)==0) {
grid_cset(p_ui,-1,y ,'0'+(((y-1)/300)%10),0);
grid_cset(p_ui,-1,y+1,'0'+(((y-1)/ 30)%10),0);
grid_cset(p_ui,-1,y+2,'0'+(((y-1)/ 3)%10),0);
grid_cset(p_ui,-2,y ,'0'+(((y-1)/300)%10),0);
grid_cset(p_ui,-2,y+1,'0'+(((y-1)/ 30)%10),0);
grid_cset(p_ui,-2,y+2,'0'+(((y-1)/ 3)%10),0);
}
}
for(x=1;x<3*p_grid->w+1;x++) {
grid_cset(p_ui,x,0,'b',0);
grid_cset(p_ui,x,p_grid->h*3+1,'y',0);
if(((x-1)%15)==0) {
grid_cset(p_ui,x ,-1,'0'+(((x-1)/300)%10),0);
grid_cset(p_ui,x+1,-1,'0'+(((x-1)/ 30)%10),0);
grid_cset(p_ui,x+2,-1,'0'+(((x-1)/ 3)%10),0);
grid_cset(p_ui,x ,-2,'0'+(((x-1)/300)%10),0);
grid_cset(p_ui,x+1,-2,'0'+(((x-1)/ 30)%10),0);
grid_cset(p_ui,x+2,-2,'0'+(((x-1)/ 3)%10),0);
}
}
grid_cset(p_ui,0,0,'m',0);
grid_cset(p_ui,p_grid->w*3+1,0,'c',0);
grid_cset(p_ui,0,p_grid->h*3+1,'r',0);
grid_cset(p_ui,p_grid->w*3+1,p_grid->h*3+1,'i',0);
for(y=0;y<p_grid->h;y++) {
for(x=0;x<p_grid->w;x++) {
bg=(p_grid->data[x+y*p_grid->w]<0x80)?1:0;
grid_cset(p_ui,x*3+1,y*3+1,'t',bg);
grid_cset(p_ui,x*3+2,y*3+1,'y',bg);
grid_cset(p_ui,x*3+3,y*3+1,'u',bg);
grid_cset(p_ui,x*3+1,y*3+2,'g',bg);
grid_cset(p_ui,x*3+2,y*3+2,'ñ',bg);
grid_cset(p_ui,x*3+3,y*3+2,'h',bg);
grid_cset(p_ui,x*3+1,y*3+3,'v',bg);
grid_cset(p_ui,x*3+2,y*3+3,'b',bg);
grid_cset(p_ui,x*3+3,y*3+3,'n',bg);
}
}
if(p_grid->l) for(y=0;y<p_ui->h-0;y++) {
r_char(p_ui->x+p_view->x,p_ui->y+p_view->y+y,'a',0,0);
}
if(p_grid->w*3+2-p_grid->l>p_ui->w) for(y=0;y<p_ui->h-0;y++) {
r_char(p_ui->x+p_view->x+p_ui->w-1,p_ui->y+p_view->y+y,'d',0,0);
}
if(p_grid->t) for(x=0;x<p_ui->w-0;x++) {
r_char(p_ui->x+p_view->x+x,p_ui->y+p_view->y,'w',0,0);
}
if(p_grid->h*3+2-p_grid->t>p_ui->h) for(x=0;x<p_ui->w-0;x++) {
r_char(p_ui->x+p_view->x+x,p_ui->y+p_view->y+p_ui->h-1,'s',0,0);
}
if(p_ui->state&8) {
r_done(p_ui->x+p_view->x-1,p_ui->y+p_view->y-1,p_ui->w+2,p_ui->h+2);
}
}
}
if(p_ui->state&4) {
grid_focus(p_ui);
}
p_ui->state=0;
*/
grid_t *p_grid=p_ui->obj;
view_t *p_view=p_ui->view;
uint16_t x,y;
Expand Down Expand Up @@ -261,7 +184,7 @@ static void grid_draw(uiobj_t *p_ui) {
grid_cset(p_ui,p_grid->w*2+1,p_grid->h*2+1,'i',0);
for(y=0;y<p_grid->h;y++) {
for(x=0;x<p_grid->w;x++) {
bg=(p_grid->data[x+y*p_grid->w]<0x80)?1:0;
bg=0xF-(p_grid->data[x+y*p_grid->w]&0xF);
grid_cset(p_ui,x*2+1,y*2+1,'t',bg);
grid_cset(p_ui,x*2+2,y*2+1,'u',bg);
grid_cset(p_ui,x*2+1,y*2+2,'v',bg);
Expand Down Expand Up @@ -292,60 +215,17 @@ static void grid_draw(uiobj_t *p_ui) {
}

static bool grid_key(uiobj_t *p_ui,SDL_Keycode sym) {
/*
grid_t *p_grid=p_ui->obj;
switch(sym) {
case SDLK_LEFT:
if(p_grid->x>0) {
p_grid->x--;
p_ui->state|=4;
}
break;
case SDLK_RIGHT:
if(p_grid->x<p_grid->w-1) {
p_grid->x++;
p_ui->state|=4;
}
break;
case SDLK_UP:
if(p_grid->y>0) {
p_grid->y--;
p_ui->state|=4;
}
break;
case SDLK_DOWN:
if(p_grid->y<p_grid->h-1) {
p_grid->y++;
p_ui->state|=4;
}
break;
case SDLK_SPACE:
p_grid->data[p_grid->x+p_grid->y*p_grid->w]=p_grid->data[p_grid->x+p_grid->y*p_grid->w]<0x80?0xFF:0x00;
p_ui->state|=8;
return true;
}
if((p_grid->x*3+2)-2<p_grid->l) {
p_grid->l=(p_grid->x*3+2)-2;
p_ui->state|=8;
} else if( (p_grid->x*3+2)+3>p_grid->l+p_ui->w ) {
p_grid->l=(p_grid->x*3+2)+3-p_ui->w;
p_ui->state|=8;
}
if((p_grid->y*3+2)-2<p_grid->t) {
p_grid->t=(p_grid->y*3+2)-2;
p_ui->state|=8;
} else if( (p_grid->y*3+2)+3>p_grid->t+p_ui->h ) {
p_grid->t=(p_grid->y*3+2)+3-p_ui->h;
p_ui->state|=8;
}
return false;
*/
grid_t *p_grid=p_ui->obj;
switch(sym) {
uint16_t x;
uint8_t sample=0;
if((sym>=SDLK_0&&sym<=SDLK_3)) {
for(x=0;x<p_grid->w;x++) {
if(p_grid->data[x+p_grid->y*p_grid->w]<0xF) {
p_grid->data[x+p_grid->y*p_grid->w]=sym-SDLK_0;
p_ui->state|=8;
}
}
} else switch(sym) {
case SDLK_LEFT:
if(p_grid->x>0) {
p_grid->x--;
Expand All @@ -371,7 +251,13 @@ static bool grid_key(uiobj_t *p_ui,SDL_Keycode sym) {
}
break;
case SDLK_SPACE:
p_grid->data[p_grid->x+p_grid->y*p_grid->w]=p_grid->data[p_grid->x+p_grid->y*p_grid->w]<0x80?0xFF:0x00;
for(x=0;x<p_grid->w;x++) {
if(p_grid->data[x+p_grid->y*p_grid->w]<0xF) {
sample=p_grid->data[x+p_grid->y*p_grid->w];
break;
}
}
p_grid->data[p_grid->x+p_grid->y*p_grid->w]=p_grid->data[p_grid->x+p_grid->y*p_grid->w]<0x0F?0xFF:sample;
p_ui->state|=8;
break;
default:
Expand Down
4 changes: 2 additions & 2 deletions lib/include/image.h
Expand Up @@ -14,10 +14,10 @@ extern "C" {
uint8_t *image_alloc(uint16_t width,uint16_t height);

// get pixel from image
bool image_sample(uint8_t *p_image,uint16_t width,uint16_t x,uint16_t y);
uint8_t image_sample(uint8_t *p_image,uint16_t width,uint16_t x,uint16_t y);

// set pixel in image
void image_pset(uint8_t *p_image,uint16_t width,uint16_t x,uint16_t y,bool pixel);
void image_pset(uint8_t *p_image,uint16_t width,uint16_t x,uint16_t y,uint8_t pixel);

// read image file
uint8_t *image_read(FILE *f,uint16_t *width,uint16_t *height);
Expand Down

0 comments on commit a408f96

Please sign in to comment.