FUNC_STATUS WORD mat_setXformSpec ( IP_XFORM_HANDLE hXform, /* in: handle for xform */ DWORD_OR_PVOID aXformInfo[]) /* in: xform information */ { PMAT_INST g; int *ptr; HANDLE_TO_PTR (hXform, g); ptr = (int*)aXformInfo[0].pvoid; INSURE (ptr != NULL); memcpy (g->mat, ptr, sizeof(g->mat)); return IP_DONE; fatal_error: return IP_FATAL_ERROR; }
FUNC_STATUS WORD pnm_setDefaultInputTraits ( IP_XFORM_HANDLE hXform, /* in: handle for xform */ PIP_IMAGE_TRAITS pTraits) /* in: default image traits */ { PPNM_INST g; HANDLE_TO_PTR (hXform, g); g->traits = *pTraits; /* a structure copy */ if (g->fIsEncode) { /* insure that traits we care about are known */ INSURE (pTraits->iPixelsPerRow>0 && pTraits->iBitsPerPixel>0); g->dwBytesPerRow = (g->traits.iPixelsPerRow*g->traits.iBitsPerPixel + 7) / 8; } return IP_DONE; fatal_error: return IP_FATAL_ERROR; }
FUNC_STATUS WORD fakeMono_setDefaultInputTraits ( IP_XFORM_HANDLE hXform, /* in: handle for xform */ PIP_IMAGE_TRAITS pTraits) /* in: default image traits */ { PFMON_INST g; HANDLE_TO_PTR (hXform, g); /* insure that traits we care about are known */ INSURE (pTraits->iPixelsPerRow > 0 && pTraits->iBitsPerPixel == 24 && pTraits->iComponentsPerPixel == 3); g->traits = *pTraits; /* a structure copy */ g->dwBytesPerRow = (g->traits.iPixelsPerRow*g->traits.iBitsPerPixel + 7) / 8; return IP_DONE; fatal_error: return IP_FATAL_ERROR; }
EXPORT(WORD) ipGetFuncPtrs (LPIP_JUMP_TBL lpJumpTbl) { PRINT0 (_T("ipGetFuncPtrs\n")); INSURE (lpJumpTbl!=NULL && lpJumpTbl->wStructSize==sizeof(IP_JUMP_TBL)); lpJumpTbl->ipOpen = (LPVOID) ipOpen; lpJumpTbl->ipConvert = (LPVOID) ipConvert; lpJumpTbl->ipClose = (LPVOID) ipClose; lpJumpTbl->ipGetClientDataPtr = (LPVOID) ipGetClientDataPtr; lpJumpTbl->ipResultMask = (LPVOID) ipResultMask; lpJumpTbl->ipSetDefaultInputTraits = (LPVOID) ipSetDefaultInputTraits; lpJumpTbl->ipGetImageTraits = (LPVOID) ipGetImageTraits; lpJumpTbl->ipInsertedData = (LPVOID) ipInsertedData; lpJumpTbl->ipOverrideDPI = (LPVOID) ipOverrideDPI; lpJumpTbl->ipGetOutputTraits = (LPVOID) ipGetOutputTraits; return IP_DONE; fatal_error: return IP_FATAL_ERROR; }
FUNC_STATUS WORD invert_setDefaultInputTraits ( IP_XFORM_HANDLE hXform, /* in: handle for xform */ PIP_IMAGE_TRAITS pTraits) /* in: default image traits */ { PINVERT_INST g; HANDLE_TO_PTR (hXform, g); /* insure that traits we care about are known */ INSURE (pTraits->iPixelsPerRow>0 && pTraits->iBitsPerPixel>0); g->traits = *pTraits; /* a structure copy */ g->dwBytesPerRow = (g->traits.iPixelsPerRow*g->traits.iBitsPerPixel + 7) / 8; if (pTraits->iBitsPerPixel>3) { g->dwAddToNot=1; } else { g->dwAddToNot=0; } return IP_DONE; fatal_error: return IP_FATAL_ERROR; }
EXPORT(WORD) ipSetDefaultInputTraits ( IP_HANDLE hJob, /* in: handle to conversion job */ LPIP_IMAGE_TRAITS pTraits) /* in: default image traits */ { PINST g; PIP_IMAGE_TRAITS p; PRINT0 (_T("ipSetDefaultInputTraits: hJob=%p PixelsPerRow=%d BitsPerPixel=%d ComponentsPerPixel=%d HorzDPI=%ld VertDPI=%ld Rows=%ld Pages=%d PageNum=%d\n"), (void*)hJob, pTraits->iPixelsPerRow, pTraits->iBitsPerPixel, pTraits->iComponentsPerPixel, pTraits->lHorizDPI, pTraits->lVertDPI, pTraits->lNumRows, pTraits->iNumPages, pTraits->iPageNum); HANDLE_TO_PTR (hJob, g); INSURE (g->xfArray[0].eState == XS_NONEXISTENT); g->xfArray[0].inTraits = *pTraits; /* a structure copy */ /* Convert DPI from integer to 16.16 fixed-pt if necessary */ p = &(g->xfArray[0].inTraits); if (p->lHorizDPI < 0x10000) p->lHorizDPI <<= 16; if (p->lVertDPI < 0x10000) p->lVertDPI <<= 16; return IP_DONE; fatal_error: return IP_FATAL_ERROR; }
static WORD table_convert ( IP_XFORM_HANDLE hXform, DWORD dwInputAvail, /* in: # avail bytes in in-buf */ PBYTE pbInputBuf, /* in: ptr to in-buffer */ PDWORD pdwInputUsed, /* out: # bytes used from in-buf */ PDWORD pdwInputNextPos, /* out: file-pos to read from next */ DWORD dwOutputAvail, /* in: # avail bytes in out-buf */ PBYTE pbOutputBuf, /* in: ptr to out-buffer */ PDWORD pdwOutputUsed, /* out: # bytes written in out-buf */ PDWORD pdwOutputThisPos) /* out: file-pos to write the data */ { PTBL_INST g; int nBytes, nTable; PBYTE pIn, pOut, pOutAfter; HANDLE_TO_PTR (hXform, g); /**** Check if we were told to flush ****/ if (pbInputBuf == NULL) { PRINT (_T("table_convert: Told to flush.\n"), 0, 0); *pdwInputUsed = *pdwOutputUsed = 0; *pdwInputNextPos = g->dwInNextPos; *pdwOutputThisPos = g->dwOutNextPos; return IP_DONE; } /**** Output a Row ****/ nBytes = g->dwBytesPerRow; INSURE (dwInputAvail >= (DWORD)nBytes); INSURE (dwOutputAvail >= (DWORD)nBytes); pIn = pbInputBuf; pOut = pbOutputBuf; pOutAfter = pOut + nBytes; if (g->bWhich == IP_TABLE_PASS_THRU) { memcpy (pOut, pIn, nBytes); } else if (g->traits.iBitsPerPixel==16 || g->traits.iBitsPerPixel==48) { /* 16 bits per channel -- interpolate between table-entries */ int x, xHi, y1, y2; WORD *pwTable, *pwIn, *pwOut, *pwOutAfter; BYTE *pbTable; pwIn = (WORD*)pIn; pwOut = (WORD*)pOut; pwOutAfter = (WORD*)pOutAfter; if (g->bBigTable) { /* we're using 12-bit table(s) */ while (pwOut < pwOutAfter) { for (nTable=0; nTable<g->nTables; nTable++) { pwTable = g->pwTables[nTable]; x = (unsigned)(*pwIn++); xHi = x >> 4; /* hi 12 bits is used for indexing into the table */ y1 = (unsigned)pwTable[xHi ]; /* index is in 0..4095 */ y2 = (unsigned)pwTable[xHi+1]; /* extra entry in table is for index=4096 */ /* interpolate the lowest 4 bits */ *pwOut++ = (WORD)(((y2-y1)*(x&0x0f)>>4) + y1); } } } else /* we're using 8-bit table(s) */ { while (pwOut < pwOutAfter) {
EXPORT(WORD) ipConvert ( IP_HANDLE hJob, /* in: handle to conversion job */ DWORD dwInputAvail, /* in: # avail bytes in input buf */ PBYTE pbInputBuf, /* in: ptr to input buffer */ PDWORD pdwInputUsed, /* out: # bytes used from input buf */ PDWORD pdwInputNextPos, /* out: file-pos to read from next */ DWORD dwOutputAvail, /* in: # avail bytes in output buf */ PBYTE pbOutputBuf, /* in: ptr to output buffer */ PDWORD pdwOutputUsed, /* out: # bytes written in out buf */ PDWORD pdwOutputThisPos) /* out: file-pos to write this data */ { PINST g; WORD ipResult; int iXform; WORD result; PGENBUF pgbIn, pgbOut; BOOL atTheHead, atTheTail; PXFORM_INFO pXform, pPriorXform, pNextXform; BOOL needInput, selectCnvState; DWORD dwBytes; int i; DWORD n; DWORD dwInUsed, dwOutUsed; DWORD dwInNextPos, dwOutThisPos; DWORD dwTheInLen, dwTheOutLen; PBYTE pbTemp; PBYTE pbTheInBuf, pbTheOutBuf; DWORD dwJunk; if (pbOutputBuf == NULL) { /* client wants us to discard all data */ pdwOutputUsed = &dwJunk; pdwOutputThisPos = &dwJunk; dwOutputAvail = 0xfffffffu; } PRINT0 (_T("ipConvert: hJob=%p, pbInputBuf=%p InputBufSize=%d pbOutputBuf=%p OutputBufSize=%d\n"), (void*)hJob, pbInputBuf, dwInputAvail, pbOutputBuf, dwOutputAvail); INSURE (pdwInputUsed !=NULL && pdwInputNextPos !=NULL && pdwOutputUsed!=NULL && pdwOutputThisPos!=NULL); HANDLE_TO_PTR (hJob, g); INSURE (g->xfCount>=1); pgbIn = &g->gbIn; pgbOut = &g->gbOut; *pdwInputUsed = 0; *pdwOutputUsed = 0; ipResult = 0; /**************************/ /* Beginning of Main Loop */ /**************************/ while (TRUE) { /**** Output any data in the output genbuf ****/ if (*pdwOutputUsed == 0) *pdwOutputThisPos = pgbOut->dwFilePos; if (pgbOut->dwValidLen != 0) { /* output genbuf is not empty */ /* Logic below: * * 1. If next output file-pos doesn't match output genbuf, exit loop. * * 2. Copy as much as possible from output genbuf to clients output buf. * 2.1 decide number of bytes to copy * 2.2 copy them * 2.3 update misc variables * * 3. If output genbuf is not empty, exit loop (client's buf is full), * else set wValidStart to 0 because output genbuf is empty. */ if ((*pdwOutputThisPos+*pdwOutputUsed) != pgbOut->dwFilePos) { PRINT0 (_T("ipConvert: output seek to %d\n"), pgbOut->dwFilePos); goto exitLoop; } dwBytes = pgbOut->dwValidLen; if (dwOutputAvail < dwBytes) dwBytes = dwOutputAvail; if (pbOutputBuf != NULL) { memcpy (pbOutputBuf + *pdwOutputUsed, pgbOut->pbBuf + pgbOut->dwValidStart, dwBytes); } *pdwOutputUsed += dwBytes; dwOutputAvail -= dwBytes; pgbOut->dwValidStart += dwBytes; pgbOut->dwFilePos += dwBytes; pgbOut->dwValidLen -= dwBytes; if (pgbOut->dwValidLen != 0) goto exitLoop; pgbOut->dwValidStart = 0; /* output genbuf is now empty */ } if (g->pendingInsert) { g->pendingInsert = FALSE; ipResult |= IP_WRITE_INSERT_OK; } /**** If ipResult has any returnable bits set, exit loop now ****/ if (ipResult & g->wResultMask) goto exitLoop; /**** Select an xform to run ****/ /* select the owner of input midbuf, or negative means 'none selected' */ iXform = g->iOwner; if (iXform < 0) { for (i=g->xfCount-1; i>=0; i--) { if (g->xfArray[i].eState == XS_CONV_NOT_RFD) { /* select last xform that's convnotrfd; this xform * is outputting (or thinking) but not inputting */ iXform = i; break; } } } if (iXform < 0) { for (i=0; i<g->xfCount; i++) { if (g->xfArray[i].eState != XS_DONE) { /* select first xform that's not done */ iXform = i; break; } } } if (iXform < 0) { /* all xforms are done: discard all input, and report that we're done */ *pdwInputUsed = dwInputAvail; ipResult |= IP_DONE; /* patch the last outtraits with actual # of rows output, so that * ipGetImageTraits will return actual row-count after we're done */ g->xfArray[g->xfCount-1].outTraits.lNumRows = g->lOutRows; /* patch first intraits for the same reason */ g->xfArray[0].inTraits.lNumRows = g->lInRows; goto exitLoop; } /**** Miscellaneous preparation ****/ pXform = &(g->xfArray[iXform]); atTheHead = (iXform == 0); atTheTail = (iXform == g->xfCount-1); pPriorXform = atTheHead ? NULL : &(g->xfArray[iXform-1]); pNextXform = atTheTail ? NULL : &(g->xfArray[iXform+1]); /**** Create the Xform if necessary ****/ if (pXform->eState == XS_NONEXISTENT) { PRINT0 (_T("ipConvert: creating xform %d\n"), iXform); INSURE (atTheHead || pPriorXform->eState>=XS_CONVERTING); if (atTheHead) { /* this xform's input traits were set by ipSetDefaultInputTraits */ } else { /* this xform's input traits are prior xform's output traits */ memcpy (&pXform->inTraits, &pPriorXform->outTraits, sizeof(IP_IMAGE_TRAITS)); if (atTheTail) { /* apply any DPI overrides */ if (g->dwForcedHorizDPI != 0) pXform->inTraits.lHorizDPI = (long)g->dwForcedHorizDPI; if (g->dwForcedVertDPI != 0) pXform->inTraits.lVertDPI = (long)g->dwForcedVertDPI; } } result = pXform->pXform->openXform (&pXform->hXform); INSURE (result == IP_DONE); result = pXform->pXform->setDefaultInputTraits ( pXform->hXform, &pXform->inTraits); INSURE (result == IP_DONE); result = pXform->pXform->setXformSpec ( pXform->hXform, pXform->aXformInfo); INSURE (result == IP_DONE); result = pXform->pXform->getHeaderBufSize ( pXform->hXform, &pXform->dwMinInBufLen); INSURE (result == IP_DONE); if (! atTheHead) { /* a header is only allowed on first xform */ INSURE (pXform->dwMinInBufLen == 0); } else { /* allocate the input genbuf */ if (pXform->dwMinInBufLen == 0) pXform->dwMinInBufLen = 1; PRINT0 (_T("ipConvert: alloc input genbuf, len=%d\n"), pXform->dwMinInBufLen); IP_MEM_ALLOC (pXform->dwMinInBufLen, pgbIn->pbBuf); pgbIn->dwBufLen = pXform->dwMinInBufLen; pgbIn->dwValidStart = 0; pgbIn->dwValidLen = 0; pgbIn->dwFilePos = 0; } pXform->eState = XS_PARSING_HEADER; } /**** Enter flushing state if appropriate ****/ if (pXform->eState == XS_CONVERTING && (( atTheHead && pbInputBuf==NULL && pgbIn->dwValidLen==0) || (!atTheHead && pPriorXform->eState==XS_DONE && g->iOwner<0))) { /* there will never be any more input to this xform: start flushing */ PRINT0 (_T("ipConvert: xform %d is now flushing\n"), iXform); pXform->eState = XS_FLUSHING; } /**** Check that input data and output space are available ****/ needInput = (pXform->eState==XS_PARSING_HEADER || pXform->eState==XS_CONVERTING); if (needInput) { if (! atTheHead) { /* the input midbuf must contain data */ INSURE (g->iOwner>=0 && g->dwMidValidLen>0); PRINT1 (_T("not at head, pixels = %08x\n"), *(DWORD*)(g->pbMidInBuf)); } else if (pbInputBuf != NULL) { DWORD dwUnusedStart; /* left-justify data in input genbuf if necessary */ if (pgbIn->dwBufLen-pgbIn->dwValidStart < pXform->dwMinInBufLen) { /* too much wasted space on left end, so left justify */ memmove (pgbIn->pbBuf, pgbIn->pbBuf + pgbIn->dwValidStart, pgbIn->dwValidLen); pgbIn->dwValidStart = 0; PRINT1 (_T("left just, pixels = %08x\n"), *(DWORD*)(pgbIn->pbBuf)); } /* put as much client input as possible into the input genbuf */ dwUnusedStart = pgbIn->dwValidStart + pgbIn->dwValidLen; dwBytes = pgbIn->dwBufLen - dwUnusedStart; if (dwBytes > dwInputAvail) dwBytes = dwInputAvail; memcpy (pgbIn->pbBuf + dwUnusedStart, pbInputBuf + *pdwInputUsed, dwBytes); pgbIn->dwValidLen += dwBytes; *pdwInputUsed += dwBytes; dwInputAvail -= dwBytes; *pdwInputNextPos += dwBytes; /* if input genbuf has insufficient data, exit loop */ if (pgbIn->dwValidLen < pXform->dwMinInBufLen) goto exitLoop; PRINT1 (_T("at head, pixels = %08x\n"), *(DWORD*)(pgbIn->pbBuf)); } } if (atTheTail && pXform->eState!=XS_PARSING_HEADER) { /* output might be produced; output genbuf must be empty */ INSURE (pgbOut->dwValidLen == 0); } /**** Call the Conversion Routine ****/ pbTheInBuf = atTheHead ? pgbIn->pbBuf + pgbIn->dwValidStart : g->pbMidInBuf; dwTheInLen = atTheHead ? pgbIn->dwValidLen : g->dwMidValidLen; pbTheOutBuf = atTheTail ? pgbOut->pbBuf : g->pbMidOutBuf; dwTheOutLen = atTheTail ? pgbOut->dwBufLen : g->dwMidLen; if (pXform->eState == XS_PARSING_HEADER) { result = pXform->pXform->getActualTraits ( pXform->hXform, dwTheInLen, pbTheInBuf, &dwInUsed, &dwInNextPos, &pXform->inTraits, &pXform->outTraits); dwOutUsed = 0; dwOutThisPos = 0; } else { if (pXform->eState == XS_FLUSHING) pbTheInBuf = NULL; result = pXform->pXform->convert ( pXform->hXform, dwTheInLen, pbTheInBuf, &dwInUsed, &dwInNextPos, dwTheOutLen, pbTheOutBuf, &dwOutUsed, &dwOutThisPos); } PRINT1 (_T("ipConvert: xform %d returned %04x\n"), iXform, result); PRINT1 (_T("ipConvert: consumed %d and produced %d bytes\n"), dwInUsed, dwOutUsed); if (pbTheOutBuf != NULL) PRINT1 (_T("ipConvert: out data = %08x\n"), *(DWORD*)pbTheOutBuf); INSURE ((result & IP_FATAL_ERROR) == 0); /**** Update Input and Output Buffers ****/ if (dwInUsed > 0) { if (pXform->pfReadPeek != NULL) { #if defined _WIN32 __try { #endif pXform->pfReadPeek (hJob, &(pXform->inTraits), dwInUsed, pbTheInBuf, pgbIn->dwFilePos, pXform->pUserData); #if defined _WIN32 } __except (EXCEPTION_EXECUTE_HANDLER) { goto fatal_error; } #endif } if (! atTheHead) { /* We _assume_ that the xform consumed all the data in the midbuf */ g->iOwner = -1; /* input midbuf is consumed and un-owned now */ g->dwMidValidLen = 0; } } if (needInput && atTheHead) { if (dwInUsed >= pgbIn->dwValidLen) { /* consumed all input; mark input genbuf as empty */ pgbIn->dwValidLen = 0; pgbIn->dwValidStart = 0; pgbIn->dwFilePos = dwInNextPos; } else { /* advance counters in genbuf */ pgbIn->dwValidLen -= dwInUsed; pgbIn->dwValidStart += dwInUsed; pgbIn->dwFilePos += dwInUsed; } /* if new genbuf file-pos doesn't match what xform wants, * discard remainder of buffer */ if (pgbIn->dwFilePos != dwInNextPos) { PRINT0 (_T("ipConvert: input seek to %d\n"), dwInNextPos); pgbIn->dwValidLen = 0; pgbIn->dwValidStart = 0; pgbIn->dwFilePos = dwInNextPos; } } if (dwOutUsed > 0) { if (pXform->pfWritePeek != NULL) { #if defined _WIN32 __try { #endif pXform->pfWritePeek (hJob, &(pXform->outTraits), dwOutUsed, pbTheOutBuf, dwOutThisPos, pXform->pUserData); #if defined _WIN32 } __except (EXCEPTION_EXECUTE_HANDLER) { goto fatal_error; } #endif } if (atTheTail) { pgbOut->dwFilePos = dwOutThisPos; pgbOut->dwValidStart = 0; pgbOut->dwValidLen = dwOutUsed; } else { INSURE (g->iOwner < 0); /* mid inbuf must be unowned here */ g->iOwner = iXform + 1; /* next xform hereby owns mid inbuf */ /* swap input and output midbuf pointers */ pbTemp = g->pbMidInBuf; g->pbMidInBuf = g->pbMidOutBuf; g->pbMidOutBuf = pbTemp; g->dwMidValidLen = dwOutUsed; } }
EXPORT(WORD) ipOpen ( int nXforms, /* in: number of xforms in lpXforms below */ LPIP_XFORM_SPEC lpXforms, /* in: the xforms we should perform */ int nClientData, /* in: # bytes of additional client data */ PIP_HANDLE phJob) /* out: handle for conversion job */ { PINST g; int i; PIP_XFORM_SPEC src; PXFORM_INFO dest; #ifdef HPIP_DEBUG char *ipIn = "/tmp/ipIn.dib"; #endif PRINT0 (_T("ipOpen: nXforms=%d\n"), nXforms); INSURE (nXforms>0 && lpXforms!=NULL && nClientData>=0 && phJob!=NULL); #ifdef HPIP_DEBUG for (i=0; i<nXforms; i++) { switch (lpXforms[i].eXform) { case X_FAX_DECODE: PRINT0("Fax_format=%d\n", lpXforms[i].aXformInfo[IP_FAX_FORMAT].dword); ipIn = "/tmp/ipIn.pbm"; break; case X_JPG_DECODE: PRINT0("JPG_decode=%d\n", lpXforms[i].aXformInfo[IP_JPG_DECODE_FROM_DENALI].dword); ipIn = "/tmp/ipIn.jpg"; break; case X_CNV_COLOR_SPACE: PRINT0("Color_space conversion=%d\n", lpXforms[i].aXformInfo[IP_CNV_COLOR_SPACE_WHICH_CNV].dword); PRINT0("Color_space gamma=%d\n", lpXforms[i].aXformInfo[IP_CNV_COLOR_SPACE_GAMMA].dword); break; case X_CROP: PRINT0("Crop_left=%d\n", lpXforms[i].aXformInfo[IP_CROP_LEFT].dword); PRINT0("Crop_right=%d\n", lpXforms[i].aXformInfo[IP_CROP_RIGHT].dword); PRINT0("Crop_top=%d\n", lpXforms[i].aXformInfo[IP_CROP_TOP].dword); PRINT0("Crop_maxoutrows=%d\n", lpXforms[i].aXformInfo[IP_CROP_MAXOUTROWS].dword); break; case X_PAD: PRINT0("Pad_left=%d\n", lpXforms[i].aXformInfo[IP_PAD_LEFT].dword); PRINT0("Pad_right=%d\n", lpXforms[i].aXformInfo[IP_PAD_RIGHT].dword); PRINT0("Pad_top=%d\n", lpXforms[i].aXformInfo[IP_PAD_TOP].dword); PRINT0("Pad_bottom=%d\n", lpXforms[i].aXformInfo[IP_PAD_BOTTOM].dword); PRINT0("Pad_value=%d\n", lpXforms[i].aXformInfo[IP_PAD_VALUE].dword); PRINT0("Pad_minheight=%d\n", lpXforms[i].aXformInfo[IP_PAD_MIN_HEIGHT].dword); break; default: PRINT0("Unknown xform\n"); break; } } infd = creat(ipIn, 0600); outfd = creat("/tmp/ipOut.ppm", 0600); #endif /**** Create Instance and Init Misc Variables ****/ IP_MEM_ALLOC (sizeof(INST) + nClientData, g); *phJob = g; memset (g, 0, sizeof(INST)); g->dwValidChk = CHECK_VALUE; g->iOwner = -1; g->wResultMask = PERMANENT_RESULTS; /**** Transfer the Xforms to xfArray ****/ g->xfCount = (WORD)nXforms; for (i=0; i<nXforms; i++) { src = &(lpXforms[i]); dest = &(g->xfArray[i]); dest->eState = XS_NONEXISTENT; dest->pXform = (src->pXform != NULL) ? src->pXform : xformJumpTables[src->eXform]; INSURE (dest->pXform != NULL); dest->pfReadPeek = src->pfReadPeek; dest->pfWritePeek = src->pfWritePeek; dest->pUserData = src->pUserData; memcpy (dest->aXformInfo, src->aXformInfo, sizeof(dest->aXformInfo)); } return IP_DONE; fatal_error: return IP_FATAL_ERROR; }
static WORD tonemap_convert ( IP_XFORM_HANDLE hXform, DWORD dwInputAvail, /* in: # avail bytes in in-buf */ PBYTE pbInputBuf, /* in: ptr to in-buffer */ PDWORD pdwInputUsed, /* out: # bytes used from in-buf */ PDWORD pdwInputNextPos, /* out: file-pos to read from next */ DWORD dwOutputAvail, /* in: # avail bytes in out-buf */ PBYTE pbOutputBuf, /* in: ptr to out-buffer */ PDWORD pdwOutputUsed, /* out: # bytes written in out-buf */ PDWORD pdwOutputThisPos) /* out: file-pos to write the data */ { PTMAP_INST g; int nBytes; PBYTE pIn, pOut, pOutAfter; HANDLE_TO_PTR (hXform, g); /**** Check if we were told to flush ****/ if (pbInputBuf == NULL) { PRINT (_T("tonemap_convert: Told to flush.\n"), 0, 0); *pdwInputUsed = *pdwOutputUsed = 0; *pdwInputNextPos = g->dwInNextPos; *pdwOutputThisPos = g->dwOutNextPos; return IP_DONE; } /**** Output a Row ****/ nBytes = g->dwBytesPerRow; INSURE (dwInputAvail >= (DWORD)nBytes ); INSURE (dwOutputAvail >= (DWORD)nBytes); pIn = pbInputBuf; pOut = pbOutputBuf; pOutAfter = pOut + nBytes; if (g->traits.iBitsPerPixel == 8) { /* easiest case */ while (pOut < pOutAfter) { *pOut++ = g->tonemap[*pIn++]; } } else if (g->traits.iBitsPerPixel == 24) { if (g->bLumSpace) { /* easy case: 24-bit color in a luminance space */ while (pOut < pOutAfter) { *pOut = g->tonemap[*pIn]; pIn += 3; pOut += 3; } } else { /* 24-bit color in RGB */ int rv, gv, bv; int l_old, l_new, dl; while (pOut < pOutAfter) { rv = *pIn++; gv = *pIn++; bv = *pIn++; l_old = NTSC_LUMINANCE (rv, gv, bv); l_new = g->tonemap[l_old]; /* new luminance */ dl = l_new - l_old; rv += dl; gv += dl; bv += dl; if (rv > 255) rv = 255; else if (rv < 0) rv = 0; if (gv > 255) gv = 255; else if (gv < 0) gv = 0; if (bv > 255) bv = 255; else if (bv < 0) bv = 0; *pOut++ = (BYTE)rv; *pOut++ = (BYTE)gv; *pOut++ = (BYTE)bv; } } } else { /* 48 bits/pixel */ PWORD src = (PWORD)pIn; PWORD dst = (PWORD)pOut; PWORD dstAfter = (PWORD)pOutAfter; int rv, gv, bv; int l_old, l_old8, l_new1, l_new2, l_new, dl; while (dst < dstAfter) { rv = *src++; gv = *src++; bv = *src++; /* use linear interpolation between tonemap entries * to compute new luminance (l_new) */ l_old = g->bLumSpace ? rv : NTSC_LUMINANCE (rv, gv, bv); l_old8 = l_old >> 8; l_new1 = g->tonemap[l_old8]; l_new2 = l_old8<255 ? g->tonemap[l_old8+1] : l_new1; l_new = (l_new2-l_new1)*(l_old&0x00ff) + (l_new1<<8); dl = l_new - l_old; rv += dl; if (rv > 65535) rv = 65535; else if (rv < 0) rv = 0; if (! g->bLumSpace) { gv += dl; bv += dl; if (gv > 65535) gv = 65535; else if (gv < 0) gv = 0; if (bv > 65535) bv = 65535; else if (bv < 0) bv = 0; } *dst++ = (WORD)rv; *dst++ = (WORD)gv; *dst++ = (WORD)bv; } } *pdwInputUsed = nBytes; g->dwInNextPos += nBytes; *pdwInputNextPos = g->dwInNextPos; *pdwOutputUsed = nBytes; *pdwOutputThisPos = g->dwOutNextPos; g->dwOutNextPos += nBytes; g->dwRowsDone += 1; return IP_CONSUMED_ROW | IP_PRODUCED_ROW | IP_READY_FOR_DATA; fatal_error: return IP_FATAL_ERROR; }
static WORD thumb_convert ( IP_XFORM_HANDLE hXform, DWORD dwInputAvail, /* in: # avail bytes in in-buf */ PBYTE pbInputBuf, /* in: ptr to in-buffer */ PDWORD pdwInputUsed, /* out: # bytes used from in-buf */ PDWORD pdwInputNextPos, /* out: file-pos to read from next */ DWORD dwOutputAvail, /* in: # avail bytes in out-buf */ PBYTE pbOutputBuf, /* in: ptr to out-buffer */ PDWORD pdwOutputUsed, /* out: # bytes written in out-buf */ PDWORD pdwOutputThisPos) /* out: file-pos to write the data */ { PTN_INST g; PBYTE pIn, pOut; BYTE bMask, bVal=0; ULONG ulSum, sum0, sum1, sum2; ULONG *pulSum, *pulSumAfter; UINT u; BOOL fSentRow; HANDLE_TO_PTR (hXform, g); pulSumAfter = g->pulSums + g->dwOutRowBytes; /**** Check if we were told to flush ****/ if (pbInputBuf == NULL) { PRINT (_T("thumb_convert: Told to flush.\n"), 0, 0); *pdwInputUsed = *pdwOutputUsed = 0; *pdwInputNextPos = g->dwInNextPos; *pdwOutputThisPos = g->dwOutNextPos; return IP_DONE; } /**** Sum this Input Row ****/ INSURE (dwInputAvail >= g->dwInRowBytes); pIn = pbInputBuf; switch (g->inTraits.iBitsPerPixel) { case 1: /* bilevel input */ bMask = 0; for (pulSum=g->pulSums; pulSum<pulSumAfter; pulSum++) { ulSum = *pulSum; for (u=g->wScale; u>0; u--) { if (bMask == 0) { bMask = 0x80u; bVal = *pIn++; } if ((bMask & bVal) == 0) { /* since the sum is a measure of overall whiteness, * increment it for a *white* input pixel (0) */ ulSum += 1; } bMask >>= 1; } *pulSum = ulSum; } break; case 8: /* 8-bit gray input */ for (pulSum=g->pulSums; pulSum<pulSumAfter; pulSum++) { ulSum = *pulSum; for (u=g->wScale; u>0; u--) ulSum += (ULONG)(*pIn++); *pulSum = ulSum; } break; case 24: /* 3-component color input */ for (pulSum=g->pulSums; pulSum<pulSumAfter; pulSum+=3) { sum0 = pulSum[0]; sum1 = pulSum[1]; sum2 = pulSum[2]; for (u=g->wScale; u>0; u--) { sum0 += (ULONG)(*pIn++); sum1 += (ULONG)(*pIn++); sum2 += (ULONG)(*pIn++); } pulSum[0] = sum0; pulSum[1] = sum1; pulSum[2] = sum2; } break; } /* switch */ *pdwInputUsed = g->dwInRowBytes; g->dwInNextPos += g->dwInRowBytes; *pdwInputNextPos = g->dwInNextPos; g->ulRowsInput += 1; /**** If it's time, Compute Output Row ****/ *pdwOutputThisPos = g->dwOutNextPos; g->wMoreRows2Sum -= 1; if (g->wMoreRows2Sum > 0) { fSentRow = FALSE; *pdwOutputUsed = 0; } else { g->wMoreRows2Sum = g->wScale; fSentRow = TRUE; g->ulRowsOutput += 1; INSURE (dwOutputAvail >= g->dwOutRowBytes); *pdwOutputUsed = g->dwOutRowBytes; g->dwOutNextPos += g->dwOutRowBytes; pulSum = g->pulSums; pOut = pbOutputBuf; for (pulSum=g->pulSums; pulSum<pulSumAfter; pulSum++) { *pOut++ = (BYTE)((*pulSum >> g->wPreShift) * g->dwSumFac >> 16); } memset (g->pulSums, 0, g->dwOutRowBytes*sizeof(ULONG)); } /**** Return ****/ return IP_CONSUMED_ROW | IP_READY_FOR_DATA | (fSentRow ? IP_PRODUCED_ROW : 0); fatal_error: return IP_FATAL_ERROR; }
static WORD thumb_getActualTraits ( IP_XFORM_HANDLE hXform, /* in: handle for xform */ DWORD dwInputAvail, /* in: # avail bytes in input buf */ PBYTE pbInputBuf, /* in: ptr to input buffer */ PDWORD pdwInputUsed, /* out: # bytes used from input buf */ PDWORD pdwInputNextPos,/* out: file-pos to read from next */ PIP_IMAGE_TRAITS pInTraits, /* out: input image traits */ PIP_IMAGE_TRAITS pOutTraits) /* out: output image traits */ { PTN_INST g; int N; long lMaxSum; long nBytes; HANDLE_TO_PTR (hXform, g); /* Since there is no header, we'll report no usage of input */ *pdwInputUsed = 0; *pdwInputNextPos = 0; /* Compute N in our scale-factor of 1/N */ if (g->iFactorSpec <= 0) { N = -(g->iFactorSpec); } else { /* the +iFactorSpec-1 below biases N high (cieling function), * so the output width is biased low, so that we'll never go * larger than the requested output width. */ N = (g->inTraits.iPixelsPerRow + g->iFactorSpec - 1) / g->iFactorSpec; } if (N < 1) N = 1; g->wScale = N; /* Compute max summation of N-by-N input pixels */ lMaxSum = (long)N*N * (g->inTraits.iBitsPerPixel==1 ? 1 : 255); /* Compute pre-shift so that max sum does not exceed 16 bits */ if (lMaxSum >= (1L<<28)) g->wPreShift = 16; else if (lMaxSum >= (1L<<24)) g->wPreShift = 12; else if (lMaxSum >= (1L<<20)) g->wPreShift = 8; else if (lMaxSum >= (1L<<16)) g->wPreShift = 4; else g->wPreShift = 0; /* Now do the pre-shift on max sum */ lMaxSum >>= g->wPreShift; INSURE (lMaxSum < (1L<<16)); /* make sure it fits in 16 bits */ /* And compute the factor for converting a sum into a 0..255 pixel */ g->dwSumFac = (DWORD)((255.0/(float)lMaxSum) * (float)(1L<<16)); *pInTraits = g->inTraits; /* structure copies */ *pOutTraits = g->inTraits; if (pOutTraits->iBitsPerPixel == 1) pOutTraits->iBitsPerPixel = 8; pOutTraits->iPixelsPerRow = g->dwOutputWidth = pInTraits->iPixelsPerRow / N; if (pOutTraits->lNumRows >= 0) pOutTraits->lNumRows /= N; g->wMoreRows2Sum = N; g->dwInRowBytes = (pInTraits->iPixelsPerRow * pInTraits->iBitsPerPixel + 7) / 8; g->dwOutRowBytes = g->dwOutputWidth * pInTraits->iComponentsPerPixel; nBytes = g->dwOutRowBytes * sizeof(ULONG); IP_MEM_ALLOC (nBytes, g->pulSums); memset (g->pulSums, 0, nBytes); return IP_DONE | IP_READY_FOR_DATA; fatal_error: return IP_FATAL_ERROR; }
FUNC_STATUS WORD fakeMono_convert ( IP_XFORM_HANDLE hXform, DWORD dwInputAvail, /* in: # avail bytes in in-buf */ PBYTE pbInputBuf, /* in: ptr to in-buffer */ PDWORD pdwInputUsed, /* out: # bytes used from in-buf */ PDWORD pdwInputNextPos, /* out: file-pos to read from next */ DWORD dwOutputAvail, /* in: # avail bytes in out-buf */ PBYTE pbOutputBuf, /* in: ptr to out-buffer */ PDWORD pdwOutputUsed, /* out: # bytes written in out-buf */ PDWORD pdwOutputThisPos) /* out: file-pos to write the data */ { PFMON_INST g; int nBytes; PBYTE pIn, pInAfter, pOut; unsigned rv, gv, bv; int gray; HANDLE_TO_PTR (hXform, g); /**** Check if we were told to flush ****/ if (pbInputBuf == NULL) { PRINT (_T("fakeMono_convert: Told to flush.\n"), 0, 0); *pdwInputUsed = *pdwOutputUsed = 0; *pdwInputNextPos = g->dwInNextPos; *pdwOutputThisPos = g->dwOutNextPos; return IP_DONE; } /**** Output a Row ****/ nBytes = g->dwBytesPerRow; INSURE (dwInputAvail >= (DWORD)nBytes ); INSURE (dwOutputAvail >= (DWORD)nBytes); pIn = pbInputBuf; pOut = pbOutputBuf; pInAfter = pIn + nBytes; if (g->iFakeDPI == 1) { // faking bi-level while (pIn < pInAfter) { rv = *pIn++; gv = *pIn++; bv = *pIn++; gray = NTSC_LUMINANCE (rv, gv, bv); gray = (gray >= 128) ? 255 : 0; *pOut++ = (BYTE)gray; *pOut++ = (BYTE)gray; *pOut++ = (BYTE)gray; } } else { // faking grayscale while (pIn < pInAfter) { rv = *pIn++; gv = *pIn++; bv = *pIn++; gray = NTSC_LUMINANCE (rv, gv, bv); *pOut++ = (BYTE)gray; *pOut++ = (BYTE)gray; *pOut++ = (BYTE)gray; } } *pdwInputUsed = nBytes; g->dwInNextPos += nBytes; *pdwInputNextPos = g->dwInNextPos; *pdwOutputUsed = nBytes; *pdwOutputThisPos = g->dwOutNextPos; g->dwOutNextPos += nBytes; g->dwRowsDone += 1; return IP_CONSUMED_ROW | IP_PRODUCED_ROW | IP_READY_FOR_DATA; fatal_error: return IP_FATAL_ERROR; }
static WORD crop_getActualTraits ( IP_XFORM_HANDLE hXform, /* in: handle for xform */ DWORD dwInputAvail, /* in: # avail bytes in input buf */ PBYTE pbInputBuf, /* in: ptr to input buffer */ PDWORD pdwInputUsed, /* out: # bytes used from input buf */ PDWORD pdwInputNextPos,/* out: file-pos to read from next */ PIP_IMAGE_TRAITS pInTraits, /* out: input image traits */ PIP_IMAGE_TRAITS pOutTraits) /* out: output image traits */ { PCROP_INST g; int left, right, shift; int inWidth, outWidth; int bpp; long actualOut, maxOut; HANDLE_TO_PTR (hXform, g); /* Since there is no header, we'll report no usage of input */ *pdwInputUsed = 0; *pdwInputNextPos = 0; /* Compute the crop info */ bpp = g->traits.iBitsPerPixel; left = g->dwLeft; right = g->dwRight; inWidth = g->traits.iPixelsPerRow; outWidth = inWidth - left - right; INSURE (outWidth >= 0); if (bpp == 1) { /* shift to start at nearest byte boundary */ shift = ((left+4) & ~7) - left; left += shift; /* this is now a multiple of 8 */ right += shift; } g->dwInBytesPerRow = (bpp*inWidth + 7) / 8; g->dwOutBytesPerRow = (bpp*outWidth + 7) / 8; g->dwLeftCropBytes = (bpp*left + 7) / 8; /* Report the traits */ *pInTraits = g->traits; /* structure copies */ *pOutTraits = g->traits; pOutTraits->iPixelsPerRow = outWidth; /* compute the output lNumRows, if possible */ if (pInTraits->lNumRows > 0) { maxOut = g->dwMaxOutRows; actualOut = pInTraits->lNumRows - (long)g->dwTop; INSURE (actualOut >= 0); pOutTraits->lNumRows = actualOut<maxOut ? actualOut : maxOut; } return IP_DONE | IP_READY_FOR_DATA; fatal_error: return IP_FATAL_ERROR; }