-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
8 changed files
with
358 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
*.o | ||
*.gpl |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |