// // "$Id: png2fti.cxx 1291 2004-06-14 16:03:10Z mike $" // // Simple utility which converts a PNG or XPM icon file to a 3D SGI FTI // icon file. // // Copyright 2004 by Michael Sweet. // #include #include #include //#define DEBUG #ifdef DEBUG # define DEBUG_printf(x) printf x #else # define DEBUG_printf(x) #endif // DEBUG // // 'print_vertex()' - Print an image vertex... // void print_vertex(Fl_Shared_Image *img, // I - Shared image int x, // I - X position in image int y, // I - Y position in image const float matrix[2][3], // I - Transform matrix float &xmin, // IO - Minimum X float &ymin, // IO - Minimum Y float &xmax, // IO - Maximum X float &ymax) // IO - Maximum Y { float fx, fy; // Floating point X/Y float tx, ty; // Transformed x/y // Map integer coords to floating point... fx = 100.0f * (float)x / (float)(img->w() - 1); fy = 100.0f - 100.0f * (float)y / (float)(img->h() - 1); // Project x, y in image space to 3D using the current matrix... tx = matrix[0][0] * fx + matrix[0][1] * fy + matrix[0][2]; ty = matrix[1][0] * fx + matrix[1][1] * fy + matrix[1][2]; // Update the bounding box... if (tx < xmin) xmin = tx; if (tx > xmax) xmax = tx; if (ty < ymin) ymin = ty; if (ty > ymax) ymax = ty; // Write the current vertex... DEBUG_printf(("\t# %d,%d\n", x, y)); printf("\tvertex(%.2f, %.2f);\n", tx, ty); } // // 'main()' - Convert a PNG image to FTI format... // int // O - Exit status main(int argc, // I - Number of command-line args char *argv[]) // I - Command-line arguments { Fl_Shared_Image *img; // PNG icon int x, y; // X & Y in image int startx, // Starting X in image endy, // Ending Y in image tempy; // Current Y in image int c, // Current color temp; // Temporary color const uchar *data; // Pointer into image float xmin, xmax, // Bounding box ymin, ymax; float matrix[2][3]; // Transform matrix int lines[256][768],// Lines (color, startx, endx) *lineptr; // Pointer into line int polys[256]; // Number of polygons per line int did_poly; // Non-zero if we did a polygon if (argc != 3 || (strcmp(argv[1], "-c") && strcmp(argv[1], "-d") && strcmp(argv[1], "-o"))) { puts("Usage: png2fti -[cdo] filename.png >filename.fti"); puts(" -c = closed exec"); puts(" -d = document"); puts(" -o = open exec"); return (1); } fl_register_images(); img = Fl_Shared_Image::get(argv[2]); if (!img || !img->count() || !img->w() || !img->h()) { printf("Unable to open image file \"%s\"!\n", argv[2]); return (1); } if (img->count() != 1) { puts("Sorry, indexed images are not supported at this time."); return (1); } xmin = 1000.0f; xmax = -1000.0f; ymin = 1000.0f; ymax = -1000.0f; printf("# Converted using \"png2fti %s %s\"...\n\n", argv[1], argv[2]); // Create the proper transform for the specified type of icon... switch (argv[1][1]) { case 'c' : // Closed exec matrix[0][0] = 1.0f / 3.0f; matrix[0][1] = -1.0f / 3.0f; matrix[0][2] = 49.0f; matrix[1][0] = 0.5f / 3.0f; matrix[1][1] = 0.5f / 3.0f; matrix[1][2] = 14.5f; break; case 'd' : // Document matrix[0][0] = 1.0f / 3.0f; matrix[0][1] = 0.0f; matrix[0][2] = 42.5f; matrix[1][0] = 0.5f / 3.0f; matrix[1][1] = 1.0f / 3.0f; matrix[1][2] = 26.0f; break; case 'o' : // Open exec matrix[0][0] = 1.0f / 3.0f; matrix[0][1] = 0.0f; matrix[0][2] = 14.0f; matrix[1][0] = 0.5f / 3.0f; matrix[1][1] = 1.0f / 3.0f; matrix[1][2] = 38.0f; break; } // Loop through grayscale or RGB image and add polys... for (y = 0, data = (const uchar *)(*(img->data())); y < img->h(); y ++, data += img->ld()) { polys[y] = 0; lineptr = lines[y]; for (x = 0, startx = 0, c = -1; x < img->w(); x ++, data += img->d()) { switch (img->d()) { case 2 : if (data[1] < 128) { temp = -1; break; } case 1 : temp = fl_gray_ramp(data[0] * (FL_NUM_GRAY - 1) / 255); break; default : if (data[3] < 128) { temp = -1; break; } case 3 : if (data[0] == data[1] && data[1] == data[2]) temp = fl_gray_ramp(data[0] * (FL_NUM_GRAY - 1) / 255); else temp = fl_color_cube(data[0] * (FL_NUM_RED - 1) / 255, data[1] * (FL_NUM_GREEN - 1) / 255, data[2] * (FL_NUM_BLUE - 1) / 255); break; } if (temp != c) { if (c != -1) { polys[y] ++; *lineptr++ = c; *lineptr++ = startx; *lineptr++ = x; } c = temp; startx = x; } } if (x > startx && c != -1) { polys[y] ++; *lineptr++ = c; *lineptr++ = startx; *lineptr++ = x; } } #if 1 // Now loop through the polygons and find polys with a common prefix color for (did_poly = 1; did_poly;) { for (y = 0, did_poly = 0; y < img->h();) { if (polys[y] == 0) { y ++; continue; } fprintf(stderr, "\ry = %d ", y); fflush(stderr); did_poly = 1; for (endy = y + 1; endy < (img->h() - 1) && polys[endy] > 0 && lines[y][0] == lines[endy][0]; endy ++) if (lines[y][1] > lines[endy][2] || lines[y][2] < lines[endy][1]) break; if ((endy - y) == 1) { // Just do a single row... DEBUG_printf(("# %d,%d to %d,%d...\n", lines[y][1], y, lines[y][2], y + 1)); printf("color(%d);\n", lines[y][0]); puts("bgnoutlinepolygon();"); print_vertex(img, lines[y][1], y, matrix, xmin, ymin, xmax, ymax); print_vertex(img, lines[y][2], y, matrix, xmin, ymin, xmax, ymax); print_vertex(img, lines[y][2], y + 1, matrix, xmin, ymin, xmax, ymax); print_vertex(img, lines[y][1], y + 1, matrix, xmin, ymin, xmax, ymax); printf("endoutlinepolygon(%d);\n", lines[y][0]); } else { // Combine multiple rows... #ifdef DEBUG for (tempy = y; tempy < endy; tempy ++) printf("# %d,%d to %d,%d...\n", lines[tempy][1], tempy, lines[tempy][2], tempy + 1); #endif // DEBUG printf("color(%d);\n", lines[y][0]); puts("bgnpolygon();"); print_vertex(img, lines[y][1], y, matrix, xmin, ymin, xmax, ymax); for (tempy = y; tempy < endy; tempy ++) { print_vertex(img, lines[tempy][2], tempy, matrix, xmin, ymin, xmax, ymax); while (tempy < (endy - 2) && lines[tempy][2] == lines[tempy + 1][2]) tempy ++; if (tempy >= (endy - 1) || lines[tempy][2] != lines[tempy + 1][2]) print_vertex(img, lines[tempy][2], tempy + 1, matrix, xmin, ymin, xmax, ymax); } for (tempy = endy - 1; tempy >= y; tempy --) { print_vertex(img, lines[tempy][1], tempy + 1, matrix, xmin, ymin, xmax, ymax); while (tempy > y && lines[tempy][1] == lines[tempy - 1][1]) tempy --; if (tempy > y && lines[tempy][1] != lines[tempy - 1][1]) print_vertex(img, lines[tempy][1], tempy, matrix, xmin, ymin, xmax, ymax); } puts("endpolygon();"); } for (tempy = y; tempy < endy; tempy ++) { polys[tempy] --; if (polys[tempy] > 0) memmove(lines[tempy], lines[tempy] + 3, 3 * polys[tempy] * sizeof(int)); } y = endy; } } #else for (y = 0; y < img->h(); y ++) { for (x = polys[y], lineptr = lines[y]; x > 0; x --, lineptr += 3) { printf("color(%d);\n", lineptr[0]); puts("bgnpolygon();"); print_vertex(img, lineptr[1], y, matrix, xmin, ymin, xmax, ymax); print_vertex(img, lineptr[2], y, matrix, xmin, ymin, xmax, ymax); print_vertex(img, lineptr[2], y + 1, matrix, xmin, ymin, xmax, ymax); print_vertex(img, lineptr[1], y + 1, matrix, xmin, ymin, xmax, ymax); puts("endpolygon();"); } } #endif // 0 printf("# Bounding box = [ %.2f %.2f %.2f %.2f ]\n", xmin, ymin, xmax, ymax); fputs("\rDone! \n", stderr); return (0); } // // End of "$Id: png2fti.cxx 1291 2004-06-14 16:03:10Z mike $". //