1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030 |
- /*
- * Copyright (C) =USTC= Fu Li
- *
- * Author : Fu Li
- * Create : 2005-7-29
- * Home : http://www.crazy-bit.com/
- * Mail : crazybit@263.net
- * History :
- */
- #ifndef __FOO_PIXEL_PROCESSOR_BASE__2005_07_29__H__
- #define __FOO_PIXEL_PROCESSOR_BASE__2005_07_29__H__
- #include "../FHistogram.h"
- //class FCInterface_PixelProcess ;
- class FCSinglePixelProcessBase ;
- class FCPixelConvertTo16Bit ; // 1, 4, 8, 24, 32 ==> 16
- class FCPixelConvertTo8BitGray ; // 1, 4, 8, 16, 24, 32 ==> 8bit gray
- class FCPixelGrayscale ; // gray scale (>=24 bit)
- class FCPixelFillColor ; // fill color (>=24 bit)
- class FCPixelFillPattern ; // fill pattern (32 bit)
- class FCPixelCombineColor ; // combine color (32 bit)
- class FCPixelHueSaturation ; // hue saturation (>=24 bit)]
- class FCPixelMirror ; // mirror (>=8 bit)
- class FCPixelFlip ; // flip (>=8 bit)
- class FCPixelShift ; // shift (>=24 bit)
- class FCPixelAutoContrast ; // auto contrast (>=24 bit)
- class FCPixelAutoColorEnhance ; // auto color enhance (>=24 bit)
- class FCPixelEmboss ; // emboss (>=24 bit)
- class FCPixelIllusion ; // illusion (>=24 bit)
- class FCPixelBlinds ; // blinds (>=24 bit)
- class FCPixelMosaic ; // mosaic (32 bit)
- class FCPixelFill3DSolidFrame ; // fill 3D solid frame (>=24 bit)
- class FCPixelAdjustRGB ; // adjust RGB (>=24 bit)
- class FCPixelColorLevel ; // color level (>=24 bit)
- class FCPixelThreshold ; // threshold (>=24 bit)
- class FCPixelRotate90 ; // clockwise rotate 90' (>=8 bit)
- class FCPixelRotate270 ; // clockwise rotate 270' (>=8 bit)
- class FCPixelDeinterlace ; // de-interlace (32 bit)
- class FCPixelHalftoneM3 ; // halftone (>=24 bit)
- class FCPixelOilPaint ; // oil paint (>=24 bit)
- class FCPixelColorTone ; // color tone (>=24 bit)
- class FCPixelAddRandomNoise ; // add random noise (>=24 bit)
- class FCPixelSplash ; // splash (>=24 bit)
- class FCPixelVideo ; // video (>=24 bit)
- class FCPixelColorBalance ; // color balance (>=24 bit)
- class FCPixelFillGrid ; // fill grid (>=24 bit)
- class FCPixel3DGrid ; // add 3D grid (>=24 bit)
- class FCPixelMedianFilter ; // Median filter (>=24 bit)
- class FCPixelSpliteChannel_RGB ; // splite RGB channel (>=24 bit)
- class FCPixelCombineChannel_RGB ; // combine RGB channel (>=24 bit)
- class FCPixelConvolute ; // image convolute (>= 24 bit)
- class FCPixelGaussianBlur3x3 ; // Standard 3x3 gaussian blur (>=24 bit)
- class FCPixelGaussianBlur5x5 ; // Standard 5x5 gaussian blur (>=24 bit)
- class FCPixelDetectEdges ; // Detect edges (>=24 bit)
- class FCPixelSharp ; // Sharp (laplacian template) (>=24 bit)
- class FCPixelGradientBase ; // base class of gradient fill (>=24 bit)
- class FCPixelGradientLine ; // gradient fill linear (>=24 bit)
- class FCPixelGradientBiLine ; // gradient fill bilinear (>=24 bit)
- class FCPixelGradientConicalSym ; // gradient fill symmetric conical (>=24 bit)
- class FCPixelGradientConicalASym ; // gradient fill Anti-symmetric conical (>=24 bit)
- class FCPixelGradientRect ; // gradient fill rect (>=24 bit)
- class FCPixelGradientRadial ; // gradient fill radial (>=24 bit)
- class FCPixelBilinearDistord ; // bilinear distord (>=24 bit)
- class FCPixelCylinder ; // cylinder (>=24 bit)
- class FCPixelWave ; // wave (>=24 bit)
- class FCPixelWhirlPinch ; // whirl & pinch (>=24 bit)
- class FCPixelFractalTrace ; // Fractal trace (>=24 bit)
- class FCPixelLens ; // lens (>=24 bit)
- class FCPixelSkew ; // skew transform (>=24 bit)
- class FCPixelPerspective ; // perspective transform (>=24 bit)
- class FCPixelRotate ; // rotate (>=24 bit)
- class FCPixelRibbon ; // ribbon (>=24 bit)
- class FCPixelRipple ; // ripple (>=24 bit)
- class FCPixelSmallTile ; // tile (>=24 bit)
- class FCPixelLUTRoutine ; // LUT(look up table) routine (>=24 bit)
- class FCPixelBrightness ; // adjust brightness (>=24 bit)
- class FCPixelContrast ; // adjust contrast (>=24 bit)
- class FCPixelGamma ; // adjust gamma (>=24 bit)
- class FCPixelInvert ; // negate (>=24 bit)
- class FCPixelSolarize ; // Solarize (>=24 bit)
- class FCPixelPosterize ; // posterize (>=24 bit)
- class FCPixelColorsCount ; // count image's number of color (>=24 bit)
- class FCPixelGetKeyColor ; // Find a color unused in image (>=24 bit)
- class FCPixelWholeImageBase ; // process whole image.
- class FCPixelExportAscII ; // save a ASCII text file (>=24 bit)
- class FCPixelConvertQuantize ; // quantize (Need FREEIMAGE)
- class FCPixelGlasstile ; // glasstile (>=24 bit)
- class FCPixelBlur_Box ; // box smooth (>=24 bit)
- class FCPixelBlur_Zoom ; // blur zoom (>=24 bit)
- class FCPixelBlur_Radial ; // blur radial (>=24 bit)
- class FCPixelBlur_Motion ; // blur motion (>=24 bit)
- class FCPixelBlur_Gauss_IIR ; // blur IIR gauss (>=24 bit)
- class FCPixelInnerBevel ; // add inner bevel frame (>=24 bit)
- class FCPixelSmoothEdge ; // smooth edge (32 bit)
- class FCPixelAddShadow ; // add shadow (32 bit)
- //=============================================================================
- /**
- * Base class of processor.
- */
- class FCSinglePixelProcessBase : public FCInterface_PixelProcess
- {
- public:
- FCSinglePixelProcessBase() : m_pImgOld(0) {}
- virtual ~FCSinglePixelProcessBase() {if(m_pImgOld) delete m_pImgOld;}
- /// whether the image can be disposed by this processor.
- /// default test image's bpp >= 24
- virtual bool ValidateColorBits (const FCObjImage* pImg)
- {
- return pImg->IsValidImage() && (pImg->ColorBits() >= 24) ;
- }
- protected:
- void SetBackupImage (const FCObjImage* pImg)
- {
- if (pImg)
- {
- if (m_pImgOld)
- delete m_pImgOld ;
- m_pImgOld = new FCObjImage(*pImg) ;
- }
- }
- FCObjImage* GetBackupImage() const {return m_pImgOld;}
- private:
- FCObjImage * m_pImgOld ; // backup image
- };
- //=============================================================================
- /**
- * 1, 4, 8, 24, 32 ==> 16.
- @verbatim
- example:
- FCPixelConvertTo16Bit aCmd ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelConvertTo16Bit : public FCSinglePixelProcessBase
- {
- virtual bool ValidateColorBits (const FCObjImage* pImg) {return pImg->IsValidImage() && (pImg->ColorBits() != 16) ;}
- virtual void OnEnterProcess (FCObjImage* pImg)
- {
- SetBackupImage(pImg) ;
- // make it easier, now we only need 24(32) ==> 16
- if (pImg->ColorBits() <= 8)
- GetBackupImage()->ConvertTo24Bit() ;
- pImg->Create (pImg->Width(), pImg->Height(), 16) ;
- }
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- *(WORD*)pPixel = Combine16Bit_555 (GetBackupImage()->GetBits(x,y)) ; // 24,32 ==> 16
- }
- static WORD Combine16Bit_555 (const void* pRGB)
- {
- const WORD wR = ((PCL_R(pRGB) >> 3) << 10),
- wG = ((PCL_G(pRGB) >> 3) << 5),
- wB = (PCL_B(pRGB) >> 3) ;
- return (wR | wG | wB) ;
- }
- };
- //=============================================================================
- /**
- * 1, 4, 8, 16, 24, 32 ==> 8bit gray.
- @verbatim
- example:
- FCPixelConvertTo8BitGray aCmd ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelConvertTo8BitGray : public FCSinglePixelProcessBase
- {
- virtual bool ValidateColorBits (const FCObjImage* pImg) {return pImg->IsValidImage();}
- virtual void OnEnterProcess (FCObjImage* pImg)
- {
- SetBackupImage(pImg) ;
- // make it easier, now we only need 24(32) ==> 8bit gray
- if (pImg->ColorBits() <= 16)
- GetBackupImage()->ConvertTo24Bit() ;
- pImg->Create (pImg->Width(), pImg->Height(), 8) ; // default to set a gray palette
- }
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- *pPixel = FCColor::GetGrayscale (GetBackupImage()->GetBits(x,y)) ;
- }
- };
- //=============================================================================
- /**
- * Gray scale image (>=24 bit).
- * all channel are same after process.
- @verbatim
- example:
- FCPixelGrayscale aCmd ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelGrayscale : public FCSinglePixelProcessBase
- {
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- PCL_R(pPixel) = PCL_G(pPixel) = PCL_B(pPixel) = FCColor::GetGrayscale(pPixel) ;
- }
- };
- //=============================================================================
- /**
- * Fill color (>=24 bit).
- @verbatim
- example:
- const RGBQUAD cr = PCL_RGBA(0,0,255) ;
- FCPixelFillColor aCmd (cr, 192) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelFillColor : public FCSinglePixelProcessBase
- {
- public:
- /// Constructor.
- /// @param nAlpha == -1, not fill alpha
- FCPixelFillColor (RGBQUAD crFill, int nAlpha=-1) : m_crFill(crFill), m_nAlpha(nAlpha), m_bIsFillAlpha(false) {}
- private:
- virtual bool ValidateColorBits (const FCObjImage* pImg)
- {
- if (pImg->IsValidImage() && (pImg->ColorBits() >= 24))
- {
- m_bIsFillAlpha = ((m_nAlpha != -1) && (pImg->ColorBits() == 32)) ;
- PCL_A(&m_crFill) = m_bIsFillAlpha ? FClamp0255(m_nAlpha) : 0 ;
- return true ;
- }
- return false ;
- }
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- FCColor::CopyPixel (pPixel, &m_crFill, m_bIsFillAlpha ? 4 : 3) ;
- }
- RGBQUAD m_crFill ;
- int m_nAlpha ;
- bool m_bIsFillAlpha ;
- };
- //=============================================================================
- /**
- * Fill pattern image (32 bit).
- @verbatim
- example:
- FCObjImage * pMask = new FCObjImage ("c:\\test.jpg") ;
- FCPixelFillPattern aCmd (pMask, 192, false) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelFillPattern : public FCSinglePixelProcessBase
- {
- public:
- /// Constructor.
- FCPixelFillPattern (FCObjImage* pPattern, int nAlpha, bool bOnlyTexture) : m_pPattern(pPattern), m_nAlpha(FClamp0255(nAlpha)), m_bOnlyTexture(bOnlyTexture)
- {
- if (pPattern)
- pPattern->ConvertTo24Bit() ;
- }
- private:
- virtual bool ValidateColorBits (const FCObjImage* pImg)
- {
- return pImg->IsValidImage() && (pImg->ColorBits() == 32) && m_pPattern.get() && (m_pPattern->ColorBits() >= 24) ;
- }
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- BYTE * pPat = m_pPattern->GetBits (x % m_pPattern->Width(), y % m_pPattern->Height()) ;
- if (m_bOnlyTexture)
- {
- // calculate texture
- int n = (PCL_B(pPat)+PCL_G(pPat)+PCL_R(pPat) - 384) * m_nAlpha / 765 ;
- PCL_B(pPixel) = FClamp0255 (PCL_B(pPixel) - n) ;
- PCL_G(pPixel) = FClamp0255 (PCL_G(pPixel) - n) ;
- PCL_R(pPixel) = FClamp0255 (PCL_R(pPixel) - n) ;
- }
- else
- {
- FCColor::CombineAlphaPixel ((RGBQUAD*)pPixel, *(RGBQUAD*)pPixel, pPat, m_nAlpha) ;
- }
- }
- std::auto_ptr<FCObjImage> m_pPattern ; // 24bit or 32bit
- int m_nAlpha ;
- bool m_bOnlyTexture ;
- };
- //=============================================================================
- /**
- * Combine color (32 bit).
- @verbatim
- example:
- const RGBQUAD cr = PCL_RGBA(0,0,255,128) ;
- FCPixelCombineColor aCmd (cr) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelCombineColor : public FCSinglePixelProcessBase
- {
- public:
- /// Constructor.
- FCPixelCombineColor (RGBQUAD crFill) : m_crFill(crFill) {}
- private:
- virtual bool ValidateColorBits (const FCObjImage* pImg)
- {
- return pImg->IsValidImage() && (pImg->ColorBits() == 32) ;
- }
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- RGBQUAD * p = (RGBQUAD*)pPixel ;
- FCColor::CombineAlphaPixel (p, *p, &m_crFill, PCL_A(&m_crFill)) ;
- }
- RGBQUAD m_crFill ;
- };
- //=============================================================================
- /**
- * Adjust image's hue & saturation (>=24 bit).
- @verbatim
- example:
- FCPixelHueSaturation aCmd (100, 150) ; // not change hue, add 50% saturation
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelHueSaturation : public FCSinglePixelProcessBase
- {
- public:
- /// Constructor (param's unit is percentage).
- /// nPercentHue range is (0,200)
- FCPixelHueSaturation (int nPercentHue, int nPercentSat) : m_nPercentHue(FMax(0,nPercentHue)), m_nPercentSat(FMax(0,nPercentSat)) {}
- protected:
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- double H, L, S ;
- FCColor::RGBtoHLS (pPixel, &H, &L, &S) ;
- if (m_nPercentHue != 100)
- {
- if (m_nPercentHue > 100)
- {
- H = H + (1.0 - H) * (m_nPercentHue-100) / 100 ;
- }
- else
- {
- H = H - H * (100-m_nPercentHue) / 100 ;
- }
- }
- if (m_nPercentSat != 100)
- {
- S = S * m_nPercentSat / 100 ;
- }
- RGBQUAD cr = FCColor::HLStoRGB (H, L, S) ;
- FCColor::CopyPixel (pPixel, &cr, 3) ;
- }
- int m_nPercentHue, m_nPercentSat ;
- };
- //=============================================================================
- /**
- * Left-Right mirror image (>=8 bit).
- @verbatim
- example:
- FCPixelMirror aCmd ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelMirror : public FCSinglePixelProcessBase
- {
- virtual bool ValidateColorBits (const FCObjImage* pImg)
- {
- return pImg->IsValidImage() && (pImg->ColorBits() >= 8) ;
- }
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- if (x < pImg->Width()/2)
- {
- BYTE * pRight = pImg->GetBits (pImg->Width()-1-x, y) ;
- for (int i=0 ; i < pImg->ColorBits()/8 ; i++)
- FSwap (pPixel[i], pRight[i]) ; // bytes of per pixel
- }
- }
- };
- //=============================================================================
- /**
- * Top-Bottom flip image (>=8 bit).
- @verbatim
- example:
- FCPixelFlip aCmd ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelFlip : public FCSinglePixelProcessBase
- {
- virtual bool ValidateColorBits (const FCObjImage* pImg)
- {
- return pImg->IsValidImage() && (pImg->ColorBits() >= 8) ;
- }
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- if (y < pImg->Height()/2)
- {
- BYTE * pBottom = pImg->GetBits (x, pImg->Height()-1-y) ;
- for (int i=0 ; i < pImg->ColorBits()/8 ; i++)
- FSwap (pPixel[i], pBottom[i]) ; // bytes of per pixel
- }
- }
- };
- //=============================================================================
- /**
- * Shift (>=24 bit).
- @verbatim
- example:
- FCPixelShift aCmd(5) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelShift : public FCSinglePixelProcessBase
- {
- public:
- FCPixelShift (int nAmount) : m_nAmount (FMax(0,nAmount)) {srand((unsigned int)time(0));}
- private:
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- const int nSpan = pImg->ColorBits() / 8 ;
- int nShift = rand() % (m_nAmount+1) ;
- // first pixel every line
- if (x || !m_nAmount || !nShift)
- return ;
- BYTE crLeft[4], crRight[4] ; // L/R edge pixel color
- FCColor::CopyPixel (crLeft, pImg->GetBits(y), nSpan) ;
- FCColor::CopyPixel (crRight, pImg->GetBits(pImg->Width()-1,y), nSpan) ;
- if (rand() % 2)
- {
- // shift right
- if (pImg->Width() > nShift)
- memmove (pImg->GetBits(nShift,y), pPixel, (pImg->Width()-nShift)*nSpan) ;
- else
- nShift = pImg->Width() ;
- for (int i=0 ; i < nShift ; i++, pPixel+=nSpan)
- FCColor::CopyPixel (pPixel, crLeft, nSpan) ;
- }
- else
- {
- // shift left
- if (pImg->Width() > nShift)
- memmove (pPixel, pImg->GetBits(nShift,y), (pImg->Width()-nShift)*nSpan) ;
- else
- nShift = pImg->Width() ;
- pPixel = pImg->GetBits(pImg->Width()-1, y) ;
- for (int i=0 ; i < nShift ; i++, pPixel-=nSpan)
- FCColor::CopyPixel (pPixel, crRight, nSpan) ;
- }
- }
- int m_nAmount ; // max shift pixel
- };
- //=============================================================================
- /**
- * Auto contrast (>=24 bit).
- @verbatim
- example:
- FCPixelAutoContrast aCmd ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelAutoContrast : public FCSinglePixelProcessBase
- {
- virtual void OnEnterProcess (FCObjImage* pImg)
- {
- BYTE byCmin[3] = {255, 255, 255},
- byCmax[3] = {0, 0, 0} ;
- // Get minimum and maximum values for each channel
- for (int y=0 ; y < pImg->Height() ; y++)
- for (int x=0 ; x < pImg->Width() ; x++)
- {
- BYTE * pPixel = pImg->GetBits(x,y) ;
- for (int b=0 ; b < 3 ; b++)
- {
- if (pPixel[b] < byCmin[b]) byCmin[b] = pPixel[b] ;
- if (pPixel[b] > byCmax[b]) byCmax[b] = pPixel[b] ;
- }
- }
- // Calculate LUTs with stretched contrast
- for (int b=0 ; b < 3 ; b++)
- {
- const int nRange = byCmax[b] - byCmin[b] ;
- if (nRange)
- {
- for (int x=byCmin[b] ; x <= byCmax[b] ; x++)
- m_byLut[x][b] = 255 * (x - byCmin[b]) / nRange ;
- }
- else
- m_byLut[byCmin[b]][b] = byCmin[b] ;
- }
- }
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- for (int b=0 ; b < 3 ; b++)
- pPixel[b] = m_byLut[pPixel[b]][b] ;
- }
- BYTE m_byLut[256][3] ;
- };
- //=============================================================================
- /**
- * Auto color enhance (>=24 bit).
- @verbatim
- example:
- FCPixelAutoColorEnhance aCmd ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelAutoColorEnhance : public FCSinglePixelProcessBase
- {
- virtual void OnEnterProcess (FCObjImage* pImg)
- {
- m_vhi = 0.0 ; m_vlo = 1.0 ;
- // Get minimum and maximum values
- for (int y=0 ; y < pImg->Height() ; y++)
- for (int x=0 ; x < pImg->Width() ; x++)
- {
- BYTE * pPixel = pImg->GetBits(x,y) ;
- int c = 255 - PCL_B(pPixel),
- m = 255 - PCL_G(pPixel),
- y = 255 - PCL_R(pPixel),
- k = c ;
- if (m < k) k = m ;
- if (y < k) k = y ;
- BYTE byMap[4] = { c-k, m-k, y-k } ;
- double h, z, v ;
- FCColor::RGBtoHSV (byMap, &h, &z, &v) ;
- if (v > m_vhi) m_vhi = v ;
- if (v < m_vlo) m_vlo = v ;
- }
- }
- virtual void ProcessPixel (FCObjImage* pImg, int nx, int ny, BYTE* pPixel)
- {
- int c = 255 - PCL_B(pPixel),
- m = 255 - PCL_G(pPixel),
- y = 255 - PCL_R(pPixel),
- k = c ;
- if (m < k) k = m ;
- if (y < k) k = y ;
- BYTE byMap[4] = { c-k, m-k, y-k } ;
- double h, z, v ;
- FCColor::RGBtoHSV (byMap, &h, &z, &v) ;
- if (m_vhi != m_vlo)
- v = (v-m_vlo) / (m_vhi-m_vlo) ;
- *(RGBQUAD*)byMap = FCColor::HSVtoRGB (h, z, v) ;
- c = byMap[0] ; m = byMap[1] ; y = byMap[2] ;
- c += k ; if (c > 255) c = 255 ;
- m += k ; if (m > 255) m = 255 ;
- y += k ; if (y > 255) y = 255 ;
- PCL_B(pPixel) = 255 - c ;
- PCL_G(pPixel) = 255 - m ;
- PCL_R(pPixel) = 255 - y ;
- }
- double m_vhi, m_vlo ;
- };
- //=============================================================================
- /**
- * Emboss effect (>=24 bit).
- @verbatim
- example:
- FCPixelEmboss aCmd(5) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelEmboss : public FCSinglePixelProcessBase
- {
- public:
- /// Constructor.
- FCPixelEmboss (int nLevel) : m_nLevel(nLevel) {}
- private:
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- int nGray ;
- if (x == pImg->Width()-1)
- nGray = 128 ; // the last right col pixel
- else
- {
- BYTE * pNext = pImg->GetBits (x+1, y) ;
- int nSum = PCL_R(pPixel) + PCL_G(pPixel) + PCL_B(pPixel),
- nSumNx = PCL_R(pNext) + PCL_G(pNext) + PCL_B(pNext) ;
- nGray = FClamp0255 (m_nLevel * (nSum - nSumNx) / 3 + 128) ;
- }
- PCL_R(pPixel) = PCL_G(pPixel) = PCL_B(pPixel) = nGray ;
- }
- int m_nLevel ;
- };
- //=============================================================================
- /**
- * Illusion effect (>=24 bit).
- @verbatim
- example:
- FCPixelIllusion aCmd(3) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelIllusion : public FCSinglePixelProcessBase
- {
- public:
- FCPixelIllusion (int nAmount) : m_nAmount(nAmount) {}
- private:
- virtual void OnEnterProcess (FCObjImage* pImg)
- {
- SetBackupImage (pImg) ;
- m_fScale = FHypot ((double)pImg->Width(),(double)pImg->Height()) / 2.0 ;
- m_fOffset = (int)(m_fScale / 2.0) ;
- }
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- const double fXCen = pImg->Width() / 2.0,
- fYCen = pImg->Height() / 2.0,
- cx = (x - fXCen) / m_fScale,
- cy = (y - fYCen) / m_fScale,
- fTmp = LIB_PI / (double)m_nAmount ;
- double angle = floor (atan2(cy,cx) / 2.0 / fTmp) * 2.0 * fTmp + fTmp ;
- double radius = FHypot (cx, cy) ;
-
- int xx = (int)(x - m_fOffset * cos (angle)),
- yy = (int)(y - m_fOffset * sin (angle)) ;
- xx = FClamp (xx, 0, pImg->Width()-1) ;
- yy = FClamp (yy, 0, pImg->Height()-1) ;
- const BYTE * pPixel2 = GetBackupImage()->GetBits (xx, yy) ;
- for (int i=0 ; i < pImg->ColorBits()/8 ; i++)
- pPixel[i] = FClamp0255 (pPixel[i] + (int)(radius * (pPixel2[i] - pPixel[i]))) ;
- }
- int m_nAmount ;
- double m_fScale, m_fOffset ;
- };
- //=============================================================================
- /**
- * Blind effect (>=24 bit).
- @verbatim
- example:
- FCPixelBlinds aCmd(AXIS_X, 10, 50, PCL_RGBA(0,0,255)) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelBlinds : public FCSinglePixelProcessBase
- {
- public:
- /// Constructor.
- /// @param nOpacity : percentage [1,100]
- FCPixelBlinds (AXIS_SYS nDirect, int nWidth, int nOpacity, RGBQUAD crBlind) : m_nWidth(nWidth), m_crBlind(crBlind)
- {
- m_nOpacity = FClamp (nOpacity, 1, 100) ;
- m_nDirect = nDirect ;
- if ((m_nDirect != AXIS_X) && (m_nDirect != AXIS_Y))
- m_nDirect = AXIS_X ;
- }
- private:
- virtual void OnEnterProcess (FCObjImage* pImg)
- {
- int nMaxWidth = FMax (pImg->Width(), pImg->Height()) ;
- m_nWidth = FClamp (m_nWidth, 2, nMaxWidth) ;
- }
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- int nMod ;
- if (m_nDirect == AXIS_X) // horizontal direction
- nMod = y % m_nWidth ;
- else if (m_nDirect == AXIS_Y) // vertical direction
- nMod = x % m_nWidth ;
- double fAlphaAdd = 255.0 * m_nOpacity/100.0 / (m_nWidth-1.0) ;
- FCColor::AlphaBlendPixel (pPixel, (BYTE*)&m_crBlind, FClamp0255((int)(nMod * fAlphaAdd))) ;
- }
- AXIS_SYS m_nDirect ;
- int m_nWidth ;
- int m_nOpacity ;
- RGBQUAD m_crBlind ;
- };
- //=============================================================================
- /**
- * Mosaic effect (32 bit).
- @verbatim
- example:
- FCPixelMosaic aCmd(5) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelMosaic : public FCSinglePixelProcessBase
- {
- public:
- /// Constructor.
- /// @param nBlock : pixel width of block
- FCPixelMosaic (int nBlock) : m_nBlock(FMax(2,nBlock)) {}
- private:
- virtual bool ValidateColorBits (const FCObjImage* pImg) {return pImg->IsValidImage() && (pImg->ColorBits() == 32);}
- virtual void OnEnterProcess (FCObjImage* pImg)
- {
- SetBackupImage (pImg) ;
- }
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- if ((x % m_nBlock == 0) && (y % m_nBlock == 0))
- {
- RGBQUAD cr = GetBlockAverage(x, y) ;
- FCColor::CopyPixel (pPixel, &cr, 4) ;
- }
- else
- FCColor::CopyPixel (pPixel, pImg->GetBits(x/m_nBlock*m_nBlock, y/m_nBlock*m_nBlock), 4) ;
- }
- RGBQUAD GetBlockAverage (int x, int y)
- {
- RECT rc = {x, y, x+m_nBlock, y+m_nBlock} ;
- GetBackupImage()->BoundRect(rc) ;
- int nNum = RECTWIDTH(rc) * RECTHEIGHT(rc) ;
- double nSumR=0, nSumG=0, nSumB=0, nSumA=0 ;
- for (int yy=rc.top ; yy < rc.bottom ; yy++)
- {
- for (int xx=rc.left ; xx < rc.right ; xx++)
- {
- BYTE * p = GetBackupImage()->GetBits (xx, yy) ;
- nSumB += PCL_B(p)*PCL_A(p) ; nSumG += PCL_G(p)*PCL_A(p) ;
- nSumR += PCL_R(p)*PCL_A(p) ; nSumA += PCL_A(p) ;
- }
- }
- return PCL_RGBA (nSumA ? (int)(nSumR / nSumA) : 0,
- nSumA ? (int)(nSumG / nSumA) : 0,
- nSumA ? (int)(nSumB / nSumA) : 0,
- nNum ? (int)(nSumA / nNum) : 0xFF) ;
- }
- private:
- int m_nBlock ;
- };
- //=============================================================================
- /**
- * Fill a 3D solid frame (>=24 bit).
- @verbatim
- example:
- FCPixelFill3DSolidFrame aCmd (5) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelFill3DSolidFrame : public FCSinglePixelProcessBase
- {
- public:
- /// Constructor.
- FCPixelFill3DSolidFrame (int nWidth) : m_nWidth(FMax(3,nWidth)) {}
- private:
- virtual void OnEnterProcess (FCObjImage* pImg)
- {
- m_rcOut.left = m_rcOut.top = 0 ;
- m_rcOut.right = pImg->Width() ;
- m_rcOut.bottom = pImg->Height() ;
- const int nShadow = (int)ceil(m_nWidth / 4.0),
- nMid = m_nWidth - 2*nShadow ;
- m_rcO = m_rcOut ; InflateRect (&m_rcO, -nShadow, -nShadow) ;
- m_rcI = m_rcO ; InflateRect (&m_rcI, -nMid, -nMid) ;
- m_rcIn = m_rcI ; InflateRect (&m_rcIn, -nShadow, -nShadow) ;
- }
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- const POINT ptPixel = {x,y} ;
- if (PtInRect (&m_rcIn, ptPixel))
- return ; // in frame, just return
- static RGBQUAD crMain = {192,192,192,255},
- crHighlight = FCColor::crWhite(),
- crShadow = {128,128,128,255} ;
- RGBQUAD crFill ;
- if (PtInRect (&m_rcI, ptPixel))
- {
- crFill = __pcl_CalcRoundColor (ptPixel, m_rcI, m_rcIn, crShadow, crHighlight) ;
- }
- else if (PtInRect (&m_rcO, ptPixel))
- crFill = crMain ;
- else if (PtInRect (&m_rcOut, ptPixel))
- {
- crFill = __pcl_CalcRoundColor (ptPixel, m_rcOut, m_rcO, crHighlight, crShadow) ;
- }
- FCColor::CopyPixel (pPixel, &crFill, pImg->ColorBits()/8) ;
- }
- static RGBQUAD __pcl_CalcRoundColor (const POINT& pt, const RECT& rcOut, const RECT& rcIn, RGBQUAD crLT, RGBQUAD crRB)
- {
- if (pt.x < rcIn.left)
- return (pt.y - rcOut.top < RECTHEIGHT(rcOut) + rcOut.left - pt.x) ? crLT : crRB ;
- if (pt.x >= rcIn.right)
- return (pt.y - rcOut.top < rcOut.right - pt.x) ? crLT : crRB ;
- if (pt.y < rcIn.top)
- return crLT ;
- return crRB ; // pt.y >= rcIn.bottom
- }
- int m_nWidth ; // >=3
- RECT m_rcOut, m_rcO, m_rcI, m_rcIn ;
- };
- //=============================================================================
- /**
- * Adjust image's RGB value (>=24 bit).
- @verbatim
- example:
- FCPixelAdjustRGB aCmd (-100, 50, 220) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelAdjustRGB : public FCSinglePixelProcessBase
- {
- public:
- /// Constructor (param's unit is delta).
- FCPixelAdjustRGB (int nR, int nG, int nB) : m_R(nR), m_G(nG), m_B(nB) {}
- void AdjustRGB (BYTE* pPixel)
- {
- PCL_B(pPixel) = FClamp0255 (PCL_B(pPixel) + m_B) ;
- PCL_G(pPixel) = FClamp0255 (PCL_G(pPixel) + m_G) ;
- PCL_R(pPixel) = FClamp0255 (PCL_R(pPixel) + m_R) ;
- }
- private:
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- AdjustRGB (pPixel) ;
- }
- int m_R, m_G, m_B ;
- };
- //=============================================================================
- /**
- * Color level (>=24 bit).
- @verbatim
- example:
- FCPixelColorLevel aCmd (false, 20, 230) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelColorLevel : public FCSinglePixelProcessBase
- {
- public:
- /// Constructor.
- FCPixelColorLevel (bool bAuto, int nInLow, int nInHigh, IMAGE_CHANNEL nChannel = CHANNEL_RGB)
- {
- m_bAuto = bAuto ;
- m_nInputLow[0] = m_nInputLow[1] = m_nInputLow[2] = FClamp0255(nInLow) ;
- m_nInputHigh[0] = m_nInputHigh[1] = m_nInputHigh[2] = FClamp0255(nInHigh) ;
- m_nOutputLow = 0 ; m_nOutputHigh = 255 ;
- m_bChannelR = (nChannel & CHANNEL_RED) ? true : false ;
- m_bChannelG = (nChannel & CHANNEL_GREEN) ? true : false ;
- m_bChannelB = (nChannel & CHANNEL_BLUE) ? true : false ;
- }
- private:
- virtual void OnEnterProcess (FCObjImage* pImg)
- {
- SetBackupImage (pImg) ;
- if (m_bAuto)
- {
- FCHistogram histo(*pImg) ;
- this->AutoColorLevelChannel (histo, CHANNEL_RED) ;
- this->AutoColorLevelChannel (histo, CHANNEL_GREEN) ;
- this->AutoColorLevelChannel (histo, CHANNEL_BLUE) ;
- }
- }
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- double fInten ;
- if (m_bChannelB)
- {
- fInten = PCL_B(pPixel) - m_nInputLow[0] ;
- if (m_nInputHigh[0] != m_nInputLow[0])
- fInten /= (double)(m_nInputHigh[0] - m_nInputLow[0]) ;
- PCL_B(pPixel) = FClamp0255(FRound(fInten * 255.0)) ;
- }
- if (m_bChannelG)
- {
- fInten = PCL_G(pPixel) - m_nInputLow[1] ;
- if (m_nInputHigh[1] != m_nInputLow[1])
- fInten /= (double)(m_nInputHigh[1] - m_nInputLow[1]) ;
- PCL_G(pPixel) = FClamp0255(FRound(fInten * 255.0)) ;
- }
- if (m_bChannelR)
- {
- fInten = PCL_R(pPixel) - m_nInputLow[2] ;
- if (m_nInputHigh[2] != m_nInputLow[2])
- fInten /= (double)(m_nInputHigh[2] - m_nInputLow[2]) ;
- PCL_R(pPixel) = FClamp0255(FRound(fInten * 255.0)) ;
- }
- }
- void AutoColorLevelChannel (const FCHistogram& histo, IMAGE_CHANNEL nChannel)
- {
- int nIndex = 0 ;
- switch (nChannel)
- {
- case CHANNEL_RED : nIndex = 2 ; break ;
- case CHANNEL_GREEN : nIndex = 1 ; break ;
- case CHANNEL_BLUE : nIndex = 0 ; break ;
- default : assert(false) ; break ;
- }
- const int nCount = histo.GetCount (nChannel) ;
- if (nCount == 0)
- {
- m_nInputLow[nIndex] = m_nInputHigh[nIndex] = 0 ;
- }
- else
- {
- m_nInputLow[nIndex] = 0 ;
- m_nInputHigh[nIndex] = 255 ;
- // Set the low input
- int new_count = 0, i ;
- for (i=0 ; i < 255 ; i++)
- {
- new_count += histo.GetValueCount (i, nChannel) ;
- double percentage = new_count / (double)nCount ;
- double next_percentage = (new_count + histo.GetValueCount (i+1, nChannel)) / (double)nCount ;
- if (fabs (percentage - 0.006) < fabs (next_percentage - 0.006))
- {
- m_nInputLow[nIndex] = i + 1 ;
- break ;
- }
- }
- // Set the high input
- new_count = 0 ;
- for (i=255 ; i > 0 ; i--)
- {
- new_count += histo.GetValueCount (i, nChannel) ;
- double percentage = new_count / (double)nCount ;
- double next_percentage = (new_count + histo.GetValueCount (i-1, nChannel)) / (double)nCount ;
- if (fabs (percentage - 0.006) < fabs (next_percentage - 0.006))
- {
- m_nInputHigh[nIndex] = i - 1 ;
- break ;
- }
- }
- }
- }
- private:
- int m_nInputLow[3], m_nInputHigh[3] ;
- int m_nOutputLow, m_nOutputHigh ;
- bool m_bAuto, m_bChannelR, m_bChannelG, m_bChannelB ;
- };
- //=============================================================================
- /**
- * Threshold image (>=24 bit).
- @verbatim
- example:
- FCPixelThreshold aCmd (128) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelThreshold : public FCSinglePixelProcessBase
- {
- public:
- /// Constructor.
- FCPixelThreshold (int nLevel) : m_nLevel(FClamp0255(nLevel)) {}
- private:
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- RGBQUAD cr = (FCColor::GetGrayscale(pPixel) > m_nLevel) ? FCColor::crWhite() : FCColor::crBlack() ;
- FCColor::CopyPixel (pPixel, &cr, 3) ;
- }
- int m_nLevel ;
- };
- //=============================================================================
- /**
- * Clockwise rotate 90' (>=8 bit).
- @verbatim
- example:
- FCPixelRotate90 aCmd ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelRotate90 : public FCSinglePixelProcessBase
- {
- virtual bool ValidateColorBits (const FCObjImage* pImg)
- {
- return pImg->IsValidImage() && (pImg->ColorBits() >= 8) ;
- }
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- FCColor::CopyPixel (pPixel,
- GetBackupImage()->GetBits (y, pImg->Width()-1-x),
- pImg->ColorBits()/8) ;
- }
- virtual void OnEnterProcess (FCObjImage* pImg)
- {
- SetBackupImage (pImg) ;
- // create new rotated image
- pImg->Create (pImg->Height(), pImg->Width(), pImg->ColorBits()) ;
- if (pImg->ColorBits() <= 8)
- pImg->CopyPalette(*GetBackupImage()) ;
- }
- };
- //=============================================================================
- /**
- * Clockwise rotate 270' (>=8 bit).
- @verbatim
- example:
- FCPixelRotate270 aCmd ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelRotate270 : public FCPixelRotate90
- {
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- FCColor::CopyPixel (pPixel,
- GetBackupImage()->GetBits (pImg->Height()-1-y, x),
- pImg->ColorBits()/8) ;
- }
- };
- //=============================================================================
- /**
- * De-interlace (32 bit).
- @verbatim
- example:
- FCPixelDeinterlace aCmd (FCPixelDeinterlace::SCAN_EVEN) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelDeinterlace : public FCSinglePixelProcessBase
- {
- public:
- enum SCAN_FIELDS { SCAN_EVEN=0, SCAN_ODD=1 };
- /// Constructor.
- /// @param EliminateFields : SCAN_EVEN rebuild even line / SCAN_ODD rebuild odd line.
- FCPixelDeinterlace (SCAN_FIELDS EliminateFields) : m_Fields(EliminateFields) {}
- private:
- virtual bool ValidateColorBits (const FCObjImage* pImg)
- {
- return pImg->IsValidImage() && (pImg->ColorBits() == 32) ;
- }
- // adapted from GIMP v1.2.5 --- code v1.00
- // Deinterlace is useful for processing images from video capture cards.
- // When only the odd or even fields get captured, deinterlace can be used to
- // interpolate between the existing fields to correct this.
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- if ((y == 0) || (y == pImg->Height()-1))
- return ;
- if (y % 2 == m_Fields)
- {
- BYTE * pUp = pImg->GetBits (x, y-1),
- * pDown = pImg->GetBits (x, y+1) ;
- int nSumA = PCL_A(pUp) + PCL_A(pDown) ;
- PCL_A(pPixel) = nSumA / 2 ;
- if (PCL_A(pPixel))
- for (int i=0 ; i < 3 ; i++)
- pPixel[i] = (pUp[i]*PCL_A(pUp) + pDown[i]*PCL_A(pDown)) / nSumA ;
- }
- }
- SCAN_FIELDS m_Fields ;
- };
- //=============================================================================
- /**
- * Halftone (>=24 bit), use Limb Pattern M3 algorithm.
- @verbatim
- example:
- FCPixelHalftoneM3 aCmd ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelHalftoneM3 : public FCSinglePixelProcessBase
- {
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- static const BYTE BayerPattern[8][8] = // 64 level gray
- {
- 0,32,8,40,2,34,10,42,
- 48,16,56,24,50,18,58,26,
- 12,44,4,36,14,46,6,38,
- 60,28,52,20,62,30,54,22,
- 3,35,11,43,1,33,9,41,
- 51,19,59,27,49,17,57,25,
- 15,47,7,39,13,45,5,37,
- 63,31,55,23,61,29,53,21
- };
- const BYTE gr = FCColor::GetGrayscale (pPixel) ;
- PCL_R(pPixel) = PCL_G(pPixel) = PCL_B(pPixel) = (((gr>>2) > BayerPattern[y&7][x&7]) ? 0xFF : 0) ;
- }
- };
- //=============================================================================
- /**
- * Oil paint (>=24 bit).
- @verbatim
- example:
- FCPixelOilPaint aCmd (2) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelOilPaint : public FCSinglePixelProcessBase
- {
- public:
- /// Constructor (nRadius >= 1).
- FCPixelOilPaint (int nRadius)
- {
- m_nRadius = FMax(1,nRadius) ;
- m_nLength = 2*m_nRadius + 1 ; // Stat. block
- }
- private:
- virtual void OnEnterProcess (FCObjImage* pImg)
- {
- SetBackupImage (pImg) ;
- GetBackupImage()->ExpandFrame (true, m_nRadius, m_nRadius, m_nRadius, m_nRadius) ;
- // calculate block gray
- m_ImgGray = *GetBackupImage() ;
- FCPixelConvertTo8BitGray aCmd ;
- m_ImgGray.SinglePixelProcessProc(aCmd) ;
- }
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- BYTE * pSelPixel = NULL ;
- int nMaxNum = 0,
- pHistogram[256] ;
- memset (pHistogram, 0, sizeof(int) * 256) ;
- // replace every pixel use most frequency
- for (int ny=0 ; ny < m_nLength ; ny++)
- {
- BYTE * pGray = m_ImgGray.GetBits (x, y+ny) ;
- for (int i=0 ; i < m_nLength ; i++, pGray++)
- if (++pHistogram[*pGray] > nMaxNum)
- {
- nMaxNum = pHistogram[*pGray] ;
- pSelPixel = GetBackupImage()->GetBits (x+i, y+ny) ;
- }
- }
- FCColor::CopyPixel (pPixel, pSelPixel, 3) ; // leave alpha=channel
- }
- int m_nRadius ; // >= 1
- int m_nLength ; // 2*m_nRadius + 1
- FCObjImage m_ImgGray ;
- };
- //=============================================================================
- /**
- * Color tone (>=24 bit).
- @verbatim
- example:
- FCPixelColorTone aCmd (PCL_RGBA(0,0,255)) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelColorTone : public FCSinglePixelProcessBase
- {
- public:
- /// Constructor.
- FCPixelColorTone (RGBQUAD crTone)
- {
- double L, S ;
- FCColor::RGBtoHLS (&crTone, &m_nHue, &L, &S) ;
- }
- FCPixelColorTone (RGBQUAD crTone, double saturation)
- {
- double L, S ;
- m_saturation=saturation,
- FCColor::RGBtoHLS (&crTone, &m_nHue, &L, &S) ;
- }
- FCPixelColorTone (double crTone, double saturation)
- {
- m_saturation=saturation;
- m_nHue=crTone;
- }
- private:
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- int n = FCColor::GetGrayscale(pPixel) ;
- PCL_B(pPixel) = (BYTE)(255 * pow(n/255.0, 1.2)) ;
- PCL_G(pPixel) = (BYTE)(255 * pow(n/255.0, 1)) ;
- PCL_R(pPixel) = (BYTE)(255 * pow(n/255.0, 0.8)) ;
- double H, L, S ;
- FCColor::RGBtoHLS (pPixel, &H, &L, &S) ;
- if(1)//m_saturation)
- {
- RGBQUAD cr = FCColor::HLStoRGB (m_nHue, L, S * m_saturation) ;
- FCColor::CopyPixel (pPixel, &cr, 3) ;
- }
- else
- {
- RGBQUAD cr = FCColor::HLStoRGB (m_nHue, L, S * 150 / 100) ;
- FCColor::CopyPixel (pPixel, &cr, 3) ;
- }
- }
- double m_nHue ;
- double m_saturation ;
- };
- //=============================================================================
- /**
- * Add random noise (>=24 bit).
- @verbatim
- example:
- FCPixelAddRandomNoise aCmd (5) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelAddRandomNoise : public FCSinglePixelProcessBase
- {
- public:
- /// Constructor.
- FCPixelAddRandomNoise (int nLevel) : m_nLevel(nLevel) {srand((unsigned int)time(NULL));}
- private:
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- int nDelta[3] ;
- for (int i=0 ; i < 3 ; i++)
- {
- nDelta[i] = FRound ((rand()/(double)RAND_MAX - 0.5) * m_nLevel) ;
- }
- PCL_B(pPixel) = FClamp0255 (PCL_B(pPixel) + nDelta[0]) ;
- PCL_G(pPixel) = FClamp0255 (PCL_G(pPixel) + nDelta[1]) ;
- PCL_R(pPixel) = FClamp0255 (PCL_R(pPixel) + nDelta[2]) ;
- }
- int m_nLevel ;
- };
- //=============================================================================
- /**
- * Noisify (>=24 bit).
- @verbatim
- example:
- FCPixelNoisify aCmd (5) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelNoisify : public FCSinglePixelProcessBase
- {
- public:
- /// Constructor.
- /// @param nLevel : level (0 <= nLevel <= 100).
- FCPixelNoisify (int nLevel) : m_nLevel(FClamp(nLevel,0,100)) {srand((unsigned int)time(NULL));}
- private:
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- int nNoise = (int)(m_nLevel * GenGauss() * 127.0 / 100.0) ;
- PCL_B(pPixel) = FClamp0255 (PCL_B(pPixel) + nNoise) ;
- PCL_G(pPixel) = FClamp0255 (PCL_G(pPixel) + nNoise) ;
- PCL_R(pPixel) = FClamp0255 (PCL_R(pPixel) + nNoise) ;
- }
- static double GenGauss()
- {
- return (rand() + rand() + rand() + rand()) * 5.28596089837e-5 - 3.46410161514 ;
- }
- int m_nLevel ;
- };
- //=============================================================================
- /**
- * Splash image (>=24 bit).
- @verbatim
- example:
- FCPixelSplash aCmd (5) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelSplash : public FCSinglePixelProcessBase
- {
- public:
- /// Constructor.
- /// @param nBlock : splash level (>=3).
- FCPixelSplash (int nBlock)
- {
- m_nBlock = FMax (3, nBlock) ;
- srand((unsigned int)time(0)) ;
- }
- private:
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- int xCopy = x - m_nBlock/2 + (rand() % m_nBlock),
- yCopy = y - m_nBlock/2 + (rand() % m_nBlock) ;
- xCopy = FClamp (xCopy, 0, pImg->Width()-1) ;
- yCopy = FClamp (yCopy, 0, pImg->Height()-1) ;
- BYTE * pSrc = GetBackupImage()->GetBits(xCopy,yCopy) ;
- FCColor::CopyPixel (pPixel, pSrc, pImg->ColorBits()/8) ;
- }
- virtual void OnEnterProcess (FCObjImage* pImg)
- {
- SetBackupImage (pImg) ;
- }
- int m_nBlock ;
- };
- //=============================================================================
- /**
- * Video (>=24 bit).
- @verbatim
- example:
- FCPixelVideo aCmd (FCPixelVideo::VIDEO_STAGGERED) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelVideo : public FCSinglePixelProcessBase
- {
- public:
- enum VIDEO_TYPE {VIDEO_STAGGERED=0, VIDEO_TRIPED=1, VIDEO_3X3=2, VIDEO_DOTS=3} ;
- /// Constructor.
- /// @param nVideoType : VIDEO_STAGGERED, VIDEO_TRIPED, VIDEO_3X3, VIDEO_DOTS
- FCPixelVideo (VIDEO_TYPE nVideoType) : m_VideoType(nVideoType)
- {
- assert(nVideoType>=VIDEO_STAGGERED && nVideoType<=VIDEO_DOTS);
- }
- private:
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- static const int pattern_width[] = {2, 1, 3, 5} ;
- static const int pattern_height[] = {6, 3, 3, 15} ;
- static const int video_pattern[4][15 * 5/* max pattern size */] =
- {
- {
- 0, 1,
- 0, 2,
- 1, 2,
- 1, 0,
- 2, 0,
- 2, 1,
- },
- {
- 0,
- 1,
- 2,
- },
- {
- 0, 1, 2,
- 2, 0, 1,
- 1, 2, 0,
- },
- {
- 0, 1, 2, 0, 0,
- 1, 1, 1, 2, 0,
- 0, 1, 2, 2, 2,
- 0, 0, 1, 2, 0,
- 0, 1, 1, 1, 2,
- 2, 0, 1, 2, 2,
- 0, 0, 0, 1, 2,
- 2, 0, 1, 1, 1,
- 2, 2, 0, 1, 2,
- 2, 0, 0, 0, 1,
- 1, 2, 0, 1, 1,
- 2, 2, 2, 0, 1,
- 1, 2, 0, 0, 0,
- 1, 1, 2, 0, 1,
- 1, 2, 2, 2, 0,
- }
- };
- const int nWidth = pattern_width[m_VideoType],
- nHeight = pattern_height[m_VideoType] ;
- for (int i=0 ; i < 3 ; i++)
- if (video_pattern[m_VideoType][nWidth * (y%nHeight) + (x%nWidth)] == i)
- pPixel[i] = FClamp0255 (2 * pPixel[i]) ;
- }
- VIDEO_TYPE m_VideoType ;
- };
- //=============================================================================
- /**
- * Color balance (>=24 bit).
- @verbatim
- example:
- FCPixelColorBalance aCmd (true, TONE_SHADOWS, -30, 20, 30) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelColorBalance : public FCSinglePixelProcessBase
- {
- public:
- /// Constructor.
- FCPixelColorBalance (bool bPreLum, TONE_REGION ToneRgn, int cyan_red, int magenta_green, int yellow_blue)
- {
- m_bPreserveLuminosity = bPreLum ;
- int cyan_red_rgn[3] = {0,0,0},
- magenta_green_rgn[3] = {0,0,0},
- yellow_blue_rgn[3] = {0,0,0} ;
- cyan_red_rgn[ToneRgn] = cyan_red ;
- magenta_green_rgn[ToneRgn] = magenta_green ;
- yellow_blue_rgn[ToneRgn] = yellow_blue ;
- // add for lightening, sub for darkening
- PCL_array<double> highlights_add(256), midtones_add(256), shadows_add(256),
- highlights_sub(256), midtones_sub(256), shadows_sub(256) ;
- int i ;
- for (i=0 ; i < 256 ; i++)
- {
- highlights_add[i] = shadows_sub[255 - i] = (1.075 - 1 / (i / 16.0 + 1)) ;
- midtones_add[i] = midtones_sub[i] = 0.667 * (1 - FSquare ((i - 127.0) / 127.0)) ;
- shadows_add[i] = highlights_sub[i] = 0.667 * (1 - FSquare ((i - 127.0) / 127.0)) ;
- }
- // Set the transfer arrays (for speed)
- double * cyan_red_transfer[3], * magenta_green_transfer[3], * yellow_blue_transfer[3] ;
- cyan_red_transfer[TONE_SHADOWS] = (cyan_red_rgn[TONE_SHADOWS] > 0) ? shadows_add.get() : shadows_sub.get() ;
- cyan_red_transfer[TONE_MIDTONES] = (cyan_red_rgn[TONE_MIDTONES] > 0) ? midtones_add.get() : midtones_sub.get() ;
- cyan_red_transfer[TONE_HIGHLIGHTS] = (cyan_red_rgn[TONE_HIGHLIGHTS] > 0) ? highlights_add.get() : highlights_sub.get() ;
- magenta_green_transfer[TONE_SHADOWS] = (magenta_green_rgn[TONE_SHADOWS] > 0) ? shadows_add.get() : shadows_sub.get() ;
- magenta_green_transfer[TONE_MIDTONES] = (magenta_green_rgn[TONE_MIDTONES] > 0) ? midtones_add.get() : midtones_sub.get() ;
- magenta_green_transfer[TONE_HIGHLIGHTS] = (magenta_green_rgn[TONE_HIGHLIGHTS] > 0) ? highlights_add.get() : highlights_sub.get() ;
- yellow_blue_transfer[TONE_SHADOWS] = (yellow_blue_rgn[TONE_SHADOWS] > 0) ? shadows_add.get() : shadows_sub.get() ;
- yellow_blue_transfer[TONE_MIDTONES] = (yellow_blue_rgn[TONE_MIDTONES] > 0) ? midtones_add.get() : midtones_sub.get() ;
- yellow_blue_transfer[TONE_HIGHLIGHTS] = (yellow_blue_rgn[TONE_HIGHLIGHTS] > 0) ? highlights_add.get() : highlights_sub.get() ;
- for (i=0 ; i < 256 ; i++)
- {
- int r_n = i, g_n = i, b_n = i ;
- r_n += (int)(cyan_red_rgn[TONE_SHADOWS] * cyan_red_transfer[TONE_SHADOWS][r_n]); r_n = FClamp0255(r_n);
- r_n += (int)(cyan_red_rgn[TONE_MIDTONES] * cyan_red_transfer[TONE_MIDTONES][r_n]); r_n = FClamp0255(r_n);
- r_n += (int)(cyan_red_rgn[TONE_HIGHLIGHTS] * cyan_red_transfer[TONE_HIGHLIGHTS][r_n]); r_n = FClamp0255(r_n);
- g_n += (int)(magenta_green_rgn[TONE_SHADOWS] * magenta_green_transfer[TONE_SHADOWS][g_n]); g_n = FClamp0255(g_n);
- g_n += (int)(magenta_green_rgn[TONE_MIDTONES] * magenta_green_transfer[TONE_MIDTONES][g_n]); g_n = FClamp0255(g_n);
- g_n += (int)(magenta_green_rgn[TONE_HIGHLIGHTS] * magenta_green_transfer[TONE_HIGHLIGHTS][g_n]); g_n = FClamp0255(g_n);
- b_n += (int)(yellow_blue_rgn[TONE_SHADOWS] * yellow_blue_transfer[TONE_SHADOWS][b_n]); b_n = FClamp0255(b_n);
- b_n += (int)(yellow_blue_rgn[TONE_MIDTONES] * yellow_blue_transfer[TONE_MIDTONES][b_n]); b_n = FClamp0255(b_n);
- b_n += (int)(yellow_blue_rgn[TONE_HIGHLIGHTS] * yellow_blue_transfer[TONE_HIGHLIGHTS][b_n]); b_n = FClamp0255(b_n);
- m_pLookupR[i] = r_n ;
- m_pLookupG[i] = g_n ;
- m_pLookupB[i] = b_n ;
- }
- }
- private:
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- RGBQUAD rgb ;
- PCL_B(&rgb) = m_pLookupB[PCL_B(pPixel)] ;
- PCL_G(&rgb) = m_pLookupG[PCL_G(pPixel)] ;
- PCL_R(&rgb) = m_pLookupR[PCL_R(pPixel)] ;
- if (m_bPreserveLuminosity) // preserve luminosity
- {
- double H, L, S ;
- FCColor::RGBtoHLS (&rgb, &H, &L, &S) ;
- // calculate L value
- int cmax = FMax (PCL_R(pPixel), FMax (PCL_G(pPixel), PCL_B(pPixel))),
- cmin = FMin (PCL_R(pPixel), FMin (PCL_G(pPixel), PCL_B(pPixel))) ;
- L = (cmax+cmin) / 2.0 / 255.0 ;
- rgb = FCColor::HLStoRGB (H, L, S) ;
- }
- PCL_B(pPixel) = PCL_B(&rgb) ;
- PCL_G(pPixel) = PCL_G(&rgb) ;
- PCL_R(pPixel) = PCL_R(&rgb) ;
- }
- BYTE m_pLookupR[256], m_pLookupG[256], m_pLookupB[256] ;
- bool m_bPreserveLuminosity ;
- };
- //=============================================================================
- /**
- * Fill grid (>=24 bit).
- @verbatim
- example:
- FCPixelFillGrid aCmd (PCL_RGBA(0,255,0), PCL_RGBA(0,0,255), 5) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelFillGrid : public FCSinglePixelProcessBase
- {
- public:
- /// Constructor.
- /// @param nPitch : width of grid.
- FCPixelFillGrid (RGBQUAD cr1, RGBQUAD cr2, int nPitch) : m_cr1(cr1), m_cr2(cr2), m_nPitch(FMax(1,nPitch)) {}
- private:
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- int nX = x / m_nPitch, nY = y / m_nPitch ;
- FCColor::CopyPixel (pPixel, ((nX + nY) % 2 == 0) ? &m_cr1 : &m_cr2, 3) ;
- }
- RGBQUAD m_cr1, m_cr2 ;
- int m_nPitch ;
- };
- //=============================================================================
- /**
- * Add 3D grid (>=24 bit).
- @verbatim
- example:
- FCPixel3DGrid aCmd (32, 60) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixel3DGrid : public FCSinglePixelProcessBase
- {
- public:
- FCPixel3DGrid (int nSize, int nDepth) : m_nSize(FMax(1,nSize)), m_nDepth(nDepth) {}
- private:
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- int nDelta = 0 ;
- if (((y-1) % m_nSize == 0) && (x % m_nSize != 0) && ((x+1) % m_nSize != 0))
- nDelta = -m_nDepth ; // top
- else if (((y+2) % m_nSize == 0) && (x % m_nSize != 0) && ((x+1) % m_nSize != 0))
- nDelta = m_nDepth ; // bottom
- else if (((x-1) % m_nSize == 0) && (y % m_nSize != 0) && ((y+1) % m_nSize != 0))
- nDelta = m_nDepth ; // left
- else if (((x+2) % m_nSize == 0) && (y % m_nSize != 0) && ((y+1) % m_nSize != 0))
- nDelta = -m_nDepth ; // right
- PCL_R(pPixel) = FClamp0255 (PCL_R(pPixel) + nDelta) ;
- PCL_G(pPixel) = FClamp0255 (PCL_G(pPixel) + nDelta) ;
- PCL_B(pPixel) = FClamp0255 (PCL_B(pPixel) + nDelta) ;
- }
- int m_nSize, m_nDepth ;
- };
- //=============================================================================
- /**
- * Median filter (>=24 bit).
- @verbatim
- example:
- FCPixelMedianFilter aCmd (3) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelMedianFilter : public FCSinglePixelProcessBase
- {
- public:
- /// Constructor (nSize >= 2).
- FCPixelMedianFilter (int nSize) : m_nSize(nSize), m_pBlock(0), m_nBlockNum(FSquare(nSize)) {}
- virtual ~FCPixelMedianFilter() {if(m_pBlock) delete[] m_pBlock;}
- private:
- virtual void OnEnterProcess (FCObjImage* pImg)
- {
- m_pBlock = new BlockElem[m_nBlockNum] ;
- SetBackupImage (pImg) ;
- // duplicate edge
- int nLeftTop = m_nSize/2,
- nRightDown = nLeftTop ;
- GetBackupImage()->ExpandFrame (true, nLeftTop, nLeftTop, nRightDown, nRightDown) ;
- m_BakImage = *GetBackupImage() ;
- // calculate gray
- FCPixelConvertTo8BitGray aCmd ;
- GetBackupImage()->SinglePixelProcessProc (aCmd) ;
- }
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- int i = 0 ;
- for (int m=0 ; m < m_nSize ; m++)
- for (int n=0 ; n < m_nSize ; n++)
- {
- m_pBlock[i].nGray = *GetBackupImage()->GetBits (x+n, y+m) ;
- FCColor::CopyPixel (&m_pBlock[i].crOrigin, m_BakImage.GetBits(x+n, y+m), 3) ;
- i++ ;
- }
- ::qsort (m_pBlock, m_nBlockNum, sizeof(BlockElem), __CompareGray) ;
- FCColor::CopyPixel (pPixel, &m_pBlock[m_nBlockNum/2], 3) ;
- }
- struct BlockElem
- {
- RGBQUAD crOrigin ;
- int nGray ;
- };
- static int __CompareGray (const void* arg1, const void* arg2)
- {
- return ((BlockElem*)arg1)->nGray - ((BlockElem*)arg2)->nGray ;
- }
- int m_nSize ;
- int m_nBlockNum ;
- BlockElem * m_pBlock ;
- FCObjImage m_BakImage ;
- };
- //=============================================================================
- /**
- * Splite RGB channel (>=24 bit).
- @verbatim
- example:
- FCObjImage imgBlue, imgGreen ;
- FCPixelSpliteChannel_RGB aCmd (NULL, &imgGreen, &imgBlue) ; // get green & blue channel
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelSpliteChannel_RGB : public FCSinglePixelProcessBase
- {
- public:
- /// Constructor (the received image's bpp is 32).
- /// if you needn't some channel, set the param to NULL.
- FCPixelSpliteChannel_RGB (FCObjImage* pImgR, FCObjImage* pImgG, FCObjImage* pImgB) : m_pImgR(pImgR), m_pImgG(pImgG), m_pImgB(pImgB) {}
- private:
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- if (m_pImgB) *(RGBQUAD*)m_pImgB->GetBits(x,y) = PCL_RGBA(PCL_B(pPixel),PCL_B(pPixel),PCL_B(pPixel),PCL_A(pPixel)) ;
- if (m_pImgG) *(RGBQUAD*)m_pImgG->GetBits(x,y) = PCL_RGBA(PCL_G(pPixel),PCL_G(pPixel),PCL_G(pPixel),PCL_A(pPixel)) ;
- if (m_pImgR) *(RGBQUAD*)m_pImgR->GetBits(x,y) = PCL_RGBA(PCL_R(pPixel),PCL_R(pPixel),PCL_R(pPixel),PCL_A(pPixel)) ;
- }
- virtual void OnEnterProcess (FCObjImage* pImg)
- {
- if (m_pImgR) m_pImgR->Create (pImg->Width(), pImg->Height(), 32) ;
- if (m_pImgG) m_pImgG->Create (pImg->Width(), pImg->Height(), 32) ;
- if (m_pImgB) m_pImgB->Create (pImg->Width(), pImg->Height(), 32) ;
- }
- FCObjImage * m_pImgR, * m_pImgG, * m_pImgB ;
- };
- //=============================================================================
- /**
- * Combine RGB channel (>=24 bit).
- * all channel image must same width & height, bpp == 8.
- @verbatim
- example:
- FCPixelCombineChannel_RGB aCmd (&imgRed, &imgGreen, &imgBlue) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelCombineChannel_RGB : public FCSinglePixelProcessBase
- {
- public:
- FCPixelCombineChannel_RGB (FCObjImage* pImgR, FCObjImage* pImgG, FCObjImage* pImgB) : m_pImgR(pImgR), m_pImgG(pImgG), m_pImgB(pImgB) {}
- private:
- virtual bool ValidateColorBits (const FCObjImage* pImg)
- {
- bool b=m_pImgR && m_pImgG && m_pImgB &&
- (m_pImgR->ColorBits() == 8) && (m_pImgG->ColorBits() == 8) && (m_pImgB->ColorBits() == 8) &&
- (m_pImgR->Width() == m_pImgG->Width()) && (m_pImgR->Width() == m_pImgB->Width()) &&
- (m_pImgR->Height() == m_pImgG->Height()) && (m_pImgR->Height() == m_pImgB->Height()) ;
- if (b)
- const_cast<FCObjImage*>(pImg)->Create (m_pImgR->Width(), m_pImgR->Height(), 32) ;
- return b ;
- }
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- PCL_B(pPixel) = *m_pImgB->GetBits(x,y) ;
- PCL_G(pPixel) = *m_pImgG->GetBits(x,y) ;
- PCL_R(pPixel) = *m_pImgR->GetBits(x,y) ;
- PCL_A(pPixel) = 0xFF ;
- }
- FCObjImage * m_pImgR, * m_pImgG, * m_pImgB ;
- };
- //=============================================================================
- /// Image convolute (>= 24 bit)
- class FCPixelConvolute : public FCSinglePixelProcessBase
- {
- public:
- /// Constructor.
- FCPixelConvolute() : m_pElement(0)
- {
- m_iBlock=0 ; m_nOffset=0 ; m_iDivisor=1 ;
- }
- virtual ~FCPixelConvolute()
- {
- if (m_pElement)
- delete[] m_pElement ;
- }
- /**
- * Set convolute kernel.
- * @param nElements : array from top-left of matrix.
- * @param iBlockLen : width of matrix.
- */
- void SetKernel (const int* nElements, int iBlockLen, int iDivisor, int nOffset=0)
- {
- if (!nElements || (iBlockLen < 1))
- {assert(false); return;}
- if (m_pElement)
- delete[] m_pElement ;
- m_pElement = new int[FSquare(iBlockLen)] ;
- for (int i=0 ; i < FSquare(iBlockLen) ; i++)
- m_pElement[i] = nElements[i] ;
- m_iBlock = iBlockLen ;
- m_iDivisor = FMax(1,iDivisor) ;
- m_nOffset = nOffset ;
- }
- private:
- virtual void OnEnterProcess (FCObjImage* pImg)
- {
- SetBackupImage (pImg) ;
- // duplicate edge, easier to processs
- int nLeftTop = m_iBlock/2,
- nRightDown = nLeftTop ;
- GetBackupImage()->ExpandFrame (true, nLeftTop, nLeftTop, nRightDown, nRightDown) ;
- }
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- // calculate the sum of sub-block
- int nSumR=0, nSumG=0, nSumB=0, i=0 ;
- for (int iy=0 ; iy < m_iBlock ; iy++)
- for (int ix=0 ; ix < m_iBlock ; ix++, i++)
- {
- BYTE * pOld = GetBackupImage()->GetBits (x+ix,y+iy) ;
- nSumB += PCL_B(pOld) * m_pElement[i] ;
- nSumG += PCL_G(pOld) * m_pElement[i] ;
- nSumR += PCL_R(pOld) * m_pElement[i] ;
- }
- // set pixel
- PCL_B(pPixel) = FClamp0255 (m_nOffset + nSumB / m_iDivisor) ;
- PCL_G(pPixel) = FClamp0255 (m_nOffset + nSumG / m_iDivisor) ;
- PCL_R(pPixel) = FClamp0255 (m_nOffset + nSumR / m_iDivisor) ;
- }
- int * m_pElement ;
- int m_iBlock, m_iDivisor, m_nOffset ;
- };
- //=============================================================================
- /**
- * Standard 3x3 gaussian blur (>=24 bit).
- @verbatim
- example:
- FCPixelGaussianBlur3x3 aCmd ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelGaussianBlur3x3 : public FCPixelConvolute
- {
- public:
- FCPixelGaussianBlur3x3()
- {
- int arKernel[] = {1,2,1,2,4,2,1,2,1},
- nBlock = 3,
- nDivisor = 16,
- nOffset = 0 ;
- SetKernel (arKernel, nBlock, nDivisor, nOffset) ;
- }
- };
- //=============================================================================
- /**
- * Standard 5x5 gaussian blur (>=24 bit).
- @verbatim
- example:
- FCPixelGaussianBlur5x5 aCmd ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelGaussianBlur5x5 : public FCPixelConvolute
- {
- public:
- FCPixelGaussianBlur5x5 ()
- {
- int arKernel[] = {0,1,2,1,0,1,3,4,3,1,2,4,8,4,2,1,3,4,3,1,0,1,2,1,0},
- nBlock = 5,
- nDivisor = 52,
- nOffset = 0 ;
- SetKernel (arKernel, nBlock, nDivisor, nOffset) ;
- }
- };
- //=============================================================================
- /**
- * Detect edges (>=24 bit).
- @verbatim
- example:
- FCPixelDetectEdges aCmd(3) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelDetectEdges : public FCPixelConvolute
- {
- public:
- /// Constructor (nRadius >= 1).
- FCPixelDetectEdges (int nRadius = 3)
- {
- int nBlock = 2*FMax(1,nRadius) + 1,
- nDivisor = 1,
- nOffset = 0,
- nWidth = nBlock * nBlock ;
- PCL_array<int> pKernel (nWidth) ;
- for (int i=0 ; i < nWidth ; i++)
- pKernel[i] = -1 ;
- pKernel[nWidth/2] = nWidth - 1 ;
- SetKernel (pKernel.get(), nBlock, nDivisor, nOffset) ;
- }
- };
- //=============================================================================
- /**
- * Sharp (laplacian template) (>=24 bit).
- @verbatim
- example:
- FCPixelSharp aCmd(3) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelSharp : public FCPixelConvolute
- {
- public:
- /// Constructor (nStep >= 1).
- FCPixelSharp (int nStep)
- {
- int arKernel[] = {-1,-1,-1,-1,8+nStep,-1,-1,-1,-1},
- nBlock = 3,
- nDivisor = FMax (1,nStep),
- nOffset = 0 ;
- SetKernel (arKernel, nBlock, nDivisor, nOffset) ;
- }
- };
- //=============================================================================
- /// Base class of gradient fill (>=24 bit)
- class FCPixelGradientBase : public FCSinglePixelProcessBase
- {
- public:
- /// Constructor.
- FCPixelGradientBase (RGBQUAD crStart, RGBQUAD crEnd, REPEAT_MODE nRepeat=REPEAT_NONE) : m_crStart(crStart), m_crEnd(crEnd), m_nRepeat(nRepeat) {}
- protected:
- /// calculate factor of point(x,y)
- virtual double CalculateFactor (int nX, int nY) =0 ;
- private:
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- double fFac = this->CalculateFactor (x, y) ;
- switch (m_nRepeat)
- {
- case REPEAT_NONE : fFac = FClamp (fFac, 0.0, 1.0); break;
- case REPEAT_SAWTOOTH :
- if (fFac < 0.0)
- fFac = 1.0 - FDoubleMod1 (-fFac) ;
- else
- fFac = FDoubleMod1 (fFac) ;
- break ;
- case REPEAT_TRIANGULAR :
- if (fFac < 0.0)
- fFac = -fFac ;
- if ( ((int)fFac) & 1 )
- fFac = 1.0 - FDoubleMod1 (fFac) ;
- else
- fFac = FDoubleMod1 (fFac) ;
- break ;
- }
- PCL_B(pPixel) = (BYTE)(PCL_B(&m_crStart) + (PCL_B(&m_crEnd)-PCL_B(&m_crStart)) * fFac) ;
- PCL_G(pPixel) = (BYTE)(PCL_G(&m_crStart) + (PCL_G(&m_crEnd)-PCL_G(&m_crStart)) * fFac) ;
- PCL_R(pPixel) = (BYTE)(PCL_R(&m_crStart) + (PCL_R(&m_crEnd)-PCL_R(&m_crStart)) * fFac) ;
- }
- double FDoubleMod1 (const double &x)
- {
- // the function <fmod> is extreme slow :-(, so we just do it.
- // the function == fmod (x, 1.0)
- return x - (int)x ;
- }
- RGBQUAD m_crStart, m_crEnd ;
- REPEAT_MODE m_nRepeat ; // type of repeat
- };
- //=============================================================================
- /**
- * Gradient fill linear (>=24 bit).
- @verbatim
- example:
- POINT ptStart={0,0}, ptEnd={100,100} ;
- FCPixelGradientLine aCmd (ptStart, ptEnd, PCL_RGBA(0,0,0), PCL_RGBA(0,0,255), REPEAT_NONE) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelGradientLine : public FCPixelGradientBase
- {
- public:
- /**
- * Constructor.
- * @param ptStart : start coordinate on image.
- * @param ptEnd : end coordinate on image.
- * @param nRepeat : REPEAT_NONE, REPEAT_SAWTOOTH, REPEAT_TRIANGULAR
- */
- FCPixelGradientLine (POINT ptStart, POINT ptEnd, RGBQUAD crStart, RGBQUAD crEnd, REPEAT_MODE nRepeat = REPEAT_NONE) : FCPixelGradientBase (crStart, crEnd, nRepeat)
- {
- m_ptStart = ptStart; m_ptEnd = ptEnd;
- m_fDist = FHypot ((double)(m_ptStart.x-m_ptEnd.x), (double)(m_ptStart.y-m_ptEnd.y)) ;
- m_fRatX = (m_ptEnd.x-m_ptStart.x) / m_fDist ;
- m_fRatY = (m_ptEnd.y-m_ptStart.y) / m_fDist ;
- }
- protected:
- virtual double CalculateFactor (int nX, int nY)
- {
- double rat = m_fRatX * (nX-m_ptStart.x) + m_fRatY * (nY-m_ptStart.y) ;
- rat = rat / m_fDist ;
- return (rat < 0.0) ? 0.0 : rat ;
- }
- protected:
- POINT m_ptStart, m_ptEnd ; // coordinate on image
- double m_fRatX, m_fRatY ;
- double m_fDist ;
- };
- //=============================================================================
- /**
- * Gradient fill bilinear (>=24 bit).
- @verbatim
- example:
- POINT ptStart={0,0}, ptEnd={100,100} ;
- FCPixelGradientBiLine aCmd (ptStart, ptEnd, PCL_RGBA(0,0,0), PCL_RGBA(0,0,255), REPEAT_NONE) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelGradientBiLine : public FCPixelGradientLine
- {
- public:
- /**
- * Constructor.
- * @param ptStart : start coordinate on image.
- * @param ptEnd : end coordinate on image.
- * @param nRepeat : REPEAT_NONE, REPEAT_SAWTOOTH, REPEAT_TRIANGULAR
- */
- FCPixelGradientBiLine (POINT ptStart, POINT ptEnd, RGBQUAD crStart, RGBQUAD crEnd, REPEAT_MODE nRepeat = REPEAT_NONE) : FCPixelGradientLine (ptStart, ptEnd, crStart, crEnd, nRepeat) {}
- protected:
- virtual double CalculateFactor (int nX, int nY)
- {
- double rat = m_fRatX * (nX-m_ptStart.x) + m_fRatY * (nY-m_ptStart.y) ;
- rat = rat / m_fDist ;
- return fabs(rat) ;
- }
- };
- //=============================================================================
- /**
- * Gradient fill symmetric conical (>=24 bit).
- @verbatim
- example:
- POINT ptStart={0,0}, ptEnd={100,100} ;
- FCPixelGradientConicalSym aCmd (ptStart, ptEnd, PCL_RGBA(0,0,0), PCL_RGBA(0,0,255), REPEAT_NONE) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelGradientConicalSym : public FCPixelGradientLine
- {
- public:
- /**
- * Constructor.
- * @param ptStart : start coordinate on image.
- * @param ptEnd : end coordinate on image.
- * @param nRepeat : REPEAT_NONE, REPEAT_SAWTOOTH, REPEAT_TRIANGULAR
- */
- FCPixelGradientConicalSym (POINT ptStart, POINT ptEnd, RGBQUAD crStart, RGBQUAD crEnd, REPEAT_MODE nRepeat = REPEAT_NONE) : FCPixelGradientLine (ptStart, ptEnd, crStart, crEnd, nRepeat) {}
- protected:
- virtual double CalculateFactor (int nX, int nY)
- {
- double rat ;
- double dx = nX-m_ptStart.x, dy = nY-m_ptStart.y ;
- if ((dx != 0) || (dy != 0))
- {
- double dr = FHypot (dx, dy) ;
- rat = m_fRatX * dx / dr + m_fRatY * dy / dr ;
- rat = FClamp (rat, -1.0, 1.0) ;
- rat = acos(rat) / LIB_PI ;
- rat = FClamp (rat, 0.0, 1.0) ;
- }
- else
- rat = 0.5 ;
- return rat ;
- }
- };
- //=============================================================================
- /**
- * Gradient fill Anti-symmetric conical (>=24 bit).
- @verbatim
- example:
- POINT ptStart={0,0}, ptEnd={100,100} ;
- FCPixelGradientConicalSym aCmd (ptStart, ptEnd, PCL_RGBA(0,0,0), PCL_RGBA(0,0,255), REPEAT_NONE) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelGradientConicalASym : public FCPixelGradientLine
- {
- public:
- /**
- * Constructor.
- * @param ptStart : start coordinate on image.
- * @param ptEnd : end coordinate on image.
- * @param nRepeat : REPEAT_NONE, REPEAT_SAWTOOTH, REPEAT_TRIANGULAR
- */
- FCPixelGradientConicalASym (POINT ptStart, POINT ptEnd, RGBQUAD crStart, RGBQUAD crEnd, REPEAT_MODE nRepeat = REPEAT_NONE) : FCPixelGradientLine (ptStart, ptEnd, crStart, crEnd, nRepeat) {}
- protected:
- virtual double CalculateFactor (int nX, int nY)
- {
- double rat ;
- double dx = nX-m_ptStart.x, dy = nY-m_ptStart.y ;
- if ((dx != 0) || (dy != 0))
- {
- double ang0, ang1, ang ;
- ang0 = atan2 (m_fRatX, m_fRatY) + LIB_PI ;
- ang1 = atan2 (dx, dy) + LIB_PI ;
- ang = ang1 - ang0 ;
- if (ang < 0.0)
- ang += LIB_2PI ;
- rat = ang / LIB_2PI ;
- rat = FClamp (rat, 0.0, 1.0) ;
- }
- else
- rat = 0.5 ;
- return rat ;
- }
- };
- //=============================================================================
- /**
- * Gradient fill rect (>=24 bit).
- @verbatim
- example:
- RECT rc = {0, 0, 100, 100} ;
- FCPixelGradientRect aCmd (rc, PCL_RGBA(0,0,0), PCL_RGBA(0,0,255), REPEAT_NONE) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelGradientRect : public FCPixelGradientBase
- {
- public:
- /**
- * Constructor.
- * @param rcRect : rect on image.
- * @param nRepeat : REPEAT_NONE, REPEAT_SAWTOOTH, REPEAT_TRIANGULAR
- */
- FCPixelGradientRect (RECT rcRect, RGBQUAD crStart, RGBQUAD crEnd, REPEAT_MODE nRepeat = REPEAT_NONE) : FCPixelGradientBase (crStart, crEnd, nRepeat)
- {
- assert (!IsRectEmpty(&rcRect)) ;
- m_fCenX = (rcRect.left + rcRect.right) / 2.0 ;
- m_fCenY = (rcRect.top + rcRect.bottom) / 2.0 ;
- m_fRadiusX = RECTWIDTH(rcRect) / 2.0 ;
- m_fRadiusY = RECTHEIGHT(rcRect) / 2.0 ;
- }
- protected:
- virtual double CalculateFactor (int nX, int nY)
- {
- double ratX = fabs((nX-m_fCenX) / m_fRadiusX),
- ratY = fabs((nY-m_fCenY) / m_fRadiusY) ;
- return FMax(ratX, ratY) ;
- }
- protected:
- double m_fCenX, m_fCenY ;
- double m_fRadiusX, m_fRadiusY ;
- };
- //=============================================================================
- /**
- * Gradient fill radial (>=24 bit).
- @verbatim
- example:
- RECT rc = {0, 0, 100, 100} ;
- FCPixelGradientRadial aCmd (rc, PCL_RGBA(0,0,0), PCL_RGBA(0,0,255), REPEAT_NONE) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelGradientRadial : public FCPixelGradientBase
- {
- public:
- /**
- * Constructor.
- * @param rcEllipse : rect on image.
- * @param nRepeat : REPEAT_NONE, REPEAT_SAWTOOTH, REPEAT_TRIANGULAR
- */
- FCPixelGradientRadial (RECT rcEllipse, RGBQUAD crStart, RGBQUAD crEnd, REPEAT_MODE nRepeat = REPEAT_NONE) : FCPixelGradientBase (crStart, crEnd, nRepeat)
- {
- assert (!IsRectEmpty(&rcEllipse)) ;
- m_fCenX = (rcEllipse.left + rcEllipse.right) / 2.0 ;
- m_fCenY = (rcEllipse.top + rcEllipse.bottom) / 2.0 ;
- m_fRadiusX = RECTWIDTH(rcEllipse) / 2.0 ;
- m_fRadiusY = RECTHEIGHT(rcEllipse) / 2.0 ;
- }
- protected:
- virtual double CalculateFactor (int nX, int nY)
- {
- double rat = FHypot((nX-m_fCenX)/m_fRadiusX, (nY-m_fCenY)/m_fRadiusY) ;
- return rat ;
- }
- private:
- double m_fCenX, m_fCenY ;
- double m_fRadiusX, m_fRadiusY ;
- };
- //=============================================================================
- /// Bilinear distord (>=24 bit).
- /// if derived class override OnEnterProcess, it must call OnEnterProcess of base.
- class FCPixelBilinearDistord : public FCSinglePixelProcessBase
- {
- protected:
- virtual bool ValidateColorBits (const FCObjImage* pImg)
- {
- return FCSinglePixelProcessBase::ValidateColorBits(pImg) && (pImg->Width() >= 2) && (pImg->Height() >= 2) ;
- }
- virtual void OnEnterProcess (FCObjImage* pImg)
- {
- SetBackupImage (pImg) ;
- }
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- double un_x, un_y ;
- if (!calc_undistorted_coord (x, y, un_x, un_y))
- return ;
- un_x = FClamp (un_x, 0.0, GetBackupImage()->Width() - 1.1) ;
- un_y = FClamp (un_y, 0.0, GetBackupImage()->Height() - 1.1) ;
- const int nSrcX = (int)un_x, nSrcY = (int)un_y,
- nSrcX_1 = nSrcX+1, nSrcY_1 = nSrcY+1 ;
- const BYTE * pcrPixel[4] =
- {
- GetBackupImage()->GetBits(nSrcX,nSrcY),
- GetBackupImage()->GetBits(nSrcX_1,nSrcY),
- GetBackupImage()->GetBits(nSrcX,nSrcY_1),
- GetBackupImage()->GetBits(nSrcX_1,nSrcY_1)
- } ;
- RGBQUAD cr = FCColor::Get_Bilinear_Pixel (un_x-nSrcX, un_y-nSrcY, pImg->ColorBits() == 32, pcrPixel) ;
- FCColor::CopyPixel (pPixel, &cr, pImg->ColorBits()/8) ;
- }
- // returned bool variable to declare continue or not
- virtual bool calc_undistorted_coord (int x, int y, double& un_x, double& un_y) const =0 ;
- };
- //=============================================================================
- /**
- * Cylinder (>=24 bit).
- @verbatim
- example:
- FCPixelCylinder aCmd ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelCylinder : public FCPixelBilinearDistord
- {
- virtual void OnEnterProcess (FCObjImage* pImg)
- {
- FCPixelBilinearDistord::OnEnterProcess(pImg) ;
- // pos in origin image.
- double R = pImg->Width() / 2.0 ;
- for (int x=0 ; x < pImg->Width() ; x++)
- {
- double fIndex = pImg->Width() * acos ((R-x)/R) / LIB_PI ;
- m_ColIndex.push_back (fIndex) ;
- }
- }
- virtual bool calc_undistorted_coord (int x, int y, double& un_x, double& un_y) const
- {
- un_x = m_ColIndex[x] ;
- un_y = y ;
- return true ;
- }
- std::deque<double> m_ColIndex ;
- };
- //=============================================================================
- /**
- * Wave (>=24 bit).
- @verbatim
- example:
- FCPixelWave aCmd (25, 30) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelWave : public FCPixelBilinearDistord
- {
- public:
- /// Constructor.
- FCPixelWave (int nWavelength, int nAmplitude, double fPhase=0) : m_nWavelength(2*FMax(1,nWavelength)), m_nAmplitude(FMax(1,nAmplitude)), m_fPhase(fPhase) {}
- private:
- virtual bool calc_undistorted_coord (int x, int y, double& un_x, double& un_y) const
- {
- const int nImgWidth = GetBackupImage()->Width(),
- nImgHeight = GetBackupImage()->Height() ;
- double fScaleX = 1.0, fScaleY = 1.0 ;
- if (nImgWidth < nImgHeight)
- fScaleX = nImgHeight / (double)nImgWidth ;
- else if (nImgWidth > nImgHeight)
- fScaleY = nImgWidth / (double)nImgHeight ;
- // Distances to center, scaled
- double fCenX = GetBackupImage()->Width() / 2.0,
- fCenY = GetBackupImage()->Height() / 2.0,
- dx = (x - fCenX) * fScaleX,
- dy = (y - fCenY) * fScaleY,
- amnt = m_nAmplitude * sin (LIB_2PI * FHypot(dx,dy) / (double)m_nWavelength + m_fPhase) ;
- un_x = (amnt + dx) / fScaleX + fCenX ;
- un_y = (amnt + dy) / fScaleY + fCenY ;
- return true ;
- }
- double m_fPhase ; // [0..2n]
- int m_nAmplitude ;
- int m_nWavelength ;
- };
- //=============================================================================
- /**
- * Whirl & Pinch (>=24 bit).
- @verbatim
- example:
- FCPixelWhirlPinch aCmd (1.5, 0.5) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelWhirlPinch : public FCPixelBilinearDistord
- {
- public:
- /// Constructor.
- /// @param fWhirl : [-2n,2n]
- /// @param fPinch : [-1.0,1.0]
- FCPixelWhirlPinch (double fWhirl, double fPinch)
- {
- m_fWhirl = FClamp (fWhirl, -LIB_2PI, LIB_2PI) ;
- m_fPinch = FClamp (fPinch, -1.0, 1.0) ;
- }
- private:
- virtual bool calc_undistorted_coord (int x, int y, double& un_x, double& un_y) const
- {
-
- int nImgWidth = GetBackupImage()->Width(),
- nImgHeight = GetBackupImage()->Height() ;
- double fScaleX = 1.0, fScaleY = 1.0 ;
- if (nImgWidth < nImgHeight)
- fScaleX = nImgHeight / (double)nImgWidth ;
- else if (nImgWidth > nImgHeight)
- fScaleY = nImgWidth / (double)nImgHeight ;
- // Distances to center, scaled
- double fCenX = GetBackupImage()->Width() / 2.0,
- fCenY = GetBackupImage()->Height() / 2.0,
- fRadius = FMax (fCenX, fCenY),
- dx = (x - fCenX) * fScaleX,
- dy = (y - fCenY) * fScaleY ;
- double d = dx*dx + dy*dy ; // Distance^2 to center of *circle* (scaled ellipse)
- double fSqrtD = sqrt (d) ;
- // If we are inside circle, then distort, else, just return the same position
- bool bInside = (fSqrtD < fRadius) ;
- // exclude center point
- if (fSqrtD < FLT_EPSILON)
- bInside = false ;
- if (bInside)
- {
- // double fDist = sqrt (d / m_fRadiusScale) / m_fRadius ;
- double fDist = fSqrtD / fRadius ;
- // Pinch
- double fFactor = pow (sin (LIB_PI / 2.0 * fDist), -m_fPinch) ;
- dx *= fFactor ; dy *= fFactor ;
- // Whirl
- double fAng = m_fWhirl * FSquare (1.0 - fDist) ;
- double sina = sin (fAng), cosa = cos (fAng) ;
- un_x = (cosa * dx - sina * dy) / fScaleX + fCenX ;
- un_y = (sina * dx + cosa * dy) / fScaleY + fCenY ;
- }
- else
- {
- un_x = x ; un_y = y ;
- }
- return bInside;
- }
- double m_fWhirl ; // radian of whirl
- double m_fPinch ; // [-1.0, 1.0]
- // double m_fRadiusScale ; // [0.0, 2.0]
- };
- //=============================================================================
- /**
- * Fractal trace (>=24 bit).
- @verbatim
- example:
- FCPixelFractalTrace aCmd (2) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelFractalTrace : public FCPixelBilinearDistord
- {
- public:
- /// Constructor (nDepth >= 1).
- FCPixelFractalTrace (int nDepth) : m_nDepth(FMax(1,nDepth)) {}
- private:
- void mandelbrot (const double& x, const double& y, double* u, double* v) const
- {
- int iter = 0 ;
- double xx = x, yy = y ;
- double x2 = xx * xx,
- y2 = yy * yy ;
- while (iter++ < m_nDepth)
- {
- const double tmp = x2 - y2 + x ;
- yy = 2 * xx * yy + y ;
- xx = tmp ;
- x2 = xx * xx ;
- y2 = yy * yy ;
- }
- *u = xx ; *v = yy ;
- }
- virtual bool calc_undistorted_coord (int x, int y, double& un_x, double& un_y) const
- {
- double fImgWidth = GetBackupImage()->Width(),
- fImgHeight = GetBackupImage()->Height(),
- fScaleX = 1.5 / fImgWidth,
- fScaleY = 2.0 / fImgHeight,
- cy = -1.0 + y * fScaleY,
- cx = -1.0 + x * fScaleX,
- px, py ;
- mandelbrot (cx, cy, &px, &py) ;
- un_x = (px + 1.0) / fScaleX ;
- un_y = (py + 1.0) / fScaleY ;
- if ( !(0 <= un_x && un_x < fImgWidth && 0 <= un_y && un_y < fImgHeight) )
- {
- un_x = fmod (un_x, fImgWidth) ;
- un_y = fmod (un_y, fImgHeight) ;
- if (un_x < 0.0) un_x += fImgWidth ;
- if (un_y < 0.0) un_y += fImgHeight ;
- }
- return true ;
- }
- int m_nDepth ; // >=1
- };
- //=============================================================================
- /**
- * Lens (>=24 bit).
- @verbatim
- example:
- FCPixelLens aCmd (1.5) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelLens : public FCPixelBilinearDistord
- {
- public:
- /// Constructor (fRefraction >= 1.0).
- FCPixelLens (double fRefraction, bool bKeepBk) : m_fRefraction(FMax(1.0,fRefraction)), m_bKeepBk(bKeepBk) {}
- private:
- virtual void OnEnterProcess (FCObjImage* pImg)
- {
- FCPixelBilinearDistord::OnEnterProcess (pImg) ;
- // clear background ?
- if (!m_bKeepBk)
- memset (pImg->GetMemStart(), 0, pImg->GetPitch()*pImg->Height()) ;
- }
- virtual bool calc_undistorted_coord (int x, int y, double& un_x, double& un_y) const
- {
- const double fCenX = GetBackupImage()->Width() / 2.0,
- fCenY = GetBackupImage()->Height() / 2.0,
- asqr = fCenX * fCenX,
- bsqr = fCenY * fCenY,
- csqr = FSquare(FMin(fCenX,fCenY)),
- dy = fCenY - y,
- ysqr = FSquare(dy),
- dx = x - fCenX,
- xsqr = FSquare(dx) ;
- if (ysqr < (bsqr - (bsqr * xsqr) / asqr))
- {
- double fTmp = sqrt ((1 - xsqr/asqr - ysqr/bsqr) * csqr) ;
- double fTmpsqr = FSquare(fTmp) ;
- double nxangle = acos (dx / sqrt(xsqr+fTmpsqr)) ;
- double theta2 = asin (sin (LIB_PI/2.0 - nxangle) / m_fRefraction) ;
- theta2 = LIB_PI/2.0 - nxangle - theta2 ;
- double xx = dx - tan (theta2) * fTmp ;
- double nyangle = acos (dy / sqrt(ysqr+fTmpsqr)) ;
- theta2 = asin (sin (LIB_PI/2.0 - nyangle) / m_fRefraction) ;
- theta2 = LIB_PI/2.0 - nyangle - theta2 ;
- double yy = dy - tan (theta2) * fTmp ;
- un_x = xx + fCenX ;
- un_y = fCenY - yy ;
- return true ;
- }
- return false ;
- }
- double m_fRefraction ; // >= 1.0
- bool m_bKeepBk ;
- };
- //=============================================================================
- /**
- * Skew transform (>=24 bit).
- */
- class FCPixelSkew : public FCPixelBilinearDistord
- {
- public:
- /// Constructor.
- /// @param ptPos, order by LT, RT, RB, LB
- FCPixelSkew (const POINT ptPos[4])
- {
- memcpy (m_ptNewPos, ptPos, sizeof(POINT) * 4) ;
- }
- private:
- virtual void OnEnterProcess (FCObjImage* pImg)
- {
- FCPixelBilinearDistord::OnEnterProcess (pImg) ;
- // create skewed image
- m_nNewWidth = FMax (abs(m_ptNewPos[0].x-m_ptNewPos[2].x), abs(m_ptNewPos[1].x-m_ptNewPos[3].x)) ;
- m_nNewHeight = FMax (abs(m_ptNewPos[0].y-m_ptNewPos[2].y), abs(m_ptNewPos[1].y-m_ptNewPos[3].y)) ;
- pImg->Create (m_nNewWidth, m_nNewHeight, pImg->ColorBits()) ;
- }
- virtual bool calc_undistorted_coord (int x, int y, double& un_x, double& un_y) const
- {
- if (m_ptNewPos[0].x != m_ptNewPos[3].x)
- {
- // x axis slope
- const int nDelta = m_ptNewPos[0].x - m_ptNewPos[3].x ;
- un_x = x - ((nDelta > 0) ? (m_nNewHeight - y) : y) * abs(nDelta) / (double)m_nNewHeight ;
- un_y = y * GetBackupImage()->Height() / (double)m_nNewHeight ;
- }
- else if (m_ptNewPos[0].y != m_ptNewPos[1].y)
- {
- // y axis slope
- const int nDelta = m_ptNewPos[0].y - m_ptNewPos[1].y ;
- un_x = x * GetBackupImage()->Width() / (double)m_nNewWidth ;
- un_y = y - ((nDelta > 0) ? (m_nNewWidth - x) : x) * abs(nDelta) / (double)m_nNewWidth ;
- }
- else
- {
- un_x=x ; un_y=y;
- }
- if (un_x<0.0 || un_x>GetBackupImage()->Width()-1 || un_y<0.0 || un_y>GetBackupImage()->Height()-1)
- return false ;
- else
- return true ;
- }
- private:
- POINT m_ptNewPos[4] ; // LT, RT, RB, LB
- int m_nNewWidth ;
- int m_nNewHeight ;
- };
- //=============================================================================
- /**
- * Perspective transform (>=24 bit).
- */
- class FCPixelPerspective : public FCPixelBilinearDistord
- {
- public:
- /// Constructor.
- /// @param ptPos, order by LT, RT, RB, LB
- FCPixelPerspective (const POINT ptPos[4])
- {
- memcpy (m_ptNewPos, ptPos, sizeof(POINT) * 4) ;
- }
- private:
- virtual void OnEnterProcess (FCObjImage* pImg)
- {
- FCPixelBilinearDistord::OnEnterProcess (pImg) ;
- // create sloped image
- m_nNewWidth = FMax (abs(m_ptNewPos[0].x-m_ptNewPos[1].x), abs(m_ptNewPos[2].x-m_ptNewPos[3].x)) ;
- m_nNewHeight = FMax (abs(m_ptNewPos[0].y-m_ptNewPos[3].y), abs(m_ptNewPos[1].y-m_ptNewPos[2].y)) ;
- pImg->Create (m_nNewWidth, m_nNewHeight, pImg->ColorBits()) ;
- }
- virtual bool calc_undistorted_coord (int x, int y, double& un_x, double& un_y) const
- {
- if (m_ptNewPos[0].y != m_ptNewPos[1].y)
- {
- // y axis perspective
- int nDelta = abs(m_ptNewPos[0].y-m_ptNewPos[3].y) - abs(m_ptNewPos[1].y-m_ptNewPos[2].y) ;
- double fOffset = fabs(nDelta * ((nDelta > 0) ? x : (m_nNewWidth-x)) / (2.0 * m_nNewWidth)) ;
- un_y = GetBackupImage()->Height() * (y - fOffset) / (m_nNewHeight - 2.0 * fOffset) ;
- un_x = GetBackupImage()->Width() * x / (double)m_nNewWidth ;
- }
- else if (m_ptNewPos[0].x != m_ptNewPos[3].x)
- {
- // x axis perspective
- int nDelta = abs(m_ptNewPos[0].x-m_ptNewPos[1].x) - abs(m_ptNewPos[2].x-m_ptNewPos[3].x) ;
- double fOffset = fabs(nDelta * ((nDelta > 0) ? y : (m_nNewHeight-y)) / (2.0 * m_nNewHeight)) ;
- un_x = GetBackupImage()->Width() * (x - fOffset) / (m_nNewWidth - 2.0 * fOffset) ;
- un_y = GetBackupImage()->Height() * y / (double)m_nNewHeight ;
- }
- else
- {
- un_x = x ; un_y = y ;
- }
- if (un_x<0.0 || un_x>GetBackupImage()->Width()-1 || un_y<0.0 || un_y>GetBackupImage()->Height()-1)
- return false ;
- else
- return true ;
- }
- private:
- POINT m_ptNewPos[4] ; // LT, RT, RB, LB
- int m_nNewWidth ;
- int m_nNewHeight ;
- };
- //=============================================================================
- /**
- * Rotate (>=24 bit).
- @verbatim
- example:
- FCPixelRotate aCmd (37) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelRotate : public FCPixelBilinearDistord
- {
- public:
- /// Constructor.
- FCPixelRotate (int nAngle)
- {
- nAngle %= 360 ;
- while (nAngle < 0)
- nAngle += 360 ;
- m_fAngle = AngleToRadian(nAngle) ;
- m_fInvAngle = AngleToRadian(360 - nAngle) ;
- }
- private:
- virtual void OnEnterProcess (FCObjImage* pImg)
- {
- FCPixelBilinearDistord::OnEnterProcess (pImg) ;
- // calculate new width & height
- const POINT_F ptCenter = {pImg->Width()/2.0, pImg->Height()/2.0} ;
- const POINT ptLT = {0,0}, ptRT = {pImg->Width(),0},
- ptLB = {0,pImg->Height()}, ptRB = {pImg->Width(), pImg->Height()} ;
- POINT ptR[4] ;
- ptR[0] = FClockwisePoint (ptLT, ptCenter, m_fAngle) ;
- ptR[1] = FClockwisePoint (ptRT, ptCenter, m_fAngle) ;
- ptR[2] = FClockwisePoint (ptLB, ptCenter, m_fAngle) ;
- ptR[3] = FClockwisePoint (ptRB, ptCenter, m_fAngle) ;
- int L = FMin(ptR[0].x,FMin(ptR[1].x,FMin(ptR[2].x,ptR[3].x))),
- T = FMin(ptR[0].y,FMin(ptR[1].y,FMin(ptR[2].y,ptR[3].y))),
- R = FMax(ptR[0].x,FMax(ptR[1].x,FMax(ptR[2].x,ptR[3].x))),
- B = FMax(ptR[0].y,FMax(ptR[1].y,FMax(ptR[2].y,ptR[3].y))) ;
- m_nNewWidth = R - L ;
- m_nNewHeight = B - T ;
- pImg->Create (m_nNewWidth, m_nNewHeight, pImg->ColorBits()) ;
- }
- virtual bool calc_undistorted_coord (int x, int y, double& un_x, double& un_y) const
- {
- const POINT ptRot = {x, y} ;
- const POINT_F ptCenter = {(m_nNewWidth-1)/2.0, (m_nNewHeight-1)/2.0} ;
- POINT ptR = FClockwisePoint (ptRot, ptCenter, m_fInvAngle) ;
- un_x = ptR.x ;
- un_y = ptR.y ;
- const double fOffX = (m_nNewWidth - GetBackupImage()->Width()) / 2.0,
- fOffY = (m_nNewHeight - GetBackupImage()->Height()) / 2.0 ;
- un_x -= fOffX ;
- un_y -= fOffY ;
- if (un_x<0.0 || un_x>GetBackupImage()->Width()-1 || un_y<0.0 || un_y>GetBackupImage()->Height()-1)
- return false ;
- else
- return true ;
- }
- double m_fAngle, m_fInvAngle ;
- int m_nNewWidth, m_nNewHeight ;
- };
- //=============================================================================
- /**
- * Ribbon (>=24 bit).
- @verbatim
- example:
- FCPixelRibbon aCmd (80, 30) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelRibbon : public FCPixelBilinearDistord
- {
- public:
- /// Constructor.
- /// @param nSwing : [0..100], percentage
- /// @param nFrequency : >=0, a pi every 10
- FCPixelRibbon (int nSwing, int nFrequency)
- {
- m_nSwing = FClamp (nSwing, 0, 100) ;
- m_nFreq = FMax (nFrequency, 0) ;
- }
- private:
- virtual void OnEnterProcess (FCObjImage* pImg)
- {
- FCPixelBilinearDistord::OnEnterProcess (pImg) ;
-
- // clear image
- memset (pImg->GetMemStart(), 0, pImg->GetPitch()*pImg->Height()) ;
- m_nDelta = m_nSwing * pImg->Height() * 75/100/100 ; // upper, max 75%
- const double fAngleSpan = m_nFreq * LIB_PI / pImg->Width() / 10.0 ;
- for (int x=0 ; x < pImg->Width() ; x++)
- {
- int nPush = FRound ((1.0-cos(x * fAngleSpan)) * m_nDelta / 2.0) ;
- m_ShiftDown.push_back (nPush) ;
- }
- }
- virtual bool calc_undistorted_coord (int x, int y, double& un_x, double& un_y) const
- {
- un_x = x ;
- un_y = y + m_nDelta - m_ShiftDown[x] ;
- if ((un_y < m_nDelta) || (un_y > GetBackupImage()->Height()-1))
- return false ;
- return true ;
- }
- int m_nSwing, m_nFreq ;
- int m_nDelta ;
- std::deque<int> m_ShiftDown ;
- };
- //=============================================================================
- /**
- * Ripple (>=24 bit).
- @verbatim
- example:
- FCPixelRipple aCmd (10, 30) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelRipple : public FCPixelBilinearDistord
- {
- public:
- /// Constructor.
- FCPixelRipple (int nWavelength, int nAmplitude, bool bSinType = true)
- {
- m_nWavelength = FMax (1, nWavelength) ;
- m_nAmplitude = FMax (1, nAmplitude) ;
- m_bSinType = bSinType ;
- }
- private:
- virtual bool calc_undistorted_coord (int x, int y, double& un_x, double& un_y) const
- {
- const double fWidth = GetBackupImage()->Width() ;
- un_x = fmod (x + fWidth + shift_amount(y), fWidth) ;
- un_y = y ;
- return true ;
- }
- double shift_amount (int nPos) const
- {
- if (m_bSinType)
- return m_nAmplitude * sin(nPos*LIB_2PI/(double)m_nWavelength) ;
- else
- return floor (m_nAmplitude * (fabs ((((nPos % m_nWavelength) / (double)m_nWavelength) * 4) - 2) - 1)) ;
- }
- int m_nWavelength ;
- int m_nAmplitude ;
- bool m_bSinType ;
- };
- //=============================================================================
- /**
- * Tile (>=24 bit).
- @verbatim
- example:
- FCPixelSmallTile aCmd (2,2) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelSmallTile : public FCPixelBilinearDistord
- {
- public:
- /// Constructor.
- FCPixelSmallTile (int nXNum, int nYNum) : m_nXNum(FMax(1,nXNum)), m_nYNum(FMax(1,nYNum)) {}
- private:
- virtual bool calc_undistorted_coord (int x, int y, double& un_x, double& un_y) const
- {
- un_x = (x * m_nXNum) % GetBackupImage()->Width() ;
- un_y = (y * m_nYNum) % GetBackupImage()->Height() ;
- return true ;
- }
- int m_nXNum ;
- int m_nYNum ;
- };
- //=============================================================================
- /// LUT(look up table) routine (>=24 bit)
- class FCPixelLUTRoutine : public FCSinglePixelProcessBase
- {
- public:
- /// Constructor.
- /// @param nChannel : process channel, use OR to combine
- FCPixelLUTRoutine (IMAGE_CHANNEL nChannel = CHANNEL_RGB)
- {
- m_bChannelR = nChannel & CHANNEL_RED ;
- m_bChannelG = nChannel & CHANNEL_GREEN ;
- m_bChannelB = nChannel & CHANNEL_BLUE ;
- }
- protected:
- /// Initialize LUT.
- virtual int InitLUTtable (int nLUTIndex) =0 ;
- private:
- virtual void OnEnterProcess (FCObjImage* pImg)
- {
- for (int i=0 ; i <= 0xFF ; i++)
- m_LUT[i] = this->InitLUTtable (i) ;
- }
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- if (m_bChannelB) PCL_B(pPixel) = m_LUT[PCL_B(pPixel)] ;
- if (m_bChannelG) PCL_G(pPixel) = m_LUT[PCL_G(pPixel)] ;
- if (m_bChannelR) PCL_R(pPixel) = m_LUT[PCL_R(pPixel)] ;
- }
- private:
- int m_LUT[256] ;
- int m_bChannelR, m_bChannelG, m_bChannelB ;
- };
- //=============================================================================
- /**
- * Adjust brightness (>=24 bit).
- @verbatim
- example:
- FCPixelBrightness aCmd (150) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelBrightness : public FCPixelLUTRoutine
- {
- public:
- /// Constructor (param's unit is percentage).
- FCPixelBrightness (int nPercent, IMAGE_CHANNEL nChannel = CHANNEL_RGB) : FCPixelLUTRoutine(nChannel), m_nPercent(FMax(0,nPercent)) {}
- private:
- virtual int InitLUTtable (int nLUTIndex)
- {
- return FClamp0255 (nLUTIndex * m_nPercent / 100) ;
- }
- int m_nPercent ;
- };
- //=============================================================================
- /**
- * Adjust contrast (>=24 bit).
- @verbatim
- example:
- FCPixelContrast aCmd (150) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelContrast : public FCPixelLUTRoutine
- {
- public:
- /// Constructor (param's unit is percentage).
- FCPixelContrast (int nPercent, IMAGE_CHANNEL nChannel = CHANNEL_RGB) : FCPixelLUTRoutine(nChannel), m_nPercent(FMax(0,nPercent)) {}
- private:
- virtual int InitLUTtable (int nLUTIndex)
- {
- return FClamp0255 (128 + (nLUTIndex - 128) * m_nPercent / 100) ;
- }
- int m_nPercent ;
- };
- //=============================================================================
- /**
- * Adjust gamma (>=24 bit).
- @verbatim
- example:
- FCPixelGamma aCmd (0.5) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelGamma : public FCPixelLUTRoutine
- {
- public:
- /// Constructor (param must >= 0.0).
- FCPixelGamma (double fGamma, IMAGE_CHANNEL nChannel = CHANNEL_RGB) : FCPixelLUTRoutine(nChannel)
- {
- fGamma = FMax (0.0, fGamma) ;
- m_fInvGamma = 1.0 / fGamma ;
- }
- private:
- virtual int InitLUTtable (int nLUTIndex)
- {
- double fMax = pow (255.0, m_fInvGamma) / 255.0 ;
- return FClamp0255 (FRound (pow((double)nLUTIndex, m_fInvGamma) / fMax)) ;
- }
- double m_fInvGamma ;
- };
- //=============================================================================
- /**
- * Negate image(>=24 bit).
- @verbatim
- example:
- FCPixelInvert aCmd ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelInvert : public FCPixelLUTRoutine
- {
- public:
- FCPixelInvert (IMAGE_CHANNEL nChannel = CHANNEL_RGB) : FCPixelLUTRoutine(nChannel) {}
- private:
- virtual int InitLUTtable (int nLUTIndex)
- {
- return (255 - nLUTIndex) ;
- }
- };
- //=============================================================================
- /**
- * Solarize image(>=24 bit).
- @verbatim
- example:
- FCPixelSolarize aCmd (128) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelSolarize : public FCPixelLUTRoutine
- {
- public:
- /// Constructor (nThreshold in [0-255]).
- FCPixelSolarize (int nThreshold, IMAGE_CHANNEL nChannel = CHANNEL_RGB) : FCPixelLUTRoutine(nChannel), m_nThreshold(FClamp0255(nThreshold)) {}
- private:
- virtual int InitLUTtable (int nLUTIndex)
- {
- return (nLUTIndex >= m_nThreshold) ? (255 - nLUTIndex) : nLUTIndex ;
- }
- int m_nThreshold ;
- };
- //=============================================================================
- /**
- * Posterize image(>=24 bit).
- @verbatim
- example:
- FCPixelPosterize aCmd (2) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelPosterize : public FCPixelLUTRoutine
- {
- public:
- /// Constructor (nLevel >= 2).
- FCPixelPosterize (int nLevel, IMAGE_CHANNEL nChannel = CHANNEL_RGB) : FCPixelLUTRoutine(nChannel), m_nLevel(FMax(2,nLevel)) {}
- private:
- virtual int InitLUTtable (int nLUTIndex)
- {
- double du1 = 255.0 / (m_nLevel - 1.0) ;
- return FClamp0255 (FRound (du1 * FRound (nLUTIndex / du1))) ;
- }
- int m_nLevel ;
- };
- //=============================================================================
- /**
- * Count image's number of color (>=24 bit).
- @verbatim
- example:
- FCPixelColorsCount aCmd ;
- img.SinglePixelProcessProc (aCmd) ;
- aCmd.GetColorsNumber() ;
- @endverbatim
- */
- class FCPixelColorsCount : public FCSinglePixelProcessBase
- {
- public:
- FCPixelColorsCount() : m_pMap(0), m_nCount(0) {}
- virtual ~FCPixelColorsCount() {if(m_pMap) delete[] m_pMap;}
- /// Get used number of color.
- unsigned int GetColorsNumber() const {return m_nCount;}
- protected:
- virtual void OnEnterProcess (FCObjImage* pImg)
- {
- int iMaxColor = 1 << 24 ;
- m_pMap = new BYTE[iMaxColor+1] ;
- memset (m_pMap, 0, iMaxColor+1) ;
- }
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- DWORD i = 0 ;
- FCColor::CopyPixel (&i, pPixel, 3) ;
- if (m_pMap[i] == 0)
- {
- m_pMap[i] = 1 ;
- m_nCount++ ;
- }
- }
- unsigned int m_nCount ;
- BYTE * m_pMap ;
- };
- //=============================================================================
- /**
- * Find a color unused in image (>=24 bit).
- @verbatim
- example:
- FCPixelGetKeyColor aCmd ;
- img.SinglePixelProcessProc (aCmd) ;
- aCmd.IsFind() ;
- aCmd.GetKeyColor() ;
- @endverbatim
- */
- class FCPixelGetKeyColor : public FCPixelColorsCount
- {
- public:
- /// Is found a color unused in image.
- bool IsFind() const {return m_bFind;}
- /// Get the color unused in image.
- RGBQUAD GetKeyColor() const {return m_crKey;}
- private:
- virtual void OnLeaveProcess (FCObjImage* pImg)
- {
- m_bFind = false ;
- for (int i=0 ; i <= 0xFFFFFF ; i++)
- if (m_pMap[i] == 0)
- {
- *(DWORD*)&m_crKey = i ;
- m_bFind = true ;
- break ;
- }
- }
- RGBQUAD m_crKey ;
- bool m_bFind ;
- };
- //=============================================================================
- /// Base class to process whole image.
- class FCPixelWholeImageBase : public FCSinglePixelProcessBase
- {
- virtual PROCESS_TYPE QueryProcessType() {return PROCESS_TYPE_WHOLE;}
- private:
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel) {assert(false);}
- };
- //=============================================================================
- /**
- * Save a ASCII text file (>=24 bit).
- @verbatim
- example:
- FCPixelExportAscII aCmd ("c:\\PhoXo.txt") ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelExportAscII : public FCPixelWholeImageBase
- {
- public:
- /// Constructor.
- FCPixelExportAscII (const char* szFileName)
- {
- #ifdef VC60
- m_pFile = fopen (szFileName, "wb") ; assert(m_pFile);
- #else
- _tfopen_s(&m_pFile, szFileName, _T("wb"));
- assert(m_pFile);
- #endif
- char ch[95] =
- {
- ' ',
- '`','1','2','3','4','5','6','7','8','9','0','-','=','\\',
- 'q','w','e','r','t','y','u','i','o','p','[',']',
- 'a','s','d','f','g','h','j','k','l',';','\'',
- 'z','x','c','v','b','n','m',',','.','/',
- '~','!','@','#','$','%','^','&','*','(',')','_','+','|',
- 'Q','W','E','R','T','Y','U','I','O','P','{','}',
- 'A','S','D','F','G','H','J','K','L',':','"',
- 'Z','X','C','V','B','N','M','<','>','?'
- };
- int gr[95] =
- {
- 0,
- 7,22,28,31,31,27,32,22,38,32,40, 6,12,20,38,32,26,20,24,40,
- 29,24,28,38,32,32,26,22,34,24,44,33,32,32,24,16, 6,22,26,22,
- 26,34,29,35,10, 6,20,14,22,47,42,34,40,10,35,21,22,22,16,14,
- 26,40,39,29,38,22,28,36,22,36,30,22,22,36,26,36,25,34,38,24,
- 36,22,12,12,26,30,30,34,39,42,41,18,18,22
- };
- // Bubble Sort
- for (int i=0 ; i < 94 ; i++)
- for (int j=i+1 ; j < 95 ; j++)
- if (gr[i] > gr[j])
- {
- FSwap (ch[i], ch[j]) ;
- FSwap (gr[i], gr[j]) ;
- }
- memcpy (m_chIndex, ch, 95*sizeof(char)) ;
- memcpy (m_nGray, gr, 95*sizeof(int)) ;
- }
- virtual ~FCPixelExportAscII()
- {
- if (m_pFile)
- fclose(m_pFile) ;
- }
- private:
- virtual void OnEnterProcess (FCObjImage* pImg)
- {
- SetBackupImage (pImg) ;
- }
- virtual void ProcessWholeImage (FCObjImage* pImg, FCObjProgress* pProgress)
- {
- FCPixelInvert aCmd ; // most of image is brightness
- GetBackupImage()->SinglePixelProcessProc (aCmd) ;
- FCPixelConvertTo8BitGray aGray ;
- GetBackupImage()->SinglePixelProcessProc (aGray) ;
- const int nTransWidth = pImg->Width() / 8,
- nTransHeight = pImg->Height() / 16 ;
- for (int y=0 ; y < nTransHeight ; y++)
- {
- for (int x=0 ; x < nTransWidth ; x++)
- {
- int nGray = 0 ;
- for (int k=0 ; k < 16 ; k++)
- for(int h=0 ; h < 8 ; h++)
- {
- BYTE * pGray = GetBackupImage()->GetBits (8*x+h, y*16+k) ;
- nGray += *pGray ;
- }
- nGray /= 16*8 ;
- nGray = m_nGray[94] * nGray / 255 ;
- int t = 0 ;
- while (m_nGray[t+1] < nGray)
- t++ ;
- fwrite (&m_chIndex[t], 1, sizeof(char), m_pFile) ;
- }
- char tchar = (char)0x0D ;
- fwrite (&tchar, 1, sizeof(char), m_pFile) ;
- tchar = (char)0x0A ;
- fwrite (&tchar, 1, sizeof(char), m_pFile) ;
- }
- }
- char m_chIndex[95] ;
- int m_nGray[95] ;
- FILE * m_pFile ;
- };
- //=============================================================================
- #ifdef PCL_3RD_LIBRARY_USE_FREEIMAGE
- #include "../FreeImage_Helper.h"
- /**
- * Quantize image.
- @verbatim
- example:
- FCPixelConvertQuantize aCmd (8) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelConvertQuantize : public FCPixelWholeImageBase
- {
- public:
- /// Constructor (nBPP = 1 or 4 or 8).
- FCPixelConvertQuantize (int nBPP) : m_nBPP(nBPP),m_nTransparency(-1) {}
- int GetTransparencyIndex() {return m_nTransparency;}
- private:
- virtual bool ValidateColorBits (const FCObjImage* pImg)
- {
- if ((m_nBPP == 1) || (m_nBPP == 4) || (m_nBPP == 8))
- return pImg->IsValidImage() ;
- assert(false) ;
- return false ;
- }
- virtual void OnEnterProcess (FCObjImage* pImg)
- {
- if (pImg->ColorBits() == 32)
- {
- // find a key color
- FCPixelGetKeyColor aCmd ;
- pImg->SinglePixelProcessProc (aCmd) ;
- const RGBQUAD cr = aCmd.GetKeyColor() ;
- // set pixel (alpha=0) key color
- for (int y=0 ; y < pImg->Height() ; y++)
- for (int x=0 ; x < pImg->Width() ; x++)
- {
- BYTE * p = pImg->GetBits(x,y) ;
- if (PCL_A(p) == 0)
- {
- FCColor::CopyPixel (p, &cr, 3) ;
- m_pt.x=x ; m_pt.y=y ;
- m_nTransparency = 1 ;
- }
- }
- }
- SetBackupImage (pImg) ;
- GetBackupImage()->ConvertTo24Bit() ; // easy to handle
- }
- virtual void ProcessWholeImage (FCObjImage* pImg, FCObjProgress* pProgress)
- {
- FIBITMAP * pFI = __pcl_AllocateFreeImage (*GetBackupImage()) ;
- if (pFI)
- {
- FIBITMAP * pQu = FreeImage_ColorQuantizeEx (pFI, FIQ_NNQUANT, 1<<m_nBPP) ;
- if (pQu)
- {
- __pcl_FreeImage_to_PCLImage (pQu, *pImg) ;
- FreeImage_Unload (pQu) ;
- }
- FreeImage_Unload (pFI) ;
- }
- // set transparency
- if (pImg->IsValidImage() && (m_nTransparency == 1) && pImg->IsInside(m_pt.x,m_pt.y))
- {
- m_nTransparency = (int)pImg->GetPixelData(m_pt.x,m_pt.y) ;
- }
- }
- POINT m_pt ;
- int m_nBPP ;
- int m_nTransparency ;
- };
- #endif // PCL_3RD_LIBRARY_USE_FREEIMAGE
- //=============================================================================
- /**
- * Glass tile (>=24 bit).
- @verbatim
- example:
- FCPixelGlasstile aCmd (6, 6) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelGlasstile : public FCPixelWholeImageBase
- {
- public:
- /// Constructor (account of X/Y tile).
- FCPixelGlasstile (int nXTile, int nYTile)
- {
- m_nXTile = FMax(2, nXTile) ;
- m_nYTile = FMax(2, nYTile) ;
- }
- private:
- virtual void OnEnterProcess (FCObjImage* pImg)
- {
- SetBackupImage (pImg) ;
- }
- virtual void ProcessWholeImage (FCObjImage* pImg, FCObjProgress* pProgress)
- {
- int xhalv = m_nXTile / 2, yhalv = m_nYTile / 2 ;
- int xplus = m_nXTile % 2, yplus = m_nYTile % 2 ;
- int ymitt = 0, yoffs = 0 ;
- for (int y=0 ; y < pImg->Height() ; y++)
- {
- int ypixel2 = FClamp (ymitt + yoffs*2, 0, pImg->Height()-1) ;
- yoffs++ ;
- if (yoffs == yhalv)
- {
- ymitt += m_nYTile ;
- yoffs = -(yhalv + yplus) ;
- }
- int xmitt = 0, xoffs = 0 ;
- for (int x=0 ; x < pImg->Width() ; x++)
- {
- int xpixel2 = FClamp (xmitt + xoffs*2, 0, pImg->Width()-1) ;
- FCColor::CopyPixel (pImg->GetBits(x,y), GetBackupImage()->GetBits(xpixel2,ypixel2), pImg->ColorBits()/8) ;
- xoffs++ ;
- if (xoffs == xhalv)
- {
- xmitt += m_nXTile ;
- xoffs = -(xhalv + xplus) ;
- }
- }
- if (pProgress)
- pProgress->SetProgress (100 * y / pImg->Height()) ;
- }
- }
- int m_nXTile, m_nYTile ; // >=2
- };
- //=============================================================================
- /**
- * Box smooth (>=24 bit).
- @verbatim
- example:
- FCPixelBlur_Box aCmd (5, true) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelBlur_Box : public FCPixelWholeImageBase
- {
- public:
- /// Constructor.
- FCPixelBlur_Box (int iBlockLen, bool bCopyEdge)
- {
- m_iBlock = FMax(2, iBlockLen) ;
- m_bCopyEdge = bCopyEdge ;
- }
- private:
- // if m_iBlock>200, the sum maybe exceed int32
- void in_UpdateSum (int& R, int& G, int& B, int& A, const void* pAdd, const void* pSub)
- {
- int nAddA = (GetBackupImage()->ColorBits() == 32) ? PCL_A(pAdd) : 0xFF,
- nSubA = (GetBackupImage()->ColorBits() == 32) ? PCL_A(pSub) : 0xFF ;
- B = B + PCL_B(pAdd)*nAddA - PCL_B(pSub)*nSubA ;
- G = G + PCL_G(pAdd)*nAddA - PCL_G(pSub)*nSubA ;
- R = R + PCL_R(pAdd)*nAddA - PCL_R(pSub)*nSubA ;
- A = A + nAddA - nSubA ;
- }
- void in_SetPixel (int R, int G, int B, int A, void* pPixel)
- {
- PCL_B(pPixel) = A ? (B/A) : 0 ;
- PCL_G(pPixel) = A ? (G/A) : 0 ;
- PCL_R(pPixel) = A ? (R/A) : 0 ;
- if (GetBackupImage()->ColorBits() == 32)
- PCL_A(pPixel) = A / FSquare(m_iBlock) ; // pixel number of block
- }
- virtual void OnEnterProcess (FCObjImage* pImg)
- {
- SetBackupImage (pImg) ;
- // expand edge
- int nLeftTop = m_iBlock/2, // left & top
- nRightDown = nLeftTop; // right & bottom : -((m_iBlock % 2)^1)
- GetBackupImage()->ExpandFrame (m_bCopyEdge, nLeftTop, nLeftTop, nRightDown, nRightDown) ;
- }
- virtual void ProcessWholeImage (FCObjImage* pImg, FCObjProgress* pProgress)
- {
- // RGBA sum of every scanline start
- int iFirstR=0, iFirstG=0, iFirstB=0, iFirstA=0 ;
- for (int y=0 ; y < pImg->Height() ; y++)
- {
- if (y == 0) // first line
- {
- for (int ny=0 ; ny < m_iBlock ; ny++)
- for (int nx=0 ; nx < m_iBlock ; nx++)
- {
- BYTE * pPixel = GetBackupImage()->GetBits (nx,ny) ;
- int nA = (GetBackupImage()->ColorBits() == 32) ? PCL_A(pPixel) : 0xFF ;
- iFirstB += PCL_B(pPixel) * nA ;
- iFirstG += PCL_G(pPixel) * nA ;
- iFirstR += PCL_R(pPixel) * nA ;
- iFirstA += nA ;
- }
- }
- else // Y move down
- {
- // sub up line & add down line
- for (int i=0 ; i < m_iBlock ; i++)
- in_UpdateSum (iFirstR, iFirstG, iFirstB, iFirstA,
- GetBackupImage()->GetBits (i, y-1+m_iBlock),
- GetBackupImage()->GetBits (i, y-1)) ;
- }
- // set first pixel per scanline
- in_SetPixel (iFirstR, iFirstG, iFirstB, iFirstA, pImg->GetBits(y)) ;
- // X move
- int iCurrR=iFirstR, iCurrG=iFirstG, iCurrB=iFirstB, iCurrA=iFirstA ;
- for (int x=1 ; x < pImg->Width() ; x++)
- {
- // sub left pixel & add right pixel
- for (int i=0 ; i < m_iBlock ; i++)
- in_UpdateSum (iCurrR, iCurrG, iCurrB, iCurrA,
- GetBackupImage()->GetBits (x-1+m_iBlock, y+i),
- GetBackupImage()->GetBits (x-1, y+i)) ;
- in_SetPixel (iCurrR, iCurrG, iCurrB, iCurrA, pImg->GetBits(x,y)) ;
- }
- if (pProgress)
- pProgress->SetProgress ((y+1) * 100 / pImg->Height()) ;
- } // end of for(Y)
- }
- int m_iBlock ; // >=2
- bool m_bCopyEdge ;
- };
- //=============================================================================
- /**
- * Blur zoom (>=24 bit).
- @verbatim
- example:
- FCPixelBlur_Zoom aCmd (15) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelBlur_Zoom : public FCPixelWholeImageBase
- {
- public:
- /// Constructor.
- FCPixelBlur_Zoom (int nLength) : m_nLength(FMax(0,nLength)) {}
- private:
- virtual void OnEnterProcess (FCObjImage* pImg)
- {
- SetBackupImage (pImg) ;
- }
- virtual void ProcessWholeImage (FCObjImage* pImg, FCObjProgress* pProgress)
- {
- for (int y=0 ; y < pImg->Height() ; y++)
- {
- for (int x=0 ; x < pImg->Width() ; x++)
- {
- // Stat.
- int nSumB=0, nSumG=0, nSumR=0, nSumA=0,
- i=0 ;
- for (i=0 ; i < m_nLength ; i++)
- {
- int nCenX = pImg->Width()/2, nCenY = pImg->Height()/2,
- xx = (int)(nCenX + (x-nCenX) * (1.0 + 0.02 * i)),
- yy = (int)(nCenY + (y-nCenY) * (1.0 + 0.02 * i)) ;
- if (!GetBackupImage()->IsInside(xx,yy))
- break ;
- BYTE * p = GetBackupImage()->GetBits (xx, yy) ;
- int nA = (pImg->ColorBits() == 32) ? PCL_A(p) : 0xFF ;
- nSumA += nA ;
- nSumB += nA * PCL_B(p) ;
- nSumG += nA * PCL_G(p) ;
- nSumR += nA * PCL_R(p) ;
- }
- // set pixel
- BYTE * pWrite = pImg->GetBits(x,y) ;
- if (nSumA)
- {
- PCL_B(pWrite) = nSumB/nSumA ;
- PCL_G(pWrite) = nSumG/nSumA ;
- PCL_R(pWrite) = nSumR/nSumA ;
- }
- if ((pImg->ColorBits() == 32) && i)
- PCL_A(pWrite) = nSumA/i ;
- }
- if (pProgress)
- pProgress->SetProgress (100 * (y+1) / pImg->Height()) ;
- }
- }
- int m_nLength ;
- };
- //=============================================================================
- /**
- * Blur radial (>=24 bit).
- @verbatim
- example:
- FCPixelBlur_Radial aCmd (30) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelBlur_Radial : public FCPixelWholeImageBase
- {
- public:
- /// Constructor.
- FCPixelBlur_Radial (int nAngle) : m_nAngle(abs(nAngle) % 360) {}
- private:
- virtual void OnEnterProcess (FCObjImage* pImg)
- {
- SetBackupImage (pImg) ;
- }
- virtual void ProcessWholeImage (FCObjImage* pImg, FCObjProgress* pProgress)
- {
- int nCenX = pImg->Width()/2, nCenY = pImg->Height()/2,
- R = (int)FHypot ((double)FMax(nCenX,pImg->Width()-nCenX), (double)FMax(nCenY,pImg->Height()-nCenY)),
- n = (int)(4 * AngleToRadian(m_nAngle) * sqrt((double)R) + 2) ;
- PCL_array<double> ct(n),
- st(n) ;
- double theta = (double)AngleToRadian(m_nAngle) / ((double)(n - 1)),
- offset = double(theta * (n - 1) / 2.0) ;
- for (int i=0 ; i < n ; i++)
- {
- ct[i] = cos (theta * i - offset) ;
- st[i] = sin (theta * i - offset) ;
- }
- for (int y=0 ; y < pImg->Height() ; y++)
- {
- for (int x=0 ; x < pImg->Width() ; x++)
- {
- int xr = x - nCenX, yr = y - nCenY,
- r = (int)sqrt ((double)FSquare(xr) + (double)FSquare(yr)),
- nStep ;
- if (r == 0)
- nStep = 1 ;
- else
- {
- nStep = R/r ;
- if (nStep == 0)
- nStep = 1 ;
- else
- if (nStep > n-1)
- nStep = n-1 ;
- }
- // Stat.
- int nSumB=0, nSumG=0, nSumR=0, nSumA=0,
- nCount = 0 ;
- for (int i=0 ; i < n ; i += nStep)
- {
- int xx = (int)(nCenX + xr * ct[i] - yr * st[i]),
- yy = (int)(nCenY + xr * st[i] + yr * ct[i]) ;
- if (!GetBackupImage()->IsInside(xx,yy))
- continue ;
- nCount++ ;
- BYTE * p = GetBackupImage()->GetBits (xx,yy) ;
- int nA = (pImg->ColorBits() == 32) ? PCL_A(p) : 0xFF ;
- nSumA += nA ;
- nSumB += nA * PCL_B(p) ;
- nSumG += nA * PCL_G(p) ;
- nSumR += nA * PCL_R(p) ;
- }
- // set pixel
- BYTE * pWrite = pImg->GetBits(x,y) ;
- if (nSumA)
- {
- PCL_B(pWrite) = nSumB/nSumA ;
- PCL_G(pWrite) = nSumG/nSumA ;
- PCL_R(pWrite) = nSumR/nSumA ;
- }
- if ((pImg->ColorBits() == 32) && nCount)
- PCL_A(pWrite) = nSumA/nCount ;
- }
- if (pProgress)
- pProgress->SetProgress (100 * (y+1) / pImg->Height()) ;
- }
- }
- int m_nAngle ; // [0, 360]
- };
- //=============================================================================
- /**
- * Blur motion (>=24 bit).
- @verbatim
- example:
- FCPixelBlur_Motion aCmd (15, DIRECT_LEFT) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelBlur_Motion : public FCPixelWholeImageBase
- {
- public:
- /// Constructor.
- FCPixelBlur_Motion (int nStep, DIRECT_SYS Direct) : m_nStep(nStep), m_Direct(Direct) {}
- private:
- virtual void ProcessWholeImage (FCObjImage* pImg, FCObjProgress* pProgress)
- {
- if (pImg->Width() < 5)
- return ;
- m_nStep = FClamp (m_nStep, 2, (int)pImg->Width()-2) ;
- for (int y=0 ; y < pImg->Height() ; y++)
- {
- int nCurrX = 0,
- nSpanX = 1 ;
- RGBQUAD rgb ; // pixel at edge
- switch (m_Direct)
- {
- case DIRECT_LEFT :
- FCColor::CopyPixel (&rgb, pImg->GetBits(pImg->Width()-1, y), pImg->ColorBits()/8) ;
- nCurrX = 0 ;
- nSpanX = 1 ;
- break ;
- case DIRECT_RIGHT :
- FCColor::CopyPixel (&rgb, pImg->GetBits(0, y), pImg->ColorBits()/8) ;
- nCurrX = pImg->Width()-1 ;
- nSpanX = -1 ;
- break ;
- }
- // first block
- int B=0, G=0, R=0, A=0, i=0 ;
- for (i=0 ; i < m_nStep ; i++)
- {
- BYTE * p = pImg->GetBits (nCurrX + i*nSpanX, y) ;
- B += PCL_B(p) ;
- G += PCL_G(p) ;
- R += PCL_R(p) ;
- A += PCL_A(p) ;
- }
- // move block
- for (i=0 ; i < pImg->Width() - 2 ; i++, nCurrX+=nSpanX) // leave 2 pixel edge
- {
- int newB = FClamp0255 (B / m_nStep), // don't set pixel current
- newG = FClamp0255 (G / m_nStep),
- newR = FClamp0255 (R / m_nStep),
- newA = FClamp0255 (A / m_nStep) ;
- BYTE * p = pImg->GetBits (nCurrX, y) ;
- // step
- if (i >= pImg->Width() - m_nStep) // edge
- {
- B = B - PCL_B(p) + PCL_B(&rgb) ;
- G = G - PCL_G(p) + PCL_G(&rgb) ;
- R = R - PCL_R(p) + PCL_R(&rgb) ;
- if (pImg->ColorBits() == 32)
- A = A - PCL_A(p) + PCL_A(&rgb) ;
- }
- else
- {
- BYTE * pA = pImg->GetBits (nCurrX + nSpanX*m_nStep, y) ;
- B = B - PCL_B(p) + PCL_B(pA) ;
- G = G - PCL_G(p) + PCL_G(pA) ;
- R = R - PCL_R(p) + PCL_R(pA) ;
- if (pImg->ColorBits() == 32)
- A = A - PCL_A(p) + PCL_A(pA) ;
- }
- PCL_B(p) = newB ;
- PCL_G(p) = newG ;
- PCL_R(p) = newR ;
- if (pImg->ColorBits() == 32)
- PCL_A(p) = newA ;
- }
- if (pProgress)
- pProgress->SetProgress ((y+1) * 100 / pImg->Height()) ;
- }
- }
- DIRECT_SYS m_Direct ;
- int m_nStep ; // (>= 2)
- };
- //=============================================================================
- /**
- * Blur IIR gauss (>=24 bit).
- @verbatim
- example:
- FCPixelBlur_Gauss_IIR aCmd (10, 10) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelBlur_Gauss_IIR : public FCPixelWholeImageBase
- {
- public:
- FCPixelBlur_Gauss_IIR (int nHorz, int nVert)
- {
- m_nHorz = FMax(1,nHorz) ;
- m_nVert = FMax(1,nVert) ;
- }
- private:
- static void find_constants (double n_p[], double n_m[], double d_p[], double d_m[], double bd_p[], double bd_m[], double std_dev)
- {
- // The constants used in the implemenation of a casual sequence
- // using a 4th order approximation of the gaussian operator
- const double div = sqrt(LIB_2PI) * std_dev ;
- const double constants [8] =
- {
- -1.783/std_dev, -1.723/std_dev, 0.6318/std_dev, 1.997/std_dev,
- 1.6803/div, 3.735/div, -0.6803/div, -0.2598/div
- } ;
- n_p[0] = constants[4] + constants[6] ;
- n_p[1] = exp(constants[1]) * (constants[7] * sin(constants[3]) - (constants[6] + 2*constants[4]) * cos(constants[3])) + exp(constants[0]) * (constants[5] * sin (constants[2]) - (2 * constants[6] + constants[4]) * cos(constants[2])) ;
- n_p[2] = 2 * exp (constants[0] + constants[1]) * ((constants[4] + constants[6]) * cos (constants[3]) * cos (constants[2]) - constants[5] * cos (constants[3]) * sin (constants[2]) - constants[7] * cos (constants[2]) * sin (constants[3]))
- + constants[6] * exp (2 * constants[0]) + constants[4] * exp (2 * constants[1]) ;
- n_p[3] = exp (constants[1] + 2 * constants[0]) * (constants[7] * sin (constants[3]) - constants[6] * cos (constants[3])) + exp (constants[0] + 2 * constants[1]) * (constants[5] * sin (constants[2]) - constants[4] * cos (constants[2])) ;
- n_p[4] = 0.0 ;
- d_p[0] = 0.0 ;
- d_p[1] = -2 * exp (constants[1]) * cos (constants[3]) - 2 * exp (constants[0]) * cos (constants[2]) ;
- d_p[2] = 4 * cos (constants[3]) * cos (constants[2]) * exp (constants[0] + constants[1]) + exp (2 * constants[1]) + exp (2 * constants[0]) ;
- d_p[3] = -2 * cos (constants[2]) * exp (constants[0] + 2 * constants[1]) - 2 * cos (constants[3]) * exp (constants[1] + 2 * constants[0]) ;
- d_p[4] = exp (2 * constants[0] + 2 * constants[1]) ;
- int i ;
- for (i=0 ; i <= 4 ; i++)
- {
- d_m[i] = d_p[i] ;
- }
- n_m[0] = 0.0 ;
- for (i=1 ; i <= 4 ; i++)
- {
- n_m[i] = n_p[i] - d_p[i] * n_p[0] ;
- }
- double sum_n_p=0.0, sum_n_m=0.0, sum_d=0.0 ;
- for (i=0 ; i <= 4 ; i++)
- {
- sum_n_p += n_p[i] ;
- sum_n_m += n_m[i] ;
- sum_d += d_p[i] ;
- }
- const double a = sum_n_p / (1.0 + sum_d),
- b = sum_n_m / (1.0 + sum_d) ;
- for (i = 0; i <= 4; i++)
- {
- bd_p[i] = d_p[i] * a;
- bd_m[i] = d_m[i] * b ;
- }
- }
- void GaussIIRBlurImage (FCObjImage& img, int nLength, FCObjProgress* pProgress)
- {
- int i, j, b;
- double n_p[5], n_m[5], d_p[5], d_m[5], bd_p[5], bd_m[5];
- nLength = FMax (2, nLength + 1) ;
- double std_dev = sqrt (-(nLength * nLength) / (2 * log (1.0 / 255.0)));
- // derive the constants for calculating the gaussian from the std dev
- find_constants (n_p, n_m, d_p, d_m, bd_p, bd_m, std_dev);
- FCObjImage imgOld(img) ;
- int nSpan = img.ColorBits() / 8 ; // 3, 4
- PCL_array<double> val_p(img.Width() * 3),
- val_m(img.Width() * 3) ;
- for (int y=0 ; y < img.Height() ; y++)
- {
- memset(val_p.get(), 0, val_p.GetArrayBytes());
- memset(val_m.get(), 0, val_m.GetArrayBytes());
- BYTE * sp_p = imgOld.GetBits(y) ;
- BYTE * sp_m = imgOld.GetBits(img.Width()-1, y) ;
- double * vp = val_p.get();
- double * vm = val_m.get() + (img.Width() - 1) * 3;
- // Set up the first vals
- int initial_p[3], initial_m[3];
- for (i = 0; i < 3; i++)
- {
- initial_p[i] = sp_p[i];
- initial_m[i] = sp_m[i];
- }
- for (int x=0 ; x < img.Width() ; x++)
- {
- double *vpptr, *vmptr;
- int terms = (x < 4) ? x : 4;
- for (b = 0; b < 3; b++)
- {
- vpptr = vp + b; vmptr = vm + b;
- for (i = 0; i <= terms; i++)
- {
- *vpptr += n_p[i] * sp_p[(-i * nSpan) + b] - d_p[i] * vp[(-i * 3) + b];
- *vmptr += n_m[i] * sp_m[(i * nSpan) + b] - d_m[i] * vm[(i * 3) + b];
- }
- for (j = i; j <= 4; j++)
- {
- *vpptr += (n_p[j] - bd_p[j]) * initial_p[b];
- *vmptr += (n_m[j] - bd_m[j]) * initial_m[b];
- }
- }
- sp_p += nSpan ; sp_m -= nSpan ;
- vp += 3 ; vm -= 3 ;
- }
- double * pTmp_p = val_p.get(), * pTmp_m = val_m.get() ;
- for (int mm=0 ; mm < img.Width() ; mm++)
- {
- BYTE * p = img.GetBits (mm, y) ;
- p[0] = FClamp0255 (int(*pTmp_p + *pTmp_m)) ; pTmp_p++ ; pTmp_m++ ;
- p[1] = FClamp0255 (int(*pTmp_p + *pTmp_m)) ; pTmp_p++ ; pTmp_m++ ;
- p[2] = FClamp0255 (int(*pTmp_p + *pTmp_m)) ; pTmp_p++ ; pTmp_m++ ;
- }
- if (pProgress)
- pProgress->SetProgress ((y+1) * 100 / img.Height()) ;
- }
- }
- virtual void ProcessWholeImage (FCObjImage* pImg, FCObjProgress* pProgress)
- {
- GaussIIRBlurImage (*pImg, m_nHorz, 0) ;
- FCPixelRotate90 aImg90 ;
- pImg->SinglePixelProcessProc (aImg90) ;
- GaussIIRBlurImage (*pImg, m_nVert, pProgress) ;
- FCPixelRotate270 aImg270 ;
- pImg->SinglePixelProcessProc (aImg270) ;
- }
- int m_nHorz, m_nVert ;
- };
- //=============================================================================
- /**
- * Add inner bevel frame (>=24 bit).
- @verbatim
- example:
- FCPixelInnerBevel aCmd (20, 10) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelInnerBevel : public FCPixelWholeImageBase
- {
- public:
- FCPixelInnerBevel (int nSize, int nSmooth)
- {
- m_nSize = FMax (1, nSize) ;
- m_nSmooth = nSmooth ;
- }
- private:
- // the temporary object adjust brightness
- class __FCPixelFillInnerBevel : public FCSinglePixelProcessBase
- {
- public :
- __FCPixelFillInnerBevel (FCObjImage* pImg) : m_pImgBright(pImg) {}
- private:
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- BYTE * p = m_pImgBright->GetBits(x,y) ;
- PCL_B(pPixel) = FClamp0255 (PCL_B(pPixel) * PCL_A(p) / 100) ;
- PCL_G(pPixel) = FClamp0255 (PCL_G(pPixel) * PCL_A(p) / 100) ;
- PCL_R(pPixel) = FClamp0255 (PCL_R(pPixel) * PCL_A(p) / 100) ;
- }
- FCObjImage * m_pImgBright ;
- };
- virtual void ProcessWholeImage (FCObjImage* pImg, FCObjProgress* pProgress)
- {
- // image brightness
- const int nLeft=160, nTop=160,
- nRight=40, nBottom=40 ;
- FCObjImage imgBright (pImg->Width(), pImg->Height(), 32) ;
- for (int y=0 ; y < imgBright.Height() ; y++)
- for (int x=0 ; x < imgBright.Width() ; x++)
- {
- BYTE * p = imgBright.GetBits(x,y) ;
- if ((x < m_nSize) && (y < imgBright.Height()-x) && (y > x))
- PCL_A(p) = nLeft ;
- else if ((y < m_nSize) && (x < imgBright.Width()-y) && (x > y))
- PCL_A(p) = nTop ;
- else if ((x > imgBright.Width()-m_nSize) && (y > imgBright.Width()-x) && (y < imgBright.Height()+x-imgBright.Width()))
- PCL_A(p) = nRight ;
- else if (y > imgBright.Height()-m_nSize)
- PCL_A(p) = nBottom ;
- else
- PCL_A(p) = 100 ;
- }
- FCPixelBlur_Box cmdBlur (m_nSmooth, true) ;
- imgBright.SinglePixelProcessProc (cmdBlur) ;
- __FCPixelFillInnerBevel cmdBevel (&imgBright) ;
- pImg->SinglePixelProcessProc (cmdBevel, pProgress) ;
- }
- int m_nSize, m_nSmooth ;
- };
- //=============================================================================
- /**
- * Smooth edge (32 bit).
- @verbatim
- example:
- FCPixelSmoothEdge aCmd (15) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelSmoothEdge : public FCPixelWholeImageBase
- {
- public:
- FCPixelSmoothEdge (int iBlock) : m_iBlock(FMax(1,iBlock)) {}
- private:
- int m_iBlock ; // >=1
- private:
- virtual bool ValidateColorBits (const FCObjImage* pImg)
- {
- return pImg->IsValidImage() && (pImg->ColorBits() == 32) ;
- }
- static void RecordHaloPoint (const FCObjImage& imgAlpha, std::deque<POINT>& listHalo)
- {
- // expand edge to search easily
- FCObjImage imgSearch (imgAlpha.Width()+2, imgAlpha.Height()+2, imgAlpha.ColorBits()) ;
- imgSearch.CoverBlock (imgAlpha, 1, 1) ;
- // record halo point
- FCObjImage imgRecord (imgSearch.Width(), imgSearch.Height(), 8) ;
- POINT nDirect[4] = {{0,-1}, {0,1}, {-1,0}, {1,0}} ; // up-down-left-right
- for (int y=1 ; y < imgSearch.Height()-1 ; y++)
- for (int x=1 ; x < imgSearch.Width()-1 ; x++)
- {
- BYTE * p = imgSearch.GetBits(x,y) ;
- for (int i=0 ; i < 4 ; i++)
- {
- // direction
- int nDX = x + nDirect[i].x,
- nDY = y + nDirect[i].y ;
- BYTE * pTmp = imgSearch.GetBits (nDX, nDY) ;
- if (*pTmp == *p)
- continue ;
- // draw halo at smaller alpha
- POINT pt ;
- if (*pTmp < *p)
- {
- pt.x=nDX ; pt.y=nDY ;
- }
- else
- {
- pt.x=x ; pt.y=y ;
- }
- *imgRecord.GetBits (pt.x, pt.y) = 0xFF ;
- }
- }
- // halo point
- listHalo.clear() ;
- {
- for (int y=0 ; y < imgRecord.Height() ; y++)
- for (int x=0 ; x < imgRecord.Width() ; x++)
- if (*imgRecord.GetBits(x,y) == 0xFF)
- {
- POINT pt = {x-1, y-1} ; // remember -1
- listHalo.push_back (pt) ;
- }
- }
- }
- void DrawHalo (FCObjImage& imgDest, FCObjImage& imgAlpha, FCObjImage& imgHalo, POINT ptCenter)
- {
- int nLT = (imgHalo.Width()-1) / 2 ;
- RECT rcHalo = {ptCenter.x-nLT, ptCenter.y-nLT, ptCenter.x+nLT+1, ptCenter.y+nLT+1},
- rcAlpha = {0,0,imgAlpha.Width(),imgAlpha.Height()}, rcDest ;
- if (::IntersectRect (&rcDest, &rcHalo, &rcAlpha) == 0)
- return ;
- int nCenter = 0 ;
- if (imgAlpha.IsInside (ptCenter.x, ptCenter.y))
- nCenter = *imgAlpha.GetBits (ptCenter.x, ptCenter.y) ;
- for (int y=rcDest.top ; y < rcDest.bottom ; y++)
- for (int x=rcDest.left ; x < rcDest.right ; x++)
- {
- BYTE * pDest = imgDest.GetBits (x, y),
- * pAlpha = imgAlpha.GetBits (x, y),
- * pHalo = imgHalo.GetBits (x-rcHalo.left, y-rcHalo.top) ;
- // calculate percentage
- int nNew = FMax (nCenter, *pAlpha * *pHalo / 0xFF) ;
- if (nNew < *pDest)
- *pDest = nNew ;
- }
- }
- virtual void ProcessWholeImage (FCObjImage* pImg, FCObjProgress* pProgress)
- {
- // get alpha channel
- FCObjImage imgAlpha ;
- pImg->GetAlphaChannel (&imgAlpha) ;
- // get draw halo point
- std::deque<POINT> listHalo ;
- RecordHaloPoint (imgAlpha, listHalo) ;
- if (listHalo.empty())
- return ;
- // create halo image
- FCObjImage imgHalo ;
- FCPixelCreateHalo aCmdCreateHalo(m_iBlock, 0, 0xFF) ;
- imgHalo.SinglePixelProcessProc (aCmdCreateHalo) ;
- // make alpha image
- FCObjImage imgDest = imgAlpha ;
- for (size_t i=0 ; i < listHalo.size() ; i++)
- {
- DrawHalo (imgDest, imgAlpha, imgHalo, listHalo[i]) ;
- if (pProgress)
- pProgress->SetProgress (100*i/listHalo.size()) ;
- }
- pImg->AppendAlphaChannel (imgDest) ;
- }
- private:
- class FCPixelCreateHalo : public FCSinglePixelProcessBase
- {
- public:
- FCPixelCreateHalo (int nRadius, int crCenter, int crEdge) : m_crCenter(crCenter), m_crEdge(crEdge)
- {
- m_fRadius = FMax (1, nRadius) ;
- m_fRadius += 1.0 ;
- m_ptCenter.x = (int)m_fRadius ; m_ptCenter.y = (int)m_fRadius ;
- }
- private:
- virtual bool ValidateColorBits (const FCObjImage* pImg) {return true;}
- virtual void OnEnterProcess (FCObjImage* pImg)
- {
- int nWidth = (int)(2*m_fRadius + 1) ;
- pImg->Create (nWidth, nWidth, 8) ;
- }
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- double fDist = FHypot((double)(x-m_ptCenter.x), (double)(y-m_ptCenter.y)) ;
- if (fDist <= m_fRadius)
- *pPixel = FRound (m_crCenter + (m_crEdge-m_crCenter)*fDist/m_fRadius) ;
- else
- *pPixel = m_crEdge ;
- }
- double m_fRadius ;
- int m_crCenter, m_crEdge ;
- POINT m_ptCenter ;
- };
- };
- //=============================================================================
- /// Calculate optimized image's rect.
- class FCPixelGetOptimizedRect : public FCSinglePixelProcessBase
- {
- public:
- FCPixelGetOptimizedRect()
- {
- memset (&m_rcOptimized, 0, sizeof(m_rcOptimized)) ;
- m_bFirst = true ;
- }
- virtual bool ValidateColorBits (const FCObjImage* pImg)
- {
- return pImg->IsValidImage() && (pImg->ColorBits() == 32) ;
- }
- virtual void ProcessPixel (FCObjImage* pImg, int x, int y, BYTE* pPixel)
- {
- if (PCL_A(pPixel))
- if (m_bFirst)
- {
- m_rcOptimized.left = x ;
- m_rcOptimized.right = x+1 ;
- m_rcOptimized.top = y ;
- m_rcOptimized.bottom = y+1 ;
- m_bFirst = false ;
- }
- else
- {
- if (x < m_rcOptimized.left) m_rcOptimized.left = x ;
- if (x+1 > m_rcOptimized.right) m_rcOptimized.right = x+1 ;
- if (y < m_rcOptimized.top) m_rcOptimized.top = y ;
- if (y+1 > m_rcOptimized.bottom) m_rcOptimized.bottom = y+1 ;
- }
- }
- public:
- RECT m_rcOptimized ;
- bool m_bFirst ;
- };
- //=============================================================================
- /**
- * Add shadow (32 bit).
- @verbatim
- example:
- SHADOWDATA ShData ;
- ShData.crShadow = FCColor::crWhite() ;
- ShData.nAlpha = 75 ;
- ShData.nSmooth = 10 ;
- ShData.nOffsetX = 5 ;
- ShData.nOffsetY = 5 ;
- FCPixelAddShadow aCmd (ShData) ;
- img.SinglePixelProcessProc (aCmd) ;
- @endverbatim
- */
- class FCPixelAddShadow : public FCPixelWholeImageBase
- {
- public:
- FCPixelAddShadow (SHADOWDATA ShData)
- {
- m_ShadowData = ShData ;
- m_ShadowData.nSmooth = FMax (2, (int)m_ShadowData.nSmooth) ;
- m_ShadowData.nAlpha = FClamp ((int)m_ShadowData.nAlpha, 1, 100) ;
- }
- private:
- virtual bool ValidateColorBits (const FCObjImage* pImg)
- {
- return pImg->IsValidImage() && (pImg->ColorBits() == 32) ;
- }
- virtual void ProcessWholeImage (FCObjImage* pImg, FCObjProgress* pProgress)
- {
- // backup image
- const FCObjImage imgOld(*pImg) ;
- // calculate new image size
- RECT rcImg = {0, 0, pImg->Width(), pImg->Height()},
- rcShadowOffset = rcImg ;
- ::OffsetRect (&rcShadowOffset, m_ShadowData.nOffsetX, m_ShadowData.nOffsetY) ;
- RECT rcShadow = rcShadowOffset ;
- ::InflateRect (&rcShadow, m_ShadowData.nSmooth, m_ShadowData.nSmooth) ;
- RECT rcResult ;
- ::UnionRect (&rcResult, &rcImg, &rcShadow) ;
- // create shadow background and box-blur it
- pImg->Create (RECTWIDTH(rcResult), RECTHEIGHT(rcResult), 32) ;
- int nStartX = rcShadowOffset.left - rcResult.left,
- nStartY = rcShadowOffset.top - rcResult.top ;
- for (int y=0 ; y < imgOld.Height() ; y++)
- for (int x=0 ; x < imgOld.Width() ; x++)
- {
- RGBQUAD cr = m_ShadowData.crShadow ;
- PCL_A(&cr) = PCL_A(imgOld.GetBits(x,y)) * m_ShadowData.nAlpha / 100 ;
- *(RGBQUAD*)pImg->GetBits (nStartX + x, nStartY + y) = cr ;
- }
- // box-blur alpha-channel
- FCPixelBlur_Box cmdSmooth (m_ShadowData.nSmooth, false) ;
- pImg->SinglePixelProcessProc (cmdSmooth, pProgress) ;
- // combine origin image
- pImg->CombineImage (imgOld, rcImg.left-rcResult.left, rcImg.top-rcResult.top) ;
- // adjust new img's position
- pImg->SetGraphObjPos (imgOld.GetGraphObjPos().x - rcImg.left + rcResult.left,
- imgOld.GetGraphObjPos().y - rcImg.top + rcResult.top) ;
- }
- private:
- SHADOWDATA m_ShadowData ;
- };
- //=============================================================================
- // inline Implement
- //=============================================================================
- #endif
|