Files
argyllcms/render/timage.c
T
2026-08-20 20:28:40 +01:00

757 lines
21 KiB
C

/*
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <fcntl.h>
#include "copyright.h"
#include "aconfig.h"
#include "numsup.h"
#include "render.h"
#define DEF_DPI 200
#define DITHER 0 /* [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 (default 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 */
static 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;
}