#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <jpeglib.h>
#include <png.h>
typedef struct {
int width;
int height;
int bytes_per_pixel;
unsigned char **scanLine;
} Image;
/*
typedef struct {
unsigned width;
unsigned height;
unsigned bytes_per_pixel;
unsigned char pixel_data[];
} Image;
*/
typedef struct {
unsigned magic;
unsigned version;
unsigned size;
unsigned imageCount;
} Images;
typedef struct {
char name[32];
unsigned width;
unsigned height;
unsigned pixel_data_bpp;
unsigned pixel_advance;
unsigned pixel_data_offset;
unsigned alpha_data_bpp;
unsigned alpha_advance;
unsigned alpha_data_offset;
} ImageNew;
Image *createImage(int width, int height)
{
int i;
Image *img = (Image *)malloc(sizeof(Image));
img->width = width;
img->height = height;
//printf("Allocating Image: %i x %i\n", width, height);
img->scanLine = (unsigned char**)malloc(sizeof(char*)*height);
for (i = height - 1; i >= 0; i--)
img->scanLine[i] = (unsigned char*)malloc(4*width);
return img;
}
Image *loadJpegImage(char *jpegFileName)
{
int i;
Image *img;
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr err;
/* Open and initialise */
FILE *file = fopen(jpegFileName, "r");
if ( !file ) {
printf("Error opening file %s\n", jpegFileName);
return 0;
}
cinfo.err = jpeg_std_error(&err);
//printf("loading image: %s (%i)\n", jpegFileName, file);
jpeg_create_decompress(&cinfo);
jpeg_stdio_src(&cinfo, file);
jpeg_read_header(&cinfo, 1);
jpeg_calc_output_dimensions(&cinfo);
jpeg_start_decompress(&cinfo);
/* Setup image */
img = createImage(cinfo.output_width, cinfo.output_height);
img->bytes_per_pixel = 3;
/* Decode image */
for (i = 0; i < img->height; i++)
jpeg_read_scanlines(&cinfo, (void*)&img->scanLine[i], 1);
/* Clean up */
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
fclose(file);
return img;
}
Image *loadPngImage(char *pngFileName)
{
Image *img;
png_structp png;
png_infop cinfo;
png_infop cinfo_end;
struct png_read_struct *reads;
int width, height;
/* Open and initialise */
FILE *file = fopen(pngFileName, "r");
if ( !file ) {
printf("Error opening file %s\n", pngFileName);
return 0;
}
png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
cinfo = png_create_info_struct(png);
cinfo_end = png_create_info_struct(png);
png_init_io(png, file);
png_read_info(png, cinfo);
width = png_get_image_width(png, cinfo);
height = png_get_image_height(png, cinfo);
/* Setup image */
img = createImage(width, height);
img->bytes_per_pixel = 4;
/* Decode image */
png_start_read_image(png);
png_read_image(png, (png_bytepp)img->scanLine);
/* Clean up */
png_read_end(png, cinfo_end);
png_destroy_read_struct(&png, &cinfo, &cinfo_end);
return img;
}
Image *loadImage(char *fileName)
{
if (fileName) {
int i = strlen(fileName) - 1;
while (fileName[i] != '.')
i--;
if (!strcmp(fileName + i, ".png"))
return loadPngImage(fileName);
if (!strcmp(fileName + i, ".jpg"))
return loadJpegImage(fileName);
}
return 0;
}
void writeInt(int fd, unsigned val)
{
unsigned char c1 = (val >> 0) & 0xFF;
unsigned char c2 = (val >> 8) & 0xFF;
unsigned char c3 = (val >> 16) & 0xFF;
unsigned char c4 = (val >> 24) & 0xFF;
write(fd, &c1, 1);
write(fd, &c2, 1);
write(fd, &c3, 1);
write(fd, &c4, 1);
}
#define FORMAT_TO_16
void writeMapableImage(const char *name, Image *image)
{
unsigned i, j;
int fd = open(name, O_WRONLY | O_CREAT, 0600);
writeInt(fd, image->width);
writeInt(fd, image->height);
#ifdef FORMAT_TO_16
if ( image->bytes_per_pixel == 3 ) {
writeInt(fd, 2);
writeInt(fd, 0);
for (j = 0; j < image->height; j++) {
unsigned char *row = image->scanLine[j];
for (i = 0; i < (image->width>>1); i++) {
unsigned int col1 = ((row[2]>>3)<<11) | ((row[1]>>2)<<5) | (row[0]>>3);
unsigned int col2 = ((row[5]>>3)<<11) | ((row[4]>>2)<<5) | (row[3]>>3);
unsigned int dst = (col2 << 16) | col1;
write(fd, &dst, 4);
row += 6;
}
if (image->width & 1) {
unsigned short col1 = ((row[0]>>3)<<11) | ((row[1]>>2)<<5) | (row[2]>>3);
write(fd, &col1, 2);
}
}
} else if ( image->bytes_per_pixel == 4 ) {
writeInt(fd, -2);
writeInt(fd, 0);
for (j = 0; j < image->height; j++) {
unsigned char *row = image->scanLine[j];
for (i = 0; i < image->width; i++) {
unsigned int r, g, b, col1;
unsigned char r1, g1, b1;
unsigned int a1 = row[3];
r1 = (a1 * row[0]) / 255;
g1 = (a1 * row[1]) / 255;
b1 = (a1 * row[2]) / 255;
// r1 = r;
// g1 = g;
// b1 = b;
a1 = 255 - a1;
write(fd, &r1, 1);
write(fd, &g1, 1);
write(fd, &b1, 1);
write(fd, &a1, 1);
row += 4;
}
}
// for (j = 0; j < image->height; j++)
// write(fd, image->scanLine[j], image->width*image->bytes_per_pixel);
/*
writeInt(fd, -2);
writeInt(fd, 0);
for (j = 0; j < image->height; j++) {
char *line = image->scanLine[j];
for (i = 0; i < image->width; i++) {
unsigned short col = ((line[0]>>3)<<11) | ((line[1]>>2)<<5) | (line[2]>>3);
write(fd, &col, 2);
write(fd, &line[3], 1);
line += 4;
}
}
*/
} else {
printf("Not supported depth (shouldn't happen)\n");
}
#else
writeInt(fd, image->bytes_per_pixel);
writeInt(fd, 0);
for (j = 0; j < image->height; j++)
write(fd, image->scanLine[j], image->width*image->bytes_per_pixel);
#endif
close(fd);
}
int main(int argc, char *argv[])
{
writeMapableImage(argv[2], loadImage(argv[1]));
return 0;
}