| 18 |
|
|
| 19 |
|
struct tmStruct *tmTop = NULL; /* current tone mapping stack */ |
| 20 |
|
|
| 21 |
+ |
/* our list of conversion packages */ |
| 22 |
+ |
struct tmPackage *tmPkg[TM_MAXPKG]; |
| 23 |
+ |
int tmNumPkgs = 0; /* number of registered packages */ |
| 24 |
|
|
| 25 |
+ |
int tmLastError; /* last error incurred by library */ |
| 26 |
+ |
char *tmLastFunction; /* error-generating function name */ |
| 27 |
+ |
|
| 28 |
+ |
|
| 29 |
|
int |
| 30 |
|
tmErrorReturn(func, err) /* error return (with message) */ |
| 31 |
|
char *func; |
| 32 |
|
int err; |
| 33 |
|
{ |
| 34 |
+ |
tmLastFunction = func; |
| 35 |
+ |
tmLastError = err; |
| 36 |
|
if (tmTop != NULL && tmTop->flags & TM_F_NOSTDERR) |
| 37 |
|
return(err); |
| 38 |
|
fputs(func, stderr); |
| 71 |
|
tmnew->clf[GRN] = cmat[1][1]; |
| 72 |
|
tmnew->clf[BLU] = cmat[1][2]; |
| 73 |
|
} |
| 65 |
– |
tmnew->clfb[RED] = 256.*tmnew->clf[RED] + .5; |
| 66 |
– |
tmnew->clfb[GRN] = 256.*tmnew->clf[GRN] + .5; |
| 67 |
– |
tmnew->clfb[BLU] = 256.*tmnew->clf[BLU] + .5; |
| 68 |
– |
tmnew->clfb[EXP] = COLXS; |
| 74 |
|
/* set gamma value */ |
| 75 |
|
if (gamval < MINGAM) |
| 76 |
|
tmnew->mongam = DEFGAM; |
| 77 |
|
else |
| 78 |
|
tmnew->mongam = gamval; |
| 79 |
< |
for (i = TM_GAMTSZ; i--; ) |
| 80 |
< |
tmnew->gamb[i] = 256.*pow((i+.5)/TM_GAMTSZ, 1./tmnew->mongam); |
| 79 |
> |
/* set color divisors */ |
| 80 |
> |
for (i = 0; i < 3; i++) |
| 81 |
> |
tmnew->cdiv[i] = 256.*pow(tmnew->clf[i], 1./tmnew->mongam); |
| 82 |
> |
|
| 83 |
|
/* set input transform */ |
| 84 |
|
tmnew->inppri = tmnew->monpri; |
| 85 |
|
tmnew->cmat[0][0] = tmnew->cmat[1][1] = tmnew->cmat[2][2] = |
| 86 |
|
tmnew->inpsf = WHTEFFICACY; |
| 80 |
– |
tmnew->inpsfb = TM_BRTSCALE*log(tmnew->inpsf) + .5; |
| 87 |
|
tmnew->cmat[0][1] = tmnew->cmat[0][2] = tmnew->cmat[1][0] = |
| 88 |
|
tmnew->cmat[1][2] = tmnew->cmat[2][0] = tmnew->cmat[2][1] = 0.; |
| 89 |
< |
tmnew->flags &= ~TM_F_NEEDMAT; |
| 84 |
< |
tmnew->brmin = tmnew->brmax = 0; |
| 89 |
> |
tmnew->hbrmin = tmnew->hbrmax = 0; |
| 90 |
|
tmnew->histo = NULL; |
| 91 |
+ |
tmnew->mbrmin = tmnew->mbrmax = 0; |
| 92 |
|
tmnew->lumap = NULL; |
| 93 |
< |
tmnew->tmprev = NULL; |
| 94 |
< |
|
| 95 |
< |
tmnew->flags |= TM_F_INITED; |
| 96 |
< |
/* make it current */ |
| 93 |
> |
/* zero private data */ |
| 94 |
> |
for (i = TM_MAXPKG; i--; ) |
| 95 |
> |
tmnew->pd[i] = NULL; |
| 96 |
> |
/* make tmnew current */ |
| 97 |
|
tmnew->tmprev = tmTop; |
| 98 |
|
return(tmTop = tmnew); |
| 99 |
|
} |
| 116 |
|
returnOK; |
| 117 |
|
tmTop->inppri = pri; /* let's set it */ |
| 118 |
|
tmTop->inpsf = sf; |
| 113 |
– |
tmTop->inpsfb = TM_BRTSCALE*log(sf) + (sf>=1. ? .5 : -.5); |
| 119 |
|
|
| 120 |
|
if (tmTop->flags & TM_F_BW) { /* color doesn't matter */ |
| 121 |
|
tmTop->monpri = tmTop->inppri; /* eliminate xform */ |
| 122 |
|
if (tmTop->inppri == TM_XYZPRIM) { |
| 123 |
|
tmTop->clf[CIEX] = tmTop->clf[CIEZ] = 0.; |
| 124 |
|
tmTop->clf[CIEY] = 1.; |
| 120 |
– |
tmTop->clfb[CIEX] = tmTop->clfb[CIEZ] = 0; |
| 121 |
– |
tmTop->clfb[CIEY] = 255; |
| 125 |
|
} else { |
| 126 |
|
comprgb2xyzmat(tmTop->cmat, tmTop->monpri); |
| 127 |
|
tmTop->clf[RED] = tmTop->cmat[1][0]; |
| 145 |
|
for (i = 0; i < 3; i++) |
| 146 |
|
for (j = 0; j < 3; j++) |
| 147 |
|
tmTop->cmat[i][j] *= tmTop->inpsf; |
| 148 |
< |
if (tmTop->inppri != tmTop->monpri) |
| 149 |
< |
tmTop->flags |= TM_F_NEEDMAT; |
| 150 |
< |
else |
| 151 |
< |
tmTop->flags &= ~TM_F_NEEDMAT; |
| 148 |
> |
/* set color divisors */ |
| 149 |
> |
for (i = 0; i < 3; i++) |
| 150 |
> |
if (tmTop->clf[i] > .001) |
| 151 |
> |
tmTop->cdiv[i] = |
| 152 |
> |
256.*pow(tmTop->clf[i], 1./tmTop->mongam); |
| 153 |
> |
else |
| 154 |
> |
tmTop->cdiv[i] = 1; |
| 155 |
> |
/* notify packages */ |
| 156 |
> |
for (i = tmNumPkgs; i--; ) |
| 157 |
> |
if (tmTop->pd[i] != NULL && tmPkg[i]->NewSpace != NULL) |
| 158 |
> |
(*tmPkg[i]->NewSpace)(tmTop); |
| 159 |
|
returnOK; |
| 160 |
|
} |
| 161 |
|
|
| 165 |
|
{ |
| 166 |
|
if (tmTop == NULL || tmTop->histo == NULL) |
| 167 |
|
return; |
| 168 |
< |
free((char *)tmTop->histo); |
| 168 |
> |
free((MEM_PTR)tmTop->histo); |
| 169 |
|
tmTop->histo = NULL; |
| 170 |
|
} |
| 171 |
|
|
| 178 |
|
int len; |
| 179 |
|
{ |
| 180 |
|
static char funcName[] = "tmCvColors"; |
| 181 |
+ |
static COLOR csmall = {1e-6, 1e-6, 1e-6}; |
| 182 |
|
COLOR cmon; |
| 183 |
|
double lum, slum; |
| 184 |
|
register double d; |
| 189 |
|
if (ls == NULL | scan == NULL | len <= 0) |
| 190 |
|
returnErr(TM_E_ILLEGAL); |
| 191 |
|
for (i = len; i--; ) { |
| 192 |
< |
if (tmTop->flags & TM_F_NEEDMAT) /* get monitor RGB */ |
| 192 |
> |
if (tmNeedMatrix(tmTop)) /* get monitor RGB */ |
| 193 |
|
colortrans(cmon, tmTop->cmat, scan[i]); |
| 194 |
|
else { |
| 195 |
|
cmon[RED] = tmTop->inpsf*scan[i][RED]; |
| 201 |
|
tmTop->clf[GRN]*cmon[GRN] + |
| 202 |
|
tmTop->clf[BLU]*cmon[BLU] ; |
| 203 |
|
/* check range */ |
| 204 |
< |
if (clipgamut(cmon, lum, CGAMUT_LOWER, cblack, cwhite)) |
| 204 |
> |
if (clipgamut(cmon, lum, CGAMUT_LOWER, csmall, cwhite)) |
| 205 |
|
lum = tmTop->clf[RED]*cmon[RED] + |
| 206 |
|
tmTop->clf[GRN]*cmon[GRN] + |
| 207 |
|
tmTop->clf[BLU]*cmon[BLU] ; |
| 234 |
|
cmon[RED] = cmon[GRN] = cmon[BLU] = lum; |
| 235 |
|
} |
| 236 |
|
d = tmTop->clf[RED]*cmon[RED]/lum; |
| 237 |
< |
/* cs[3*i ] = d>.999 ? 255 : 256.*pow(d, 1./tmTop->mongam); */ |
| 238 |
< |
cs[3*i ] = d>.999 ? 255 : tmTop->gamb[(int)(d*TM_GAMTSZ)]; |
| 237 |
> |
cs[3*i ] = d>=.999 ? 255 : |
| 238 |
> |
(int)(256.*pow(d, 1./tmTop->mongam)); |
| 239 |
|
d = tmTop->clf[GRN]*cmon[GRN]/lum; |
| 240 |
< |
/* cs[3*i+1] = d>.999 ? 255 : 256.*pow(d, 1./tmTop->mongam); */ |
| 241 |
< |
cs[3*i+1] = d>.999 ? 255 : tmTop->gamb[(int)(d*TM_GAMTSZ)]; |
| 240 |
> |
cs[3*i+1] = d>=.999 ? 255 : |
| 241 |
> |
(int)(256.*pow(d, 1./tmTop->mongam)); |
| 242 |
|
d = tmTop->clf[BLU]*cmon[BLU]/lum; |
| 243 |
< |
/* cs[3*i+2] = d>.999 ? 255 : 256.*pow(d, 1./tmTop->mongam); */ |
| 244 |
< |
cs[3*i+2] = d>.999 ? 255 : tmTop->gamb[(int)(d*TM_GAMTSZ)]; |
| 243 |
> |
cs[3*i+2] = d>=.999 ? 255 : |
| 244 |
> |
(int)(256.*pow(d, 1./tmTop->mongam)); |
| 245 |
|
} |
| 246 |
|
returnOK; |
| 247 |
|
} |
| 254 |
|
int wt; |
| 255 |
|
{ |
| 256 |
|
static char funcName[] = "tmAddHisto"; |
| 257 |
< |
int sum, oldorig, oldlen, horig, hlen; |
| 257 |
> |
int oldorig, oldlen, horig, hlen; |
| 258 |
|
register int i, j; |
| 259 |
|
|
| 260 |
|
if (len <= 0) |
| 267 |
|
; |
| 268 |
|
if (i < 0) |
| 269 |
|
returnOK; |
| 270 |
< |
tmTop->brmin = tmTop->brmax = ls[i]; |
| 270 |
> |
tmTop->hbrmin = tmTop->hbrmax = ls[i]; |
| 271 |
|
oldlen = 0; |
| 272 |
|
} else { |
| 273 |
< |
oldorig = (tmTop->brmin-MINBRT)/HISTEP; |
| 274 |
< |
oldlen = (tmTop->brmax-MINBRT)/HISTEP + 1 - oldorig; |
| 273 |
> |
oldorig = (tmTop->hbrmin-MINBRT)/HISTEP; |
| 274 |
> |
oldlen = (tmTop->hbrmax-MINBRT)/HISTEP + 1 - oldorig; |
| 275 |
|
} |
| 276 |
|
for (i = len; i--; ) { |
| 277 |
|
if ((j = ls[i]) < MINBRT) |
| 278 |
|
continue; |
| 279 |
< |
if (j < tmTop->brmin) |
| 280 |
< |
tmTop->brmin = j; |
| 281 |
< |
else if (j > tmTop->brmax) |
| 282 |
< |
tmTop->brmax = j; |
| 279 |
> |
if (j < tmTop->hbrmin) |
| 280 |
> |
tmTop->hbrmin = j; |
| 281 |
> |
else if (j > tmTop->hbrmax) |
| 282 |
> |
tmTop->hbrmax = j; |
| 283 |
|
} |
| 284 |
< |
horig = (tmTop->brmin-MINBRT)/HISTEP; |
| 285 |
< |
hlen = (tmTop->brmax-MINBRT)/HISTEP + 1 - horig; |
| 284 |
> |
horig = (tmTop->hbrmin-MINBRT)/HISTEP; |
| 285 |
> |
hlen = (tmTop->hbrmax-MINBRT)/HISTEP + 1 - horig; |
| 286 |
|
if (hlen > oldlen) { /* (re)allocate histogram */ |
| 287 |
|
register int *newhist = (int *)calloc(hlen, sizeof(int)); |
| 288 |
|
if (newhist == NULL) |
| 290 |
|
if (oldlen) { /* copy and free old */ |
| 291 |
|
for (i = oldlen, j = i+oldorig-horig; i; ) |
| 292 |
|
newhist[--j] = tmTop->histo[--i]; |
| 293 |
< |
free((char *)tmTop->histo); |
| 293 |
> |
free((MEM_PTR)tmTop->histo); |
| 294 |
|
} |
| 295 |
|
tmTop->histo = newhist; |
| 285 |
– |
if (tmTop->lumap != NULL) { /* invalid tone map */ |
| 286 |
– |
free((char *)tmTop->lumap); |
| 287 |
– |
tmTop->lumap = NULL; |
| 288 |
– |
} |
| 296 |
|
} |
| 297 |
|
if (wt == 0) |
| 298 |
|
returnOK; |
| 350 |
|
Ldmin = Ldmax/Lddyn; |
| 351 |
|
logLddyn = log(Lddyn); |
| 352 |
|
Ldavg = sqrt(Ldmax*Ldmin); |
| 353 |
< |
i = (tmTop->brmin-MINBRT)/HISTEP; |
| 353 |
> |
i = (tmTop->hbrmin-MINBRT)/HISTEP; |
| 354 |
|
brt0 = MINBRT + HISTEP/2 + i*HISTEP; |
| 355 |
< |
histlen = (tmTop->brmax-MINBRT)/HISTEP + 1 - i; |
| 355 |
> |
histlen = (tmTop->hbrmax-MINBRT)/HISTEP + 1 - i; |
| 356 |
|
/* histogram total and mean */ |
| 357 |
|
histot = 0; sum = 0; |
| 358 |
|
j = brt0 + histlen*HISTEP; |
| 378 |
|
sum += histo[i]; |
| 379 |
|
} |
| 380 |
|
cumf[i] = 1.; |
| 381 |
< |
Tr = histot * (double)(tmTop->brmax - tmTop->brmin) / |
| 381 |
> |
Tr = histot * (double)(tmTop->hbrmax - tmTop->hbrmin) / |
| 382 |
|
((double)histlen*TM_BRTSCALE) / logLddyn; |
| 383 |
|
ceiling = Tr + 1.; |
| 384 |
|
trimmings = 0; /* clip to envelope */ |
| 399 |
|
trimmings > threshold); |
| 400 |
|
} |
| 401 |
|
/* allocate luminance map */ |
| 402 |
< |
if (tmTop->lumap == NULL) { |
| 403 |
< |
tmTop->lumap = (unsigned short *)malloc( |
| 404 |
< |
(tmTop->brmax-tmTop->brmin+1)*sizeof(unsigned short) ); |
| 405 |
< |
if (tmTop->lumap == NULL) |
| 406 |
< |
returnErr(TM_E_NOMEM); |
| 407 |
< |
} |
| 402 |
> |
if (tmTop->lumap != NULL) |
| 403 |
> |
free((MEM_PTR)tmTop->lumap); |
| 404 |
> |
tmTop->mbrmin = tmTop->hbrmin; |
| 405 |
> |
tmTop->mbrmax = tmTop->hbrmax; |
| 406 |
> |
tmTop->lumap = (unsigned short *)malloc( |
| 407 |
> |
(tmTop->mbrmax-tmTop->mbrmin+1)*sizeof(unsigned short) ); |
| 408 |
> |
if (tmTop->lumap == NULL) |
| 409 |
> |
returnErr(TM_E_NOMEM); |
| 410 |
|
if (tmTop->flags & TM_F_LINEAR || histot <= threshold) { |
| 411 |
|
/* linear tone mapping */ |
| 412 |
|
if (tmTop->flags & TM_F_HCONTR) |
| 414 |
|
else |
| 415 |
|
d = Ldavg / Lwavg; |
| 416 |
|
d = log(d/Ldmax); |
| 417 |
< |
for (i = tmTop->brmax-tmTop->brmin+1; i--; ) |
| 417 |
> |
for (i = tmTop->mbrmax-tmTop->mbrmin+1; i--; ) |
| 418 |
|
tmTop->lumap[i] = 256. * exp( |
| 419 |
< |
( d + (tmTop->brmin+i)/(double)TM_BRTSCALE ) |
| 419 |
> |
( d + (tmTop->mbrmin+i)/(double)TM_BRTSCALE ) |
| 420 |
|
/ gamval ); |
| 421 |
|
} else { |
| 422 |
|
/* histogram adjustment */ |
| 423 |
< |
for (i = tmTop->brmax-tmTop->brmin+1; i--; ) { |
| 424 |
< |
j = d = (double)i/(tmTop->brmax-tmTop->brmin)*histlen; |
| 423 |
> |
for (i = tmTop->mbrmax-tmTop->mbrmin+1; i--; ) { |
| 424 |
> |
j = d = (double)i/(tmTop->mbrmax-tmTop->mbrmin)*histlen; |
| 425 |
|
d -= (double)j; |
| 426 |
|
Ld = Ldmin*exp(logLddyn*((1.-d)*cumf[j]+d*cumf[j+1])); |
| 427 |
|
d = (Ld - Ldmin)/(Ldmax - Ldmin); |
| 429 |
|
} |
| 430 |
|
} |
| 431 |
|
if (!(tmTop->flags & TM_F_LINEAR)) { |
| 432 |
< |
free((char *)histo); |
| 433 |
< |
free((char *)cumf); |
| 432 |
> |
free((MEM_PTR)histo); |
| 433 |
> |
free((MEM_PTR)cumf); |
| 434 |
|
} |
| 435 |
|
returnOK; |
| 436 |
|
} |
| 444 |
|
int len; |
| 445 |
|
{ |
| 446 |
|
static char funcName[] = "tmMapPixels"; |
| 447 |
< |
int rdiv, gdiv, bdiv; |
| 439 |
< |
register int li, pv; |
| 447 |
> |
register int4 li, pv; |
| 448 |
|
|
| 449 |
|
if (tmTop == NULL || tmTop->lumap == NULL) |
| 450 |
|
returnErr(TM_E_TMINVAL); |
| 451 |
|
if (ps == NULL | ls == NULL | len <= 0) |
| 452 |
|
returnErr(TM_E_ILLEGAL); |
| 445 |
– |
rdiv = tmTop->gamb[((int4)TM_GAMTSZ*tmTop->clfb[RED])>>8]; |
| 446 |
– |
gdiv = tmTop->gamb[((int4)TM_GAMTSZ*tmTop->clfb[GRN])>>8]; |
| 447 |
– |
bdiv = tmTop->gamb[((int4)TM_GAMTSZ*tmTop->clfb[BLU])>>8]; |
| 453 |
|
while (len--) { |
| 454 |
< |
if ((li = *ls++) < tmTop->brmin) |
| 455 |
< |
li = tmTop->brmin; |
| 456 |
< |
else if (li > tmTop->brmax) |
| 457 |
< |
li = tmTop->brmax; |
| 458 |
< |
li = tmTop->lumap[li - tmTop->brmin]; |
| 454 |
> |
if ((li = *ls++) < tmTop->mbrmin) |
| 455 |
> |
li = tmTop->mbrmin; |
| 456 |
> |
else if (li > tmTop->mbrmax) |
| 457 |
> |
li = tmTop->mbrmax; |
| 458 |
> |
li = tmTop->lumap[li - tmTop->mbrmin]; |
| 459 |
|
if (cs == TM_NOCHROM) |
| 460 |
|
*ps++ = li>255 ? 255 : li; |
| 461 |
|
else { |
| 462 |
< |
pv = *cs++ * li / rdiv; |
| 462 |
> |
pv = *cs++ * li / tmTop->cdiv[RED]; |
| 463 |
|
*ps++ = pv>255 ? 255 : pv; |
| 464 |
< |
pv = *cs++ * li / gdiv; |
| 464 |
> |
pv = *cs++ * li / tmTop->cdiv[GRN]; |
| 465 |
|
*ps++ = pv>255 ? 255 : pv; |
| 466 |
< |
pv = *cs++ * li / bdiv; |
| 466 |
> |
pv = *cs++ * li / tmTop->cdiv[BLU]; |
| 467 |
|
*ps++ = pv>255 ? 255 : pv; |
| 468 |
|
} |
| 469 |
|
} |
| 505 |
|
} |
| 506 |
|
|
| 507 |
|
|
| 508 |
+ |
struct tmStruct * |
| 509 |
+ |
tmDup() /* duplicate top tone mapping */ |
| 510 |
+ |
{ |
| 511 |
+ |
int len; |
| 512 |
+ |
register int i; |
| 513 |
+ |
register struct tmStruct *tmnew; |
| 514 |
+ |
|
| 515 |
+ |
if (tmTop == NULL) /* anything to duplicate? */ |
| 516 |
+ |
return(NULL); |
| 517 |
+ |
tmnew = (struct tmStruct *)malloc(sizeof(struct tmStruct)); |
| 518 |
+ |
if (tmnew == NULL) |
| 519 |
+ |
return(NULL); |
| 520 |
+ |
*tmnew = *tmTop; /* copy everything */ |
| 521 |
+ |
if (tmnew->histo != NULL) { /* duplicate histogram */ |
| 522 |
+ |
len = (tmnew->hbrmax-MINBRT)/HISTEP + 1 - |
| 523 |
+ |
(tmnew->hbrmin-MINBRT)/HISTEP; |
| 524 |
+ |
tmnew->histo = (int *)malloc(len*sizeof(int)); |
| 525 |
+ |
if (tmnew->histo != NULL) |
| 526 |
+ |
for (i = len; i--; ) |
| 527 |
+ |
tmnew->histo[i] = tmTop->histo[i]; |
| 528 |
+ |
} |
| 529 |
+ |
if (tmnew->lumap != NULL) { /* duplicate luminance mapping */ |
| 530 |
+ |
len = tmnew->mbrmax-tmnew->mbrmin+1; |
| 531 |
+ |
tmnew->lumap = (unsigned short *)malloc( |
| 532 |
+ |
len*sizeof(unsigned short) ); |
| 533 |
+ |
if (tmnew->lumap != NULL) |
| 534 |
+ |
for (i = len; i--; ) |
| 535 |
+ |
tmnew->lumap[i] = tmTop->lumap[i]; |
| 536 |
+ |
} |
| 537 |
+ |
/* clear package data */ |
| 538 |
+ |
for (i = tmNumPkgs; i--; ) |
| 539 |
+ |
tmnew->pd[i] = NULL; |
| 540 |
+ |
tmnew->tmprev = tmTop; /* make copy current */ |
| 541 |
+ |
return(tmTop = tmnew); |
| 542 |
+ |
} |
| 543 |
+ |
|
| 544 |
+ |
|
| 545 |
|
int |
| 546 |
|
tmPush(tms) /* push tone mapping on top of stack */ |
| 547 |
|
register struct tmStruct *tms; |
| 548 |
|
{ |
| 549 |
|
static char funcName[] = "tmPush"; |
| 550 |
|
/* check validity */ |
| 551 |
< |
if (tms == NULL || !(tms->flags & TM_F_INITED)) |
| 551 |
> |
if (tms == NULL) |
| 552 |
|
returnErr(TM_E_ILLEGAL); |
| 553 |
|
if (tms == tmTop) /* check necessity */ |
| 554 |
|
returnOK; |
| 565 |
|
tmDone(tms) /* done with tone mapping -- destroy it */ |
| 566 |
|
register struct tmStruct *tms; |
| 567 |
|
{ |
| 568 |
+ |
register int i; |
| 569 |
|
/* NULL arg. is equiv. to tmTop */ |
| 570 |
|
if (tms == NULL && (tms = tmTop) == NULL) |
| 571 |
|
return; |
| 573 |
|
(void)tmPull(tms); |
| 574 |
|
/* free tables */ |
| 575 |
|
if (tms->histo != NULL) |
| 576 |
< |
free((char *)tms->histo); |
| 576 |
> |
free((MEM_PTR)tms->histo); |
| 577 |
|
if (tms->lumap != NULL) |
| 578 |
< |
free((char *)tms->lumap); |
| 579 |
< |
tms->flags = 0; |
| 580 |
< |
free((char *)tms); /* free basic structure */ |
| 578 |
> |
free((MEM_PTR)tms->lumap); |
| 579 |
> |
/* free private data */ |
| 580 |
> |
for (i = tmNumPkgs; i--; ) |
| 581 |
> |
if (tms->pd[i] != NULL) |
| 582 |
> |
(*tmPkg[i]->Free)(tms->pd[i]); |
| 583 |
> |
free((MEM_PTR)tms); /* free basic structure */ |
| 584 |
|
} |