/* convert_argb_png.c compile with: gcc convert_argb_png.c -o convert_argb_png -lpng -ljpeg this tool takes a 32bit RGB+A PNG file, for example produced by photoshop, and splits the data into RGB and A. The RGB data is then lossy compressed with JPEG, the alpha channel is lossless compressed as PNG. enigma2 can then pickup those two files, and combine them on load. This gives the possibilty to use truecolor RGB pictures without storing them lossless (which would be inefficient). */ #include #include #include #include #include int main(int argc, char **argv) { if (argc != 4) { fprintf(stderr, "usage: %s \n", *argv); return 1; } const char *infile = argv[1]; const char *outfile = argv[2]; int jpeg_quality = atoi(argv[3]); FILE *fpin = fopen(infile, "rb"); if (!fpin) { perror(infile); return 1; } unsigned char header[8]; fread(header, 1, 8, fpin); if (png_sig_cmp(header, 0, 8)) { fprintf(stderr, "this is not a PNG file\n"); return 1; } png_structp png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, 0, 0, 0); assert(png_ptr); png_infop info_ptr = png_create_info_struct(png_ptr); assert(info_ptr); png_infop end_info = png_create_info_struct(png_ptr); assert (end_info); if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(fpin); fprintf(stderr, "failed.\n"); return 1; } png_init_io(png_ptr, fpin); png_set_sig_bytes(png_ptr, 8); png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, 0); png_bytep * row_pointers = png_get_rows(png_ptr, info_ptr); png_uint_32 width, height; int bit_depth, color_type; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0); if (color_type != PNG_COLOR_TYPE_RGB_ALPHA) { fprintf(stderr, "input PNG must be RGB+Alpha\n"); return 1; } if (bit_depth != 8) { fprintf(stderr, "input bit depth must be 8bit!\n"); return 1; } printf("png is %ldx%ld\n", width, height); int channels = png_get_channels(png_ptr, info_ptr); if (channels != 4) { fprintf(stderr, "channels must be 4.\n"); return 1; } /* now write jpeg */ struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; JSAMPROW jrow_pointer[1]; FILE *outfp; char filename[strlen(outfile) + 10]; strcpy(filename, outfile); strcat(filename, ".rgb.jpg"); outfp = fopen(filename, "wb"); if (!outfp) { perror(filename); return 1; } cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); jpeg_stdio_dest(&cinfo, outfp); cinfo.image_width = width; cinfo.image_height = height; cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, jpeg_quality, 1); jpeg_start_compress(&cinfo, 1); unsigned char *row = malloc(width * 3); while (cinfo.next_scanline < cinfo.image_height) { int x; jrow_pointer[0] = row; unsigned char *source = row_pointers[cinfo.next_scanline]; for (x = 0; x < width; ++x) { row[x * 3 + 0] = source[0]; row[x * 3 + 1] = source[1]; row[x * 3 + 2] = source[2]; source += 4; } jpeg_write_scanlines(&cinfo, jrow_pointer, 1); } jpeg_finish_compress(&cinfo); fclose(outfp); jpeg_destroy_compress(&cinfo); /* and write png */ strcpy(filename, outfile); strcat(filename, ".a.png"); outfp = fopen(filename, "wb"); if (!outfp) { perror(filename); return 1; } png_structp png_ptr_w = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); png_infop info_ptr_w = png_create_info_struct(png_ptr_w); if (setjmp(png_jmpbuf(png_ptr_w))) { png_destroy_write_struct(&png_ptr_w, &info_ptr_w); fclose(outfp); return 1; } png_init_io(png_ptr_w, outfp); png_set_IHDR(png_ptr_w, info_ptr_w, width, height, 8, PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); /* turn RGBA into A, in-place */ int x, y; for (y=0; y < height; ++y) { unsigned char *source = row_pointers[y]; unsigned char *dst = source; for (x=0; x < width; ++x) { *dst++ = source[3]; source += 4; } } png_set_rows(png_ptr_w, info_ptr_w, row_pointers); png_write_png(png_ptr_w, info_ptr_w, PNG_TRANSFORM_IDENTITY, 0); png_write_end(png_ptr_w, info_ptr_w); png_destroy_write_struct(&png_ptr_w, &info_ptr_w); return 0; }