* ******************************************************************************** * FUNCTION Manipulate( ) ******************************************************************************** #include "xbp.ch" #include "Appevent.ch" #include "Gra.ch" #include "common.ch" #include "font.ch" #include "fileio.ch" #include "dll.ch" #pragma library("XppUi2") #define TRANSBG 100 #define TEST 200 #define ROT_LEFT 300 #define ROT_RIGHT 400 #define EXTEND 500 #define EXTEND_DIS 600 STATIC aBG_RGB := {} STATIC aIntDiv3 := {} STATIC aUnDo := {} STATIC cDefExtIn := "" STATIC cDefExtOut := "" STATIC cDirPathIn := "" STATIC cDirPathOut:= "" STATIC cFile := "" STATIC cFileOut := "Temp" STATIC cKey := "BRIGHTNESS" STATIC hDCx := 0 STATIC hWndx := 0 STATIC lBG := .F. STATIC lHotSpot := .F. STATIC lRotRight := .T. STATIC nDegrees := (-90) STATIC nID := 0 STATIC nStepVal := 5 STATIC oBar := nil STATIC oImage := nil STATIC oBtnUndo := nil STATIC oCap := nil STATIC oStatbar := nil STATIC oDa := nil STATIC lExtended := .F. STATIC oRotInd := nil STATIC oExtend := nil STATIC oBitmap := nil STATIC oPS := nil * ******************************************************************************** * FUNCTION Manipulate( ) ******************************************************************************** FUNCTION Manipulate( oBitmap, cKeyWord, nStepVal, oDlg ) LOCAL aClrTable := nil LOCAL aModifier := 0 LOCAL c8BitData := "" LOCAL cBG_BGR := "" LOCAL cBGCaddress := "" LOCAL cBlock := "" LOCAL cPad := "" LOCAL cDataNew := "" LOCAL cDump := "" LOCAL cPalette := "" LOCAL hSource := 0 LOCAL hTarget := 0 LOCAL i,j := 0 LOCAL n8BitLinePad := 0 LOCAL nB := 0 LOCAL nBIncr := 0 LOCAL nColors := 0 LOCAL nCosT := 0 LOCAL nG := 0 LOCAL nGIncr := 0 LOCAL nGray := 0 LOCAL nHandle := 0 LOCAL nIncr := 0 LOCAL nLastLine := 0 LOCAL nLastOnLine := 0 LOCAL nLineData := 0 LOCAL nLineSize := 0 LOCAL nMeanVal := 0 LOCAL nOffSet := 0 LOCAL nOffSetN := 0 LOCAL nPointer := 1 LOCAL nR := 0 LOCAL nRGB := 0 LOCAL nRIncr := 0 LOCAL nSinT := 0 LOCAL nSize := 0 LOCAL nNewX := 0 LOCAL nNewY := 0 LOCAL nT := 0 LOCAL nTableLen := 0 LOCAL nTick := 0 LOCAL nX2 := 0 LOCAL nXdatum := 0 LOCAL nY2 := 0 LOCAL nYdatum := 0 * LOCAL cData := "" LOCAL nBits := oBitMap:bits LOCAL cBuffer := oBitMap:setBuffer() LOCAL nFirstPixel := oBitMap:bufferOffset +1 // 0 based so add 1 LOCAL nXSize := oBitMap:xSize LOCAL nYSize := oBitMap:ySize LOCAL nBmpHeaderSize := Bin2U( substr(cBuffer,1,4) ) ***** Grab the current bitmap data for UNDO IF (nBits == 24) ***** Pull the data cData := ; Substr(cBuffer,nBmpHeaderSize+1, ; (nXSize*nYSize*3) +nYsize*(nXSize%4)) cPalette:="0" // dummy for array ELSE aClrTable := oBitMap:getColorTable() nBmpHeaderSize := Bin2U( substr(cBuffer,1,4) ) nTableLen := Len( aClrTable ) cPalette := Replicate( chr(0), 4*nTableLen ) FOR nRGB := 1 TO nTableLen ***** Make a Palette cPalette[nPointer+3] := "0" // Filler cPalette[nPointer+2] := Chr(aClrTable[nRGB,1]) // R cPalette[nPointer+1] := Chr(aClrTable[nRGB,2]) // G cPalette[nPointer] := Chr(aClrTable[nRGB,3]) // B nPointer+=4 NEXT ***** Reset the pointer nPointer := 1 cData:= substr( cBuffer, nFirstPixel ) ENDIF ***** Save it aAdd(aUndo, {cData,nBits, nXSize,nYsize,aClone(aBG_RGB),cPalette,lExtended} ) ***** ONLY 8 and 24 Bits supported IF (nBits == 8 .OR. nBits == 24) IF nBits == 24 * *********************** * 24 BIT OPERATIONS *********************** ***** Check if a custom background was selected ***** if not, set it to white. IF Empty(aBG_RGB) cBG_BGR:= Replicate(Chr(255),3) ELSE // Blue Green Red cBG_BGR:= Chr(aBG_RGB[3])+Chr(aBG_RGB[2])+Chr(aBG_RGB[1]) ENDIF // ELSEIF Upper(cKeyword) == "BRIGHTNESS-" ; IF Upper(cKeyword) == "BRIGHTNESS-" ; .OR. Upper(cKeyword) == "BRIGHTNESS+" * ********************************************* * 24 BIT BRIGHTNESS ********************************************* IF Upper(cKeyword) == "BRIGHTNESS-" nIncr := -nStepVal ELSE nIncr := nStepVal ENDIF ***** Pull the data cData := ; Substr(cBuffer,nBmpHeaderSize+1, ; (nXSize*nYSize*3) +nYsize*(nXSize%4)) ***** Pad RGB LineSize out to a 32Bit boundary nLineSize := (nXSize * 3) + nXSize%4 ***** Determine the last line to process nLastLine := Len(cData) - nLineSize +1 ***** Determine the last RGB block to process ***** (For:Next commences at 1, so deduct 1) nLastOnLine := (nXSize * 3) -1 nT:= 0 nTick := Int(nLastLine*0.05/nLineSize)*nLineSize //+06.12.2008 22:55 oBar:show() FOR i := 1 TO nLastLine Step nLineSize FOR j := i TO i+nLastOnLine Step 3 ***** Pop the colour values nB := Asc(cData[j]) + nIncr nG := Asc(cData[j+1]) + nIncr nR := Asc(cData[j+2]) + nIncr ***** Not negative IF nB < 0 nB := 0 ENDIF ***** Not negative IF nG < 0 nG := 0 ENDIF ***** Not negative IF nR < 0 nR := 0 ENDIF ***** Not > 255 IF nB > 255 nB := 255 ENDIF ***** Not > 255 IF nG > 255 nG := 255 ENDIF ***** Not > 255 IF nR > 255 nR := 255 ENDIF ***** Push the values cData[j] := Chr(nB) // B cData[j+1] := Chr(nG) // G cData[j+2] := Chr(nR) // R NEXT j IF i%nTick == 1 //+06.12.2008 22:55 oBar:setcaption(Replicate(Chr(103),nT)) nT++ ENDIF NEXT i //+06.12.2008 22:55 oBar:Hide() ***** Rebuild the buffer cBuffer := Left( cBuffer, nBmpHeaderSize ) + cData ENDIF //24Bit ELSEIF nBits == 8 ******************************* * 8 BIT IMAGE MANIPULATION ******************************* // ELSEIF Upper(cKeyword) == "BRIGHTNESS-" ; IF Upper(cKeyword) == "BRIGHTNESS-" ; .OR. Upper(cKeyword) == "BRIGHTNESS+" * ********************************************* * 8 BIT BRIGHTNESS ********************************************* IF Upper(cKeyword) == "BRIGHTNESS-" nIncr := -nStepVal ELSE nIncr := nStepVal ENDIF aClrTable := oBitMap:getColorTable() nBmpHeaderSize := Bin2U( substr(cBuffer,1,4) ) nTableLen := Len( aClrTable ) cPalette := Replicate( chr(0), 4*nTableLen ) FOR nRGB := 1 TO nTableLen ***** Pop the colour values nR := aClrTable[nRGB,1] + nIncr nG := aClrTable[nRGB,2] + nIncr nB := aClrTable[nRGB,3] + nIncr ***** Not negative IF nB < 0 nB := 0 ENDIF ***** Not negative IF nG < 0 nG := 0 ENDIF ***** Not negative IF nR < 0 nR := 0 ENDIF ***** Not > 255 IF nB > 255 nB := 255 ENDIF ***** Not > 255 IF nG > 255 nG := 255 ENDIF ***** Not > 255 IF nR > 255 nR := 255 ENDIF ***** Push the values cPalette[nPointer] := Chr(nB) // B cPalette[nPointer+1] := Chr(nG) // G cPalette[nPointer+2] := Chr(nR) // R cPalette[nPointer+3] := "0" // Filler nPointer+=4 NEXT ***** Build the new bitmap buffer. ***** Header + palette + Pixel Data cBuffer := ; Left( cBuffer, nBmpHeaderSize )+ ; cPalette + substr( cBuffer, nFirstPixel ) ENDIF // 8 Bit ENDIF // 24 Bit ENDIF // lUnDoAll / lUnDo / > 24Bit //+02.12.2008 09:50 hier wird ersteinmal cBuffer zurckgegeben RETURN cBuffer //++// /* ********************************************* * MAKE NEW BITMAP IMAGE ********************************************* IF (nBits == 8 .OR. nBits == 24) IF (nBits == 24) ***** Pull the data cData := ; Substr(cBuffer,nBmpHeaderSize+1, ; (nXSize*nYSize*3) +nYsize*(nXSize%4)) ***** Need to pass new conditions to Xbase++ ***** FErase( "~$$$.Bmp" ) SaveBmp24Bit("~$$$.Bmp", cData, nXSize, nYSize ) ENDIF IF (nBits == 8) nFirstPixel := oBitMap:bufferOffset +1 // 0 based so add 1 cData:= substr( cBuffer, nFirstPixel ) FErase( "~$$$.Bmp" ) SaveBmp8Bit("~$$$.Bmp", 8, cPalette, cData, nXSize, nYSize ) ENDIF LoadBitmap( oDa, ,.T.) nBits := oBitMap:bits cBuffer := oBitMap:setBuffer() nFirstPixel := oBitMap:bufferOffset +1 // 0 based so add 1 nXSize := oBitMap:xSize nYSize := oBitMap:ySize nBmpHeaderSize := Bin2U( substr(cBuffer,1,4) ) oBtnUndo:setcaption("Undo: "+Ltrim(Str(Len(aUnDo)))) ENDIF RETURN oBitMap */ * END FUNCTION Manipulate( ) ******************************************************************************** * ******************************************************************************** * ******************************************************************************** * FUNCTION LoadBitmap( ) * * This code is used each time a new bitmap is loaded so it was taken out * of the 'main stream' to be accessible from other areas. * ******************************************************************************** * FUNCTION LoadBitmap( oDa,lFile,lReadFile) ***** Get the size LOCAL aBmpSize := {nil,nil} LOCAL aBmpPos := {nil,nil} IF Valtype(lReadFile) == "U" lReadFile:= .F. ENDIF IF hDCx > 0 ReleaseDC( hWndx, hDCx) ENDIF IF lReadFile oBitMap:loadFile( "~$$$.Bmp" ) ENDIF aBmpSize:= {oBitmap:xSize, oBitmap:ySize} IF aBmpSize[1] == aBmpSize[2] .OR. ; Abs(aBmpSize[1] - aBmpSize[2]) == 1 oExtend:setcaption(EXTEND_DIS) ELSE oExtend:setcaption(EXTEND) ENDIF ***** Center bmp or position it at lowest coordinates depending on size IF aBmpSize[1] < 490 .AND. aBmpSize[2] < 425 aBmpPos[1] := (oDa:currentSize()[1]- aBmpSize[1]) / 2 aBmpPos[2] := ((oDa:currentSize()[2]+ 100 - aBmpSize[2]) / 2) ELSE aBmpPos := {(oDa:currentSize()[1]- aBmpSize[1]) / 2,100} ENDIF IF Valtype(oImage) == "O" oImage:destroy() oImage:= nil ENDIF oImage := XbpStatic():new( oDa, , aBmpPos, aBmpSize ) //oImage:caption := oBitmap oImage:clipSiblings := .F. oImage:type := XBPSTATIC_TYPE_BITMAP oImage:paint := { ; |x,y,obj| x:=obj:currentSize(), ; oBitmap:draw( oPS, {0, 0, x[1], x[2]}, ; {0, 0, oBitmap:xSize, oBitmap:ySize},, ; GRA_BLT_BBO_IGNORE), Sleep(0.1) } oImage:create() oPS := XbpPresSpace():new():create( oImage:winDevice() ) ***** This is needed to enable reading of pixel colours hWndx:= oImage:getHWND() ***** API call, don't forget to ReleaseDC.... hDCx := GetWindowDC( hWndx ) ***** Enable getting background colour if lBG is true ***** Watch the mouse if it is over the bitmap ***** Read the pixels and store the values ***** Change the background colour of the stat bar ***** as a visual indicator. oImage:motion := ; {|MP1,Mp2, o| IIF(lBG,(MouseTrap(o,MP1), ; IIF(lHotSpot, ( aBg_RGB := aClone(GetRGBVals( ; GetPixel(hDCx, MP1[1], o:currentsize()[2]-MP1[2]))), ; oStatbar:setColorBG(ARGB(aBg_RGB))), ; nil)) ,nil)} ***** If lBG it true and LB is clicked on bitmap ***** set lBG false, the colour has been stored in aBg_RGB oImage:lbclick := {|MP1,Mp2, o| IIF(lBG, lBG:= .F., nil)} ***** If lBG is true set aBg_RGB to {} and lBG false oImage:rbclick := {|MP1,Mp2, o| IIF(lBG, (aBg_RGB:= {},lBG:= .F.), nil) } IF lFile == nil cFile:= "ID: "+LTrim(Str(nID)) ELSE cFile:= SubStr(cFile,Rat("\",cFile)+1) ENDIF ****** Required in case a 1,4 or 16bit file is loaded. oStatbar:setFontCompoundName( "8.Arial" ) oStatbar:setColorFG( GRA_CLR_BLACK ) oStatbar:setColorBG( GRA_CLR_PALEGRAY ) ***** Show the file data oStatBar:setcaption( ; "File: " +cFile +" "+ ; "Bits: " +Ltrim(Str(oBitmap:bits)) +" "+ ; "Width: "+Ltrim(Str(oBitmap:xSize)) +" "+ ; "Height: "+Ltrim(Str(oBitmap:ySize))+" "+ ; "FileSize.BMP: "+Ltrim(Str( 14 + Len(oBitmap:setBuffer())))) ***** Error message if not 8 or 24 bits IF !(oBitmap:bits == 8 .OR. oBitmap:bits == 24 ) oStatbar:setColorFG( GRA_CLR_YELLOW ) oStatbar:setColorBG( GRA_CLR_RED ) oStatbar:setFontCompoundName( "8.Arial Bold" ) oStatBar:setcaption(">>>>>>> ERROR: Cannot process a "+ ; Ltrim(Str(oBitmap:bits))+"-bit Bitmap Image. 8 and 24bit only. <<<<<<<") ENDIF Return nil * END FUNCTION LoadBitmap( ) ******************************************************************************** * ******************************************************************************** * FUNCTION SaveBmp8Bit() * ******************************************************************************** * FUNCTION SaveBmp8Bit(cFileName, nBits, cTable, cData, nPxWd, nPxHt ) LOCAL cFileDump, nHandle, nBytes, lOk := .F. IF ! ".BMP" $ Upper(cFileName) cFileName += ".BMP" ENDIF nHandle := FCreate( cFileName, 0 ) cFileDump:= ; "BM"+ ; // Identifier U2Bin( 54 + Len(cTable) + Len(cData ))+ ; // Filesize U2Bin( 0 )+ ; // Reserved U2Bin( 54 + Len(cTable))+ ; // Data Offset U2Bin( 40 )+ ; // Header Size U2Bin( nPxWd )+ ; // Width U2Bin( nPxHt )+ ; // Height W2Bin( 1 )+ ; // Planes W2Bin( nBits )+ ; // Bits U2Bin( 0 )+ ; // Compression (None) U2Bin( Len(cData ) )+ ; // Data length U2Bin( 0 )+ ; // Px Hres / Mt U2Bin( 0 )+ ; // Px Vres / Mt U2Bin( 0 )+ ; // Colours U2Bin( 0 )+ ; // Important Colours cTable+ ; // Colour Table cData // Pixel Data nBytes := Len( cFileDump ) lOk := (nBytes == FWrite( nHandle, cFileDump, nBytes )) FClose( nHandle ) RETURN lOk * END FUNCTION SaveBmp8Bit() ******************************************************************************** * ******************************************************************************** * FUNCTION SaveBmp24Bit() * ******************************************************************************** * FUNCTION SaveBmp24Bit(cFileName, cData, nPxWd, nPxHt ) LOCAL cFileDump, nHandle, nBytes, lOk := .F. IF ! ".BMP" $ Upper(cFileName) cFileName += ".BMP" ENDIF nHandle := FCreate( cFileName, 0 ) cFileDump:= ; "BM"+ ; // Identifier U2Bin( 54 + Len(cData ))+ ; // Filesize U2Bin( 0 )+ ; // Reserved U2Bin( 54 )+ ; // Data Offset U2Bin( 40 )+ ; // Header Size U2Bin( nPxWd )+ ; // Width U2Bin( nPxHt )+ ; // Height W2Bin( 1 )+ ; // Planes W2Bin( 24 )+ ; // Bits U2Bin( 0 )+ ; // Compression (None) U2Bin( Len(cData ) )+ ; // Data length U2Bin( 0 )+ ; // Px Hres / Mt U2Bin( 0 )+ ; // Px Vres / Mt U2Bin( 0 )+ ; // Colours U2Bin( 0 )+ ; // Important Colours ""+ ; // Colour Table cData // Pixel Data nBytes := Len( cFileDump ) lOk := (nBytes == FWrite( nHandle, cFileDump, nBytes )) FClose( nHandle ) RETURN lOk * END FUNCTION SaveBmp24Bit() ******************************************************************************** * ******************************************************************************** * * FUNCTION GetRGBVals() * * nValue = an RGB composite value, with or without a 0x1000000 mask. * * (This is used in a program where a colour value is calculated and can * result in a negative value so the Abs() is taken.) * ******************************************************************************** * FUNCTION GetRGBVals(nColor) LOCAL aRGB:= {0,0,0} ***** Allow for no argument. ***** Validate range and if necessary convert to 24bit integer value. nColor:= IIF( nColor == nil, 0, INT( Abs( nColor % 16777216 ) ) ) IF !(nColor == 0) //aRGB[1] := INT( AND(nColor,0x0000FF) ) //aRGB[2] := INT( AND(nColor,0x00FF00) / 0x000100 ) //aRGB[3] := INT( AND(nColor,0xFF0000) / 0x010000 ) aRGB[3] := INT( nColor / 65536 ) aRGB[2] := INT((nColor % 65536 ) / 256 ) aRGB[1] := INT( nColor % 256 ) ENDIF RETURN aRGB * END FUNCTION GetRGBVals() ******************************************************************************** ******************************************************************************** * * FUNCTION ARGB() * * Submitted: Array of values for Red, Green and Blue * Returned : Composite RGB value with 0x1000000 Mask * This is the Xbase++ Gra_aa_aaaaa Colour Value. * ******************************************************************************** * FUNCTION ARGB(aRGB) Return Int( aRGB[1]+ (aRGB[2]*256) + (aRGB[3]*65536) + 0x1000000 ) // Mask * * END FUNCTION ARGB() ******************************************************************************** ******************************************************************************** * * FUNCTION MouseTrap() * ******************************************************************************** * FUNCTION MouseTrap(o,aP) LOCAL aSz := o:currentSize() IF (aP[1] > 0 .AND. aP[1] < aSz[1] .AND. ; aP[2] > 0 .AND. aP[2] < aSz[2]) IF !(lHotSpot) o:captureMouse( .T. ) lHotSpot := .T. ENDIF ELSE IF lHotSpot o:captureMouse( .F. ) lHotSpot := .F. ENDIF ENDIF RETURN nil * * END FUNCTION MouseTrap() ******************************************************************************** ******************************************************************************** * FUNCTION FFlush() ******************************************************************************** * FUNCTION FFlush( hFile ) FlushFileBuffers( hFile ) RETURN Nil * END FUNCTION FFlush() ******************************************************************************** ******************************************************************************** * * API DLLs Declaration * ******************************************************************************** * DLLFUNCTION GetWindowDC( hwnd ) USING STDCALL FROM USER32.DLL DLLFUNCTION ReleaseDC(hwnd, hdc) USING STDCALL FROM USER32.DLL DLLFUNCTION GetPixel( hdc, x, y ) USING STDCALL FROM GDI32.DLL DLLFUNCTION FlushFileBuffers( hFile ) USING STDCALL FROM KERNEL32.DLL * END API DLLs Declaration ******************************************************************************** * **** END