blend testing and code cleanup
This commit is contained in:
parent
a1ca05248e
commit
32687e5360
3 changed files with 137 additions and 37 deletions
BIN
art/image.bmp
Normal file
BIN
art/image.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.1 KiB |
BIN
art/test.bmp
Normal file
BIN
art/test.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.1 KiB |
174
editor.c
174
editor.c
|
@ -30,6 +30,7 @@ SOFTWARE.
|
|||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "tinyfiledialogs.h"
|
||||
|
||||
|
@ -62,6 +63,17 @@ SOFTWARE.
|
|||
#define SGN(x) ((x < 0) ? -1 : ((x > 0) ? 1 : 0))
|
||||
#endif
|
||||
|
||||
#ifndef SQR
|
||||
#define SQR(x) ((x) * (x))
|
||||
#endif
|
||||
|
||||
enum {
|
||||
REDO_NO,
|
||||
REDO_YES
|
||||
};
|
||||
|
||||
#define PIXEL(s, x, y) (((uint8_t *)((s)->pixels))[(y) * (s)->pitch + (x) * (s)->format->BytesPerPixel])
|
||||
|
||||
/* palette */
|
||||
unsigned char palette[768] = {
|
||||
0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x10, 0x10, 0x10, 0x18, 0x18, 0x18,
|
||||
|
@ -229,6 +241,7 @@ static int top_bitmap = 1;
|
|||
/* temp layer */
|
||||
int templayer[BITMAP_HEIGHT][BITMAP_WIDTH];
|
||||
|
||||
/* tools */
|
||||
enum {
|
||||
TOOL_PEN,
|
||||
TOOL_LINE,
|
||||
|
@ -243,11 +256,12 @@ static eui_color_t current_color = 0;
|
|||
/* filter patterns for save/load dialogs */
|
||||
static const char *filter_patterns[1] = {"*.bmp"};
|
||||
|
||||
static SDL_Window *window;
|
||||
static SDL_Surface *surface8;
|
||||
static SDL_Surface *surface32;
|
||||
static SDL_Renderer *renderer;
|
||||
static SDL_Texture *texture;
|
||||
static SDL_Window *window = NULL;
|
||||
static SDL_Surface *surface8 = NULL;
|
||||
static SDL_Surface *surface32 = NULL;
|
||||
static SDL_Surface *clut = NULL;
|
||||
static SDL_Renderer *renderer = NULL;
|
||||
static SDL_Texture *texture = NULL;
|
||||
static SDL_Rect blit_rect;
|
||||
static SDL_Color colors[256];
|
||||
static Uint64 next_time = 0;
|
||||
|
@ -273,6 +287,77 @@ static void speed_limiter(void)
|
|||
next_time += DELAY;
|
||||
}
|
||||
|
||||
static int palette_search(SDL_Palette *palette, int r, int g, int b)
|
||||
{
|
||||
int i, pen = 0, dist = INT_MAX;
|
||||
|
||||
for (i = 0; i < palette->ncolors; i++)
|
||||
{
|
||||
int rank =
|
||||
SQR(palette->colors[i].r - r) +
|
||||
SQR(palette->colors[i].g - g) +
|
||||
SQR(palette->colors[i].b - b);
|
||||
|
||||
if (rank < dist)
|
||||
{
|
||||
pen = i;
|
||||
dist = rank;
|
||||
}
|
||||
}
|
||||
|
||||
return pen;
|
||||
}
|
||||
|
||||
static SDL_Surface *generate_clut(SDL_Palette *palette)
|
||||
{
|
||||
SDL_Surface *clut = SDL_CreateRGBSurfaceWithFormat(0, palette->ncolors, palette->ncolors, 8, SDL_PIXELFORMAT_INDEX8);
|
||||
SDL_SetSurfacePalette(clut, palette);
|
||||
|
||||
for (int y = 0; y < palette->ncolors; y++)
|
||||
{
|
||||
for (int x = 0; x < palette->ncolors; x++)
|
||||
{
|
||||
int r, g, b;
|
||||
|
||||
r = (palette->colors[x].r + palette->colors[y].r) >> 1;
|
||||
g = (palette->colors[x].g + palette->colors[y].g) >> 1;
|
||||
b = (palette->colors[x].b + palette->colors[y].b) >> 1;
|
||||
|
||||
PIXEL(clut, x, y) = palette_search(palette, r, g, b);
|
||||
}
|
||||
}
|
||||
|
||||
return clut;
|
||||
}
|
||||
|
||||
/* setup editor colors */
|
||||
static void setup_colors(SDL_Palette *palette)
|
||||
{
|
||||
eui_config_t *config;
|
||||
|
||||
/* set palette for screen */
|
||||
SDL_SetSurfacePalette(surface8, palette);
|
||||
|
||||
/* regenerate clut */
|
||||
if (clut) SDL_FreeSurface(clut);
|
||||
clut = generate_clut(palette);
|
||||
|
||||
/* setup colors */
|
||||
config = eui_get_config();
|
||||
config->button.border_color = palette_search(palette, 0, 0, 0);
|
||||
config->button.border_color_hover = palette_search(palette, 255, 255, 255);
|
||||
config->button.bg_color = palette_search(palette, 255, 255, 255);
|
||||
config->button.bg_color_hover = palette_search(palette, 0, 0, 0);
|
||||
config->button.text_color = palette_search(palette, 0, 0, 0);
|
||||
config->button.text_color_hover = palette_search(palette, 255, 255, 255);
|
||||
}
|
||||
|
||||
/* do blend */
|
||||
static Uint8 do_blend(int x, int y, eui_color_t color)
|
||||
{
|
||||
return PIXEL(clut, bitmap[y][x], color);
|
||||
}
|
||||
|
||||
/* push bitmap to stack */
|
||||
void bitmap_push(int redo)
|
||||
{
|
||||
|
@ -295,7 +380,7 @@ void bitmap_push(int redo)
|
|||
/* move bitmap stack down */
|
||||
for (i = 0; i < current_bitmap; i++)
|
||||
{
|
||||
memcpy(&bitmap_history[i], &bitmap_history[i + 1], sizeof(bitmap_history[i]));
|
||||
SDL_memcpy(&bitmap_history[i], &bitmap_history[i + 1], sizeof(bitmap_history[i]));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -306,13 +391,13 @@ void bitmap_push(int redo)
|
|||
/* clear upper bitmap stack */
|
||||
for (i = current_bitmap; i < MAX_UNDOS; i++)
|
||||
{
|
||||
memset(&bitmap_history[i], 0, sizeof(bitmap_history[i]));
|
||||
SDL_memset(&bitmap_history[i], 0, sizeof(bitmap_history[i]));
|
||||
}
|
||||
}
|
||||
|
||||
/* copy current bitmap to next in stack */
|
||||
top_bitmap = current_bitmap;
|
||||
memcpy(&bitmap_history[current_bitmap], bitmap, sizeof(bitmap));
|
||||
SDL_memcpy(&bitmap_history[current_bitmap], bitmap, sizeof(bitmap));
|
||||
}
|
||||
|
||||
/* pop bitmap from stack */
|
||||
|
@ -328,15 +413,15 @@ void button_undo(void *user)
|
|||
{
|
||||
EUI_UNUSED(user);
|
||||
bitmap_pop();
|
||||
memcpy(bitmap, &bitmap_history[current_bitmap], sizeof(bitmap));
|
||||
SDL_memcpy(bitmap, &bitmap_history[current_bitmap], sizeof(bitmap));
|
||||
}
|
||||
|
||||
/* redo button */
|
||||
void button_redo(void *user)
|
||||
{
|
||||
EUI_UNUSED(user);
|
||||
bitmap_push(EUI_TRUE);
|
||||
memcpy(bitmap, &bitmap_history[current_bitmap], sizeof(bitmap));
|
||||
bitmap_push(REDO_YES);
|
||||
SDL_memcpy(bitmap, &bitmap_history[current_bitmap], sizeof(bitmap));
|
||||
}
|
||||
|
||||
/* clear button */
|
||||
|
@ -344,10 +429,10 @@ void button_clear(void *user)
|
|||
{
|
||||
EUI_UNUSED(user);
|
||||
|
||||
memset(&bitmap, 0, sizeof(bitmap));
|
||||
memset(templayer, -1, sizeof(templayer));
|
||||
SDL_memset(&bitmap, 0, sizeof(bitmap));
|
||||
SDL_memset(templayer, -1, sizeof(templayer));
|
||||
|
||||
bitmap_push(EUI_FALSE);
|
||||
bitmap_push(REDO_NO);
|
||||
}
|
||||
|
||||
/* save button */
|
||||
|
@ -384,7 +469,7 @@ void button_save(void *user)
|
|||
ptr = (uint8_t *)bmp->pixels;
|
||||
for (y = 0; y < bmp->h; y++)
|
||||
{
|
||||
memcpy(ptr, &bitmap[y][0], bmp->w * sizeof(eui_color_t));
|
||||
SDL_memcpy(ptr, &bitmap[y][0], bmp->w * sizeof(eui_color_t));
|
||||
ptr += bmp->pitch;
|
||||
}
|
||||
|
||||
|
@ -439,10 +524,13 @@ void button_load(void *user)
|
|||
ptr = (uint8_t *)bmp->pixels;
|
||||
for (y = 0; y < bmp->h; y++)
|
||||
{
|
||||
memcpy(&bitmap[y][0], ptr, bmp->w * sizeof(eui_color_t));
|
||||
SDL_memcpy(&bitmap[y][0], ptr, bmp->w * sizeof(eui_color_t));
|
||||
ptr += bmp->pitch;
|
||||
}
|
||||
|
||||
/* setup palette */
|
||||
setup_colors(bmp->format->palette);
|
||||
|
||||
SDL_FreeSurface(bmp);
|
||||
}
|
||||
|
||||
|
@ -476,7 +564,7 @@ void tool_fill(int x, int y, eui_color_t color)
|
|||
if (started)
|
||||
{
|
||||
/* push bitmap stack for undo/redo */
|
||||
bitmap_push(EUI_FALSE);
|
||||
bitmap_push(REDO_NO);
|
||||
|
||||
/* turn off started flag */
|
||||
started = EUI_FALSE;
|
||||
|
@ -521,7 +609,7 @@ void tool_fill(int x, int y, eui_color_t color)
|
|||
if (read == seed)
|
||||
{
|
||||
/* set pixel */
|
||||
bitmap[y][x] = color;
|
||||
bitmap[y][x] = do_blend(x, y, color);
|
||||
|
||||
/* add neighboring pixel positions */
|
||||
PUSH(x + 1, y);
|
||||
|
@ -548,7 +636,7 @@ void tool_pen(int x, int y, eui_color_t color)
|
|||
if (started)
|
||||
{
|
||||
/* push bitmap stack for undo/redo */
|
||||
bitmap_push(EUI_FALSE);
|
||||
bitmap_push(REDO_NO);
|
||||
|
||||
/* turn off started flag */
|
||||
started = EUI_FALSE;
|
||||
|
@ -562,7 +650,7 @@ void tool_pen(int x, int y, eui_color_t color)
|
|||
color = 0;
|
||||
|
||||
/* plot pixel */
|
||||
bitmap[y][x] = color;
|
||||
bitmap[y][x] = do_blend(x, y, color);
|
||||
|
||||
/* we're doing it */
|
||||
started = EUI_TRUE;
|
||||
|
@ -589,19 +677,19 @@ void tool_rect(int x, int y, eui_color_t color)
|
|||
for (xx = 0; xx < BITMAP_WIDTH; xx++)
|
||||
{
|
||||
if (templayer[yy][xx] >= 0)
|
||||
bitmap[yy][xx] = templayer[yy][xx];
|
||||
bitmap[yy][xx] = do_blend(xx, yy, templayer[yy][xx]);
|
||||
}
|
||||
}
|
||||
|
||||
/* push bitmap stack for undo/redo */
|
||||
bitmap_push(EUI_FALSE);
|
||||
bitmap_push(REDO_NO);
|
||||
|
||||
/* turn off started flag */
|
||||
started = EUI_FALSE;
|
||||
}
|
||||
|
||||
/* clear temp layer */
|
||||
memset(templayer, -1, sizeof(templayer));
|
||||
SDL_memset(templayer, -1, sizeof(templayer));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -621,7 +709,7 @@ void tool_rect(int x, int y, eui_color_t color)
|
|||
ysgn = SGN(endpos.y - startpos.y);
|
||||
|
||||
/* clear temp layer */
|
||||
memset(templayer, -1, sizeof(templayer));
|
||||
SDL_memset(templayer, -1, sizeof(templayer));
|
||||
|
||||
/* vertical lines */
|
||||
for (yy = startpos.y; yy != endpos.y; yy += ysgn)
|
||||
|
@ -675,19 +763,19 @@ void tool_line(int x, int y, eui_color_t color)
|
|||
for (xx = 0; xx < BITMAP_WIDTH; xx++)
|
||||
{
|
||||
if (templayer[yy][xx] >= 0)
|
||||
bitmap[yy][xx] = templayer[yy][xx];
|
||||
bitmap[yy][xx] = do_blend(xx, yy, templayer[yy][xx]);
|
||||
}
|
||||
}
|
||||
|
||||
/* push bitmap stack for undo/redo */
|
||||
bitmap_push(EUI_FALSE);
|
||||
bitmap_push(REDO_NO);
|
||||
|
||||
/* turn off started flag */
|
||||
started = EUI_FALSE;
|
||||
}
|
||||
|
||||
/* clear temp layer */
|
||||
memset(templayer, -1, sizeof(templayer));
|
||||
SDL_memset(templayer, -1, sizeof(templayer));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -706,7 +794,7 @@ void tool_line(int x, int y, eui_color_t color)
|
|||
endpos.y = y;
|
||||
|
||||
/* clear temp layer */
|
||||
memset(templayer, -1, sizeof(templayer));
|
||||
SDL_memset(templayer, -1, sizeof(templayer));
|
||||
|
||||
/* do line drawing */
|
||||
dir.x = endpos.x - startpos.x;
|
||||
|
@ -806,19 +894,19 @@ void tool_filled_rect(int x, int y, eui_color_t color)
|
|||
for (xx = 0; xx < BITMAP_WIDTH; xx++)
|
||||
{
|
||||
if (templayer[yy][xx] >= 0)
|
||||
bitmap[yy][xx] = templayer[yy][xx];
|
||||
bitmap[yy][xx] = do_blend(xx, yy, templayer[yy][xx]);
|
||||
}
|
||||
}
|
||||
|
||||
/* push bitmap stack for undo/redo */
|
||||
bitmap_push(EUI_FALSE);
|
||||
bitmap_push(REDO_NO);
|
||||
|
||||
/* turn off started flag */
|
||||
started = EUI_FALSE;
|
||||
}
|
||||
|
||||
/* clear temp layer */
|
||||
memset(templayer, -1, sizeof(templayer));
|
||||
SDL_memset(templayer, -1, sizeof(templayer));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -838,7 +926,7 @@ void tool_filled_rect(int x, int y, eui_color_t color)
|
|||
ysgn = SGN(endpos.y - startpos.y);
|
||||
|
||||
/* clear temp layer */
|
||||
memset(templayer, -1, sizeof(templayer));
|
||||
SDL_memset(templayer, -1, sizeof(templayer));
|
||||
|
||||
/* vertical lines */
|
||||
for (yy = startpos.y; yy != endpos.y; yy += ysgn)
|
||||
|
@ -935,11 +1023,15 @@ int main(int argc, char **argv)
|
|||
colors[i].r = palette[i * 3];
|
||||
colors[i].g = palette[i * 3 + 1];
|
||||
colors[i].b = palette[i * 3 + 2];
|
||||
colors[i].a = 255;
|
||||
}
|
||||
|
||||
/* install palette */
|
||||
SDL_SetPaletteColors(surface8->format->palette, colors, 0, 256);
|
||||
|
||||
/* setup editor colors */
|
||||
setup_colors(surface8->format->palette);
|
||||
|
||||
/* create display surface */
|
||||
format = SDL_GetWindowPixelFormat(window);
|
||||
SDL_PixelFormatEnumToMasks(format, &bpp, &rmask, &gmask, &bmask, &amask);
|
||||
|
@ -956,8 +1048,8 @@ int main(int argc, char **argv)
|
|||
blit_rect.h = HEIGHT;
|
||||
|
||||
/* clear bitmap */
|
||||
memset(&bitmap, 0, sizeof(bitmap));
|
||||
memset(templayer, -1, sizeof(templayer));
|
||||
SDL_memset(&bitmap, 0, sizeof(bitmap));
|
||||
SDL_memset(templayer, -1, sizeof(templayer));
|
||||
|
||||
/* set default color */
|
||||
current_color = 63;
|
||||
|
@ -1146,7 +1238,7 @@ int main(int argc, char **argv)
|
|||
eui_text(pos, 31, "color=---");
|
||||
|
||||
/* clear temp layer */
|
||||
memset(templayer, -1, sizeof(templayer));
|
||||
SDL_memset(templayer, -1, sizeof(templayer));
|
||||
}
|
||||
|
||||
/* move to top left alignment */
|
||||
|
@ -1261,8 +1353,15 @@ int main(int argc, char **argv)
|
|||
}
|
||||
|
||||
/* blit to screen */
|
||||
SDL_BlitSurface(surface8, &blit_rect, surface32, &blit_rect);
|
||||
SDL_UpdateTexture(texture, NULL, surface32->pixels, surface32->pitch);
|
||||
int dst_pitch;
|
||||
void *dst_pixels;
|
||||
if (SDL_LockTexture(texture, NULL, &dst_pixels, &dst_pitch) == 0)
|
||||
{
|
||||
SDL_BlitSurface(surface8, &blit_rect, surface32, &blit_rect);
|
||||
SDL_memcpy(dst_pixels, surface32->pixels, surface32->pitch * surface32->h);
|
||||
SDL_UnlockTexture(texture);
|
||||
}
|
||||
|
||||
SDL_RenderClear(renderer);
|
||||
SDL_RenderCopy(renderer, texture, NULL, NULL);
|
||||
SDL_RenderPresent(renderer);
|
||||
|
@ -1273,6 +1372,7 @@ int main(int argc, char **argv)
|
|||
|
||||
/* quit */
|
||||
done:
|
||||
SDL_FreeSurface(clut);
|
||||
SDL_FreeSurface(surface8);
|
||||
SDL_FreeSurface(surface32);
|
||||
SDL_DestroyTexture(texture);
|
||||
|
|
Loading…
Reference in a new issue