void PTRecolorAction::DoIt() { if ( mTable ) { SUOffscreen *currentBuffer = mSettings.currentBuffer; mSettings.thePaintView->CopyToUndo(); mSettings.thePaintView->SelectNone(); /* create a new buffer the same size as the image but with a depth of 8-bits. use the specified color table as the color table. */ SInt32 width = currentBuffer->GetWidth(); SInt32 height = currentBuffer->GetHeight(); SUOffscreen *newBuffer = SUOffscreen::CreateBuffer( width, height, kRecolorDepth, mTable ); /* increase the inverse table size from 4 to 5 bits. this gives substantially better color matching. */ newBuffer->IncreaseInverseTableSize(); /* Copy the image to the 8-bit buffer to downsample the colors and then back to the original 32-bit one */ newBuffer->CopyFrom( currentBuffer ); currentBuffer->CopyFrom( newBuffer ); delete newBuffer; // update the canvas mSettings.theCanvas->DrawFrom( currentBuffer ); } this->PostAsAction(); }
/*=============================================== ChangeImageSize Note: Affects only the pixpat, _not_ the black & white pattern. ================================================*/ void PTPatternView::ChangeImageSize( SInt32 inWidth, SInt32 inHeight, Boolean inStretch ) { ThrowIf_( (inWidth < mMinImageWidth) || (inHeight < mMinImageHeight) ); ThrowIf_( (inWidth > mMaxImageWidth) || (inHeight > mMaxImageHeight) ); ThrowIf_( mResourceType != ImageType_PixPat ); ThrowIfNil_( mColorSample ); ThrowIfNil_( mCurrentImage ); SInt32 savedWidth = mPixPatWidth; // in case of error... SInt32 savedHeight = mPixPatHeight; Boolean changedSize = true; SUOffscreen *newBuffer = nil; Rect destR; try { /***************************************** create a new buffer -- same depth as current one, but new size *****************************************/ newBuffer = mCurrentImage->CreateSimilarOffscreen( false, inWidth, inHeight ); /***************************************** copy the image from the old buffer into the new one *****************************************/ if ( inStretch ) ::SetRect( &destR, 0, 0, inWidth, inHeight ); else ::SetRect( &destR, 0, 0, mCurrentImage->GetWidth(), mCurrentImage->GetHeight() ); newBuffer->CopyFrom( mCurrentImage, &destR ); /***************************************** resize the pixpat sample pane *****************************************/ this->ResizeSampleWell( inWidth, inHeight ); changedSize = true; /***************************************** keep track of the changed size. do this before SetImage() because it may call GetZoomFactor. *****************************************/ mPixPatWidth = inWidth; mPixPatHeight = inHeight; /***************************************** set the current buffer -- this can trigger all sorts of things (canvas resize, etc) *****************************************/ this->SetImage( newBuffer, PTResize_All, redraw_Later ); /***************************************** change the sample pane's buffer. Notes: (1) The sample pane will own the buffer after this call (don't delete it) (2) The previous sample pane buffer will be saved away by the PTResizer object *****************************************/ mColorSample->SetRawBuffer( newBuffer ); } catch( ... ) { /* restore things to the way they were before we were called */ mPixPatWidth = savedWidth; mPixPatHeight = savedHeight; if ( changedSize ) this->ResizeSampleWell( mPixPatWidth, mPixPatHeight ); delete newBuffer; throw; } }
/*=============================================== ParseColorCursor Note: See description of CCrsr structure above. ================================================*/ void PTCursorView::ParseColorCursor( RFMap *inMap, ResIDT inResID, SUOffscreen **outColor, SUOffscreen **outBW, SUOffscreen **outMask, Point *outHotSpot ) { PixMapPtr cMap; SInt32 depth, width, height; CTabHandle theTable = nil; SUOffscreen *cBuffer = nil, *bwBuffer = nil, *maskBuffer = nil, *tempBuffer = nil; CCrsrHandle h = nil; UInt8 *p; try { /************************************************** get the raw resource handle -- this isn't the usual way of loading color cursors, so the fields -- will be raw and not filled in (as when GetCCursor is used) **************************************************/ RFResource *theRes = inMap->FindResource( ImageType_ColorCursor, inResID, false ); ThrowIfNil_( theRes ); h = (CCrsrHandle) theRes->GetResData(); ThrowIfNil_( h ); ::HLock( (Handle) h ); p = (UInt8*) *h; /************************************************** validate the handle a little bit **************************************************/ if ( (UInt16) (**h).crsrType != (UInt16) 0x8001 ) // cast *is* needed - crsrType is signed LException::Throw( err_InvalidImageFormat ); if ( ::GetHandleSize( (Handle) h ) < static_cast<Size>(sizeof(CCrsr)) ) LException::Throw( err_CorruptedResource ); /************************************************** get some info about the cursor **************************************************/ cMap = (PixMapPtr) (p + (SInt32) (**h).crsrMap); if ( cMap->pixelType != 0 ) LException::Throw( err_InvalidImageFormat ); width = cMap->bounds.right - cMap->bounds.left; height = cMap->bounds.bottom - cMap->bounds.top; depth = cMap->pixelSize; if ( (width != Cursor_Width) || (height != Cursor_Height) ) LException::Throw( err_InvalidImageSize ); if ( (depth != 1) && (depth != 2) && (depth != 4) && (depth != 8) ) LException::Throw( err_InvalidImageDepth ); /************************************************** create the bwBuffer and maskBuffer **************************************************/ bwBuffer = SUOffscreen::CreateBuffer( Cursor_Width, Cursor_Height, 1 ); ThrowIfMemFail_( bwBuffer ); bwBuffer->CopyFromRawData( (UInt8*) &(**h).crsr1Data, BWCursor_RowBytes ); maskBuffer = SUOffscreen::CreateBuffer( Cursor_Width, Cursor_Height, 1 ); ThrowIfMemFail_( maskBuffer ); maskBuffer->CopyFromRawData( (UInt8*) &(**h).crsrMask, BWCursor_RowBytes ); /************************************************** allocate the color table. note that the resource may have a minimal color table and QuickDraw doesn't work with anything but a full-sized one. **************************************************/ if ( cMap->pmTable == 0 ) // probably won't happen, but can't hurt to check theTable = SUColorUtils::NewColorTableByDepth( depth ); else theTable = SUColorUtils::NewColorTableFromPtr( depth, p + (SInt32) cMap->pmTable ); /************************************************** allocate the color bitmap **************************************************/ tempBuffer = SUOffscreen::CreateBuffer( width, height, depth, theTable ); SInt32 rowBytes = cMap->rowBytes & 0x3FFF; // clear flag bits if ( rowBytes != 0 ) tempBuffer->CopyFromRawData( p + (SInt32) (**h).crsrData, rowBytes ); /************************************************** now switch it to a 32-bit offscreen **************************************************/ cBuffer = SUOffscreen::CreateBuffer( width, height, 32 ); cBuffer->CopyFrom( tempBuffer ); } catch( ... ) { delete maskBuffer; delete bwBuffer; delete cBuffer; delete tempBuffer; if ( theTable ) ::DisposeCTable( theTable ); SUMiscUtils::DisposeHandle( h ); } // return buffers and info to the caller *outColor = cBuffer; *outBW = bwBuffer; *outMask = maskBuffer; *outHotSpot = (**h).crsrHotSpot; // don't need the color table because the offscreen makes a copy of it if ( theTable ) ::DisposeCTable( theTable ); SUMiscUtils::DisposeHandle( h ); delete tempBuffer; }