Basic dithering, file refactor
This commit is contained in:
parent
8d55289214
commit
9000ad029c
|
@ -1,5 +1,5 @@
|
|||
IMAGECON=./out/imagecon
|
||||
OBJS=out/imagecon.o out/png.o
|
||||
OBJS=out/imagecon.o out/png.o out/color.o out/dither.o out/ham.o out/palette.o out/file.o
|
||||
HOST_WARNINGS=-pedantic-errors -Wfatal-errors -Wall -Werror -Wextra -Wno-unused-parameter -Wshadow -limagequant
|
||||
HOST_CFLAGS=$(HOST_WARNINGS)
|
||||
LIBS=-lpng -limagequant
|
||||
|
@ -28,12 +28,14 @@ REFERENCE_HAM_BASE=reference/ham
|
|||
$(IMAGECON): out bin $(OBJS)
|
||||
gcc $(OBJS) -o $(IMAGECON) $(LIBS)
|
||||
|
||||
|
||||
out/imagecon.o: imagecon.h
|
||||
out/png.o: imagecon.h
|
||||
-include $(OBJS:.o=.d)
|
||||
|
||||
out/%.o: %.c
|
||||
gcc -c $(HOST_CFLAGS) $< -o $@
|
||||
@gcc -MM $(HOST_CFLAGS) $*.c > out/$*.d
|
||||
@mv -f out/$*.d out/$*.d.tmp
|
||||
@sed -e 's/.*/out\/&/' < out/$*.d.tmp > out/$*.d
|
||||
@rm -f out/$*.d.tmp
|
||||
|
||||
out:
|
||||
mkdir out
|
||||
|
|
|
@ -0,0 +1,187 @@
|
|||
#include "imagecon.h"
|
||||
|
||||
int
|
||||
color_delta(amiga_color_t c1, amiga_color_t c2)
|
||||
{
|
||||
int dr = abs((c1.r)-(c2.r));
|
||||
int dg = abs((c1.g)-(c2.g));
|
||||
int db = abs((c1.b)-(c2.b));
|
||||
return sqrt((dr*dr)+(dg*dg)+(db*db));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
color_print(amiga_color_t color)
|
||||
{
|
||||
printf("R = %03d G = %03d B = %03d A = %03d", color.r, color.g, color.b, color.a);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
color_findClosestPaletteIndex(imagecon_image_t* ic, amiga_color_t color)
|
||||
{
|
||||
int delta = INT_MAX;
|
||||
int index = 0;
|
||||
|
||||
for (int i = 0; i < ic->numColors; i++) {
|
||||
int dc = color_delta(color, ic->palette[i]);
|
||||
if (dc < delta) {
|
||||
delta = dc;
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
amiga_color_t
|
||||
color_findClosestPalettePixel(imagecon_image_t* ic, amiga_color_t color)
|
||||
{
|
||||
return ic->palette[color_findClosestPaletteIndex(ic, color)];
|
||||
}
|
||||
|
||||
ham_control_t
|
||||
color_findClosestHamPixel(imagecon_image_t* ic, amiga_color_t color, amiga_color_t last)
|
||||
{
|
||||
int delta = INT_MAX;
|
||||
|
||||
ham_control_t ham = {0};
|
||||
|
||||
for (int i = 0; i < ic->numColors; i++) {
|
||||
int dc = color_delta(color, ic->palette[i]);
|
||||
if (dc < delta) {
|
||||
delta = dc;
|
||||
ham.data = i;
|
||||
ham.pixel = ic->palette[i];
|
||||
}
|
||||
}
|
||||
|
||||
delta = color_delta(color, ham.pixel);
|
||||
if (last.r != -1) {
|
||||
for (int c = 0; c <= 0xF; c++) {
|
||||
amiga_color_t copy = last;
|
||||
copy.r = c<<4;
|
||||
int dc = color_delta(color, copy);
|
||||
if (dc < delta) {
|
||||
ham.control = 2;
|
||||
ham.data = c;
|
||||
ham.pixel = copy;
|
||||
delta = dc;
|
||||
}
|
||||
}
|
||||
for (int c = 0; c <= 0xF; c++) {
|
||||
amiga_color_t copy = last;
|
||||
copy.g = c<<4;
|
||||
int dc = color_delta(color, copy);
|
||||
if (dc < delta) {
|
||||
ham.control = 3;
|
||||
ham.data = c;
|
||||
ham.pixel = copy;
|
||||
delta = dc;
|
||||
}
|
||||
}
|
||||
for (int c = 0; c <= 0xF; c++) {
|
||||
amiga_color_t copy = last;
|
||||
copy.b = c<<4;
|
||||
int dc = color_delta(color, copy);
|
||||
if (dc < delta) {
|
||||
ham.control = 1;
|
||||
ham.data = c;
|
||||
ham.pixel = copy;
|
||||
delta = dc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ham;
|
||||
}
|
||||
|
||||
|
||||
amiga_color_t
|
||||
color_getOriginalPixel(imagecon_image_t* ic, int x, int y)
|
||||
{
|
||||
png_byte* ptr = ic->rowPointers[y] + (x*4);
|
||||
amiga_color_t color;
|
||||
color.r = ptr[0];
|
||||
color.g = ptr[1];
|
||||
color.b = ptr[2];
|
||||
color.a = ptr[3];
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
color_setOriginalPixel(imagecon_image_t* ic, int x, int y, amiga_color_t color)
|
||||
{
|
||||
png_byte* ptr = ic->rowPointers[y] + (x*4);
|
||||
ptr[0] = color.r;
|
||||
ptr[1] = color.g;
|
||||
ptr[2] = color.b;
|
||||
ptr[3] = color.a;
|
||||
}
|
||||
|
||||
|
||||
amiga_color_t
|
||||
color_getDitheredPixel(imagecon_image_t* ic, int x, int y)
|
||||
{
|
||||
return ic->dithered[(y*ic->width)+x];
|
||||
}
|
||||
|
||||
void
|
||||
color_setDitheredPixel(imagecon_image_t* ic, int x, int y, amiga_color_t color)
|
||||
{
|
||||
amiga_color_t *d = &ic->dithered[(y*ic->width)+x];
|
||||
|
||||
if (color.r > 255) {
|
||||
color.r = 255;
|
||||
}
|
||||
if (color.r < 0) {
|
||||
color.r = 0;
|
||||
}
|
||||
if (color.g > 255) {
|
||||
color.g = 255;
|
||||
}
|
||||
if (color.g < 0) {
|
||||
color.g = 0;
|
||||
}
|
||||
if (color.b > 255) {
|
||||
color.b = 255;
|
||||
}
|
||||
if (color.b < 0) {
|
||||
color.b = 0;
|
||||
}
|
||||
|
||||
d->r = color.r;
|
||||
d->g = color.g;
|
||||
d->b = color.b;
|
||||
d->a = color.a;
|
||||
}
|
||||
|
||||
amiga_color_t
|
||||
color_getPalettedPixel(imagecon_image_t* ic, int x, int y)
|
||||
{
|
||||
int paletteIndex = ic->amigaImage[(ic->width*y)+x];
|
||||
amiga_color_t color;
|
||||
color.r = ic->palette[paletteIndex].r;
|
||||
color.g = ic->palette[paletteIndex].g;
|
||||
color.b = ic->palette[paletteIndex].b;
|
||||
color.a = ic->palette[paletteIndex].a;
|
||||
return color;
|
||||
}
|
||||
|
||||
void
|
||||
color_setPalettedPixel(imagecon_image_t* ic, int x, int y, amiga_color_t color)
|
||||
{
|
||||
int paletteIndex = color_findClosestPaletteIndex(ic, color);
|
||||
ic->amigaImage[(ic->width*y)+x] = paletteIndex;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
color_transferPalettedToOriginal(imagecon_image_t* ic)
|
||||
{
|
||||
for (int y = 0; y < ic->height; y++) {
|
||||
for (int x = 0; x < ic->width; x++) {
|
||||
color_setOriginalPixel(ic, x, y, color_getPalettedPixel(ic, x, y));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
#pragma once
|
||||
|
||||
int
|
||||
color_delta(amiga_color_t c1, amiga_color_t c2);
|
||||
|
||||
amiga_color_t
|
||||
color_findClosestPalettePixel(imagecon_image_t* ic, amiga_color_t color);
|
||||
|
||||
int
|
||||
color_findClosestPaletteIndex(imagecon_image_t* ic, amiga_color_t color);
|
||||
|
||||
ham_control_t
|
||||
color_findClosestHamPixel(imagecon_image_t* ic, amiga_color_t color, amiga_color_t last);
|
||||
|
||||
amiga_color_t
|
||||
color_getPalettedPixel(imagecon_image_t* ic, int x, int y);
|
||||
|
||||
void
|
||||
color_setPalettedPixel(imagecon_image_t* ic, int x, int y, amiga_color_t color);
|
||||
|
||||
void
|
||||
color_setDitheredPixel(imagecon_image_t* ic, int x, int y, amiga_color_t color);
|
||||
|
||||
amiga_color_t
|
||||
color_getDitheredPixel(imagecon_image_t* ic, int x, int y);
|
||||
|
||||
amiga_color_t
|
||||
color_getOriginalPixel(imagecon_image_t* ic, int x, int y);
|
||||
|
||||
void
|
||||
color_setOriginalPixel(imagecon_image_t* ic, int x, int y, amiga_color_t color);
|
||||
|
||||
void
|
||||
color_transferPalettedToOriginal(imagecon_image_t* ic);
|
|
@ -0,0 +1,125 @@
|
|||
#include "imagecon.h"
|
||||
|
||||
static void
|
||||
_dither_createDither(imagecon_image_t* ic);
|
||||
|
||||
amiga_color_t
|
||||
dither_getPalettedColor(imagecon_image_t* ic, amiga_color_t color, amiga_color_t last)
|
||||
{
|
||||
return color_findClosestPalettePixel(ic, color);
|
||||
}
|
||||
|
||||
|
||||
amiga_color_t
|
||||
dither_getHamColor(imagecon_image_t* ic, amiga_color_t color, amiga_color_t last)
|
||||
{
|
||||
ham_control_t ham = color_findClosestHamPixel(ic, color, last);
|
||||
return ham.pixel;
|
||||
}
|
||||
|
||||
void
|
||||
dither_image(imagecon_image_t* ic, amiga_color_t (*selector)(imagecon_image_t*, amiga_color_t color, amiga_color_t last))
|
||||
{
|
||||
_dither_createDither(ic);
|
||||
|
||||
for (int y = 0; y < ic->height; y++) {
|
||||
amiga_color_t last = {-1, -1, -1, -1};
|
||||
for (int x = 0; x < ic->width; x++) {
|
||||
|
||||
amiga_color_t old = color_getDitheredPixel(ic, x, y);
|
||||
amiga_color_t new = selector(ic, old, last);
|
||||
|
||||
amiga_color_t error;
|
||||
error.r = old.r - new.r;
|
||||
error.g = old.g - new.g;
|
||||
error.b = old.b - new.b;
|
||||
|
||||
color_setDitheredPixel(ic, x, y, new);
|
||||
last = new;
|
||||
|
||||
amiga_color_t color;
|
||||
float factor;
|
||||
|
||||
if (x+1 < ic->width) {
|
||||
color = color_getDitheredPixel(ic, x+1, y);
|
||||
factor = 7.0/16.0;
|
||||
color.r = color.r + ((float)error.r * factor);
|
||||
color.g = color.g + ((float)error.g * factor);
|
||||
color.b = color.b + ((float)error.b * factor);
|
||||
color_setDitheredPixel(ic, x+1, y, color);
|
||||
}
|
||||
|
||||
if (x > 0 && y+1 < ic->height) {
|
||||
color = color_getDitheredPixel(ic, x-1, y+1);
|
||||
factor = 3.0/16.0;
|
||||
color.r = color.r + ((float)error.r * factor);
|
||||
color.g = color.g + ((float)error.g * factor);
|
||||
color.b = color.b + ((float)error.b * factor);
|
||||
color_setDitheredPixel(ic, x-1, y+1, color);
|
||||
}
|
||||
|
||||
if (y+1 < ic->height) {
|
||||
color = color_getDitheredPixel(ic, x, y+1);
|
||||
factor = 5.0/16.0;
|
||||
color.r = color.r + ((float)error.r * factor);
|
||||
color.g = color.g + ((float)error.g * factor);
|
||||
color.b = color.b + ((float)error.b * factor);
|
||||
color_setDitheredPixel(ic, x, y+1, color);
|
||||
|
||||
if (x+1 < ic->width) {
|
||||
color = color_getDitheredPixel(ic, x+1, y+1);
|
||||
factor = 1.0/16.0;
|
||||
color.r = color.r + ((float)error.r * factor);
|
||||
color.g = color.g + ((float)error.g * factor);
|
||||
color.b = color.b + ((float)error.b * factor);
|
||||
color_setDitheredPixel(ic, x+1, y+1, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
dither_transferToPaletted(imagecon_image_t* ic)
|
||||
{
|
||||
for (int y = 0; y < ic->height; y++) {
|
||||
for (int x = 0; x < ic->width; x++) {
|
||||
color_setPalettedPixel(ic, x, y, color_getDitheredPixel(ic, x, y));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ham_control_t*
|
||||
dither_createHams(imagecon_image_t* ic)
|
||||
{
|
||||
ham_control_t* hams = malloc(sizeof(ham_control_t)*ic->width*ic->height);
|
||||
|
||||
for (int y = 0; y < ic->height; y++) {
|
||||
amiga_color_t lastPixel = { -1, -1, -1, -1};
|
||||
for (int x = 0; x < ic->width; x++) {
|
||||
amiga_color_t orig = color_getDitheredPixel(ic, x, y);
|
||||
ham_control_t ham = color_findClosestHamPixel(ic, orig, lastPixel);
|
||||
lastPixel = ham.pixel;
|
||||
hams[(y*ic->width)+x] = ham;
|
||||
}
|
||||
}
|
||||
|
||||
return hams;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
_dither_createDither(imagecon_image_t* ic)
|
||||
{
|
||||
ic->dithered = malloc(sizeof(amiga_color_t)*ic->width*ic->height);
|
||||
|
||||
for (int y = 0; y < ic->height; y++) {
|
||||
for (int x = 0; x < ic->width; x++) {
|
||||
color_setDitheredPixel(ic, x, y, color_getOriginalPixel(ic, x, y));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
|
||||
amiga_color_t
|
||||
dither_getPalettedColor(imagecon_image_t* ic, amiga_color_t color, amiga_color_t last);
|
||||
|
||||
amiga_color_t
|
||||
dither_getHamColor(imagecon_image_t* ic, amiga_color_t color, amiga_color_t last);
|
||||
|
||||
void
|
||||
dither_image(imagecon_image_t* ic, amiga_color_t (*selector)(imagecon_image_t* ic, amiga_color_t color, amiga_color_t last));
|
||||
|
||||
void
|
||||
dither_transferToPaletted(imagecon_image_t* ic);
|
||||
|
||||
ham_control_t*
|
||||
dither_createHams(imagecon_image_t* ic);
|
|
@ -0,0 +1,39 @@
|
|||
#include "imagecon.h"
|
||||
|
||||
FILE *
|
||||
file_openWrite(const char * s, ...)
|
||||
{
|
||||
char buffer[4096];
|
||||
va_list args;
|
||||
va_start(args, s);
|
||||
vsprintf(buffer, s, args);
|
||||
va_end(args);
|
||||
|
||||
if (config.verbose) {
|
||||
printf("Opening %s for writing\n", buffer);
|
||||
}
|
||||
|
||||
FILE* fp = fopen(buffer, "w+");
|
||||
if (!fp) {
|
||||
abort_("Failed to open %s for writing\n", buffer);
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
|
||||
FILE *
|
||||
file_openRead(const char * s, ...)
|
||||
{
|
||||
char buffer[4096];
|
||||
va_list args;
|
||||
va_start(args, s);
|
||||
vsprintf(buffer, s, args);
|
||||
va_end(args);
|
||||
|
||||
FILE* fp = fopen(buffer, "r");
|
||||
if (!fp) {
|
||||
abort_("Failed to open %s for reading\n", buffer);
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
FILE *
|
||||
file_openWrite(const char * s, ...);
|
||||
|
||||
FILE *
|
||||
file_openRead(const char * s, ...);
|
|
@ -0,0 +1,111 @@
|
|||
#include "imagecon.h"
|
||||
|
||||
static void
|
||||
_ham_outputBitplanes(char* outFilename, imagecon_image_t* ic)
|
||||
{
|
||||
if (config.verbose) {
|
||||
printf("outputHamBitplanes\n");
|
||||
}
|
||||
|
||||
int numBitPlanes = 6;
|
||||
int byteWidth = (ic->width + 7) / 8;
|
||||
|
||||
char** bitplanes = malloc(sizeof(void*)*numBitPlanes);
|
||||
for (int i = 0; i < numBitPlanes; i++) {
|
||||
bitplanes[i] = calloc(byteWidth*ic->height, 1);
|
||||
}
|
||||
|
||||
|
||||
ham_control_t* hams;
|
||||
|
||||
if (config.dither) {
|
||||
dither_image(ic, dither_getHamColor);
|
||||
hams = dither_createHams(ic);
|
||||
} else {
|
||||
hams = malloc(sizeof(ham_control_t)*ic->width*ic->height);
|
||||
|
||||
for (int y = 0; y < ic->height; y++) {
|
||||
amiga_color_t lastPixel = { -1, -1, -1, -1};
|
||||
for (int x = 0; x < ic->width; x++) {
|
||||
amiga_color_t orig = color_getOriginalPixel(ic, x, y);
|
||||
ham_control_t ham = color_findClosestHamPixel(ic, orig, lastPixel);
|
||||
lastPixel = ham.pixel;
|
||||
hams[(y*ic->width)+x] = ham;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (int y = 0, writeIndex = 0; y < ic->height; y++) {
|
||||
for (int byte = 0;byte < byteWidth; byte++) {
|
||||
for (int bit = 0; bit < 8; bit++) {
|
||||
int x = byte * 8 + 7 - bit;
|
||||
ham_control_t ham = hams[(y*ic->width)+x];
|
||||
int _numBitPlanes = 4;
|
||||
for (int plane_index = 0; plane_index < _numBitPlanes; plane_index++) {
|
||||
char* plane = bitplanes[plane_index];
|
||||
plane[writeIndex] |= ((ham.data >> plane_index) & 1) << bit;
|
||||
}
|
||||
|
||||
for (int plane_index = 0; plane_index < 2; plane_index++) {
|
||||
char* plane = bitplanes[4+plane_index];
|
||||
plane[writeIndex] |= ((ham.control >> plane_index) & 1) << bit;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
writeIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FILE* fp = file_openWrite("%s-ham.bin", outFilename);
|
||||
|
||||
for (int y = 0; y < ic->height; y++) {
|
||||
for (int plane_index = 0; plane_index < numBitPlanes; plane_index++) {
|
||||
char* plane = bitplanes[plane_index];
|
||||
fwrite(&plane[y*byteWidth], byteWidth, 1, fp);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
if (config.verbose) {
|
||||
printf("done\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
void
|
||||
ham_process(char* outFilename, imagecon_image_t* ic)
|
||||
{
|
||||
config.maxColors = 256;
|
||||
generateQuantizedImage(ic, 0);
|
||||
dither_image(ic, dither_getPalettedColor);
|
||||
dither_transferToPaletted(ic);
|
||||
color_transferPalettedToOriginal(ic);
|
||||
|
||||
config.maxColors = 16;
|
||||
generateQuantizedImage(ic, 0);
|
||||
|
||||
|
||||
if (config.outputBitplanes) {
|
||||
_ham_outputBitplanes(outFilename, ic);
|
||||
}
|
||||
|
||||
palette_output(outFilename, ic);
|
||||
}
|
||||
|
||||
#else
|
||||
void
|
||||
ham_process(char* outFilename, imagecon_image_t* ic)
|
||||
{
|
||||
config.maxColors = 16;
|
||||
generateQuantizedImage(ic, 0);
|
||||
|
||||
if (config.outputBitplanes) {
|
||||
_ham_outputBitplanes(outFilename, ic);
|
||||
}
|
||||
|
||||
palette_output(outFilename, ic);
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,4 @@
|
|||
#pragma once
|
||||
|
||||
void
|
||||
ham_process(char* outFilename, imagecon_image_t* ic);
|
|
@ -2,19 +2,8 @@
|
|||
* Amiga bitplane creation inspired (copied) from https://github.com/vilcans/amiga-startup
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <math.h>
|
||||
#include <getopt.h>
|
||||
#include <libgen.h>
|
||||
#include <png.h>
|
||||
#include <pngquant/libimagequant.h>
|
||||
#include "imagecon.h"
|
||||
|
||||
|
||||
imagecon_config_t config = {
|
||||
.maxColors = MAX_PALETTE,
|
||||
.outputPalette = 0,
|
||||
|
@ -26,6 +15,7 @@ imagecon_config_t config = {
|
|||
.ehbMode = 0,
|
||||
.hamMode = 0,
|
||||
.quantize = 0,
|
||||
.dither = 0,
|
||||
.overridePalette = 0
|
||||
};
|
||||
|
||||
|
@ -47,6 +37,7 @@ usage()
|
|||
" --output-palette\n"\
|
||||
" --extra-half-brite\n"\
|
||||
" --ham\n"\
|
||||
" --dither\n"\
|
||||
" --use-palette <palette file>\n"\
|
||||
" --verbose\n", config.argv[0]);
|
||||
exit(1);
|
||||
|
@ -66,144 +57,8 @@ abort_(const char * s, ...)
|
|||
}
|
||||
|
||||
|
||||
FILE *
|
||||
openFileWrite(const char * s, ...)
|
||||
{
|
||||
char buffer[4096];
|
||||
va_list args;
|
||||
va_start(args, s);
|
||||
vsprintf(buffer, s, args);
|
||||
va_end(args);
|
||||
|
||||
if (config.verbose) {
|
||||
printf("Opening %s for writing\n", buffer);
|
||||
}
|
||||
|
||||
FILE* fp = fopen(buffer, "w+");
|
||||
if (!fp) {
|
||||
abort_("Failed to open %s for writing\n", buffer);
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
|
||||
FILE *
|
||||
openFileRead(const char * s, ...)
|
||||
{
|
||||
char buffer[4096];
|
||||
va_list args;
|
||||
va_start(args, s);
|
||||
vsprintf(buffer, s, args);
|
||||
va_end(args);
|
||||
|
||||
FILE* fp = fopen(buffer, "r");
|
||||
if (!fp) {
|
||||
abort_("Failed to open %s for reading\n", buffer);
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
outputPalette(char* outFilename, imagecon_image_t* ic)
|
||||
{
|
||||
if (config.verbose) {
|
||||
printf("outputPalette...%d colors\n", ic->numColors);
|
||||
}
|
||||
|
||||
FILE* fp = 0;
|
||||
FILE* paletteFP = 0;
|
||||
FILE* paletteAsmFP = 0;
|
||||
FILE* paletteGreyFP = 0;
|
||||
|
||||
if (config.outputCopperList) {
|
||||
fp = openFileWrite("%s-copper-list.s", outFilename);
|
||||
}
|
||||
|
||||
if (config.outputPalette) {
|
||||
paletteFP = openFileWrite("%s.pal", outFilename);
|
||||
}
|
||||
|
||||
if (config.outputPaletteGrey) {
|
||||
paletteGreyFP = openFileWrite("%s-grey.s", outFilename);
|
||||
fprintf(paletteGreyFP, "\tmovem.l d0-a6,-(sp)\n\tlea CUSTOM,a6\n");
|
||||
}
|
||||
|
||||
if (config.outputPaletteAsm) {
|
||||
paletteAsmFP = openFileWrite("%s-palette.s", outFilename);
|
||||
fprintf(paletteAsmFP, "\tmovem.l d0-a6,-(sp)\n\tlea CUSTOM,a6\n");
|
||||
}
|
||||
|
||||
if (config.verbose) {
|
||||
printf("outputPalette:\n");
|
||||
}
|
||||
|
||||
for (int i = 0; i < (config.ehbMode ? ic->numColors/2 : ic->numColors); i++) {
|
||||
if (config.verbose) {
|
||||
printf("%02d: hex=%03x r=%03d g=%03d b=%03d a=%03d\n", i , ic->palette[i].r << 8 | ic->palette[i].g << 4 | ic->palette[i].b, ic->palette[i].r, ic->palette[i].g, ic->palette[i].b, ic->palette[i].a);
|
||||
}
|
||||
if (paletteFP) {
|
||||
fprintf(paletteFP, "%03x\n", (ic->palette[i].r >> 4) << 8 | (ic->palette[i].g >>4) << 4 | (ic->palette[i].b >>4));
|
||||
}
|
||||
if (paletteAsmFP) {
|
||||
fprintf(paletteAsmFP, "\tlea COLOR%02d(a6),a0\n\tmove.w #$%03x,(a0)\n", i, (ic->palette[i].r >> 4) << 8 | (ic->palette[i].g >>4) << 4 | (ic->palette[i].b >>4));
|
||||
}
|
||||
if (paletteGreyFP) {
|
||||
// TODO: this is for compat, can be better
|
||||
unsigned grey = (((ic->palette[i].r>>4) + (ic->palette[i].g>>4) + (ic->palette[i].b>>4))/3);
|
||||
fprintf(paletteGreyFP, "\tlea COLOR%02d(a6),a0\n\tmove.w #$%03x,(a0)\n", i, grey << 8 | grey << 4 | grey);
|
||||
}
|
||||
|
||||
if (fp) {
|
||||
fprintf(fp, "\tdc.w $%x,$%x\n", 0x180+(i*2), (ic->palette[i].r >> 4) << 8 | (ic->palette[i].g >>4) << 4 | (ic->palette[i].b >>4));
|
||||
}
|
||||
}
|
||||
|
||||
if (paletteFP) {
|
||||
fclose(paletteFP);
|
||||
}
|
||||
|
||||
if (paletteGreyFP) {
|
||||
fprintf(paletteGreyFP, "\tmovem.l (sp)+,d0-a6\n");
|
||||
fclose(paletteGreyFP);
|
||||
}
|
||||
|
||||
if (paletteAsmFP) {
|
||||
fprintf(paletteAsmFP, "\tmovem.l (sp)+,d0-a6\n");
|
||||
fclose(paletteFP);
|
||||
}
|
||||
|
||||
if (fp) {
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
if (config.verbose) {
|
||||
printf("done\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
void loadPaletteFile(imagecon_image_t* ic)
|
||||
{
|
||||
FILE* fp = openFileRead(config.overridePalette);
|
||||
int paletteIndex;
|
||||
|
||||
for (paletteIndex = 0; paletteIndex < MAX_PALETTE; paletteIndex++) {
|
||||
unsigned int c;
|
||||
char buffer[255];
|
||||
char* line = fgets(buffer, 255, fp);
|
||||
if (!line) {
|
||||
break;
|
||||
}
|
||||
sscanf(buffer, "%x\n", &c);
|
||||
|
||||
ic->palette[paletteIndex].r = (c >> 8 & 0xF) << 4;
|
||||
ic->palette[paletteIndex].g = (c >> 4 & 0xF) << 4;
|
||||
ic->palette[paletteIndex].b = (c >> 0 & 0xF) << 4;
|
||||
ic->palette[paletteIndex].a = 255;
|
||||
}
|
||||
|
||||
ic->numColors = paletteIndex;
|
||||
}
|
||||
|
||||
void
|
||||
generateQuantizedImage(imagecon_image_t* ic, int usePalette)
|
||||
|
@ -227,9 +82,11 @@ generateQuantizedImage(imagecon_image_t* ic, int usePalette)
|
|||
}
|
||||
|
||||
liq_set_max_colors(attr, config.maxColors);
|
||||
// no liq_set_quality(attr, 0, 100);
|
||||
//liq_set_min_posterization(attr, 4);
|
||||
liq_set_speed(attr, 1);
|
||||
liq_result *res = liq_quantize_image(attr, image);
|
||||
|
||||
// liq_set_dithering_level(res, 1.0);
|
||||
liq_write_remapped_image(res, image, ic->amigaImage, ic->width*ic->height);
|
||||
|
||||
const liq_palette *pal = liq_get_palette(res);
|
||||
|
@ -256,35 +113,12 @@ generateQuantizedImage(imagecon_image_t* ic, int usePalette)
|
|||
ic->numColors = pal->count;
|
||||
}
|
||||
|
||||
amiga_color_t
|
||||
getOriginalColor(int x, int y, imagecon_image_t* ic)
|
||||
{
|
||||
png_byte* ptr = ic->rowPointers[y] + (x*4);
|
||||
amiga_color_t color;
|
||||
color.r = ptr[0];
|
||||
color.g = ptr[1];
|
||||
color.b = ptr[2];
|
||||
color.a = ptr[3];
|
||||
return color;
|
||||
}
|
||||
|
||||
amiga_color_t
|
||||
getColor(int x, int y, imagecon_image_t* ic)
|
||||
{
|
||||
int paletteIndex = ic->amigaImage[(ic->width*y)+x];
|
||||
amiga_color_t color;
|
||||
color.r = ic->palette[paletteIndex].r;
|
||||
color.g = ic->palette[paletteIndex].g;
|
||||
color.b = ic->palette[paletteIndex].b;
|
||||
color.a = ic->palette[paletteIndex].a;
|
||||
return color;
|
||||
}
|
||||
|
||||
void
|
||||
generatePalette(imagecon_image_t* ic)
|
||||
generatePalettedImage(imagecon_image_t* ic)
|
||||
{
|
||||
if (config.verbose) {
|
||||
printf("generatePalette...\n");
|
||||
printf("generatePalettedImage...\n");
|
||||
}
|
||||
|
||||
int paletteIndex = 0;
|
||||
|
@ -359,7 +193,7 @@ outputBitplanes(char* outFilename, imagecon_image_t* ic)
|
|||
for (int i = 0; i < numBitPlanes; i++) {
|
||||
bitplanes[i] = calloc(byteWidth*ic->height, 1);
|
||||
}
|
||||
|
||||
|
||||
for (int y = 0, writeIndex = 0; y < ic->height; y++) {
|
||||
for (int byte = 0;byte < byteWidth; byte++) {
|
||||
for (int bit = 0; bit < 8; bit++) {
|
||||
|
@ -391,7 +225,7 @@ outputBitplanes(char* outFilename, imagecon_image_t* ic)
|
|||
}
|
||||
}
|
||||
|
||||
FILE* fp = openFileWrite("%s.bin", outFilename);
|
||||
FILE* fp = file_openWrite("%s.bin", outFilename);
|
||||
|
||||
for (int y = 0; y < ic->height; y++) {
|
||||
for (int plane_index = 0; plane_index < numBitPlanes; plane_index++) {
|
||||
|
@ -425,7 +259,7 @@ outputMask(char* outFilename, imagecon_image_t* ic)
|
|||
for (int byte = 0;byte < byteWidth; byte++) {
|
||||
for (int bit = 0; bit < 8; bit++) {
|
||||
int x = byte * 8 + 7 - bit;
|
||||
amiga_color_t c = getOriginalColor(x, y, ic);
|
||||
amiga_color_t c = color_getOriginalPixel(ic, x, y);
|
||||
int bitmask = c.a > 0 ? 0xFF : 0;
|
||||
for (int plane_index = 0; plane_index < numBitPlanes; plane_index++) {
|
||||
char* plane = bitplanes[plane_index];
|
||||
|
@ -436,7 +270,7 @@ outputMask(char* outFilename, imagecon_image_t* ic)
|
|||
}
|
||||
}
|
||||
|
||||
FILE* fp = openFileWrite("%s-mask.bin", outFilename);
|
||||
FILE* fp = file_openWrite("%s-mask.bin", outFilename);
|
||||
|
||||
for (int y = 0; y < ic->height; y++) {
|
||||
for (int plane_index = 0; plane_index < numBitPlanes; plane_index++) {
|
||||
|
@ -472,194 +306,8 @@ generateEHBImage(imagecon_image_t* ic)
|
|||
generateQuantizedImage(ic, 1);
|
||||
}
|
||||
|
||||
void
|
||||
printColor(amiga_color_t color)
|
||||
{
|
||||
printf("R = %03d G = %03d B = %03d A = %03d", color.r, color.g, color.b, color.a);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
colorDelta(amiga_color_t c1, amiga_color_t c2)
|
||||
{
|
||||
int dr = abs((c1.r)-(c2.r));
|
||||
int dg = abs((c1.g)-(c2.g));
|
||||
int db = abs((c1.b)-(c2.b));
|
||||
return (dr+dg+db) / 3;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int control;
|
||||
int data;
|
||||
amiga_color_t pixel;
|
||||
} ham_control_t;
|
||||
|
||||
ham_control_t
|
||||
findBestHamPixel(imagecon_image_t* ic, amiga_color_t color, amiga_color_t orig, amiga_color_t last)
|
||||
{
|
||||
int delta = INT_MAX;
|
||||
|
||||
ham_control_t ham = {0};
|
||||
|
||||
for (int i = 0; i < ic->numColors; i++) {
|
||||
int dc = colorDelta(color, ic->palette[i]);
|
||||
if (dc < delta) {
|
||||
delta = dc;
|
||||
ham.data = i;
|
||||
ham.pixel = ic->palette[i];
|
||||
}
|
||||
}
|
||||
|
||||
delta = colorDelta(orig, ham.pixel);
|
||||
if (last.r != -1) {
|
||||
for (int c = 0; c <= 0xF; c++) {
|
||||
amiga_color_t copy = last;
|
||||
copy.r = c<<4;
|
||||
int dc = colorDelta(orig, copy);
|
||||
if (dc < delta) {
|
||||
ham.control = 2;
|
||||
ham.data = c;
|
||||
ham.pixel = copy;
|
||||
delta = dc;
|
||||
}
|
||||
}
|
||||
for (int c = 0; c <= 0xF; c++) {
|
||||
amiga_color_t copy = last;
|
||||
copy.g = c<<4;
|
||||
int dc = colorDelta(orig, copy);
|
||||
if (dc < delta) {
|
||||
ham.control = 3;
|
||||
ham.data = c;
|
||||
ham.pixel = copy;
|
||||
delta = dc;
|
||||
}
|
||||
}
|
||||
for (int c = 0; c <= 0xF; c++) {
|
||||
amiga_color_t copy = last;
|
||||
copy.b = c<<4;
|
||||
int dc = colorDelta(orig, copy);
|
||||
if (dc < delta) {
|
||||
ham.control = 1;
|
||||
ham.data = c;
|
||||
ham.pixel = copy;
|
||||
delta = dc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ham;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
outputHamBitplanes(char* outFilename, imagecon_image_t* ic)
|
||||
{
|
||||
if (config.verbose) {
|
||||
printf("outputHamBitplanes\n");
|
||||
}
|
||||
|
||||
int numBitPlanes = 6;
|
||||
int numColors = 16;
|
||||
|
||||
if (config.verbose) {
|
||||
printf("ham number of colors = %d\n", numColors);
|
||||
printf("ham number of bitplanes = %d\n", numBitPlanes);
|
||||
}
|
||||
|
||||
int byteWidth = (ic->width + 7) / 8;
|
||||
|
||||
char** bitplanes = malloc(sizeof(void*)*numBitPlanes);
|
||||
for (int i = 0; i < numBitPlanes; i++) {
|
||||
bitplanes[i] = calloc(byteWidth*ic->height, 1);
|
||||
}
|
||||
|
||||
ham_control_t* hams = malloc(sizeof(ham_control_t)*ic->width*ic->height);
|
||||
|
||||
for (int y = 0; y < ic->height; y++) {
|
||||
amiga_color_t lastPixel = { -1, -1, -1, -1};
|
||||
for (int x = 0; x < ic->width; x++) {
|
||||
|
||||
amiga_color_t color = getColor(x, y, ic);
|
||||
amiga_color_t orig = getOriginalColor(x, y, ic);
|
||||
|
||||
ham_control_t ham = findBestHamPixel(ic, color, orig, lastPixel);
|
||||
lastPixel = ham.pixel;
|
||||
|
||||
#if 0
|
||||
printf("Color: ");
|
||||
printColor(color);
|
||||
printf("\n");
|
||||
printf("Orig: ");
|
||||
printColor(orig);
|
||||
printf("\n");
|
||||
|
||||
printf("Ham:\n");
|
||||
printf("Control: %d\n", ham.control);
|
||||
printf("Data: %d\n", ham.data);
|
||||
printf("Color: ");
|
||||
printColor(ham.pixel);
|
||||
printf("\n\n");
|
||||
#endif
|
||||
|
||||
hams[(y*ic->width)+x] = ham;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (int y = 0, writeIndex = 0; y < ic->height; y++) {
|
||||
for (int byte = 0;byte < byteWidth; byte++) {
|
||||
for (int bit = 0; bit < 8; bit++) {
|
||||
int x = byte * 8 + 7 - bit;
|
||||
|
||||
ham_control_t ham = hams[(y*ic->width)+x];
|
||||
|
||||
int _numBitPlanes = 4;
|
||||
for (int plane_index = 0; plane_index < _numBitPlanes; plane_index++) {
|
||||
char* plane = bitplanes[plane_index];
|
||||
plane[writeIndex] |= ((ham.data >> plane_index) & 1) << bit;
|
||||
}
|
||||
|
||||
for (int plane_index = 0; plane_index < 2; plane_index++) {
|
||||
char* plane = bitplanes[4+plane_index];
|
||||
plane[writeIndex] |= ((ham.control >> plane_index) & 1) << bit;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
writeIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FILE* fp = openFileWrite("%s-ham.bin", outFilename);
|
||||
|
||||
for (int y = 0; y < ic->height; y++) {
|
||||
for (int plane_index = 0; plane_index < numBitPlanes; plane_index++) {
|
||||
char* plane = bitplanes[plane_index];
|
||||
fwrite(&plane[y*byteWidth], byteWidth, 1, fp);
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
if (config.verbose) {
|
||||
printf("done\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
doHamMode(char* outFilename, imagecon_image_t* ic)
|
||||
{
|
||||
config.maxColors = 16;
|
||||
generateQuantizedImage(ic, 0);
|
||||
|
||||
if (config.outputBitplanes) {
|
||||
outputHamBitplanes(outFilename, ic);
|
||||
}
|
||||
|
||||
outputPalette(outFilename, ic);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
processFile(char* outFilename, imagecon_image_t* ic)
|
||||
{
|
||||
|
@ -668,21 +316,26 @@ processFile(char* outFilename, imagecon_image_t* ic)
|
|||
}
|
||||
|
||||
if (config.hamMode) {
|
||||
doHamMode(outFilename, ic);
|
||||
ham_process(outFilename, ic);
|
||||
} else {
|
||||
if (config.quantize || config.overridePalette) {
|
||||
if (config.ehbMode) {
|
||||
generateEHBImage(ic);
|
||||
} else {
|
||||
if (config.overridePalette) {
|
||||
loadPaletteFile(ic);
|
||||
palette_loadFile(ic);
|
||||
}
|
||||
generateQuantizedImage(ic, config.overridePalette != 0);
|
||||
}
|
||||
} else {
|
||||
generatePalette(ic);
|
||||
generatePalettedImage(ic);
|
||||
}
|
||||
|
||||
|
||||
if (config.dither) {
|
||||
dither_image(ic, dither_getPalettedColor);
|
||||
dither_transferToPaletted(ic);
|
||||
}
|
||||
|
||||
if (config.outputBitplanes) {
|
||||
outputBitplanes(outFilename, ic);
|
||||
}
|
||||
|
@ -691,7 +344,7 @@ processFile(char* outFilename, imagecon_image_t* ic)
|
|||
outputMask(outFilename, ic);
|
||||
}
|
||||
|
||||
outputPalette(outFilename, ic);
|
||||
palette_output(outFilename, ic);
|
||||
}
|
||||
|
||||
if (config.verbose) {
|
||||
|
@ -779,6 +432,7 @@ main(int argc, char **argv)
|
|||
{"output-mask", no_argument, &config.outputMask, 1},
|
||||
{"extra-half-brite", no_argument, &config.ehbMode, 1},
|
||||
{"ham", no_argument, &config.hamMode, 1},
|
||||
{"dither", no_argument, &config.dither, 1},
|
||||
{"use-palette", required_argument, 0, 'p'},
|
||||
{"output", required_argument, 0, 'o'},
|
||||
{"colors", required_argument, 0, 'c'},
|
||||
|
@ -860,3 +514,5 @@ main(int argc, char **argv)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,16 @@
|
|||
#pragma once
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <math.h>
|
||||
#include <getopt.h>
|
||||
#include <libgen.h>
|
||||
#include <png.h>
|
||||
#include <pngquant/libimagequant.h>
|
||||
|
||||
#define MAX_PALETTE 32
|
||||
|
||||
typedef struct {
|
||||
|
@ -13,20 +24,13 @@ typedef struct {
|
|||
int outputCopperList;
|
||||
int ehbMode;
|
||||
int hamMode;
|
||||
int dither;
|
||||
char* overridePalette;
|
||||
int quantize;
|
||||
int verbose;
|
||||
char** argv;
|
||||
} imagecon_config_t;
|
||||
|
||||
#if 0
|
||||
typedef struct {
|
||||
unsigned char r;
|
||||
unsigned char g;
|
||||
unsigned char b;
|
||||
unsigned char a;
|
||||
} amiga_color_t;
|
||||
#else
|
||||
typedef struct {
|
||||
int r;
|
||||
int g;
|
||||
|
@ -34,7 +38,11 @@ typedef struct {
|
|||
int a;
|
||||
} amiga_color_t;
|
||||
|
||||
#endif
|
||||
typedef struct {
|
||||
int control;
|
||||
int data;
|
||||
amiga_color_t pixel;
|
||||
} ham_control_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
|
@ -44,9 +52,23 @@ typedef struct {
|
|||
png_bytep* rowPointers;
|
||||
unsigned char* amigaImage;
|
||||
amiga_color_t palette[MAX_PALETTE*2]; // extra half brite mode
|
||||
amiga_color_t* dithered;
|
||||
} imagecon_image_t;
|
||||
|
||||
|
||||
#include "color.h"
|
||||
#include "dither.h"
|
||||
#include "ham.h"
|
||||
#include "file.h"
|
||||
#include "palette.h"
|
||||
|
||||
extern imagecon_config_t config;
|
||||
extern void abort_(const char * s, ...);
|
||||
extern void png_read(char* file_name, imagecon_image_t* ic);
|
||||
|
||||
extern void
|
||||
abort_(const char * s, ...);
|
||||
|
||||
extern void
|
||||
png_read(char* file_name, imagecon_image_t* ic);
|
||||
|
||||
void
|
||||
generateQuantizedImage(imagecon_image_t* ic, int usePalette);
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
#include "imagecon.h"
|
||||
|
||||
void palette_loadFile(imagecon_image_t* ic)
|
||||
{
|
||||
FILE* fp = file_openRead(config.overridePalette);
|
||||
int paletteIndex;
|
||||
|
||||
for (paletteIndex = 0; paletteIndex < MAX_PALETTE; paletteIndex++) {
|
||||
unsigned int c;
|
||||
char buffer[255];
|
||||
char* line = fgets(buffer, 255, fp);
|
||||
if (!line) {
|
||||
break;
|
||||
}
|
||||
sscanf(buffer, "%x\n", &c);
|
||||
|
||||
ic->palette[paletteIndex].r = (c >> 8 & 0xF) << 4;
|
||||
ic->palette[paletteIndex].g = (c >> 4 & 0xF) << 4;
|
||||
ic->palette[paletteIndex].b = (c >> 0 & 0xF) << 4;
|
||||
ic->palette[paletteIndex].a = 255;
|
||||
}
|
||||
|
||||
ic->numColors = paletteIndex;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
palette_output(char* outFilename, imagecon_image_t* ic)
|
||||
{
|
||||
if (config.verbose) {
|
||||
printf("outputPalette...%d colors\n", ic->numColors);
|
||||
}
|
||||
|
||||
FILE* fp = 0;
|
||||
FILE* paletteFP = 0;
|
||||
FILE* paletteAsmFP = 0;
|
||||
FILE* paletteGreyFP = 0;
|
||||
|
||||
if (config.outputCopperList) {
|
||||
fp = file_openWrite("%s-copper-list.s", outFilename);
|
||||
}
|
||||
|
||||
if (config.outputPalette) {
|
||||
paletteFP = file_openWrite("%s.pal", outFilename);
|
||||
}
|
||||
|
||||
if (config.outputPaletteGrey) {
|
||||
paletteGreyFP = file_openWrite("%s-grey.s", outFilename);
|
||||
fprintf(paletteGreyFP, "\tmovem.l d0-a6,-(sp)\n\tlea CUSTOM,a6\n");
|
||||
}
|
||||
|
||||
if (config.outputPaletteAsm) {
|
||||
paletteAsmFP = file_openWrite("%s-palette.s", outFilename);
|
||||
fprintf(paletteAsmFP, "\tmovem.l d0-a6,-(sp)\n\tlea CUSTOM,a6\n");
|
||||
}
|
||||
|
||||
if (config.verbose) {
|
||||
printf("outputPalette:\n");
|
||||
}
|
||||
|
||||
for (int i = 0; i < (config.ehbMode ? ic->numColors/2 : ic->numColors); i++) {
|
||||
if (config.verbose) {
|
||||
printf("%02d: hex=%03x r=%03d g=%03d b=%03d a=%03d\n", i , ic->palette[i].r << 8 | ic->palette[i].g << 4 | ic->palette[i].b, ic->palette[i].r, ic->palette[i].g, ic->palette[i].b, ic->palette[i].a);
|
||||
}
|
||||
if (paletteFP) {
|
||||
fprintf(paletteFP, "%03x\n", (ic->palette[i].r >> 4) << 8 | (ic->palette[i].g >>4) << 4 | (ic->palette[i].b >>4));
|
||||
}
|
||||
if (paletteAsmFP) {
|
||||
fprintf(paletteAsmFP, "\tlea COLOR%02d(a6),a0\n\tmove.w #$%03x,(a0)\n", i, (ic->palette[i].r >> 4) << 8 | (ic->palette[i].g >>4) << 4 | (ic->palette[i].b >>4));
|
||||
}
|
||||
if (paletteGreyFP) {
|
||||
// TODO: this is for compat, can be better
|
||||
unsigned grey = (((ic->palette[i].r>>4) + (ic->palette[i].g>>4) + (ic->palette[i].b>>4))/3);
|
||||
fprintf(paletteGreyFP, "\tlea COLOR%02d(a6),a0\n\tmove.w #$%03x,(a0)\n", i, grey << 8 | grey << 4 | grey);
|
||||
}
|
||||
|
||||
if (fp) {
|
||||
fprintf(fp, "\tdc.w $%x,$%x\n", 0x180+(i*2), (ic->palette[i].r >> 4) << 8 | (ic->palette[i].g >>4) << 4 | (ic->palette[i].b >>4));
|
||||
}
|
||||
}
|
||||
|
||||
if (paletteFP) {
|
||||
fclose(paletteFP);
|
||||
}
|
||||
|
||||
if (paletteGreyFP) {
|
||||
fprintf(paletteGreyFP, "\tmovem.l (sp)+,d0-a6\n");
|
||||
fclose(paletteGreyFP);
|
||||
}
|
||||
|
||||
if (paletteAsmFP) {
|
||||
fprintf(paletteAsmFP, "\tmovem.l (sp)+,d0-a6\n");
|
||||
fclose(paletteFP);
|
||||
}
|
||||
|
||||
if (fp) {
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
if (config.verbose) {
|
||||
printf("done\n\n");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
void
|
||||
palette_output(char* outFilename, imagecon_image_t* ic);
|
||||
|
||||
void
|
||||
palette_loadFile(imagecon_image_t* ic);
|
|
@ -117,4 +117,6 @@ png_read(char* file_name, imagecon_image_t* ic)
|
|||
}
|
||||
|
||||
ic->amigaImage = calloc(ic->width*ic->height, 1);
|
||||
|
||||
|
||||
}
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue