#include #include #include #include #include #include #include #include "readpng.h" #include "writepng.h" //#define DEBUG_SCALER void usage(char * s) { fprintf(stderr, "Usage:\n"); fprintf(stderr, "\t%s filename [width height]\n", s); exit(1); } unsigned char ** scale_image(int wo, int ho, int w, int h, unsigned char ** data) { unsigned char ** ret; int i, j, k; double ofs_x, ofs_y; double xod, yod; double p, q; int xo, yo; double a, b, d; double c1, c2, c3, c4; int nx, ny; p = (double) w / (double) wo; q = (double) h / (double) ho; printf("p = %f, q = %f\n", p, q); ret = malloc(h * sizeof(char *)); /* alokacja wskaznikow dla poszczegolnych linii */ assert(ret); for (i = 0; i < h ; i++) { ret[i] = malloc(w * 3); /* alokacja linii */ assert(ret[i]); } /* alokacja pamieci dla obrazka docelowego */ for (i = 0; i < h; i++) { for (j = 0; j < w; j++) { xod = (double) j / p; yod = (double) i / q; /* punkty obrazka zrodlowego */ ofs_x = xod - floor(xod); ofs_y = yod - floor(yod); /* czesci ulamkowe punktow obrazka zrodlowego */ xo = floor(xod); yo = floor(yod); /* czesci calkowiete punktow obrazka zrodlowego */ #ifdef DEBUG_SCALER printf("(%d, %d) -> (%f, %f) offsets: (%f, %f)\n", j, i, xod, yod, ofs_x, ofs_y); #endif for (k = 0; k < 3; k++) { #if 1 nx = xo + 1; if (nx == wo) nx--; ny = yo + 1; if (ny == ho) ny--; /* "zabezpieczenie" przed pobieraniem probek spoza obrazka zrodlowego */ c1 = data[yo][xo * 3 + k]; c2 = data[yo][nx * 3 + k]; c3 = data[ny][xo * 3 + k]; c4 = data[ny][nx * 3 + k]; #ifdef DEBUG_SCALER printf("%f %f %f %f\n", c1, c2, c3, c4); fflush(stdout); #endif a = c1 + (c2 - c1) * ofs_x; b = c3 + (c4 - c3) * ofs_x; d = a + (b - a) * ofs_y; #endif ret[i][j * 3 + k] = d; } } } return ret; } int main(int ac, char ** av) { int rv; FILE * fp; FILE * fpw; int w, h; unsigned char ** data; if (ac < 2) { usage(av[0]); } printf("Processing file: %s\n", av[1]); if ((fp = fopen(av[1], "rb")) == NULL) { fprintf(stderr, "%s: %s\n", av[1], strerror(errno)); return 1; } rv=read_png(fp); printf("File read with status %d\n", rv); if (rv != 0) { fprintf(stderr, "Error while reading file!\n"); return 1; } printf("Image info:\n"); printf("%ldx%ld, %d bits per channel\n", info_ptr->width, info_ptr->height, info_ptr->bit_depth); printf("color type: %d\n", info_ptr->color_type); printf("%d channels, %d bits per pixel\n", info_ptr->channels, info_ptr->pixel_depth); if (ac < 4) { close_png(); fclose(fp); if (ac > 2) { fprintf(stderr, "warning: extra arguments!\n"); usage(av[0]); } return 1; } if (info_ptr->color_type != PNG_COLOR_TYPE_RGB || info_ptr->bit_depth != 8 || info_ptr->channels != 3) { fprintf(stderr, "Only RGB, 8 bits per channel, 3 channel images are supported!\n"); close_png(); fclose(fp); return 1; } printf("Checking image validity...\n"); if (!(info_ptr->valid & PNG_INFO_IDAT)) { fprintf(stderr, "image invalid!\n"); close_png(); fclose(fp); return 1; } printf("Image is valid and loaded correctly!\n"); w = atoi(av[2]); h = atoi(av[3]); printf("Requested resolution: %dx%d\n", w, h); if (w <= 0 || h <= 0) { fprintf(stderr, "Invalid resolution requested!\n"); close_png(); fclose(fp); return 1; } printf("Scaling...\n"); data = scale_image(info_ptr->width, info_ptr->height, w, h, info_ptr->row_pointers); printf("Done\n"); printf("Closing source file...\n"); close_png(); fclose(fp); printf("Done.\n"); printf("Writing destination file...\n"); fpw = fopen("output_scaled.png", "wb+"); if (!fpw) { fprintf(stderr, "Cannot open file output_scaled.png for writing: %s\n", strerror(errno)); return 1; } rv = write_png(fpw, w, h, data); printf("PNG write returned: %d\n", rv); if (rv) { printf("PNG write erred!\n"); fclose(fpw); return 1; } fclose(fpw); printf("Success!\n"); return 0; }