static BOOL WriteDIBMask( /************************************************************************/ LPBITMAPINFOHEADER lpInfo, LPSTR lpMaskFile) { BOOL bRet; LPMASK lpMask; // create the mask if ( !(lpMask = MaskCreate( NULL, (int)lpInfo->biWidth, (int)lpInfo->biHeight, ON, YES )) ) return(FALSE); // write out the mask bRet = WriteMask( lpMaskFile, lpMask, FALSE ); MaskClose( lpMask ); return( bRet ); }
// Gets the current mask if any. // If no mask exists then create one using fOn and fNoUndo. // bCreated is TRUE if a new mask was created. LPMASK CImage::GetMaskEx(BOOL fOn, BOOL fNoUndo, LPINT bCreated, LPRECT lpUpdateRect) { LPMASK lpMask; LPFRAME lpFrame; FRMTYPEINFO TypeInfo; FRMDATATYPE FrameType = FDT_GRAYSCALE; AstralSetRectEmpty(lpUpdateRect); if (lpMask = GetMask()) { if (bCreated) *bCreated = FALSE; return(lpMask); } lpFrame = GetBaseEditFrame(); FrameGetTypeInfo(lpFrame, &TypeInfo); if (TypeInfo.DataType == FDT_LINEART && Mask.OneBitMask) FrameType = FDT_LINEART; if (!(lpMask = MaskCreate(NULL, FrameXSize(lpFrame), FrameYSize(lpFrame), fOn, fNoUndo, FrameType))) { Message( IDS_EMEMALLOC ); return(NULL); } // sync up the resolution of the image data and the mask // don't ever rely on the mask's resolution being correct // cause other size can change the image data resolution // without changing the mask's resolution. Also, there are // other places the mask gets created without syncing up // the resolution. I am doing it here so we can begin // to track it correctly (Ted) FrameSetResolution(AlphaGetEditFrame(lpMask), FrameResolution(lpFrame)); if (bCreated) *bCreated = TRUE; if (!Control.UseMaskAndObjects) GetObjectMarqueeRect(this, lpUpdateRect); SetMask(lpMask); return(lpMask); }
BOOL CombineObjObjects( LPIMAGE lpImage, LPCMD_PARMS lpCmdParms ) /************************************************************************/ { RECT rCombine,r; LPOBJECT lpBase, lpObj; LPALPHA lpAlpha, lpMask; LPFRAME lpDFrame, lpSFrame; LPTR lpDF, lpDM, *lpSM, *lpSF; int x, y, yy, depth; int N, H, W, i; double *lpAlphaTable, *AiXOi; double red,blue,green,k; POINT pt; double Oi, Ai, Mi, Mc; LPOBJECT *lpObject; FRMTYPEINFO TypeInfo; BOOL fCanDoOpacity; FRMDATATYPE MaskType = FDT_GRAYSCALE; if (!(lpImage)) return( FALSE ); ImgGetTypeInfo(lpImage, &TypeInfo); if (TypeInfo.DataType == FDT_LINEART && Mask.OneBitMask) MaskType = FDT_LINEART; fCanDoOpacity = CANDOTRANSPARENCY(TypeInfo.DataType); lpObj = lpBase = ImgGetBase(lpImage); if (!(depth = FrameDepth(ObjGetEditFrame(lpBase)))) depth = 1; // never worry about lineart N = ImgCountSelObjects(lpImage, NULL); ImgGetSelObjectRect(lpImage, &rCombine, YES); H = RectHeight(&rCombine); W = RectWidth (&rCombine); lpObject = NULL; AiXOi = lpAlphaTable = NULL; lpAlphaTable = (double *)Alloc((N+1) * sizeof(double)); AiXOi = (double *)Alloc(N * sizeof(double)); lpSM = (LPTR *)Alloc(N * sizeof(LPTR)); lpSF = (LPTR *)Alloc(N * sizeof(LPTR)); lpObject = (LPOBJECT *)Alloc(N * sizeof(LPOBJECT)); lpAlpha = MaskCreate(NULL, W, H, YES, Control.NoUndo, MaskType); lpDFrame = ImgGetBaseEditFrame(lpImage); lpDFrame = FrameOpen(FrameType(lpDFrame), W, H, FrameResolution(lpDFrame)); if (!lpAlphaTable || !lpObject || !AiXOi || !lpAlpha || !lpDFrame || !lpSM || !lpSF) { if (lpAlphaTable) FreeUp(lpAlphaTable); if (lpObject) FreeUp(lpObject); if (AiXOi) FreeUp(AiXOi); if (lpDFrame) FreeUp(lpDFrame); if (lpSF) FreeUp(lpSF); if (lpSM) FreeUp(lpSM); Message(IDS_EMEMALLOC); return(FALSE); } for (i=0; i < N; i++) lpObj = lpObject[i] = ImgGetSelObject(lpImage, lpObj); ImgEditInit(lpImage, ET_OBJECT, UT_DELETEOBJECTS, lpBase); ProgressBegin(1, PROGRESS_ID(IDS_UNDOOBJCOMBOBJS)); for (y = 0; y <= H; y++) { AstralClockCursor(y, H, NO); lpDF = FramePointer(lpDFrame, 0, y, YES); lpDM = PixmapPtr(&lpAlpha->Pixmap, PMT_EDIT, 0, y, YES); pt.y = y + rCombine.top; for (i=0; i < N; i++) { yy = pt.y - lpObject[i]->rObject.top; lpSFrame = ObjGetEditFrame(lpObject[i]); lpSF[i] = FramePointer(lpSFrame, 0, yy, NO); lpMask = ObjGetAlpha(lpObject[i]); lpSM[i] = PixmapPtr(&lpMask->Pixmap, PMT_EDIT, 0, yy, NO); } for (x = 0; x < W; x++) { lpAlphaTable[N] = 1.0; pt.x = x + rCombine.left; for (i=N-1; i >= 0; i--) { r = lpObject[i]->rObject; r.bottom++; r.right++; if (PtInRect(&r, pt)) { if (fCanDoOpacity) Oi = lpObject[i]->Opacity / 255.0; else Oi = 1; if (fCanDoOpacity) Ai = *lpSM[i]++ / 255.0; else if (*lpSM[i] < 128) { Ai = 0; lpSM[i]++; } else { Ai = 1; lpSM[i]++; } AiXOi[i] = Oi * Ai; lpAlphaTable[i] = lpAlphaTable[i+1] * (1.0 - AiXOi[i]); } else { AiXOi[i] = 1.0; lpAlphaTable[i] = lpAlphaTable[i+1]; } } Mc = 1.0 - lpAlphaTable[0]; lpDM[x] = (BYTE)(Mc * 255); red = blue = green = k = 0; for (i=0; i < N; i++) { r = lpObject[i]->rObject; r.bottom++; r.right++; if (PtInRect(&r, pt)) { Mi = AiXOi[i] * lpAlphaTable[i+1]; switch(depth) { case 1: red += *lpSF[i]++ * Mi; break; case 3: red += *lpSF[i]++ * Mi; green += *lpSF[i]++ * Mi; blue += *lpSF[i]++ * Mi; break; case 4: red += *lpSF[i]++ * Mi; green += *lpSF[i]++ * Mi; blue += *lpSF[i]++ * Mi; k += *lpSF[i]++ * Mi; break; } } } if (Mc == 0.0) Mc = 1.0; switch(depth) { case 1: *lpDF++ = (BYTE)(red / Mc); break; case 3: *lpDF++ = (BYTE)(red / Mc); *lpDF++ = (BYTE)(green / Mc); *lpDF++ = (BYTE)(blue / Mc); break; case 4: *lpDF++ = (BYTE)(red / Mc); *lpDF++ = (BYTE)(green / Mc); *lpDF++ = (BYTE)(blue / Mc); *lpDF++ = (BYTE)(k / Mc); break; } } } lpObj = ObjCreateFromFrame(ST_PERMANENT, lpDFrame, lpAlpha, &rCombine, Control.NoUndo ); lpObj->fSelected = YES; lpObj->fUndoDeleted = YES; ImgAddNewObject(lpImage, lpObj); for (i=0; i < N; i++) lpObject[i]->fDeleted = YES; ImgEditedObject(lpImage, lpBase, IDS_UNDOOBJCOMBOBJS, NULL); UpdateImage(lpImage, &rCombine, YES); FreeUp(lpSM); FreeUp(lpSF); FreeUp(AiXOi); FreeUp(lpAlphaTable); FreeUp(lpObject); ProgressEnd(); return( TRUE ); }
BOOL ReadObjData( LPSTR lpFileName, LPOBJECTLIST lpObjList, int outDepth, LPINT lpDataType, LPRECT lpScaleRect, LPINT lpFullFileX, LPINT lpFullFileY, LPINT lpFullResolution) /************************************************************************/ { LPFRAME lpFrame; LPOBJECT lpObject; int ifh; LPLONG lngptr; LPWORD shtptr; int nObjects, i, idFileType, nPasses; WORD wBytes, wByteOrder, wVersion; long lObjSize, lObjStart; LPOBJOFFSETS lpOffsets; OBJECT Obj; LFIXED xrate, yrate; int opix, olin, baseW, baseH; LPRECT lpLoadRect; xrate = yrate = UNITY; lpOffsets = NULL; if ( !lpObjList ) return( FALSE ); lpObjList->lpHead = lpObjList->lpTail = NULL; if ( (ifh = _lopen(lpFileName, OF_READ)) < 0) { Message( IDS_EOPEN, lpFileName ); return( FALSE ); } // Read in header info wBytes = OBJ_HDR_SIZE; if ( _lread(ifh, LineBuffer[0], wBytes) != wBytes ) goto BadRead; shtptr = (LPWORD)LineBuffer[0]; wByteOrder = GetNextWord(&shtptr); /* byte order is LSB,MSB */ if (wByteOrder != TIF_II && wByteOrder != TIF_MM) goto BadRead; wVersion = GetNextWord(&shtptr); /* Version Number */ nObjects = GetNextWord(&shtptr); /* Number of Objects */ lngptr = (LPLONG)shtptr; lObjSize = GetNextLong(&lngptr); /* size of object data */ lObjStart = GetNextLong(&lngptr); /* start of object data */ if (!(lpOffsets = (LPOBJOFFSETS)Alloc(sizeof(OBJOFFSETS)*nObjects))) { Message(IDS_EMEMALLOC); return(FALSE); } _llseek (ifh, lObjStart, 0); wBytes = (WORD)lObjSize; nPasses = 0; for (i = 0; i < nObjects; ++i) { if ( _lread(ifh, LineBuffer[0], wBytes) != wBytes ) goto BadRead; shtptr = (LPWORD)LineBuffer[0]; Obj.ObjectType = (OBJECT_TYPE)GetNextWord(&shtptr); Obj.rObject.left = GetNextWord(&shtptr); Obj.rObject.top = GetNextWord(&shtptr); Obj.rObject.right = GetNextWord(&shtptr); Obj.rObject.bottom = GetNextWord(&shtptr); Obj.Opacity = GetNextWord(&shtptr); Obj.MergeMode = (MERGE_MODE)GetNextWord(&shtptr); Obj.wGroupID = GetNextWord(&shtptr); if (i==0 && lpScaleRect) { opix = RectWidth(lpScaleRect); olin = RectHeight(lpScaleRect); baseW = RectWidth(&Obj.rObject); baseH = RectHeight(&Obj.rObject); xrate = ScaleToFit(&opix, &olin, baseW, baseH); if (opix > baseW || olin > baseH) { // No upsizing allowed opix = baseW; olin = baseH; } xrate = FGET( opix, baseW ); yrate = FGET( olin, baseH ); } // scale the object rect Obj.rObject.left = FMUL(Obj.rObject.left, xrate); Obj.rObject.top = FMUL(Obj.rObject.top, yrate); Obj.rObject.right = FMUL(Obj.rObject.right, xrate); Obj.rObject.bottom = FMUL(Obj.rObject.bottom, yrate); if (!(lpObject = ObjCreateFromFrame(ST_PERMANENT, NULL, NULL, &Obj.rObject, Control.NoUndo))) { Message(IDS_EMEMALLOC); goto BadRead; } idFileType = GetNextWord(&shtptr); lpOffsets[i].bInvert = GetNextWord(&shtptr); lpOffsets[i].rMask.left = GetNextWord(&shtptr); lpOffsets[i].rMask.top = GetNextWord(&shtptr); lpOffsets[i].rMask.right = GetNextWord(&shtptr); lpOffsets[i].rMask.bottom = GetNextWord(&shtptr); // scale the mask rect lpOffsets[i].rMask.left = FMUL(lpOffsets[i].rMask.left, xrate); lpOffsets[i].rMask.top = FMUL(lpOffsets[i].rMask.top, yrate); lpOffsets[i].rMask.right = FMUL(lpOffsets[i].rMask.right, xrate); lpOffsets[i].rMask.bottom = FMUL(lpOffsets[i].rMask.bottom, yrate); lngptr = (LPLONG)shtptr; lpOffsets[i].lDataOffset = GetNextLong(&lngptr); lpOffsets[i].lAlphaOffset = GetNextLong(&lngptr); shtptr = (LPWORD)lngptr; // versions after 1.1 saved selected state if (wVersion == 0x0101) Obj.fSelected = NO; else Obj.fSelected = GetNextWord(&shtptr); if (wVersion < 0x0103 || lObjSize == 41) { Obj.ObjectDataID = OBJECT_DATA_NONE; Obj.dwObjectData = 0; } else { Obj.ObjectDataID = GetNextWord(&shtptr); Obj.dwObjectData = *(LPDWORD)shtptr; shtptr += 2; } lpObject->ObjectType = Obj.ObjectType; lpObject->Opacity = Obj.Opacity; lpObject->MergeMode = Obj.MergeMode; lpObject->wGroupID = Obj.wGroupID; lpObject->fSelected = Obj.fSelected; lpObject->ObjectDataID = Obj.ObjectDataID; lpObject->dwObjectData = Obj.dwObjectData; ObjAddTail(lpObjList, (LPPRIMOBJECT)lpObject); ++nPasses; if (lpOffsets[i].lAlphaOffset) ++nPasses; } ProgressBegin(nPasses, 0); lpObject = NULL; i = 0; while (lpObject = (LPOBJECT)ObjGetNextObject(lpObjList, (LPPRIMOBJECT)lpObject, YES)) { if (lpScaleRect && i!=0) { lpLoadRect = &lpObject->rObject; } else lpLoadRect = lpScaleRect; _llseek (ifh, lpOffsets[i].lDataOffset, 0); lpFrame = ReadTiffData(ifh, lpFileName, outDepth, lpDataType, NO/*bReadOnly*/, lpLoadRect, NO, lpFullFileX, lpFullFileY, lpFullResolution); if (i == 0) { lpDataType = NULL; lpFullFileX = NULL; lpFullFileY = NULL; lpFullResolution = NULL; } if (!lpFrame) goto BadRead; PixmapSetup(&lpObject->Pixmap, lpFrame, Control.NoUndo); if (!lpOffsets[i].lAlphaOffset) { ++i; continue; } _llseek (ifh, lpOffsets[i].lAlphaOffset, 0); lpFrame = ReadTiffData(ifh, lpFileName, outDepth, lpDataType, NO/*bReadOnly*/, lpLoadRect, NO, NULL, NULL, NULL); if (!lpFrame) goto BadRead; lpObject->lpAlpha = MaskCreate(lpFrame, 0, 0, OFF, Control.NoUndo); if (!lpObject->lpAlpha) { Message(IDS_EMEMALLOC); goto BadRead; } lpObject->lpAlpha->bInvert = lpOffsets[i].bInvert; lpObject->lpAlpha->rMask = lpOffsets[i].rMask; ++i; } if ( lpOffsets ) FreeUp( (LPTR)lpOffsets ); _lclose(ifh); ProgressEnd(); return( TRUE ); BadRead: while (lpObject = (LPOBJECT)ObjGetNextObject(lpObjList, NULL, YES)) { ObjUnlinkObject(lpObjList, (LPPRIMOBJECT)lpObject); ObjFreeUp(lpObject); } _lclose(ifh); if ( lpOffsets ) FreeUp( (LPTR)lpOffsets ); if (nPasses) ProgressEnd(); Message( IDS_EREAD, lpFileName ); return( FALSE ); }