Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
Signed-off-by: Ørjan Malde <[email protected]>
  • Loading branch information
hiirotsuki committed Jan 23, 2022
0 parents commit 79934f2
Show file tree
Hide file tree
Showing 8 changed files with 358 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.o
*.gpl
15 changes: 15 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
CC := gcc
CFLAGS_ANSI = -ansi -pedantic
CFLAGS := -Wall -Wextra -O2
LDFLAGS :=
LIBS := -lm

all: aseconv

aseconv: ase.c lab.c gimp.c
$(CC) $(CFLAGS) $(CFLAGS_ANSI) $? -o $@ $(LDFLAGS) $(LIBS)

clean: aseconv
rm -f $?

.PHONY: clean
200 changes: 200 additions & 0 deletions ase.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <math.h>
#include <errno.h>

#include "color.h"
#include "readbytes.h"
#include "gimp.h"

float bytes_to_float(const unsigned char *bytes);
unsigned int bytes_to_rgb(const unsigned char *bytes);
struct rgb from_cmyk(const unsigned char *bytes);

int main(int argc, const char *argv[])
{
char *p;
int count;
FILE *out, *in;
float f1, f2, f3;
char filename[512];
unsigned int r, g, b;
struct rgb rgb_colors;
unsigned char buf[1024];
unsigned short chunk_size;
const char *ase = "ASEF", *rgb = "RGB ", *cmyk = "CMYK", *lab = "LAB ", *gray = "Gray";

if(argc != 2)
{
printf("usage: %s <palette.ase>\n", argv[0]);
return 1;
}

strcpy(filename, argv[1]);
p = strrchr(filename, '.');

if(!p || p[1] == '\0' || p[2] == '\0' || p[3] == '\0')
{
printf("usage: %s <palette.ase>\n", argv[0]);
return 1;
}

p[1] = 'g';
p[2] = 'p';
p[3] = 'l';
p[4] = '\0';

if(!(in = fopen(argv[1], "rb")))
{
printf("%s: %s\n", argv[0], strerror(errno));
return 1;
}

if(!(out = fopen(filename, "wb")))
{
printf("%s: %s\n", argv[0], strerror(errno));
return 1;
}

/* read header, version and chunk count */
fread(buf, 1, 12, in);

if(memcmp(ase, buf, 4))
{
puts("not an ASE file");
exit(1);
}

/* TODO: read ASE version, currently at buf 4-7 */
#if 0
printf("%x\n", buf[8]); printf("%x\n", buf[9]); printf("%x\n", buf[10]); printf("%x\n", buf[11]);
#endif

count = read_uint32_be(&buf[8]);
printf("chunk count: %d\n", count);

/* CHUNK types: */
/* palette name = 0xC0010000 */
/* mystery = 0xC0020000 */
/* swatch = 0x00010000 */

gimp_emit_header(out);

while(count)
{
if(fread(buf, 1, 6, in) != 6)
{
puts("ERROR: truncated chunk");
break;
}

/* palette name chunk, no valuable data to be found, skip */
if(!memcmp(&buf[0], "\xC0\x01", 2))
{
chunk_size = read_uint16_be(&buf[4]);
fseek(in, chunk_size, SEEK_CUR);
}
/* swatch chunk */
else if(!memcmp(&buf[0], "\x00\x01", 2))
{
chunk_size = read_uint16_be(&buf[4]);
fread(buf, 1, chunk_size, in);

if(!memcmp(rgb, &buf[chunk_size - 18], 4))
{
r = bytes_to_float(&buf[chunk_size - 14]) * 255;
g = bytes_to_float(&buf[chunk_size - 10]) * 255;
b = bytes_to_float(&buf[chunk_size - 6]) * 255;
}
else if(!memcmp(cmyk, &buf[chunk_size - 22], 4))
{
rgb_colors = from_cmyk(&buf[chunk_size - 18]);
r = rgb_colors.r;
g = rgb_colors.g;
b = rgb_colors.b;
}
else if(!memcmp(gray, &buf[chunk_size - 10], 4))
{
r = bytes_to_float(&buf[chunk_size - 6]) * 255;
g = r;
b = r;
}
else if(!memcmp(lab, &buf[chunk_size - 18], 4))
{
/* approximate conversion */
f1 = bytes_to_float(&buf[chunk_size - 14]);
f2 = bytes_to_float(&buf[chunk_size - 10]);
f3 = bytes_to_float(&buf[chunk_size - 6]);
rgb_colors = from_lab(f1 * 100, f2, f3);
r = rgb_colors.r;
g = rgb_colors.g;
b = rgb_colors.b;
}
else
{
puts("FIXME: unsupported color sequences");
count--;
continue;
}

gimp_emit_line(out, r, g, b);
}
/* I don't even know */
else if(!memcmp(&buf[0], "\xC0\x02", 2))
{
/* these mystery chunks appear to only ever be empty */
/* do nothing... */
}
else
{
/* end of the line */
break;
}
count--;
}

if(count != 0)
printf("BUG: %d chunks remain\n", count);

return 0;
}

float bytes_to_float(const unsigned char *bytes)
{
unsigned int u;
float f;
u = read_uint32_be(bytes);
memcpy(&f, &u, 4);
return f;
}

struct rgb from_cmyk(const unsigned char *bytes)
{
struct rgb color;
float f1, f2, f3, f4;
uint32_t u1, u2, u3, u4;

u1 = read_uint32_be(&bytes[0]);
u2 = read_uint32_be(&bytes[4]);
u3 = read_uint32_be(&bytes[8]);
u4 = read_uint32_be(&bytes[12]);

memcpy(&f1, &u1, 4);
memcpy(&f2, &u2, 4);
memcpy(&f3, &u3, 4);
memcpy(&f4, &u4, 4);

#if 0
color.r = (uint32_t)round(255 * (1 - f1) * (1 - f4));
color.g = (uint32_t)round(255 * (1 - f2) * (1 - f4));
color.b = (uint32_t)round(255 * (1 - f3) * (1 - f4));
#else
color.r = (uint32_t)floor((255 * (1 - f1) * (1 - f4)) + 0.5);
color.g = (uint32_t)floor((255 * (1 - f2) * (1 - f4)) + 0.5);
color.b = (uint32_t)floor((255 * (1 - f3) * (1 - f4)) + 0.5);
#endif

return color;
}
12 changes: 12 additions & 0 deletions color.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#ifndef COLOR_H
#define COLOR_H

struct rgb
{
unsigned int r, g, b;
};

struct rgb from_hsv(float hue, float saturation, float value);
struct rgb from_lab(float l, float a, float b);

#endif
12 changes: 12 additions & 0 deletions gimp.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#include <stdio.h>

void gimp_emit_header(FILE *file)
{
fprintf(file, "GIMP Palette\nName: RGB palette\nColumns: 10\n");
}

void gimp_emit_line(FILE *file, unsigned int r, unsigned int g, unsigned int b)
{
fprintf(file, "%u%c%u%c%u%c%c%02x%02x%02x%c", r, 0x09, g, 0x09, b, 0x09, '#', r, g, b, 0x0a);
printf("%u%c%u%c%u%c%c%02x%02x%02x%c", r, 0x09, g, 0x09, b, 0x09, '#', r, g, b, 0x0a);
}
7 changes: 7 additions & 0 deletions gimp.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#ifndef GIMP_H
#define GIMP_H

void gimp_emit_header(FILE *file);
void gimp_emit_line(FILE *file, unsigned int r, unsigned int g, unsigned int b);

#endif
83 changes: 83 additions & 0 deletions lab.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#include <math.h>

#include "color.h"

struct rgb from_lab(float l, float a, float b)
{
struct rgb color;
float z, y, x, fr, fg, fb;

/* L*a*b* -> XYZ */

y = (l + 16) / 116;
x = a / 500 + y;
z = y - b / 200;

if(x * x * x > 0.008856)
x = x * x * x;
else
x = (x - 16 / 116) / 7.787;

if(y * y * y > 0.008856)
y = y * y * y;
else
y = (y - 16 / 116) / 7.787;

if(z * z * z > 0.008856)
z = z * z * z;
else
z = (z - 16 / 116) / 7.787;

x = x * 95.047;
y = y * 100.000;
z = z * 108.883;

/* XYZ -> RGB */

x = x / 100;
y = y / 100;
z = z / 100;

fr = x * 3.2406 + y * -1.5372 + z * -0.4986;
fg = x * -0.9689 + y * 1.8758 + z * 0.0415;
fb = x * 0.0557 + y * -0.2040 + z * 1.0570;

if(fr > 0.0031308)
fr = 1.055 * pow(fr, 1 / 2.4) - 0.055;
else
fr = 12.92 * fr;
if(fg > 0.0031308)
fg = 1.055 * pow(fg, 1 / 2.4) - 0.055;
else
fg = 12.92 * fg;
if(fb > 0.0031308)
fb = 1.055 * pow(fb, 1 / 2.4) - 0.055;
else
fb = 12.92 * fb;

if(fr > 0)
if(fr < 1)
color.r = fr * 255;
else
color.r = 255;
else
color.r = 0;

if(fg > 0)
if(fg < 1)
color.g = fg * 255;
else
color.g = 255;
else
color.g = 0;

if(fb > 0)
if(fb < 1)
color.b = fb * 255;
else
color.b = 255;
else
color.b = 0;

return color;
}
27 changes: 27 additions & 0 deletions readbytes.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#ifndef INCLUDE_READBYTES_H
#define INCLUDE_READBYTES_H

#include <stdint.h>
#include <string.h>

uint32_t read_uint32_be(const unsigned char *bytes)
{
return((bytes[3]) | (bytes[2] << 8) | (bytes[1] << 16) | (bytes[0] << 24));
}

uint32_t read_uint32_le(const unsigned char *bytes)
{
return((bytes[0]) | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24));
}

uint16_t read_uint16_be(const unsigned char *bytes)
{
return((bytes[0] << 8) | (bytes[1]));
}

uint16_t read_uint16_le(const unsigned char *bytes)
{
return((bytes[0]) | (bytes[1] << 8));
}

#endif

0 comments on commit 79934f2

Please sign in to comment.