static void ApplyChannel (GPtr globals, ReadChannelDesc *source, PixelMemoryDesc *sDesc, ReadChannelDesc *mask, PixelMemoryDesc *mDesc, WriteChannelDesc *dest, ChannelReadPort destRead, PixelMemoryDesc *dDesc, PixelMemoryDesc *rDesc, size_t *done, size_t total) { VRect limit; int32 row, col, row2, col2; unsigned8 *s, *m, *d; unsigned8 *r = (unsigned8 *)rDesc->data; Boolean initRandom = (*r == kInitRandom); limit = source->bounds; TrimVRect (&limit, &dest->bounds); if (mask != NULL) TrimVRect (&limit, &mask->bounds); if (limit.right <= limit.left || limit.bottom <= limit.top) return; for (row = limit.top; row < limit.bottom; row += kBlockRows) for (col = limit.left; col < limit.right; col += kBlockCols) { VRect area; PSScaling scaling; VRect wrote; if (TestAbort ()) { gResult = userCanceledErr; return; } area.top = row; area.bottom = row + kBlockRows; area.left = col; area.right = col + kBlockCols; if (limit.bottom < area.bottom) area.bottom = limit.bottom; if (limit.right < area.right ) area.right = limit.right; scaling.sourceRect = area; scaling.destinationRect = area; gResult = ReadPixels (destRead, &scaling, &area, dDesc, &wrote); if (gResult != noErr) return; if (!EqualVRects (&area, &wrote)) { gResult = -1; return; } gResult = ReadPixels (source->port, &scaling, &area, sDesc, &wrote); if (gResult != noErr) return; if (!EqualVRects (&area, &wrote)) { gResult = -1; return; } if (mask != NULL) { gResult = ReadPixels (mask->port, &scaling, &area, mDesc, &wrote); if (gResult != noErr) return; if (!EqualVRects (&area, &wrote)) { gResult = -1; return; } } m = (unsigned8 *) mDesc->data; /* mask all set and ready to go */ /* heart of the routine. Compares source pixel and destination pixel and, if destination is smaller, replaces it with source */ s = (unsigned8 *) sDesc->data; d = (unsigned8 *) dDesc->data; r = (unsigned8 *) rDesc->data; for (row2 = kBlockRows; row2 > 0; --row2) for (col2 = kBlockCols; col2 > 0; --col2) { switch (gWhatArea) { case iSelectMin: if (mask != NULL && *m < *s ) *s = *m; if (*s > 127) *d = *s; else *d = 0; break; case iSelectMax: if (mask != NULL && *m < *s ) *s = *m; if (*s < 128) *d = 255 - *s; // if (*d < *s) *d = *s; else *d = 0; break; case iSelectRandom: if (initRandom) { if ((((unsigned16) rand ()) % 100) < gPercent) *r = kRandomOn; // flag as picked else *r = kRandomOff; // flag as off } if (*r == kRandomOn) *d = 255; else *d = 0; break; } ++s; ++d; ++r; if (mask != NULL) ++m; } gResult = WritePixels (dest->port, &area, dDesc); if (gResult != noErr) return; *done += (area.right - area.left) * (area.bottom - area.top); PIUpdateProgress ((int32)*done, (int32)total); } }
void DoEffect(GPtr globals) { // Get a buffer to hold each channel as we process char *pLayerData = gPSBufferSuite64->New(NULL, VSIZE * HSIZE * gXFactor * gXFactor); if (pLayerData == NULL) return; // Start with the first target composite channel ReadChannelDesc *pChannel = gDocDesc->targetCompositeChannels; // we may have a multichannel document if (pChannel == NULL) pChannel = gDocDesc->alphaChannels; // Get some information for the progress bar int32 done = 0; int32 total = NumberOfChannels(globals) + 1; // Loop through each of the channels while (pChannel != NULL && gResult == 0) { // Update the progress bar PIUpdateProgress(done++, total); // Read in this channel data, we actually don't need this data // but I will read it in anyway, it is an example you know ReadLayerData(globals, pChannel, pLayerData, false); // Stamp the "Hello World" into the data buffer HelloWorldData(globals, pLayerData); // Decide if we should blur our effect or just write out the // data. GaussianBlurEffect() will use a new channel port if (gGaussianBlurData) { Rect write_rect; write_rect.top = gPointV; write_rect.left = gPointH; write_rect.bottom = (short)(gPointV + VSIZE * gXFactor); write_rect.right = (short)(gPointH + HSIZE * gXFactor); GaussianBlurEffect(globals, &write_rect, pLayerData); } WriteLayerData(globals, pChannel, pLayerData); // off to the next channel pChannel = pChannel->next; } // Update the progress bar PIUpdateProgress(done++, total); // now update the transparency information // this will be non null for layered data pChannel = gDocDesc->targetTransparency; if (gResult == 0) { // Read in this channel data, we actually don't need this data // but I will read it in anyway, it is an example you know ReadLayerData(globals, pChannel, pLayerData, false); // Stamp the "Hello World" into the data buffer HelloWorldMaskData(globals, pLayerData); // write out the channel mask WriteLayerData(globals, pChannel, pLayerData); } // Update the progress bar PIUpdateProgress(done++, total); // dispose of that temp buffer we have been using gPSBufferSuite64->Dispose((char**)&pLayerData); }