Skip to content

Instantly share code, notes, and snippets.

@Imroy
Created July 13, 2012 14:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Imroy/3105203 to your computer and use it in GitHub Desktop.
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
/*
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