/* * Argyll Color Correction System * * RGB gamut boundary test image generator * * Author: Graeme W. Gill * Date: 28/12/2005 * * Copyright 2005 Graeme W. Gill * All rights reserved. * * This material is licenced under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 :- * see the License.txt file for licencing details. */ /* * Generate TIFF image with two RGB cube surface hexagons, * plus a rectangular grey wedges between them, on a grey * background, or a rectangular gamut surface test image. */ /* * TTBD: */ #undef DEBUG #define verbo stdout #include #include #include #include #include #include "copyright.h" #include "aconfig.h" #include "numsup.h" #include "render.h" #define DEF_DPI 200 #define DITHER 0x8002 /* [0] 1 for test 8 bit dithering, 2 for test error diffusion */ /* 0x8001 for dithering FG only, 0x8002 for err. diff. FG only */ #undef PNG_MEM /* Test PNG save to memory */ void usage(void) { fprintf(stderr,"Create test images, default hex RGB surface and wedge, Version %s\n",ARGYLL_VERSION_STR); fprintf(stderr,"Author: Graeme W. Gill, licensed under the AGPL Version 3\n"); fprintf(stderr,"usage: timage [-options] outfile.[tif|png]\n"); // fprintf(stderr," -v Verbose\n"); fprintf(stderr," -t Generate rectangular gamut boundary test chart\n"); fprintf(stderr," -p steps Generate a colorspace step chart with L* steps^2\n"); fprintf(stderr," -r res Resolution in DPI (default %d)\n",DEF_DPI); fprintf(stderr," -s Smooth blend\n"); fprintf(stderr," -x 16 bit output\n"); fprintf(stderr," -4 CMYK output\n"); fprintf(stderr," -g prop Percentage towards grey (default 0%%)\n"); fprintf(stderr," -P Save as PNG file (deffault TIFF)\n"); // fprintf(stderr," -D Debug primitives plot */ fprintf(stderr," outfile.[tif|png] Output TIFF or PNG file\n"); exit(1); } int main(int argc, char *argv[]) { int fa,nfa; /* current argument we're looking at */ int verb = 0; int rchart = 0; /* Rectangular chart */ int schart = 0; /* Step chart with steps^2 */ int smooth = 0; /* Use smooth blending */ rend_format fmt = tiff_file; /* Output filr format */ int debugchart = 0; /* Debug chart */ double res = DEF_DPI; depth2d depth = bpc8_2d; int cmyk = 0; /* Do CMYK output */ char outname[MAXNAMEL+1] = { 0 }; /* Output TIFF name */ render2d *r; color2d c; double vv[6][2]; color2d cc[4]; double gbf = 1.0; /* Grey blend factor */ double w, h; /* Size of page in mm */ int i, j; error_program = "timage"; if (argc <= 1) usage(); /* Process the arguments */ for(fa = 1;fa < argc;fa++) { nfa = fa; /* skip to nfa if next argument is used */ if (argv[fa][0] == '-') { /* Look for any flags */ char *na = NULL; /* next argument after flag, null if none */ if (argv[fa][2] != '\000') na = &argv[fa][2]; /* next is directly after flag */ else { if ((fa+1) < argc) { if (argv[fa+1][0] != '-') { nfa = fa + 1; na = argv[nfa]; /* next is seperate non-flag argument */ } } } if (argv[fa][1] == '?') usage(); else if (argv[fa][1] == 'v') verb = 1; /* Rectangular chart */ else if (argv[fa][1] == 't') { rchart = 1; schart = 0; /* Smooth blending */ } else if (argv[fa][1] == 's') smooth = 1; /* 16 bit depth */ else if (argv[fa][1] == 'x') depth = bpc16_2d; /* cmyk */ else if (argv[fa][1] == '4') cmyk = 1; /* step chart */ else if (argv[fa][1] == 'p') { fa = nfa; if (na == NULL) usage(); schart = atoi(na); if (schart <= 0) usage(); rchart = 0; } /* PNG file */ else if (argv[fa][1] == 'P') { fmt = png_file; } /* debug chart */ else if (argv[fa][1] == 'D') { debugchart = 1; } /* resolution */ else if (argv[fa][1] == 'r') { fa = nfa; if (na == NULL) usage(); res = atof(na); if (res <= 0.0) usage(); } /* grey blend */ else if (argv[fa][1] == 'g') { fa = nfa; if (na == NULL) usage(); gbf = 1.0 - 0.01 * atof(na); if (gbf < 0.0 || gbf > 1.0) usage(); } else usage(); } else break; } /* Get the file name arguments */ if (fa >= argc || argv[fa][0] == '-') usage(); strncpy(outname,argv[fa++],MAXNAMEL); outname[MAXNAMEL] = '\000'; res /= 25.4; /* Convert to DPmm */ /* Debug chart - test each primitive in RGB space */ if (debugchart) { font2d fo; h = 140.0; w = 200.0; if (cmyk) error("CMYK not supported for test chart"); if ((r = new_render2d(w, h, NULL, res, res, rgb_2d, 0, depth, DITHER, NULL, NULL, 0.0)) == NULL) { error("new_render2d() failed"); } /* Set the background color */ // c[0] = 0.5; // c[1] = 0.5; // c[2] = 0.5; c[0] = 1.0; c[1] = 1.0; c[2] = 1.0; r->set_defc(r, c); c[0] = 1.0; /* Red rectangle, bottom left */ c[1] = 0.0; c[2] = 0.0; r->add(r, new_rect2d(r, 5.0, 5.0, 8.0, 8.0, c)) ; c[0] = 0.0; /* Green to the right of red */ c[1] = 1.0; c[2] = 0.0; r->add(r, new_rect2d(r, 15.0, 5.0, 8.0, 8.0, c)) ; c[0] = 0.0; /* Blue to the right of green */ c[1] = 0.0; c[2] = 1.0; r->add(r, new_rect2d(r, 25.0, 5.0, 8.0, 8.0, c)) ; /* A vertex shaded rectangle */ cc[0][0] = 1.0; /* Red */ cc[0][1] = 0.0; cc[0][2] = 0.0; cc[1][0] = 0.0; /* Green */ cc[1][1] = 1.0; cc[1][2] = 0.0; cc[2][0] = 0.0; /* Blue */ cc[2][1] = 0.0; cc[2][2] = 1.0; cc[3][0] = 1.0; /* Yellow */ cc[3][1] = 1.0; cc[3][2] = 0.0; r->add(r, new_rectvs2d(r, 5.0, 20.0, 18.0, 18.0, cc)); /* A shaded triangle to the right of the shaded rectangle */ vv[0][0] = 30.0; vv[0][1] = 20.0; cc[0][0] = 0.0; cc[0][1] = 1.0; cc[0][2] = 1.0; vv[1][0] = 50.0; vv[1][1] = 20.0; cc[1][0] = 1.0; cc[1][1] = 0.0; cc[1][2] = 1.0; vv[2][0] = 40.0; vv[2][1] = 40.0; cc[2][0] = 1.0; cc[2][1] = 1.0; cc[2][2] = 0.0; r->add(r, new_trivs2d(r, vv, cc)); /* A circular disk right of the shaded triangle */ c[0] = 0.0; /* Cyan */ c[1] = 1.0; c[2] = 1.0; r->add(r, new_disk2d(r, 65.0, 29.0, 9.0, c)); /* A circle right of the disk */ c[0] = 1.0; /* Magenta */ c[1] = 0.0; c[2] = 1.0; add_circle2d(r, 90.0, 29.0, 9.0, 2.0, c); /* A polygon */ c[0] = 0.8; /* Brown */ c[1] = 0.8; c[2] = 0.2; vv[0][0] = 115.0; vv[0][1] = 20.0; vv[1][0] = 130.0; vv[1][1] = 20.0; vv[2][0] = 140.0; vv[2][1] = 35.0; vv[3][0] = 125.0; vv[3][1] = 25.0; vv[4][0] = 110.0; vv[4][1] = 40.0; r->add(r, new_poly2d(r, 5, vv, c)); /* A diagonal wide line */ c[0] = 0.0; c[1] = 0.0; c[2] = 0.0; r->add(r, new_line2d(r, 10.0, 45.0, 11.0, 55.0, 3.0, 1, c)); /* A dashed line */ add_dashed_line2d(r, 20.0, 45.0, 100.0, 65.0, 1.0, 3.0, 5.0, 1, c); fo = futura_l; /* rectange the size the letter A should be */ c[0] = 0.7; c[1] = 0.0; c[2] = 0.0; r->add(r, new_rect2d(r, 10.0, 60.0, 7.7, 10.0, c)) ; c[0] = 0.0; c[1] = 0.0; c[2] = 0.0; /* The letter A */ add_char2d(r, NULL, NULL, fo, 'A', 10.0, 60.0, 10.0, 0, c); /* A test string */ add_string2d(r, NULL, NULL, fo, "Testing 1234", 10.0, 70.0, 7.0, 3, c); /* The full font */ { double x, y; char chars[33]; x = 15.0; y = 125.0; for (j = 0; j < 4; j++) { for (i = 0; i < 32; i++) chars[i] = j * 32 + i; chars[i] = '\000'; add_string2d(r, NULL, NULL, fo, chars, x, y, 7.0, 0, c); y -= 10.0; } } /* RGB Hexagon chart */ } else if (rchart == 0 && schart == 0) { double r3o2; /* 0.866025 */ double bb = 0.07; /* Border proportion */ double hh = 40.0; /* Height of hexagon in mm */ color2d white; color2d red; color2d green; color2d blue; color2d cyan; color2d magenta; color2d yellow; color2d black; color2d grey; color2d kblack; r3o2 = sqrt(3.0)/2.0; /* Width to heigh of hexagon */ h = (1.0 + 2.0 * bb) * hh; w = (4.0 * bb + 0.25 + 2.0 * r3o2) * hh; if ((r = new_render2d(w, h, NULL, res, res, cmyk ? cmyk_2d : rgb_2d, 0, depth, DITHER, NULL, NULL, 0.0)) == NULL) { error("new_render2d() failed"); } if (cmyk) { white[0] = 0.0; white[1] = 0.0; white[2] = 0.0; white[3] = 0.0; red[0] = 0.0; red[1] = 1.0; red[2] = 1.0; red[3] = 0.0; green[0] = 1.0; green[1] = 0.0; green[2] = 1.0; green[3] = 0.0; blue[0] = 1.0; blue[1] = 1.0; blue[2] = 0.0; blue[3] = 0.0; cyan[0] = 1.0; cyan[1] = 0.0; cyan[2] = 0.0; cyan[3] = 0.0; magenta[0] = 0.0; magenta[1] = 1.0; magenta[2] = 0.0; magenta[3] = 0.0; yellow[0] = 0.0; yellow[1] = 0.0; yellow[2] = 1.0; yellow[3] = 0.0; kblack[0] = 0.0; kblack[1] = 0.0; kblack[2] = 0.0; kblack[3] = 1.0; grey[0] = 0.0; grey[1] = 0.0; grey[2] = 0.0; grey[3] = 0.5; black[0] = 1.0; black[1] = 1.0; black[2] = 1.0; black[3] = 0.0; } else { white[0] = 1.0; white[1] = 1.0; white[2] = 1.0; red[0] = 1.0; red[1] = 0.0; red[2] = 0.0; green[0] = 0.0; green[1] = 1.0; green[2] = 0.0; blue[0] = 0.0; blue[1] = 0.0; blue[2] = 1.0; cyan[0] = 0.0; cyan[1] = 1.0; cyan[2] = 1.0; magenta[0] = 1.0; magenta[1] = 0.0; magenta[2] = 1.0; yellow[0] = 1.0; yellow[1] = 1.0; yellow[2] = 0.0; black[0] = 0.0; black[1] = 0.0; black[2] = 0.0; grey[0] = 0.5; grey[1] = 0.5; grey[2] = 0.5; } /* Set the default color */ r->set_defc(r, grey); /* Left hand hex */ vv[0][0] = hh * bb + r3o2 * 0.5 * hh; vv[0][1] = hh * bb + hh/2.0; cc[0][0] = white[0] * gbf + (1.0 - gbf) * grey[0]; cc[0][1] = white[1] * gbf + (1.0 - gbf) * grey[1]; cc[0][2] = white[2] * gbf + (1.0 - gbf) * grey[2]; cc[0][3] = white[3] * gbf + (1.0 - gbf) * grey[3]; vv[1][0] = hh * bb + r3o2 * 0.5 * hh; vv[1][1] = hh * bb; cc[1][0] = red[0] * gbf + (1.0 - gbf) * grey[0]; cc[1][1] = red[1] * gbf + (1.0 - gbf) * grey[1]; cc[1][2] = red[2] * gbf + (1.0 - gbf) * grey[2]; cc[1][3] = red[3] * gbf + (1.0 - gbf) * grey[3]; vv[2][0] = hh * bb; vv[2][1] = hh * bb + 0.25 * hh; cc[2][0] = magenta[0] * gbf + (1.0 - gbf) * grey[0]; cc[2][1] = magenta[1] * gbf + (1.0 - gbf) * grey[1]; cc[2][2] = magenta[2] * gbf + (1.0 - gbf) * grey[2]; cc[2][3] = magenta[3] * gbf + (1.0 - gbf) * grey[3]; r->add(r, new_trivs2d(r, vv, cc)); vv[1][0] = hh * bb; vv[1][1] = hh * bb + 0.75 * hh; cc[1][0] = blue[0] * gbf + (1.0 - gbf) * grey[0]; cc[1][1] = blue[1] * gbf + (1.0 - gbf) * grey[1]; cc[1][2] = blue[2] * gbf + (1.0 - gbf) * grey[2]; cc[1][3] = blue[3] * gbf + (1.0 - gbf) * grey[3]; r->add(r, new_trivs2d(r, vv, cc)); vv[2][0] = hh * bb + r3o2 * 0.5 * hh; vv[2][1] = hh * bb + 1.0 * hh; cc[2][0] = cyan[0] * gbf + (1.0 - gbf) * grey[0]; cc[2][1] = cyan[1] * gbf + (1.0 - gbf) * grey[1]; cc[2][2] = cyan[2] * gbf + (1.0 - gbf) * grey[2]; cc[2][3] = cyan[3] * gbf + (1.0 - gbf) * grey[3]; r->add(r, new_trivs2d(r, vv, cc)); vv[1][0] = hh * bb + r3o2 * 1.0 * hh;; vv[1][1] = hh * bb + 0.75 * hh; cc[1][0] = green[0] * gbf + (1.0 - gbf) * grey[0]; cc[1][1] = green[1] * gbf + (1.0 - gbf) * grey[1]; cc[1][2] = green[2] * gbf + (1.0 - gbf) * grey[2]; cc[1][3] = green[3] * gbf + (1.0 - gbf) * grey[3]; r->add(r, new_trivs2d(r, vv, cc)); vv[2][0] = hh * bb + r3o2 * 1.0 * hh; vv[2][1] = hh * bb + 0.25 * hh; cc[2][0] = yellow[0] * gbf + (1.0 - gbf) * grey[0]; cc[2][1] = yellow[1] * gbf + (1.0 - gbf) * grey[1]; cc[2][2] = yellow[2] * gbf + (1.0 - gbf) * grey[2]; cc[2][3] = yellow[3] * gbf + (1.0 - gbf) * grey[3]; r->add(r, new_trivs2d(r, vv, cc)); vv[1][0] = hh * bb + r3o2 * 0.5 * hh;; vv[1][1] = hh * bb; cc[1][0] = red[0] * gbf + (1.0 - gbf) * grey[0]; cc[1][1] = red[1] * gbf + (1.0 - gbf) * grey[1]; cc[1][2] = red[2] * gbf + (1.0 - gbf) * grey[2]; cc[1][3] = red[3] * gbf + (1.0 - gbf) * grey[3]; r->add(r, new_trivs2d(r, vv, cc)); /* Right hand hex */ vv[0][0] = hh * (3.0 * bb + 0.25 + r3o2) + r3o2 * 0.5 * hh; vv[0][1] = hh * bb + hh/2.0; cc[0][0] = black[0] * gbf + (1.0 - gbf) * grey[0]; cc[0][1] = black[1] * gbf + (1.0 - gbf) * grey[1]; cc[0][2] = black[2] * gbf + (1.0 - gbf) * grey[2]; cc[0][3] = black[3] * gbf + (1.0 - gbf) * grey[3]; vv[1][0] = hh * (3.0 * bb + 0.25 + r3o2) + r3o2 * 0.5 * hh; vv[1][1] = hh * bb; cc[1][0] = red[0] * gbf + (1.0 - gbf) * grey[0]; cc[1][1] = red[1] * gbf + (1.0 - gbf) * grey[1]; cc[1][2] = red[2] * gbf + (1.0 - gbf) * grey[2]; cc[1][3] = red[3] * gbf + (1.0 - gbf) * grey[3]; vv[2][0] = hh * (3.0 * bb + 0.25 + r3o2); vv[2][1] = hh * bb + 0.25 * hh; cc[2][0] = magenta[0] * gbf + (1.0 - gbf) * grey[0]; cc[2][1] = magenta[1] * gbf + (1.0 - gbf) * grey[1]; cc[2][2] = magenta[2] * gbf + (1.0 - gbf) * grey[2]; cc[2][3] = magenta[3] * gbf + (1.0 - gbf) * grey[3]; r->add(r, new_trivs2d(r, vv, cc)); vv[1][0] = hh * (3.0 * bb + 0.25 + r3o2); vv[1][1] = hh * bb + 0.75 * hh; cc[1][0] = blue[0] * gbf + (1.0 - gbf) * grey[0]; cc[1][1] = blue[1] * gbf + (1.0 - gbf) * grey[1]; cc[1][2] = blue[2] * gbf + (1.0 - gbf) * grey[2]; cc[1][3] = blue[3] * gbf + (1.0 - gbf) * grey[3]; r->add(r, new_trivs2d(r, vv, cc)); vv[2][0] = hh * (3.0 * bb + 0.25 + r3o2) + r3o2 * 0.5 * hh; vv[2][1] = hh * bb + 1.0 * hh; cc[2][0] = cyan[0] * gbf + (1.0 - gbf) * grey[0]; cc[2][1] = cyan[1] * gbf + (1.0 - gbf) * grey[1]; cc[2][2] = cyan[2] * gbf + (1.0 - gbf) * grey[2]; cc[1][3] = cyan[3] * gbf + (1.0 - gbf) * grey[3]; r->add(r, new_trivs2d(r, vv, cc)); vv[1][0] = hh * (3.0 * bb + 0.25 + r3o2) + r3o2 * 1.0 * hh;; vv[1][1] = hh * bb + 0.75 * hh; cc[1][0] = green[0] * gbf + (1.0 - gbf) * grey[0]; cc[1][1] = green[1] * gbf + (1.0 - gbf) * grey[1]; cc[1][2] = green[2] * gbf + (1.0 - gbf) * grey[2]; cc[1][3] = green[3] * gbf + (1.0 - gbf) * grey[3]; r->add(r, new_trivs2d(r, vv, cc)); vv[2][0] = hh * (3.0 * bb + 0.25 + r3o2) + r3o2 * 1.0 * hh; vv[2][1] = hh * bb + 0.25 * hh; cc[2][0] = yellow[0] * gbf + (1.0 - gbf) * grey[0]; cc[2][1] = yellow[1] * gbf + (1.0 - gbf) * grey[1]; cc[2][2] = yellow[2] * gbf + (1.0 - gbf) * grey[2]; cc[2][3] = yellow[3] * gbf + (1.0 - gbf) * grey[3]; r->add(r, new_trivs2d(r, vv, cc)); vv[1][0] = hh * (3.0 * bb + 0.25 + r3o2) + r3o2 * 0.5 * hh;; vv[1][1] = hh * bb; cc[1][0] = red[0] * gbf + (1.0 - gbf) * grey[0]; cc[1][1] = red[1] * gbf + (1.0 - gbf) * grey[1]; cc[1][2] = red[2] * gbf + (1.0 - gbf) * grey[2]; cc[1][3] = red[3] * gbf + (1.0 - gbf) * grey[3]; r->add(r, new_trivs2d(r, vv, cc)); /* Center wedge */ cc[0][0] = black[0] * gbf + (1.0 - gbf) * grey[0]; cc[0][1] = black[1] * gbf + (1.0 - gbf) * grey[1]; cc[0][2] = black[2] * gbf + (1.0 - gbf) * grey[2]; cc[0][3] = black[3] * gbf + (1.0 - gbf) * grey[3]; cc[1][0] = black[0] * gbf + (1.0 - gbf) * grey[0]; cc[1][1] = black[1] * gbf + (1.0 - gbf) * grey[1]; cc[1][2] = black[2] * gbf + (1.0 - gbf) * grey[2]; cc[1][3] = black[3] * gbf + (1.0 - gbf) * grey[3]; cc[2][0] = white[0] * gbf + (1.0 - gbf) * grey[0]; cc[2][1] = white[1] * gbf + (1.0 - gbf) * grey[1]; cc[2][2] = white[2] * gbf + (1.0 - gbf) * grey[2]; cc[2][3] = white[3] * gbf + (1.0 - gbf) * grey[3]; cc[3][0] = white[0] * gbf + (1.0 - gbf) * grey[0]; cc[3][1] = white[1] * gbf + (1.0 - gbf) * grey[1]; cc[3][2] = white[2] * gbf + (1.0 - gbf) * grey[2]; cc[3][3] = white[3] * gbf + (1.0 - gbf) * grey[3]; if (cmyk) r->add(r, new_rectvs2d(r, (2.0 * bb + r3o2) * hh, bb * hh, 0.125 * hh, hh, cc)); else r->add(r, new_rectvs2d(r, (2.0 * bb + r3o2) * hh, bb * hh, 0.25 * hh, hh, cc)); /* Center CMY wedge */ if (cmyk) { cc[0][0] = kblack[0] * gbf + (1.0 - gbf) * grey[0]; cc[0][1] = kblack[1] * gbf + (1.0 - gbf) * grey[1]; cc[0][2] = kblack[2] * gbf + (1.0 - gbf) * grey[2]; cc[0][3] = kblack[3] * gbf + (1.0 - gbf) * grey[3]; cc[1][0] = kblack[0] * gbf + (1.0 - gbf) * grey[0]; cc[1][1] = kblack[1] * gbf + (1.0 - gbf) * grey[1]; cc[1][2] = kblack[2] * gbf + (1.0 - gbf) * grey[2]; cc[1][3] = kblack[3] * gbf + (1.0 - gbf) * grey[3]; cc[2][0] = white[0] * gbf + (1.0 - gbf) * grey[0]; cc[2][1] = white[1] * gbf + (1.0 - gbf) * grey[1]; cc[2][2] = white[2] * gbf + (1.0 - gbf) * grey[2]; cc[2][3] = white[3] * gbf + (1.0 - gbf) * grey[3]; cc[3][0] = white[0] * gbf + (1.0 - gbf) * grey[0]; cc[3][1] = white[1] * gbf + (1.0 - gbf) * grey[1]; cc[3][2] = white[2] * gbf + (1.0 - gbf) * grey[2]; cc[3][3] = white[3] * gbf + (1.0 - gbf) * grey[3]; r->add(r, new_rectvs2d(r, (2.0 * bb + r3o2 + 0.125) * hh, bb * hh, 0.125 * hh, hh, cc)); } /* RGB Rectangular chart */ } else if (schart == 0) { double bb = 0.07; /* Border proportion */ double hh = 50.0; /* Height of hexagon in mm */ double sc[6][3] = { /* Saturated color sequence */ { 1, 0, 0 }, { 1, 0, 1 }, { 0, 0, 1 }, { 0, 1, 1 }, { 0, 1, 0 }, { 1, 1, 0 } }; if (cmyk) error("CMYK not supported for test chart"); h = (1.0 + 2.0 * bb) * hh; w = (2.0 * bb + 0.20 * 7.0) * hh; if ((r = new_render2d(w, h, NULL, res, res, rgb_2d, 0, depth, DITHER, NULL, NULL, 0.0)) == NULL) { error("new_render2d() failed"); } /* Set the default color */ c[0] = 0.5; c[1] = 0.5; c[2] = 0.5; r->set_defc(r, c); for (i = 0; i < 7; i++) { prim2d *p; /* Top rectangle */ cc[0][0] = sc[i % 6][0] * gbf + (1.0 - gbf) * 0.5; cc[0][1] = sc[i % 6][1] * gbf + (1.0 - gbf) * 0.5; cc[0][2] = sc[i % 6][2] * gbf + (1.0 - gbf) * 0.5; cc[1][0] = sc[(i+1) % 6][0] * gbf + (1.0 - gbf) * 0.5; cc[1][1] = sc[(i+1) % 6][1] * gbf + (1.0 - gbf) * 0.5; cc[1][2] = sc[(i+1) % 6][2] * gbf + (1.0 - gbf) * 0.5; cc[2][0] = 1.0 * gbf + (1.0 - gbf) * 0.5; cc[2][1] = 1.0 * gbf + (1.0 - gbf) * 0.5; cc[2][2] = 1.0 * gbf + (1.0 - gbf) * 0.5; cc[3][0] = 1.0 * gbf + (1.0 - gbf) * 0.5; cc[3][1] = 1.0 * gbf + (1.0 - gbf) * 0.5; cc[3][2] = 1.0 * gbf + (1.0 - gbf) * 0.5; p = new_rectvs2d(r, (bb + i * 0.2) * hh, (bb + 0.5) * hh, 0.2 * hh, 0.5 * hh, cc); if (smooth) { rectvs2d *pp = (rectvs2d *)p; pp->x_blend = 2; pp->y_blend = 3; } r->add(r, p); /* Bottom rectangle */ cc[0][0] = 0.0 * gbf + (1.0 - gbf) * 0.5; cc[0][1] = 0.0 * gbf + (1.0 - gbf) * 0.5; cc[0][2] = 0.0 * gbf + (1.0 - gbf) * 0.5; cc[1][0] = 0.0 * gbf + (1.0 - gbf) * 0.5; cc[1][1] = 0.0 * gbf + (1.0 - gbf) * 0.5; cc[1][2] = 0.0 * gbf + (1.0 - gbf) * 0.5; cc[2][0] = sc[i % 6][0] * gbf + (1.0 - gbf) * 0.5; cc[2][1] = sc[i % 6][1] * gbf + (1.0 - gbf) * 0.5; cc[2][2] = sc[i % 6][2] * gbf + (1.0 - gbf) * 0.5; cc[3][0] = sc[(i+1) % 6][0] * gbf + (1.0 - gbf) * 0.5; cc[3][1] = sc[(i+1) % 6][1] * gbf + (1.0 - gbf) * 0.5; cc[3][2] = sc[(i+1) % 6][2] * gbf + (1.0 - gbf) * 0.5; p = new_rectvs2d(r, (bb + i * 0.2) * hh, bb * hh, 0.2 * hh, 0.5 * hh, cc); if (smooth) { rectvs2d *pp = (rectvs2d *)p; pp->x_blend = 2; pp->y_blend = 2; } r->add(r, p); } } else { /* Lab step chart */ double hh = 50.0; /* Height of hexagon in mm */ double bb = 0.05; /* Border proportion */ double ss, bs; /* Step size, border size */ h = hh; w = hh; if (cmyk) error("CMYK not supported for test chart"); bs = (bb * hh)/(schart + 1.0); ss = hh * (1.0 - bb)/schart; if ((r = new_render2d(w, h, NULL, res, res, lab_2d, 0, depth, DITHER, NULL, NULL, 0.0)) == NULL) { error("new_render2d() failed"); } /* Set the default color */ c[0] = 0.0; c[1] = 0.0; c[2] = 0.0; r->set_defc(r, c); for (i = 0; i < schart; i++) { for (j = 0; j < schart; j++) { double lv; lv = (double)(j * schart + i)/(schart * schart - 1.0) * 100.0; cc[0][0] = lv; cc[0][1] = -127.0; cc[0][2] = -127.0; cc[1][0] = lv; cc[1][1] = 127.0; cc[1][2] = -127.0; cc[2][0] = lv; cc[2][1] = -127.0; cc[2][2] = 127.0; cc[3][0] = lv; cc[3][1] = 127.0; cc[3][2] = 127.0; r->add(r, new_rectvs2d(r, bs + i * (bs + ss), bs + j * (bs + ss), ss, ss, cc)); } } } #ifdef PNG_MEM { char *nmode = "w"; FILE *fp; unsigned char *buf; size_t len, wlen; #if !defined(O_CREAT) && !defined(_O_CREAT) # error "Need to #include fcntl.h!" #endif #if defined(O_BINARY) || defined(_O_BINARY) nmode = "wb"; #endif if (r->write(r, "MemoryBuf", 1, &buf, &len, png_mem)) error("render->write failed"); if ((fp = fopen(outname, nmode)) == NULL) error("render2d: open '%s' for writing",outname); if (len != (wlen = fwrite(buf, 1, len, fp))) error("render2d: writing %u bytes to '%s' failed (wrote %u)",len,outname,wlen); if (fclose(fp)) error("render2d: failed to close after writing",outname); } #else if (r->write(r, outname, 1, NULL, NULL, fmt)) error("render->write failed"); #endif r->del(r); return 0; }