Created
July 13, 2012 14:31
-
-
Save Imroy/3105203 to your computer and use it in GitHub Desktop.
Convert a PNG image to a raw file for flashing to a Motorola Atrix
This file contains hidden or 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
/* | |
Convert a PNG image to a raw file for flashing to a Motorola Atrix. | |
I've not tested it with all types of input, only 24-bit RGB, | |
16-bit greyscale, and 48-bit RGB for now. | |
Theoretically handles any sized input now, so other devices might work too? | |
Also dithers using Floyd-Steinberg error diffusion. | |
Output goes to standard out, so pipe it to a file. | |
Compile: gcc Atrixlogo.c -o Atrixlogo -lpng | |
Run: ./Atrixlogo pic.png > pic.bin | |
Upload: fastboot flash logo pic.bin | |
Needs libPNG; developed with 1.5.11, don't know if it will compile with 1.2.x | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <math.h> | |
#include <png.h> | |
unsigned char header[12] = { 0x53, 0x4f, 0x4c, 0x3a, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00 }; | |
size_t fwrite_be(void *ptr, size_t size, FILE *stream) { | |
unsigned char *in = ptr + size - 1; | |
size_t n; | |
for (n = 0; n < size; n++, in--) | |
fwrite(in, 1, 1, stream); | |
return size; | |
} | |
int main(int argc, char* argv[]) { | |
if (argc == 1) { | |
fprintf(stderr, "%s <input file>\n", argv[0]); | |
exit(1); | |
} | |
char *inname = argv[1]; | |
FILE *fp = fopen(inname, "r"); | |
if (!fp) { | |
fprintf(stderr, "Could not open file \"%s\".\n", inname); | |
exit(2); | |
} | |
{ | |
unsigned char pngheader[8]; | |
fread((char*)pngheader, 1, 8, fp); | |
if (png_sig_cmp(pngheader, 0, 8)) { | |
fprintf(stderr, "File \"%s\" is not a PNG file.\n", inname); | |
exit(2); | |
} | |
} | |
png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); | |
if (!png) | |
exit(3); | |
png_infop info = png_create_info_struct(png); | |
if (!info) { | |
png_destroy_read_struct(&png, (png_infopp)NULL, (png_infopp)NULL); | |
exit(3); | |
} | |
if (setjmp(png_jmpbuf(png))) { | |
png_destroy_read_struct(&png, &info, NULL); | |
fclose(fp); | |
exit(3); | |
} | |
png_init_io(png, fp); | |
png_set_sig_bytes(png, 8); | |
png_read_png(png, info, PNG_TRANSFORM_EXPAND_16 | PNG_TRANSFORM_STRIP_ALPHA | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_SWAP_ENDIAN | PNG_TRANSFORM_GRAY_TO_RGB, NULL); | |
png_bytepp png_rows = png_get_rows(png, info); | |
png_uint_32 width, height; | |
int bit_depth, colour_type; | |
png_get_IHDR(png, info, &width, &height, | |
&bit_depth, &colour_type, NULL, NULL, NULL); | |
fwrite(header, 1, 12, stdout); | |
fwrite_be(&width, 4, stdout); | |
fwrite_be(&height, 4, stdout); | |
short int **error_rows = (short int**)malloc(2 * sizeof(short int*)); | |
unsigned int y; | |
for (y = 0; y < 2; y++) | |
error_rows[y] = (short int*)malloc(width * 3 * sizeof(short int)); | |
unsigned char curr_row = 0, next_row = 1; | |
memset(error_rows[next_row], 0, width * 3 * sizeof(short int)); | |
#define errorval(x, row, c) error_rows[row][(((x) * 3) + (c))] | |
unsigned int x; | |
for (y = 0; y < height; y++) { | |
curr_row = next_row; | |
next_row = 1 - curr_row; | |
memset(error_rows[next_row], 0, width * 3 * sizeof(short int)); | |
short unsigned int *inp = (short unsigned int*)png_rows[y]; | |
for (x = 0; x < width; x++) { | |
int tr, tg, tb; /* Target values */ | |
tr = *inp++ + (errorval(x, curr_row, 0) >> 4); | |
tg = *inp++ + (errorval(x, curr_row, 1) >> 4); | |
tb = *inp++ + (errorval(x, curr_row, 2) >> 4); | |
unsigned char r, g, b; /* Output values */ | |
r = round(tr * (31.0 / 65535)); | |
g = round(tg * (63.0 / 65535)); | |
b = round(tb * (31.0 / 65535)); | |
short int er, eg, eb; /* Error values */ | |
er = tr - (r * (65535.0 / 31)); | |
eg = tg - (g * (65535.0 / 63)); | |
eb = tb - (b * (65535.0 / 31)); | |
if (x < width - 1) { | |
errorval(x + 1, curr_row, 0) += er * 7; | |
errorval(x + 1, curr_row, 1) += eg * 7; | |
errorval(x + 1, curr_row, 2) += eb * 7; | |
} | |
if (y < height - 1) { | |
if (x > 0) { | |
errorval(x - 1, next_row, 0) += er * 3; | |
errorval(x - 1, next_row, 1) += eg * 3; | |
errorval(x - 1, next_row, 2) += eb * 3; | |
} | |
errorval(x, next_row, 0) += er * 5; | |
errorval(x, next_row, 1) += eg * 5; | |
errorval(x, next_row, 2) += eb * 5; | |
if (x < width - 1) { | |
errorval(x + 1, next_row, 0) += er; | |
errorval(x + 1, next_row, 1) += eg; | |
errorval(x + 1, next_row, 2) += eb; | |
} | |
} | |
printf("%c%c", b | ((g & 0x07) << 5), (g >> 3) | (r << 3)); | |
} | |
} | |
for (y = 0; y < 2; y++) | |
free(error_rows[y]); | |
free(error_rows); | |
png_destroy_read_struct(&png, &info, NULL); | |
fclose(fp); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment