Skip to content

Commit

Permalink
Add new palette type rather than using png_color.
Browse files Browse the repository at this point in the history
Part of #2.
  • Loading branch information
fragglet committed Jul 13, 2024
1 parent 0b627c2 commit 9038d3c
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 29 deletions.
29 changes: 15 additions & 14 deletions src/conv/graphic.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#include "common.h"
#include "fs/vfile.h"
#include "palette/palette.h"
#include "conv/error.h"
#include "conv/graphic.h"
#include "conv/vpng.h"
Expand Down Expand Up @@ -47,7 +48,7 @@ static VFILE *RGBABufferToPatch(uint8_t *buffer, size_t rowstep,
uint8_t *palettized, *post, alpha;
int x, y, post_len;

palettized = V_PalettizeRGBABuffer(doom_palette, buffer, rowstep,
palettized = V_PalettizeRGBABuffer(&doom_palette, buffer, rowstep,
hdr->width, hdr->height);

result = vfopenmem(NULL, 0);
Expand Down Expand Up @@ -138,7 +139,7 @@ static VFILE *BufferToRaw(uint8_t *imgbuf, int rowstep,
VFILE *result = vfopenmem(NULL, 0);

palettized = V_PalettizeRGBABuffer(
doom_palette, imgbuf, rowstep, hdr->width, hdr->height);
&doom_palette, imgbuf, rowstep, hdr->width, hdr->height);
assert(vfwrite(palettized, hdr->width,
hdr->height, result) == hdr->height);
free(palettized);
Expand Down Expand Up @@ -283,7 +284,7 @@ VFILE *V_ToImageFile(VFILE *input)
goto fail;
}

result = V_WritePalettizedPNG(&hdr, imgbuf, doom_palette, true);
result = V_WritePalettizedPNG(&hdr, imgbuf, &doom_palette, true);

fail:
free(imgbuf);
Expand Down Expand Up @@ -312,7 +313,7 @@ VFILE *V_FlatToImageFile(VFILE *input)
hdr.height = buf_len / 64;
hdr.topoffset = 0;
hdr.leftoffset = 0;
result = V_WritePalettizedPNG(&hdr, buf, doom_palette, false);
result = V_WritePalettizedPNG(&hdr, buf, &doom_palette, false);

fail:
free(buf);
Expand All @@ -336,27 +337,27 @@ VFILE *V_FullscreenToImageFile(VFILE *input)
hdr.height = FULLSCREEN_H;
hdr.topoffset = 0;
hdr.leftoffset = 0;
result = V_WritePalettizedPNG(&hdr, buf, doom_palette, false);
result = V_WritePalettizedPNG(&hdr, buf, &doom_palette, false);
free(buf);

return result;
}

static void ReadHiresPalette(uint8_t *buf, png_color *palette)
static void ReadHiresPalette(uint8_t *buf, struct palette *palette)
{
unsigned int i, r, g, b;

for (i = 0; i < 16; i++) {
r = buf[i * 3];
g = buf[i * 3 + 1];
b = buf[i * 3 + 2];
palette[i].red = (r << 2) | (r >> 4);
palette[i].green = (g << 2) | (g >> 4);
palette[i].blue = (b << 2) | (b >> 4);
palette->entries[i].r = (r << 2) | (r >> 4);
palette->entries[i].g = (g << 2) | (g >> 4);
palette->entries[i].b = (b << 2) | (b >> 4);
}
}

static uint8_t *PlanarToFlat(void *src, png_color *palette)
static uint8_t *PlanarToFlat(void *src, struct palette *palette)
{
const uint8_t *srcptrs[4];
uint8_t srcbits[4], *dest, *result;
Expand Down Expand Up @@ -401,7 +402,7 @@ VFILE *V_HiresToImageFile(VFILE *input)
VFILE *result;
uint8_t *lump, *screenbuf;
size_t lump_len;
png_color palette[16];
struct palette palette;
struct patch_header hdr;

lump = vfreadall(input, &lump_len);
Expand All @@ -413,12 +414,12 @@ VFILE *V_HiresToImageFile(VFILE *input)
return NULL;
}

ReadHiresPalette(lump, palette);
screenbuf = PlanarToFlat(lump + 3 * 16, palette);
ReadHiresPalette(lump, &palette);
screenbuf = PlanarToFlat(lump + 3 * 16, &palette);

hdr.width = HIRES_SCREEN_W;
hdr.height = HIRES_SCREEN_H;
result = V_WritePalettizedPNG(&hdr, screenbuf, palette, false);
result = V_WritePalettizedPNG(&hdr, screenbuf, &palette, false);

free(screenbuf);
free(lump);
Expand Down
5 changes: 3 additions & 2 deletions src/conv/palette.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#include "common.h"
#include "fs/vfile.h"
#include "palette/palette.h"
#include "conv/error.h"
#include "conv/graphic.h"
#include "conv/vpng.h"
Expand Down Expand Up @@ -144,7 +145,7 @@ VFILE *V_ColormapToImageFile(VFILE *input)
hdr.height = buf_len / 256;
hdr.topoffset = 0;
hdr.leftoffset = 0;
result = V_WritePalettizedPNG(&hdr, buf, doom_palette, false);
result = V_WritePalettizedPNG(&hdr, buf, &doom_palette, false);

fail:
free(buf);
Expand Down Expand Up @@ -173,7 +174,7 @@ VFILE *V_ColormapFromImageFile(VFILE *input)
goto fail;
}

palettized = V_PalettizeRGBABuffer(doom_palette, imgbuf, rowstep,
palettized = V_PalettizeRGBABuffer(&doom_palette, imgbuf, rowstep,
hdr.width, hdr.height);
result = vfopenmem(NULL, 0);
assert(vfwrite(palettized, hdr.width,
Expand Down
39 changes: 29 additions & 10 deletions src/conv/vpng.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include "common.h"
#include "fs/vfile.h"
#include "palette/palette.h"
#include "conv/error.h"
#include "conv/graphic.h"
#include "conv/vpng.h"
Expand All @@ -30,7 +31,7 @@ struct offsets_chunk {
static jmp_buf libpng_abort_jump;

// TODO: Get palette from current WADs
const png_color doom_palette[256] = {
const struct palette doom_palette = {{
{0x00, 0x00, 0x00}, {0x1f, 0x17, 0x0b},
{0x17, 0x0f, 0x07}, {0x4b, 0x4b, 0x4b},
{0xff, 0xff, 0xff}, {0x1b, 0x1b, 0x1b},
Expand Down Expand Up @@ -159,22 +160,22 @@ const png_color doom_palette[256] = {
{0xff, 0x7b, 0xff}, {0xff, 0x00, 0xff},
{0xcf, 0x00, 0xcf}, {0x9f, 0x00, 0x9b},
{0x6f, 0x00, 0x6b}, {0xa7, 0x6b, 0x6b},
};
}};

static void SwapOffsetsChunk(struct offsets_chunk *chunk)
{
SwapBE32(&chunk->leftoffset);
SwapBE32(&chunk->topoffset);
}

static uint8_t FindColor(const png_color *pal, int r, int g, int b)
static uint8_t FindColor(const struct palette *pal, int r, int g, int b)
{
int diff, best_diff = INT_MAX, i, best_idx = -1;

for (i = 0; i < 256; i++) {
diff = (r - pal[i].red) * (r - pal[i].red)
+ (g - pal[i].green) * (g - pal[i].green)
+ (b - pal[i].blue) * (b - pal[i].blue);
diff = (r - pal->entries[i].r) * (r - pal->entries[i].r)
+ (g - pal->entries[i].g) * (g - pal->entries[i].g)
+ (b - pal->entries[i].b) * (b - pal->entries[i].b);
if (diff == 0) {
return i;
}
Expand All @@ -187,7 +188,7 @@ static uint8_t FindColor(const png_color *pal, int r, int g, int b)
return best_idx;
}

uint8_t *V_PalettizeRGBABuffer(const png_color *palette, uint8_t *buf,
uint8_t *V_PalettizeRGBABuffer(const struct palette *pal, uint8_t *buf,
size_t rowstep, int width, int height)
{
uint8_t *result, *pixel;
Expand All @@ -199,7 +200,7 @@ uint8_t *V_PalettizeRGBABuffer(const png_color *palette, uint8_t *buf,
for (x = 0; x < width; ++x) {
pixel = &buf[y * rowstep + x * 4];
result[y * width + x] = FindColor(
palette, pixel[0], pixel[1], pixel[2]);
pal, pixel[0], pixel[1], pixel[2]);
}
}

Expand Down Expand Up @@ -418,16 +419,33 @@ static void WriteOffsetChunk(png_structp ppng, const struct patch_header *hdr)
sizeof(chunk));
}

static png_color *MakePNGPalette(const struct palette *palette)
{
png_color *result = checked_calloc(256, sizeof(png_color));
int i;

for (i = 0; i < 256; i++) {
result[i].red = palette->entries[i].r;
result[i].green = palette->entries[i].g;
result[i].blue = palette->entries[i].b;
}

return result;
}

VFILE *V_WritePalettizedPNG(struct patch_header *hdr, uint8_t *imgbuf,
const png_color *palette, bool set_transparency)
const struct palette *palette,
bool set_transparency)
{
png_color *png_pal = MakePNGPalette(palette);
VFILE *result = NULL;
uint8_t *alphabuf = NULL;
struct png_context ctx;
int y;

result = V_OpenPNGWrite(&ctx);
if (result == NULL) {
free(png_pal);
return NULL;
}

Expand All @@ -442,7 +460,7 @@ VFILE *V_WritePalettizedPNG(struct patch_header *hdr, uint8_t *imgbuf,

png_set_tRNS(ctx.ppng, ctx.pinfo, alphabuf, 256, NULL);
}
png_set_PLTE(ctx.ppng, ctx.pinfo, palette, 256);
png_set_PLTE(ctx.ppng, ctx.pinfo, png_pal, 256);
png_write_info(ctx.ppng, ctx.pinfo);
if (hdr->topoffset != 0 || hdr->leftoffset != 0) {
WriteOffsetChunk(ctx.ppng, hdr);
Expand All @@ -457,5 +475,6 @@ VFILE *V_WritePalettizedPNG(struct patch_header *hdr, uint8_t *imgbuf,
free(alphabuf);

V_ClosePNG(&ctx);
free(png_pal);
return result;
}
7 changes: 4 additions & 3 deletions src/conv/vpng.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ struct png_context {
bool write;
};

extern const png_color doom_palette[256];
extern const struct palette doom_palette;

uint8_t *V_PalettizeRGBABuffer(const png_color *palette, uint8_t *buf,
uint8_t *V_PalettizeRGBABuffer(const struct palette *palette, uint8_t *buf,
size_t rowstep, int width, int height);

bool V_OpenPNGRead(struct png_context *ctx, VFILE *input);
Expand All @@ -29,4 +29,5 @@ void V_ClosePNG(struct png_context *ctx);

uint8_t *V_ReadRGBAPNG(VFILE *input, struct patch_header *hdr, int *rowstep);
VFILE *V_WritePalettizedPNG(struct patch_header *hdr, uint8_t *imgbuf,
const png_color *palette, bool set_transparency);
const struct palette *palette,
bool set_transparency);
17 changes: 17 additions & 0 deletions src/palette/palette.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//
// Copyright(C) 2024 Simon Howard
//
// You can redistribute and/or modify this program under the terms of
// the GNU General Public License version 2 as published by the Free
// Software Foundation, or any later version. This program is
// distributed WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//

struct palette_entry {
uint8_t r, g, b;
};

struct palette {
struct palette_entry entries[256];
};

0 comments on commit 9038d3c

Please sign in to comment.