| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633 |
- /********************************* PNGwriter **********************************
- *
- * Website: Main: http://pngwriter.sourceforge.net/
- * GitHub.com: https://github.com/pngwriter/pngwriter
- * Sourceforge.net: http://sourceforge.net/projects/pngwriter/
- *
- *
- * Author: Paul Blackburn https://github.com/individual61
- * Axel Huebl https://github.com/ax3l
- * Rene Widera https://github.com/psychocoderHPC
- *
- * Email: individual61@users.sourceforge.net
- *
- * Version: 0.7.0 (January 2018)
- *
- * Description: Library that allows plotting a 48 bit
- * PNG image pixel by pixel, which can
- * then be opened with a graphics program.
- *
- * License: GNU General Public License
- * (C) 2002-2018 Paul Blackburn
- * (C) 2013-2018 Axel Huebl
- * (C) 2016-2018 Rene Widera
- *
- ******************************************************************************/
- /*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * */
- #include "pngwriter.h"
- pngwriterfont::pngwriterfont(const char *face_path, std::string& errorStr)
- {
- FT_Error error;
- loaded = false;
- error = FT_Init_FreeType(&library);
- if (error) {
- errorStr = "FreeType: Could not init Library";
- std::cerr << " PNGwriter::plot_text - ERROR **: FreeType: Could not init Library."<< std::endl;
- return;
- }
- error = FT_New_Face( library,face_path,0,&face );
- if ( error == FT_Err_Unknown_File_Format ) {
- errorStr = "FreeType: Font was opened, but type not supported";
- std::cerr << " PNGwriter::plot_text_utf8 - ERROR **: FreeType: Font was opened, but type not supported." << std::endl;
- return;
- } else if (error) {
- errorStr = "FreeType: Could not find or load font file";
- std::cerr << " PNGwriter::plot_text - ERROR **: FreeType: Could not find or load font file." << std::endl;
- return;
- }
- loaded = true;
- }
- pngwriterfont::~pngwriterfont()
- {
- /* Free the face and the library objects */
- if (loaded)
- {
- FT_Done_Face ( face );
- FT_Done_FreeType( library );
- }
- }
- bool pngwriterfont::ready() const
- { return loaded; }
- FT_Face& pngwriterfont::getFontFace()
- { return face; }
- // Default Constructor
- ////////////////////////////////////////////////////////////////////////////
- pngwriter::pngwriter()
- {
- filename_ = "out.png";
- width_ = 250;
- height_ = 250;
- backgroundcolour_ = 65535;
- compressionlevel_ = -2;
- filegamma_ = 0.5;
- transformation_ = 0;
- textauthor_ = "PNGwriter Author: Paul Blackburn";
- textdescription_ = "http://pngwriter.sourceforge.net/";
- textsoftware_ = "PNGwriter: An easy to use graphics library.";
- texttitle_ = "out.png";
- int kkkk;
- bit_depth_ = 16; //Default bit depth for new images
- colortype_=2;
- screengamma_ = 2.2;
- graph_ = (png_bytepp)malloc(height_ * sizeof(png_bytep));
- if(graph_ == NULL)
- {
- std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl;
- }
- for (kkkk = 0; kkkk < height_; kkkk++)
- {
- graph_[kkkk] = (png_bytep)malloc(6*width_ * sizeof(png_byte));
- if(graph_[kkkk] == NULL)
- {
- std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl;
- }
- }
- if(graph_ == NULL)
- {
- std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl;
- }
- int tempindex;
- for(int vhhh = 0; vhhh<height_;vhhh++)
- {
- for(int hhh = 0; hhh<width_;hhh++)
- {
- //graph_[vhhh][6*hhh + i] where i goes from 0 to 5
- tempindex = 6*hhh;
- graph_[vhhh][tempindex] = (char) floor(((double)backgroundcolour_)/256);
- graph_[vhhh][tempindex+1] = (char)(backgroundcolour_%256);
- graph_[vhhh][tempindex+2] = (char) floor(((double)backgroundcolour_)/256);
- graph_[vhhh][tempindex+3] = (char)(backgroundcolour_%256);
- graph_[vhhh][tempindex+4] = (char) floor(((double)backgroundcolour_)/256);
- graph_[vhhh][tempindex+5] = (char)(backgroundcolour_%256);
- }
- }
- }
- //Copy Constructor
- //////////////////////////////////////////////////////////////////////////
- pngwriter::pngwriter(const pngwriter &rhs)
- {
- width_ = rhs.width_;
- height_ = rhs.height_;
- backgroundcolour_ = rhs.backgroundcolour_;
- compressionlevel_ = rhs.compressionlevel_;
- filegamma_ = rhs.filegamma_;
- transformation_ = rhs.transformation_;
- filename_ = rhs.filename_;
- textauthor_ = rhs.textauthor_;
- textdescription_ = rhs.textdescription_;
- textsoftware_ = rhs.textsoftware_;
- texttitle_ = rhs.texttitle_;
- int kkkk;
- bit_depth_ = rhs.bit_depth_;
- colortype_= rhs.colortype_;
- screengamma_ = rhs.screengamma_;
- graph_ = (png_bytepp)malloc(height_ * sizeof(png_bytep));
- if(graph_ == NULL)
- {
- std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl;
- }
- for (kkkk = 0; kkkk < height_; kkkk++)
- {
- graph_[kkkk] = (png_bytep)malloc(6*width_ * sizeof(png_byte));
- if(graph_[kkkk] == NULL)
- {
- std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl;
- }
- }
- if(graph_ == NULL)
- {
- std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl;
- }
- int tempindex;
- for(int vhhh = 0; vhhh<height_;vhhh++)
- {
- for(int hhh = 0; hhh<width_;hhh++)
- {
- // graph_[vhhh][6*hhh + i ] i=0 to 5
- tempindex=6*hhh;
- graph_[vhhh][tempindex] = rhs.graph_[vhhh][tempindex];
- graph_[vhhh][tempindex+1] = rhs.graph_[vhhh][tempindex+1];
- graph_[vhhh][tempindex+2] = rhs.graph_[vhhh][tempindex+2];
- graph_[vhhh][tempindex+3] = rhs.graph_[vhhh][tempindex+3];
- graph_[vhhh][tempindex+4] = rhs.graph_[vhhh][tempindex+4];
- graph_[vhhh][tempindex+5] = rhs.graph_[vhhh][tempindex+5];
- }
- }
- }
- //Constructor for int colour levels, char * filename
- //////////////////////////////////////////////////////////////////////////
- pngwriter::pngwriter(int x, int y, int backgroundcolour, char * filename)
- {
- width_ = x;
- height_ = y;
- backgroundcolour_ = backgroundcolour;
- compressionlevel_ = -2;
- filegamma_ = 0.6;
- transformation_ = 0;
- textauthor_ = "PNGwriter Author: Paul Blackburn";
- textdescription_ = "https://github.com/pngwriter/pngwriter";
- textsoftware_ = "PNGwriter: An easy to use graphics library.";
- texttitle_ = filename;
- filename_ = filename;
- if((width_<0)||(height_<0))
- {
- std::cerr << " PNGwriter::pngwriter - ERROR **: Constructor called with negative height or width. Setting width and height to 1." << std::endl;
- width_ = 1;
- height_ = 1;
- }
- if(backgroundcolour_ >65535)
- {
- std::cerr << " PNGwriter::pngwriter - WARNING **: Constructor called with background colour greater than 65535. Setting to 65535."<<std::endl;
- backgroundcolour_ = 65535;
- }
- if(backgroundcolour_ <0)
- {
- std::cerr << " PNGwriter::pngwriter - WARNING **: Constructor called with background colour lower than 0. Setting to 0."<<std::endl;
- backgroundcolour_ = 0;
- }
- int kkkk;
- bit_depth_ = 16; //Default bit depth for new images
- colortype_=2;
- screengamma_ = 2.2;
- graph_ = (png_bytepp)malloc(height_ * sizeof(png_bytep));
- if(graph_ == NULL)
- {
- std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl;
- }
- for (kkkk = 0; kkkk < height_; kkkk++)
- {
- graph_[kkkk] = (png_bytep)malloc(6*width_ * sizeof(png_byte));
- if(graph_[kkkk] == NULL)
- {
- std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl;
- }
- }
- if(graph_ == NULL)
- {
- std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl;
- }
- if(backgroundcolour_ == 0)
- for(int vhhh = 0; vhhh<height_;vhhh++)
- memset( graph_[vhhh],
- (char) backgroundcolour_,
- width_*6 );
- else
- {
- int tempindex;
- for(int vhhh = 0; vhhh<height_;vhhh++)
- {
- for(int hhh = 0; hhh<width_;hhh++)
- {
- //graph_[vhhh][6*hhh + i] i = 0 to 5
- tempindex = 6*hhh;
- graph_[vhhh][tempindex] = (char) floor(((double)backgroundcolour_)/256);
- graph_[vhhh][tempindex+1] = (char)(backgroundcolour_%256);
- graph_[vhhh][tempindex+2] = (char) floor(((double)backgroundcolour_)/256);
- graph_[vhhh][tempindex+3] = (char)(backgroundcolour_%256);
- graph_[vhhh][tempindex+4] = (char) floor(((double)backgroundcolour_)/256);
- graph_[vhhh][tempindex+5] = (char)(backgroundcolour_%256);
- }
- }
- }
- }
- //Constructor for double levels, char * filename
- /////////////////////////////////////////////////////////////////////////
- pngwriter::pngwriter(int x, int y, double backgroundcolour, char * filename)
- {
- width_ = x;
- height_ = y;
- compressionlevel_ = -2;
- filegamma_ = 0.6;
- transformation_ = 0;
- backgroundcolour_ = int(backgroundcolour*65535);
- textauthor_ = "PNGwriter Author: Paul Blackburn";
- textdescription_ = "https://github.com/pngwriter/pngwriter";
- textsoftware_ = "PNGwriter: An easy to use graphics library.";
- texttitle_ = filename;
- filename_ = filename;
- if((width_<0)||(height_<0))
- {
- std::cerr << " PNGwriter::pngwriter - ERROR **: Constructor called with negative height or width. Setting width and height to 1." << std::endl;
- width_ = 1;
- height_ = 1;
- }
- if(backgroundcolour_ >65535)
- {
- std::cerr << " PNGwriter::pngwriter - WARNING **: Constructor called with background colour greater than 1.0. Setting to 1.0."<<std::endl;
- backgroundcolour_ = 65535;
- }
- if(backgroundcolour_ < 0)
- {
- std::cerr << " PNGwriter::pngwriter - WARNING **: Constructor called with background colour lower than 0.0. Setting to 0.0."<<std::endl;
- backgroundcolour_ = 0;
- }
- int kkkk;
- bit_depth_ = 16; //Default bit depth for new images
- colortype_=2;
- screengamma_ = 2.2;
- graph_ = (png_bytepp)malloc(height_ * sizeof(png_bytep));
- if(graph_ == NULL)
- {
- std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl;
- }
- for (kkkk = 0; kkkk < height_; kkkk++)
- {
- graph_[kkkk] = (png_bytep)malloc(6*width_ * sizeof(png_byte));
- if(graph_[kkkk] == NULL)
- {
- std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl;
- }
- }
- if(graph_ == NULL)
- {
- std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl;
- }
- if(backgroundcolour_ == 0)
- for(int vhhh = 0; vhhh<height_;vhhh++)
- memset( graph_[vhhh],
- (char) backgroundcolour_,
- width_*6 );
- else
- {
- int tempindex;
- for(int vhhh = 0; vhhh<height_;vhhh++)
- {
- for(int hhh = 0; hhh<width_;hhh++)
- {
- // graph_[vhhh][tempindex + i] where i = 0 to 5
- tempindex = 6*hhh;
- graph_[vhhh][tempindex] = (char) floor(((double)backgroundcolour_)/256);
- graph_[vhhh][tempindex+1] = (char)(backgroundcolour_%256);
- graph_[vhhh][tempindex+2] = (char) floor(((double)backgroundcolour_)/256);
- graph_[vhhh][tempindex+3] = (char)(backgroundcolour_%256);
- graph_[vhhh][tempindex+4] = (char) floor(((double)backgroundcolour_)/256);
- graph_[vhhh][tempindex+5] = (char)(backgroundcolour_%256);
- }
- }
- }
- }
- void pngwriter::deleteMembers()
- {
- for (int jjj = 0; jjj < height_; jjj++)
- {
- free(graph_[jjj]);
- graph_[jjj] = NULL;
- }
- if( graph_ )
- {
- free(graph_);
- graph_ = NULL;
- }
- }
- //Destructor
- ///////////////////////////////////////
- pngwriter::~pngwriter()
- {
- deleteMembers();
- }
- //Constructor for int levels, const char * filename
- //////////////////////////////////////////////////////////////
- pngwriter::pngwriter(int x, int y, int backgroundcolour, const char * filename)
- {
- width_ = x;
- height_ = y;
- backgroundcolour_ = backgroundcolour;
- compressionlevel_ = -2;
- filegamma_ = 0.6;
- transformation_ = 0;
- textauthor_ = "PNGwriter Author: Paul Blackburn";
- textdescription_ = "https://github.com/pngwriter/pngwriter";
- textsoftware_ = "PNGwriter: An easy to use graphics library.";
- texttitle_ = filename;
- filename_ = filename;
- if((width_<0)||(height_<0))
- {
- std::cerr << " PNGwriter::pngwriter - ERROR **: Constructor called with negative height or width. Setting width and height to 1." << std::endl;
- height_ = 1;
- width_ = 1;
- }
- if(backgroundcolour_ >65535)
- {
- std::cerr << " PNGwriter::pngwriter - WARNING **: Constructor called with background colour greater than 65535. Setting to 65535."<<std::endl;
- backgroundcolour_ = 65535;
- }
- if(backgroundcolour_ <0)
- {
- std::cerr << " PNGwriter::pngwriter - WARNING **: Constructor called with background colour lower than 0. Setting to 0."<<std::endl;
- backgroundcolour_ = 0;
- }
- int kkkk;
- bit_depth_ = 16; //Default bit depth for new images
- colortype_=2;
- screengamma_ = 2.2;
- graph_ = (png_bytepp)malloc(height_ * sizeof(png_bytep));
- if(graph_ == NULL)
- {
- std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl;
- }
- for (kkkk = 0; kkkk < height_; kkkk++)
- {
- graph_[kkkk] = (png_bytep)malloc(6*width_ * sizeof(png_byte));
- if(graph_[kkkk] == NULL)
- {
- std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl;
- }
- }
- if(graph_ == NULL)
- {
- std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl;
- }
- if(backgroundcolour_ == 0)
- for(int vhhh = 0; vhhh<height_;vhhh++)
- memset( graph_[vhhh],
- (char) backgroundcolour_,
- width_*6 );
- else
- {
- int tempindex;
- for(int vhhh = 0; vhhh<height_;vhhh++)
- {
- for(int hhh = 0; hhh<width_;hhh++)
- {
- //graph_[vhhh][6*hhh + i] where i = 0 to 5
- tempindex=6*hhh;
- graph_[vhhh][tempindex] = (char) floor(((double)backgroundcolour_)/256);
- graph_[vhhh][tempindex+1] = (char)(backgroundcolour_%256);
- graph_[vhhh][tempindex+2] = (char) floor(((double)backgroundcolour_)/256);
- graph_[vhhh][tempindex+3] = (char)(backgroundcolour_%256);
- graph_[vhhh][tempindex+4] = (char) floor(((double)backgroundcolour_)/256);
- graph_[vhhh][tempindex+5] = (char)(backgroundcolour_%256);
- }
- }
- }
- }
- //Constructor for double levels, const char * filename
- /////////////////////////////////////////////////////////////////////////
- pngwriter::pngwriter(int x, int y, double backgroundcolour, const char * filename)
- {
- width_ = x;
- height_ = y;
- compressionlevel_ = -2;
- backgroundcolour_ = int(backgroundcolour*65535);
- filegamma_ = 0.6;
- transformation_ = 0;
- textauthor_ = "PNGwriter Author: Paul Blackburn";
- textdescription_ = "https://github.com/pngwriter/pngwriter";
- textsoftware_ = "PNGwriter: An easy to use graphics library.";
- texttitle_ = filename;
- filename_ = filename;
- if((width_<0)||(height_<0))
- {
- std::cerr << " PNGwriter::pngwriter - ERROR **: Constructor called with negative height or width. Setting width and height to 1." << std::endl;
- width_ = 1;
- height_ = 1;
- }
- if(backgroundcolour_ >65535)
- {
- std::cerr << " PNGwriter::pngwriter - WARNING **: Constructor called with background colour greater than 65535. Setting to 65535."<<std::endl;
- backgroundcolour_ = 65535;
- }
- if(backgroundcolour_ <0)
- {
- std::cerr << " PNGwriter::pngwriter - WARNING **: Constructor called with background colour lower than 0. Setting to 0."<<std::endl;
- backgroundcolour_ = 0;
- }
- int kkkk;
- bit_depth_ = 16; //Default bit depth for new images
- colortype_=2;
- screengamma_ = 2.2;
- graph_ = (png_bytepp)malloc(height_ * sizeof(png_bytep));
- if(graph_ == NULL)
- {
- std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl;
- }
- for (kkkk = 0; kkkk < height_; kkkk++)
- {
- graph_[kkkk] = (png_bytep)malloc(6*width_ * sizeof(png_byte));
- if(graph_[kkkk] == NULL)
- {
- std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl;
- }
- }
- if(graph_ == NULL)
- {
- std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl;
- }
- if(backgroundcolour_ == 0)
- for(int vhhh = 0; vhhh<height_;vhhh++)
- memset( graph_[vhhh],
- (char) backgroundcolour_,
- width_*6 );
- else
- {
- int tempindex;
- for(int vhhh = 0; vhhh<height_;vhhh++)
- {
- for(int hhh = 0; hhh<width_;hhh++)
- {
- //etc
- tempindex = 6*hhh;
- graph_[vhhh][tempindex] = (char) floor(((double)backgroundcolour_)/256);
- graph_[vhhh][tempindex+1] = (char)(backgroundcolour_%256);
- graph_[vhhh][tempindex+2] = (char) floor(((double)backgroundcolour_)/256);
- graph_[vhhh][tempindex+3] = (char)(backgroundcolour_%256);
- graph_[vhhh][tempindex+4] = (char) floor(((double)backgroundcolour_)/256);
- graph_[vhhh][tempindex+5] = (char)(backgroundcolour_%256);
- }
- }
- }
- }
- // Overloading operator =
- /////////////////////////////////////////////////////////
- pngwriter & pngwriter::operator = (const pngwriter & rhs)
- {
- if( this==&rhs)
- return *this;
- // free old allocations from member variables
- deleteMembers();
- width_ = rhs.width_;
- height_ = rhs.height_;
- backgroundcolour_ = rhs.backgroundcolour_;
- compressionlevel_ = rhs.compressionlevel_;
- filegamma_ = rhs.filegamma_;
- transformation_ = rhs.transformation_;
- textauthor_ = rhs.textauthor_;
- textdescription_ = rhs.textdescription_;
- textsoftware_ = rhs.textsoftware_;
- texttitle_ = rhs.texttitle_;
- filename_ = rhs.filename_;
- int kkkk;
- bit_depth_ = rhs.bit_depth_;
- colortype_= rhs.colortype_;
- screengamma_ = rhs.screengamma_;
- graph_ = (png_bytepp)malloc(height_ * sizeof(png_bytep));
- if(graph_ == NULL)
- {
- std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl;
- }
- for (kkkk = 0; kkkk < height_; kkkk++)
- {
- graph_[kkkk] = (png_bytep)malloc(6*width_ * sizeof(png_byte));
- if(graph_[kkkk] == NULL)
- {
- std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl;
- }
- }
- if(graph_ == NULL)
- {
- std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl;
- }
- int tempindex;
- for(int vhhh = 0; vhhh<height_;vhhh++)
- {
- for(int hhh = 0; hhh<width_;hhh++)
- {
- tempindex=6*hhh;
- graph_[vhhh][tempindex] = rhs.graph_[vhhh][tempindex];
- graph_[vhhh][tempindex+1] = rhs.graph_[vhhh][tempindex+1];
- graph_[vhhh][tempindex+2] = rhs.graph_[vhhh][tempindex+2];
- graph_[vhhh][tempindex+3] = rhs.graph_[vhhh][tempindex+3];
- graph_[vhhh][tempindex+4] = rhs.graph_[vhhh][tempindex+4];
- graph_[vhhh][tempindex+5] = rhs.graph_[vhhh][tempindex+5];
- }
- }
- return *this;
- }
- ///////////////////////////////////////////////////////////////
- void pngwriter::plot(int x, int y, int red, int green, int blue)
- {
- int tempindex;
- if(red > 65535)
- {
- red = 65535;
- }
- if(green > 65535)
- {
- green = 65535;
- }
- if(blue > 65535)
- {
- blue = 65535;
- }
- if(red < 0)
- {
- red = 0;
- }
- if(green < 0)
- {
- green = 0;
- }
- if(blue < 0)
- {
- blue = 0;
- }
- if( bit_depth_ == 16 )
- {
- // if( (height_-y >-1) && (height_-y <height_) && (6*(x-1) >-1) && (6*(x-1)+5<6*width_) )
- if( (y<=height_) && (y>0) && (x>0) && (x<=width_) )
- {
- //graph_[height_-y][6*(x-1) + i] where i goes from 0 to 5
- tempindex= 6*x-6;
- graph_[height_-y][tempindex] = (char) floor(((double)red)/256);
- graph_[height_-y][tempindex+1] = (char)(red%256);
- graph_[height_-y][tempindex+2] = (char) floor(((double)green)/256);
- graph_[height_-y][tempindex+3] = (char)(green%256);
- graph_[height_-y][tempindex+4] = (char) floor(((double)blue)/256);
- graph_[height_-y][tempindex+5] = (char)(blue%256);
- }
- /*
- if(!( (height_-y >-1) && (height_-y <height_) && (6*(x-1) >-1) && (6*(x-1)+5<6*width_) ))
- {
- std::cerr << " PNGwriter::plot-- Plotting out of range! " << y << " " << x << std::endl;
- }
- */
- }
- if( bit_depth_ == 8 )
- {
- // if( (height_-y >-1) && (height_-y <height_) && (3*(x-1) >-1) && (3*(x-1)+5<3*width_) )
- if( (y<height_+1) && (y>0) && (x>0) && (x<width_+1) )
- {
- // graph_[height_-y][3*(x-1) + i] where i goes from 0 to 2
- tempindex = 3*x-3;
- graph_[height_-y][tempindex] = (char)(floor(((double)red)/256.0));
- graph_[height_-y][tempindex+1] = (char)(floor(((double)green)/256.0));
- graph_[height_-y][tempindex+2] = (char)(floor(((double)blue)/256.0));
- }
- /*
- if(!( (height_-y >-1) && (height_-y <height_) && (6*(x-1) >-1) && (6*(x-1)+5<6*width_) ))
- {
- std::cerr << " PNGwriter::plot-- Plotting out of range! " << y << " " << x << std::endl;
- }
- */
- }
- }
- void pngwriter::plot(int x, int y, double red, double green, double blue)
- {
- /* assuming values >= 0 adding +0.5 will round them to the nearest
- * * integer when typecasting it */
- this->plot(x,y,int(red*65535+0.5),int(green*65535+0.5),int(blue*65535+0.5));
- }
- ///////////////////////////////////////////////////////////////
- int pngwriter::read(int x, int y, int colour) const
- {
- int temp1,temp2;
- if((colour !=1)&&(colour !=2)&&(colour !=3))
- {
- std::cerr << " PNGwriter::read - WARNING **: Invalid argument: should be 1, 2 or 3, is " << colour << std::endl;
- return 0;
- }
- if( ( x>0 ) && ( x <= (this->width_) ) && ( y>0 ) && ( y <= (this->height_) ) )
- {
- if(bit_depth_ == 16)
- {
- /* In these cases *256 is correct, because what we actually are
- * doing is bitshifting by 8 bit and then appending the next lower
- * 8 bit.
- * These lines are inefficient. Bitshifting and bitwise anding may
- * have better performance than multiplication and addition.
- * We could also just convert (unsigned char*) to (uint16_t*).
- * If the open file function does it in the same way, then this
- * method makes no assumptions about platform endianness */
- temp2=6*(x-1);
- if(colour == 1)
- {
- temp1 = (graph_[(height_-y)][temp2])*256 + graph_[height_-y][temp2+1];
- return temp1;
- }
- if(colour == 2)
- {
- temp1 = (graph_[height_-y][temp2+2])*256 + graph_[height_-y][temp2+3];
- return temp1;
- }
- if(colour == 3)
- {
- temp1 = (graph_[height_-y][temp2+4])*256 + graph_[height_-y][temp2+5];
- return temp1;
- }
- }
- if(bit_depth_ == 8)
- {
- int const scale8To16Bit = 257; // (x/255.0)*65535.0 -> x*257
- temp2=3*(x-1);
- if(colour == 1)
- {
- temp1 = graph_[height_-y][temp2];
- return temp1*scale8To16Bit;
- }
- if(colour == 2)
- {
- temp1 = graph_[height_-y][temp2+1];
- return temp1*scale8To16Bit;
- }
- if(colour == 3)
- {
- temp1 = graph_[height_-y][temp2+2];
- return temp1*scale8To16Bit;
- }
- }
- }
- else
- {
- return 0;
- }
- std::cerr << " PNGwriter::read - WARNING **: Returning 0 because of bitdepth/colour type mismatch."<< std::endl;
- return 0;
- }
- ///////////////////////////////////////////////////////////////
- int pngwriter::read(int xxx, int yyy) const
- {
- int sumRGB = 0;
- for( int colour = 1; colour <= 3; ++colour )
- sumRGB += this->read(xxx, yyy, colour);
- return sumRGB / 3;
- }
- /////////////////////////////////////////////////////
- double pngwriter::dread(int x, int y, int colour) const
- {
- // PNGwriter converts all read images to 16bit RGB
- return double(this->read(x,y,colour))/65535.0;
- }
- double pngwriter::dread(int x, int y) const
- {
- // PNGwriter converts all read images to 16bit RGB
- return double(this->read(x,y))/65535.0;
- }
- ///////////////////////////////////////////////////////
- void pngwriter::clear()
- {
- int pen = 0;
- int pencil = 0;
- int tempindex;
- if(bit_depth_==16)
- {
- for(pencil = 0; pencil<height_;pencil++)
- {
- for(pen = 0; pen<width_;pen++)
- {
- tempindex=6*pen;
- graph_[pencil][tempindex] = 0;
- graph_[pencil][tempindex+1] = 0;
- graph_[pencil][tempindex+2] = 0;
- graph_[pencil][tempindex+3] = 0;
- graph_[pencil][tempindex+4] = 0;
- graph_[pencil][tempindex+5] = 0;
- }
- }
- }
- if(bit_depth_==8)
- {
- for(pencil = 0; pencil<height_;pencil++)
- {
- for(pen = 0; pen<width_;pen++)
- {
- tempindex=3*pen;
- graph_[pencil][tempindex] = 0;
- graph_[pencil][tempindex+1] = 0;
- graph_[pencil][tempindex+2] = 0;
- }
- }
- }
- }
- /////////////////////////////////////////////////////
- void pngwriter::pngwriter_rename(char * newname)
- {
- filename_ = newname;
- texttitle_ = newname;
- }
- ///////////////////////////////////////////////////////
- void pngwriter::pngwriter_rename(const char * newname)
- {
- filename_ = newname;
- texttitle_ = newname;
- }
- ///////////////////////////////////////////////////////
- void pngwriter::pngwriter_rename(long unsigned int index)
- {
- char buffer[255];
- // %[flags][width][.precision][modifiers]type
- //
- if( index > 999999999 )
- {
- std::cerr << " PNGwriter::pngwriter_rename - ERROR **: Numerical name is out of 0 - 999 999 999 range (" << index <<")." << std::endl;
- return;
- }
- if( 0> sprintf(buffer, "%9.9lu.png",index))
- {
- std::cerr << " PNGwriter::pngwriter_rename - ERROR **: Error creating numerical filename." << std::endl;
- return;
- }
- filename_ = buffer;
- texttitle_ = buffer;
- }
- ///////////////////////////////////////////////////////
- void pngwriter::settext(char * title, char * author, char * description, char * software)
- {
- texttitle_ = title;
- textauthor_ = author;
- textdescription_ = description;
- textsoftware_ = software;
- }
- ///////////////////////////////////////////////////////
- void pngwriter::settext(const char * title, const char * author, const char * description, const char * software)
- {
- texttitle_ = title;
- textauthor_ = author;
- textdescription_ = description;
- textsoftware_ = software;
- }
- ///////////////////////////////////////////////////////
- void pngwriter::close()
- {
- FILE *fp;
- png_structp png_ptr;
- png_infop info_ptr;
- fp = fopen(filename_.c_str(), "wb");
- if( fp == NULL)
- {
- std::cerr << " PNGwriter::close - ERROR **: Error creating file (fopen() returned NULL pointer)." << std::endl;
- perror(" PNGwriter::close - ERROR **");
- return;
- }
- png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
- info_ptr = png_create_info_struct(png_ptr);
- png_init_io(png_ptr, fp);
- if(compressionlevel_ != -2)
- {
- png_set_compression_level(png_ptr, compressionlevel_);
- }
- else
- {
- png_set_compression_level(png_ptr, PNGWRITER_DEFAULT_COMPRESSION);
- }
- png_set_IHDR(png_ptr, info_ptr, width_, height_,
- bit_depth_, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
- PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
- if(filegamma_ < 1.0e-1)
- {
- filegamma_ = 0.5; // Modified in 0.5.4 so as to be the same as the usual gamma.
- }
- png_set_gAMA(png_ptr, info_ptr, filegamma_);
- time_t gmt;
- png_time mod_time;
- png_text text_ptr[5];
- int entries = 4;
- time(&gmt);
- png_convert_from_time_t(&mod_time, gmt);
- png_set_tIME(png_ptr, info_ptr, &mod_time);
- /* key is a 1-79 character description of type char*
- *
- * attention: the pointer of `c_str()` could be invalid if a non const
- * operation to `key_title` is called
- */
- std::string key_title("Title");
- text_ptr[0].key = const_cast<char*>(key_title.c_str());
- text_ptr[0].text = const_cast<char*>(texttitle_.c_str());
- text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE;
- std::string key_author("Author");
- text_ptr[1].key = const_cast<char*>(key_author.c_str());
- text_ptr[1].text = const_cast<char*>(textauthor_.c_str());
- text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE;
- std::string key_descr("Description");
- text_ptr[2].key = const_cast<char*>(key_descr.c_str());
- text_ptr[2].text = const_cast<char *>(textdescription_.c_str());
- text_ptr[2].compression = PNG_TEXT_COMPRESSION_NONE;
- std::string key_software("Software");
- text_ptr[3].key = const_cast<char*>(key_software.c_str());
- text_ptr[3].text = const_cast<char*>(textsoftware_.c_str());
- text_ptr[3].compression = PNG_TEXT_COMPRESSION_NONE;
- #if defined(PNG_TIME_RFC1123_SUPPORTED)
- char key_create[] = "Creation Time";
- text_ptr[4].key = key_create;
- char textcrtime[29] = "tIME chunk is not present...";
- #if (PNG_LIBPNG_VER < 10600)
- memcpy(textcrtime,
- png_convert_to_rfc1123(png_ptr, &mod_time),
- 29);
- #else
- png_convert_to_rfc1123_buffer(textcrtime, &mod_time);
- #endif
- textcrtime[sizeof(textcrtime) - 1] = '\0';
- text_ptr[4].text = textcrtime;
- text_ptr[4].compression = PNG_TEXT_COMPRESSION_NONE;
- entries++;
- #endif
- png_set_text(png_ptr, info_ptr, text_ptr, entries);
- png_write_info(png_ptr, info_ptr);
- png_write_image(png_ptr, graph_);
- png_write_end(png_ptr, info_ptr);
- png_destroy_write_struct(&png_ptr, &info_ptr);
- fclose(fp);
- }
- //////////////////////////////////////////////////////
- void pngwriter::line(int xfrom, int yfrom, int xto, int yto, int red, int green,int blue)
- {
- // Bresenham Algorithm.
- //
- int dy = yto - yfrom;
- int dx = xto - xfrom;
- int stepx, stepy;
- if (dy < 0)
- {
- dy = -dy; stepy = -1;
- }
- else
- {
- stepy = 1;
- }
- if (dx < 0)
- {
- dx = -dx; stepx = -1;
- }
- else
- {
- stepx = 1;
- }
- dy <<= 1; // dy is now 2*dy
- dx <<= 1; // dx is now 2*dx
- this->plot(xfrom,yfrom,red,green,blue);
- if (dx > dy)
- {
- int fraction = dy - (dx >> 1);
- while (xfrom != xto)
- {
- if (fraction >= 0)
- {
- yfrom += stepy;
- fraction -= dx;
- }
- xfrom += stepx;
- fraction += dy;
- this->plot(xfrom,yfrom,red,green,blue);
- }
- }
- else
- {
- int fraction = dx - (dy >> 1);
- while (yfrom != yto)
- {
- if (fraction >= 0)
- {
- xfrom += stepx;
- fraction -= dy;
- }
- yfrom += stepy;
- fraction += dx;
- this->plot(xfrom,yfrom,red,green,blue);
- }
- }
- }
- void pngwriter::line(int xfrom, int yfrom, int xto, int yto, double red, double green,double blue)
- {
- this->line( xfrom,
- yfrom,
- xto,
- yto,
- int (red*65535),
- int (green*65535),
- int (blue*65535)
- );
- }
- ///////////////////////////////////////////////////////////////////////////////////////////
- void pngwriter::square(int xfrom, int yfrom, int xto, int yto, int red, int green, int blue)
- {
- this->line(xfrom, yfrom, xfrom, yto, red, green, blue);
- this->line(xto, yfrom, xto, yto, red, green, blue);
- this->line(xfrom, yfrom, xto, yfrom, red, green, blue);
- this->line(xfrom, yto, xto, yto, red, green, blue);
- }
- void pngwriter::square(int xfrom, int yfrom, int xto, int yto, double red, double green, double blue)
- {
- this->square( xfrom, yfrom, xto, yto, int(red*65535), int(green*65535), int(blue*65535));
- }
- //////////////////////////////////////////////////////////////////////////////////////////////////
- void pngwriter::filledsquare(int xfrom, int yfrom, int xto, int yto, int red, int green, int blue)
- {
- for(int caca = xfrom; caca <xto+1; caca++)
- {
- this->line(caca, yfrom, caca, yto, red, green, blue);
- }
- }
- void pngwriter::filledsquare(int xfrom, int yfrom, int xto, int yto, double red, double green, double blue)
- {
- this->filledsquare( xfrom, yfrom, xto, yto, int(red*65535), int(green*65535), int(blue*65535));
- }
- //////////////////////////////////////////////////////////////////////////////////////////////////
- void pngwriter::circle(int xcentre, int ycentre, int radius, int red, int green, int blue)
- {
- int x = 0;
- int y = radius;
- int p = (5 - radius*4)/4;
- circle_aux(xcentre, ycentre, x, y, red, green, blue);
- while (x < y)
- {
- x++;
- if (p < 0)
- {
- p += 2*x+1;
- }
- else
- {
- y--;
- p += 2*(x-y)+1;
- }
- circle_aux(xcentre, ycentre, x, y, red, green, blue);
- }
- }
- void pngwriter::circle(int xcentre, int ycentre, int radius, double red, double green, double blue)
- {
- this->circle(xcentre,ycentre,radius, int(red*65535), int(green*65535), int(blue*65535));
- }
- ////////////////////////////////////////////////////////////
- void pngwriter::circle_aux(int xcentre, int ycentre, int x, int y, int red, int green, int blue)
- {
- if (x == 0)
- {
- this->plot( xcentre, ycentre + y, red, green, blue);
- this->plot( xcentre, ycentre - y, red, green, blue);
- this->plot( xcentre + y, ycentre, red, green, blue);
- this->plot( xcentre - y, ycentre, red, green, blue);
- }
- else
- if (x == y)
- {
- this->plot( xcentre + x, ycentre + y, red, green, blue);
- this->plot( xcentre - x, ycentre + y, red, green, blue);
- this->plot( xcentre + x, ycentre - y, red, green, blue);
- this->plot( xcentre - x, ycentre - y, red, green, blue);
- }
- else
- if (x < y)
- {
- this->plot( xcentre + x, ycentre + y, red, green, blue);
- this->plot( xcentre - x, ycentre + y, red, green, blue);
- this->plot( xcentre + x, ycentre - y, red, green, blue);
- this->plot( xcentre - x, ycentre - y, red, green, blue);
- this->plot( xcentre + y, ycentre + x, red, green, blue);
- this->plot( xcentre - y, ycentre + x, red, green, blue);
- this->plot( xcentre + y, ycentre - x, red, green, blue);
- this->plot( xcentre - y, ycentre - x, red, green, blue);
- }
- }
- ////////////////////////////////////////////////////////////
- void pngwriter::filledcircle(int xcentre, int ycentre, int radius, int red, int green, int blue)
- {
- for(int jjj = ycentre-radius; jjj< ycentre+radius+1; jjj++)
- {
- this->line(xcentre - int(sqrt((double)(radius*radius) - (-ycentre + jjj)*(-ycentre + jjj ))), jjj,
- xcentre + int(sqrt((double)(radius*radius) - (-ycentre + jjj)*(-ycentre + jjj ))),jjj,red,green,blue);
- }
- }
- void pngwriter::filledcircle(int xcentre, int ycentre, int radius, double red, double green, double blue)
- {
- this->filledcircle( xcentre, ycentre, radius, int(red*65535), int(green*65535), int(blue*65535));
- }
- ////////////////Reading routines/////////////////////
- /////////////////////////////////////////////////
- // Modified with Mikkel's patch
- bool pngwriter::readfromfile(char * name)
- {
- FILE *fp;
- png_structp png_ptr;
- png_infop info_ptr;
- unsigned char **image;
- png_uint_32 width, height;
- int bit_depth, color_type, interlace_type;
- // png_uint_32 i;
- //
- fp = fopen (name,"rb");
- if (fp==NULL)
- {
- std::cerr << " PNGwriter::readfromfile - ERROR **: Error opening file \"" << std::flush;
- std::cerr << name <<std::flush;
- std::cerr << "\"." << std::endl << std::flush;
- perror(" PNGwriter::readfromfile - ERROR **");
- return false;
- }
- if(!check_if_png(name, &fp))
- {
- std::cerr << " PNGwriter::readfromfile - ERROR **: Error opening file " << name << ". This may not be a valid png file. (check_if_png() failed)." << std::endl;
- // fp has been closed already if check_if_png() fails.
- return false;
- }
- if(!read_png_info(fp, &png_ptr, &info_ptr))
- {
- std::cerr << " PNGwriter::readfromfile - ERROR **: Error opening file " << name << ". read_png_info() failed." << std::endl;
- // fp has been closed already if read_png_info() fails.
- return false;
- }
- //Input transformations
- png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL);
- bit_depth_ = bit_depth;
- colortype_ = color_type;
- // Changes palletted image to RGB
- if(color_type == PNG_COLOR_TYPE_PALETTE /*&& bit_depth<8*/)
- {
- // png_set_expand(png_ptr);
- png_set_palette_to_rgb(png_ptr); // Just an alias of png_set_expand()
- transformation_ = 1;
- }
- // Transforms grescale images of less than 8 bits to 8 bits.
- if(color_type == PNG_COLOR_TYPE_GRAY && bit_depth<8)
- {
- // png_set_expand(png_ptr);
- png_set_expand_gray_1_2_4_to_8(png_ptr); // Just an alias of the above.
- transformation_ = 1;
- }
- // Completely strips the alpha channel.
- if(color_type & PNG_COLOR_MASK_ALPHA)
- {
- png_set_strip_alpha(png_ptr);
- transformation_ = 1;
- }
- // Converts greyscale images to RGB.
- if(color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) // Used to be RGB, fixed it.
- {
- png_set_gray_to_rgb(png_ptr);
- transformation_ = 1;
- }
- // If any of the above were applied,
- if(transformation_)
- {
- // png_set_gray_to_rgb(png_ptr); //Is this really needed here?
- // After setting the transformations, libpng can update your png_info structure to reflect any transformations
- // you've requested with this call. This is most useful to update the info structure's rowbytes field so you can
- // use it to allocate your image memory. This function will also update your palette with the correct screen_gamma
- // and background if these have been given with the calls above.
- png_read_update_info(png_ptr, info_ptr);
- // Just in case any of these have changed?
- png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL);
- bit_depth_ = bit_depth;
- colortype_ = color_type;
- }
- if(!read_png_image(fp, png_ptr, info_ptr, &image, width, height))
- {
- std::cerr << " PNGwriter::readfromfile - ERROR **: Error opening file " << name << ". read_png_image() failed." << std::endl;
- // fp has been closed already if read_png_image() fails.
- return false;
- }
- //stuff should now be in image[][].
- // Mikkel's patch ends here
- // //////////////////////////////
- //
- if( image == NULL)
- {
- std::cerr << " PNGwriter::readfromfile - ERROR **: Error opening file " << name << ". Can't assign memory (after read_png_image(), image is NULL)." << std::endl;
- fclose(fp);
- return false;
- }
- //First we must get rid of the image already there, and free the memory.
- int jjj;
- for (jjj = 0; jjj < height_; jjj++) free(graph_[jjj]);
- free(graph_);
- //Must reassign the new size of the read image
- width_ = width;
- height_ = height;
- //Graph now is the image.
- graph_ = image;
- if((bit_depth_ !=16)&&(bit_depth_ !=8))
- {
- std::cerr << " PNGwriter::readfromfile() - WARNING **: Input file is of unsupported type (bad bit_depth). Output will be unpredictable.\n";
- }
- // Thanks to Mikkel's patch, PNGwriter should now be able to handle these color types:
- if(colortype_ !=2)
- {
- std::cerr << " PNGwriter::readfromfile() - WARNING **: Input file is of unsupported type (bad color_type). Output will be unpredictable.\n";
- }
- screengamma_ = 2.2;
- double file_gamma;
- if (!png_get_gAMA(png_ptr, info_ptr, &file_gamma))
- {
- file_gamma=0.45;
- }
- filegamma_ = file_gamma;
- png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
- fclose(fp);
- return true;
- }
- ///////////////////////////////////////////////////////
- bool pngwriter::readfromfile(const char * name)
- {
- return this->readfromfile((char *)(name));
- }
- /////////////////////////////////////////////////////////
- int pngwriter::check_if_png(char *file_name, FILE **fp)
- {
- char sig[PNG_BYTES_TO_CHECK];
- if ( /*(*fp = fopen(file_name, "rb")) */ *fp == NULL) // Fixed 10 10 04
- {
- // exit(EXIT_FAILURE);
- std::cerr << " PNGwriter::check_if_png - ERROR **: Could not open file " << file_name << " to read." << std::endl;
- perror(" PNGwriter::check_if_png - ERROR **");
- return 0;
- }
- if (fread(sig, 1, PNG_BYTES_TO_CHECK, *fp) != PNG_BYTES_TO_CHECK)
- {
- //exit(EXIT_FAILURE);
- std::cerr << " PNGwriter::check_if_png - ERROR **: File " << file_name << " does not appear to be a valid PNG file." << std::endl;
- perror(" PNGwriter::check_if_png - ERROR **");
- fclose(*fp);
- return 0;
- }
- if (png_sig_cmp( (png_bytep) sig, (png_size_t)0, PNG_BYTES_TO_CHECK) /*png_check_sig((png_bytep) sig, PNG_BYTES_TO_CHECK)*/ )
- {
- std::cerr << " PNGwriter::check_if_png - ERROR **: File " << file_name << " does not appear to be a valid PNG file. png_check_sig() failed." << std::endl;
- fclose(*fp);
- return 0;
- }
- return 1; //Success
- }
- ///////////////////////////////////////////////////////
- int pngwriter::read_png_info(FILE *fp, png_structp *png_ptr, png_infop *info_ptr)
- {
- *png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
- if (*png_ptr == NULL)
- {
- std::cerr << " PNGwriter::read_png_info - ERROR **: Could not create read_struct." << std::endl;
- fclose(fp);
- return 0;
- //exit(EXIT_FAILURE);
- }
- *info_ptr = png_create_info_struct(*png_ptr);
- if (*info_ptr == NULL)
- {
- png_destroy_read_struct(png_ptr, (png_infopp)NULL, (png_infopp)NULL);
- std::cerr << " PNGwriter::read_png_info - ERROR **: Could not create info_struct." << std::endl;
- //exit(EXIT_FAILURE);
- fclose(fp);
- return 0;
- }
- #if (PNG_LIBPNG_VER < 10500)
- if (setjmp((*png_ptr)->jmpbuf)) /*(setjmp(png_jmpbuf(*png_ptr)) )*//////////////////////////////////////
- #else
- if (setjmp(png_jmpbuf(*png_ptr)))
- #endif
- {
- png_destroy_read_struct(png_ptr, info_ptr, (png_infopp)NULL);
- std::cerr << " PNGwriter::read_png_info - ERROR **: This file may be a corrupted PNG file. (setjmp(*png_ptr)->jmpbf) failed)." << std::endl;
- fclose(fp);
- return 0;
- //exit(EXIT_FAILURE);
- }
- png_init_io(*png_ptr, fp);
- png_set_sig_bytes(*png_ptr, PNG_BYTES_TO_CHECK);
- png_read_info(*png_ptr, *info_ptr);
- return 1;
- }
- ////////////////////////////////////////////////////////////
- int pngwriter::read_png_image(FILE *fp, png_structp png_ptr, png_infop info_ptr,
- png_bytepp *image, png_uint_32& width, png_uint_32& height)
- {
- unsigned int i,j;
- width = png_get_image_width(png_ptr, info_ptr);
- height = png_get_image_height(png_ptr, info_ptr);
- if( width == 0 )
- {
- std::cerr << " PNGwriter::read_png_image - ERROR **: png_get_image_width() returned 0." << std::endl;
- fclose(fp);
- return 0;
- }
- if( height == 0 )
- {
- std::cerr << " PNGwriter::read_png_image - ERROR **: png_get_image_height() returned 0." << std::endl;
- fclose(fp);
- return 0;
- }
- if ((*image = (png_bytepp)malloc(height * sizeof(png_bytep))) == NULL)
- {
- std::cerr << " PNGwriter::read_png_image - ERROR **: Could not allocate memory for reading image." << std::endl;
- fclose(fp);
- return 0;
- //exit(EXIT_FAILURE);
- }
- for (i = 0; i < height; i++)
- {
- (*image)[i] = (png_bytep)malloc(png_get_rowbytes(png_ptr, info_ptr));
- if ((*image)[i] == NULL)
- {
- for (j = 0; j < i; j++) free((*image)[j]);
- free(*image);
- fclose(fp);
- std::cerr << " PNGwriter::read_png_image - ERROR **: Could not allocate memory for reading image." << std::endl;
- return 0;
- //exit(EXIT_FAILURE);
- }
- }
- png_read_image(png_ptr, *image);
- return 1;
- }
- ///////////////////////////////////
- int pngwriter::getheight(void) const
- {
- return height_;
- }
- int pngwriter::getwidth(void) const
- {
- return width_;
- }
- int pngwriter::getbitdepth(void) const
- {
- return bit_depth_;
- }
- int pngwriter::getcolortype(void) const
- {
- return colortype_;
- }
- double pngwriter::getgamma(void) const
- {
- return filegamma_;
- }
- void pngwriter::setgamma(double gamma)
- {
- filegamma_ = gamma;
- }
- // The algorithms HSVtoRGB and RGBtoHSV were found at http://www.cs.rit.edu/~ncs/
- // which is a page that belongs to Nan C. Schaller, though
- // these algorithms appear to be the work of Eugene Vishnevsky.
- //////////////////////////////////////////////
- void pngwriter::HSVtoRGB( double *r, double *g, double *b, double h, double s, double v )
- {
- // r,g,b values are from 0 to 1
- // h = [0,1], s = [0,1], v = [0,1]
- // if s == 0, then h = -1 (undefined)
- //
- h = h*360.0;
- int i;
- double f, p, q, t;
- if( s == 0 )
- {
- // achromatic (grey)
- *r = *g = *b = v;
- return;
- }
- h /= 60; // sector 0 to 5
- i = int(floor( h ));
- f = h - i; // factorial part of h
- p = v * ( 1 - s );
- q = v * ( 1 - s * f );
- t = v * ( 1 - s * ( 1 - f ) );
- switch( i )
- {
- case 0:
- *r = v;
- *g = t;
- *b = p;
- break;
- case 1:
- *r = q;
- *g = v;
- *b = p;
- break;
- case 2:
- *r = p;
- *g = v;
- *b = t;
- break;
- case 3:
- *r = p;
- *g = q;
- *b = v;
- break;
- case 4:
- *r = t;
- *g = p;
- *b = v;
- break;
- default: // case 5:
- *r = v;
- *g = p;
- *b = q;
- break;
- }
- }
- void pngwriter::RGBtoHSV( float r, float g, float b, float *h, float *s, float *v )
- {
- float min=0.0; //These values are not used.
- float max=1.0;
- float delta;
- if( (r>=g)&&(r>=b) )
- {
- max = r;
- }
- if( (g>=r)&&(g>=b) )
- {
- max = g;
- }
- if( (b>=g)&&(b>=r) )
- {
- max = b;
- }
- if( (r<=g)&&(r<=b) )
- {
- min = r;
- }
- if( (g<=r)&&(g<=b) )
- {
- min = g;
- }
- if( (b<=g)&&(b<=r) )
- {
- min = b;
- }
- *v = max; // v
- delta = max - min;
- if( max != 0 )
- *s = delta / max; // s
- else
- {
- // s = 0, v is undefined
- *s = 0;
- *h = -1;
- return;
- }
- if( r == max )
- *h = ( g - b ) / delta; // between yellow & magenta
- else if( g == max )
- *h = 2 + ( b - r ) / delta; // between cyan & yellow
- else
- *h = 4 + ( r - g ) / delta; // between magenta & cyan
- *h *= 60; // degrees
- if( *h < 0 )
- *h += 360;
- }
- //
- //////////////////////////////////////////////////////////////////////////////////
- void pngwriter::plotHSV(int x, int y, double hue, double saturation, double value)
- {
- double red,green,blue;
- double *redp;
- double *greenp;
- double *bluep;
- redp = &red;
- greenp = &green;
- bluep = &blue;
- HSVtoRGB(redp,greenp,bluep,hue,saturation,value);
- plot(x,y,red,green,blue);
- }
- void pngwriter::plotHSV(int x, int y, int hue, int saturation, int value)
- {
- plotHSV(x, y, double(hue)/65535.0, double(saturation)/65535.0, double(value)/65535.0);
- }
- //
- //////////////////////////////////////////////////////////////////////////////////
- double pngwriter::dreadHSV(int x, int y, int colour) const
- {
- if( (x>0)&&(x<=width_)&&(y>0)&&(y<=height_) )
- {
- float * huep;
- float * saturationp;
- float * valuep;
- float red,green,blue;
- float hue, saturation, value;
- red = float(dread(x,y,1));
- green = float(dread(x,y,2));
- blue = float(dread(x,y,3));
- huep = &hue;
- saturationp = &saturation;
- valuep = &value;
- RGBtoHSV( red, green, blue, huep, saturationp, valuep );
- if(colour == 1)
- {
- return double(hue)/360.0;
- }
- else if(colour == 2)
- {
- return saturation;
- }
- else if(colour == 3)
- {
- return value;
- }
- std::cerr << " PNGwriter::dreadHSV - ERROR **: Called with wrong colour argument: should be 1, 2 or 3; was: " << colour << "." << std::endl;
- }
- return 0.0;
- }
- //
- //////////////////////////////////////////////////////////////////////////////////
- int pngwriter::readHSV(int x, int y, int colour) const
- {
- if( (x>0)&&(x<=width_)&&(y>0)&&(y<=height_) )
- {
- float * huep;
- float * saturationp;
- float * valuep;
- float red,green,blue;
- float hue, saturation, value;
- red = float(dread(x,y,1));
- green = float(dread(x,y,2));
- blue = float(dread(x,y,3));
- huep = &hue;
- saturationp = &saturation;
- valuep = &value;
- RGBtoHSV( red, green, blue, huep, saturationp, valuep );
- if(colour == 1)
- {
- return int(65535*(double(hue)/360.0));
- }
- else if(colour == 2)
- {
- return int(65535*saturation);
- }
- else if(colour == 3)
- {
- return int(65535*value);
- }
- std::cerr << " PNGwriter::readHSV - ERROR **: Called with wrong colour argument: should be 1, 2 or 3; was: " << colour << "." << std::endl;
- return 0;
- }
- else
- {
- return 0;
- }
- }
- void pngwriter::setcompressionlevel(int level)
- {
- if( (level < -1)||(level > 9) )
- {
- std::cerr << " PNGwriter::setcompressionlevel - ERROR **: Called with wrong compression level: should be -1 to 9, was: " << level << "." << std::endl;
- }
- compressionlevel_ = level;
- }
- // An implementation of a Bezier curve.
- void pngwriter::bezier( int startPtX, int startPtY,
- int startControlX, int startControlY,
- int endPtX, int endPtY,
- int endControlX, int endControlY,
- double red, double green, double blue)
- {
- double cx = 3.0*(startControlX - startPtX);
- double bx = 3.0*(endControlX - startControlX) - cx;
- double ax = double(endPtX - startPtX - cx - bx);
- double cy = 3.0*(startControlY - startPtY);
- double by = 3.0*(endControlY - startControlY) - cy;
- double ay = double(endPtY - startPtY - cy - by);
- double x = startPtX;
- double y = startPtY;
- for(double t = 0.0; t<=1.005; t += 0.005)
- {
- double const newx = startPtX + t*(double(cx) + t*(double(bx) + t*(double(ax))));
- double const newy = startPtY + t*(double(cy) + t*(double(by) + t*(double(ay))));
- this->line(int(x),int(y),int(newx),int(newy),red,green,blue);
- x = newx;
- y = newy;
- }
- }
- //int version of bezier
- void pngwriter::bezier( int startPtX, int startPtY,
- int startControlX, int startControlY,
- int endPtX, int endPtY,
- int endControlX, int endControlY,
- int red, int green, int blue)
- {
- this->bezier( startPtX, startPtY,
- startControlX, startControlY,
- endPtX, endPtY,
- endControlX, endControlY,
- double(red)/65535.0, double(green)/65535.0, double(blue)/65535.0);
- }
- /*
- int pngwriter::getcompressionlevel(void)
- {
- return png_get_compression_level(png_ptr);
- }
- */
- double pngwriter::version(void)
- {
- const char *a = "Jeramy Webb (jeramyw@gmail.com), Mike Heller (mkheller@gmail.com)"; // For their generosity ;-)
- char b = a[27];
- b++;
- return (PNGWRITER_VERSION);
- }
- void pngwriter::write_png(void)
- {
- this->close();
- }
- #ifndef NO_FREETYPE
- // Freetype-based text rendering functions.
- ///////////////////////////////////////////
- void pngwriter::plot_text( char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double red, double green, double blue)
- {
- pngwriterfont font(font);
- plot_text(font, fontsize, x_start, y_start, angle, text, red, green, blue);
- }
- void pngwriter::plot_text(pngwriterfont& font, int fontsize, int x_start, int y_start, double angle, char * text, double red, double green, double blue)
- {
- FT_Matrix matrix; // transformation matrix
- FT_Vector pen;
- FT_UInt glyph_index;
- FT_Error error;
- FT_Bool use_kerning;
- FT_UInt previous = 0;
- /* Set up transformation Matrix */
- matrix.xx = (FT_Fixed)( cos(angle)*0x10000); /* It would make more sense to do this (below), but, bizzarely, */
- matrix.xy = (FT_Fixed)(-sin(angle)*0x10000); /* if one does, FT_Load_Glyph fails consistently. */
- matrix.yx = (FT_Fixed)( sin(angle)*0x10000); // matrix.yx = - matrix.xy;
- matrix.yy = (FT_Fixed)( cos(angle)*0x10000); // matrix.yy = matrix.xx;
- /* Place starting coordinates in adequate form. */
- pen.x = x_start*64 ;
- pen.y = (int)(y_start/64.0);
- /*Count the length of the string */
- int num_chars = strlen(text);
- /* Set the Char size */
- error = FT_Set_Char_Size( font.getFontFace(), /* handle to face object */
- 0, /* char_width in 1/64th of points */
- fontsize*64, /* char_height in 1/64th of points */
- 100, /* horizontal device resolution */
- 100 ); /* vertical device resolution */
- /* A way of accesing the glyph directly */
- FT_GlyphSlot slot = font.getFontFace()->glyph; // a small shortcut
- /* Does the font file support kerning? */
- use_kerning = FT_HAS_KERNING(font.getFontFace());
- int n;
- for ( n = 0; n < num_chars; n++ )
- {
- /* Convert character code to glyph index */
- glyph_index = FT_Get_Char_Index( font.getFontFace(), text[n] );
- /* Retrieve kerning distance and move pen position */
- if ( use_kerning && previous&& glyph_index )
- {
- FT_Vector delta;
- FT_Get_Kerning( font.getFontFace(),
- previous,
- glyph_index,
- ft_kerning_default, //FT_KERNING_DEFAULT,
- &delta );
- /* Transform this kerning distance into rotated space */
- pen.x += (int) (((double) delta.x)*cos(angle));
- pen.y += (int) (((double) delta.x)*( sin(angle)));
- }
- /* Set transform */
- FT_Set_Transform( font.getFontFace(), &matrix, &pen );
- /*set char size*/
- if (error) {
- std::cerr << " PNGwriter::plot_text - ERROR **: FreeType: Set char size error." << std::endl; return;
- }
- /* Retrieve glyph index from character code */
- glyph_index = FT_Get_Char_Index( font.getFontFace(), text[n] );
- /* Load glyph image into the slot (erase previous one) */
- error = FT_Load_Glyph( font.getFontFace(), glyph_index, FT_LOAD_DEFAULT );
- if (error) {
- std::cerr << " PNGwriter::plot_text - ERROR **: FreeType: Could not load glyph (in loop). (FreeType error " << std::hex << error <<")." << std::endl;
- std::cerr.copyfmt(std::ios(NULL));
- return;
- }
- /* Convert to an anti-aliased bitmap */
- // error = FT_Render_Glyph( face->glyph, FT_RENDER_MODE_NORMAL );
- error = FT_Render_Glyph( font.getFontFace()->glyph, ft_render_mode_normal );
- if (error) { std::cerr << " PNGwriter::plot_text - ERROR **: FreeType: Render glyph error." << std::endl; return;}
- /* Now, draw to our target surface */
- my_draw_bitmap( &slot->bitmap,
- slot->bitmap_left,
- y_start + slot->bitmap_top,
- red,
- green,
- blue );
- /* Advance to the next position */
- pen.x += slot->advance.x;
- pen.y += slot->advance.y;
- /* record current glyph index */
- previous = glyph_index;
- }
- }
- void pngwriter::plot_text_utf8( char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double red, double green, double blue)
- {
- FT_Library library;
- FT_Face face;
- FT_Matrix matrix; // transformation matrix
- FT_Vector pen;
- FT_UInt glyph_index;
- FT_Error error;
- FT_Bool use_kerning;
- FT_UInt previous = 0;
- /* Set up transformation Matrix */
- matrix.xx = (FT_Fixed)( cos(angle)*0x10000); /* It would make more sense to do this (below), but, bizzarely, */
- matrix.xy = (FT_Fixed)(-sin(angle)*0x10000); /* if one does, FT_Load_Glyph fails consistently. */
- matrix.yx = (FT_Fixed)( sin(angle)*0x10000); // matrix.yx = - matrix.xy;
- matrix.yy = (FT_Fixed)( cos(angle)*0x10000); // matrix.yy = matrix.xx;
- /* Place starting coordinates in adequate form. */
- pen.x = x_start*64 ;
- pen.y = (int)(y_start/64.0);
- /*Count the length of the string */
- int num_bytes=0;
- while(text[num_bytes]!=0)
- {
- num_bytes++;
- }
- /*
- std::cout << "Num bytes is: "<< num_bytes << std::endl;
- */
- //The array of ucs4 glyph indexes, which will by at most the number of bytes in the utf-8 file.
- long * ucs4text;
- ucs4text = new long[num_bytes+1];
- unsigned char u,v,w,x,y;
- int num_chars=0;
- long iii=0;
- while(iii<num_bytes)
- {
- unsigned char const z = text[iii];
- if(z<=127)
- {
- ucs4text[num_chars] = z;
- }
- if((192<=z)&&(z<=223))
- {
- iii++; y = text[iii];
- ucs4text[num_chars] = (z-192)*64 + (y -128);
- }
- if((224<=z)&&(z<=239))
- {
- iii++; y = text[iii];
- iii++; x = text[iii];
- ucs4text[num_chars] = (z-224)*4096 + (y -128)*64 + (x-128);
- }
- if((240<=z)&&(z<=247))
- {
- iii++; y = text[iii];
- iii++; x = text[iii];
- iii++; w = text[iii];
- ucs4text[num_chars] = (z-240)*262144 + (y -128)*4096 + (x-128)*64 + (w-128);
- }
- if((248<=z)&&(z<=251))
- {
- iii++; y = text[iii];
- iii++; x = text[iii];
- iii++; w = text[iii];
- iii++; v = text[iii];
- ucs4text[num_chars] = (z-248)*16777216 + (y -128)*262144 + (x-128)*4096 + (w-128)*64 +(v-128);
- }
- if((252==z)||(z==253))
- {
- iii++; y = text[iii];
- iii++; x = text[iii];
- iii++; w = text[iii];
- iii++; v = text[iii];
- u = text[iii];
- ucs4text[num_chars] = (z-252)*1073741824 + (y -128)*16777216 + (x-128)*262144 + (w-128)*4096 +(v-128)*64 + (u-128);
- }
- if((z==254)||(z==255))
- {
- std::cerr << " PNGwriter::plot_text_utf8 - ERROR **: Problem with character: invalid UTF-8 data."<< std::endl;
- }
- // std::cerr << "\nProblem at " << iii << ".\n";
- //
- iii++;
- num_chars++;
- }
- // num_chars now contains the number of characters in the string.
- /*
- std::cout << "Num chars is: "<< num_chars << std::endl;
- */
- /* Initialize FT Library object */
- error = FT_Init_FreeType( &library );
- if (error) {
- std::cerr << " PNGwriter::plot_text_utf8 - ERROR **: FreeType: Could not init Library." << std::endl;
- delete[] ucs4text;
- return;
- }
- /* Initialize FT face object */
- error = FT_New_Face( library,face_path,0,&face );
- if ( error == FT_Err_Unknown_File_Format ) {
- std::cerr << " PNGwriter::plot_text_utf8 - ERROR **: FreeType: Font was opened, but type not supported." << std::endl;
- delete[] ucs4text;
- return;
- } else if (error) {
- std::cerr << " PNGwriter::plot_text - ERROR **: FreeType: Could not find or load font file." << std::endl;
- delete[] ucs4text;
- return;
- }
- /* Set the Char size */
- error = FT_Set_Char_Size( face, /* handle to face object */
- 0, /* char_width in 1/64th of points */
- fontsize*64, /* char_height in 1/64th of points */
- 100, /* horizontal device resolution */
- 100 ); /* vertical device resolution */
- /* A way of accesing the glyph directly */
- FT_GlyphSlot slot = face->glyph; // a small shortcut
- /* Does the font file support kerning? */
- use_kerning = FT_HAS_KERNING( face );
- int n;
- for ( n = 0; n < num_chars; n++ )
- {
- /* Convert character code to glyph index */
- glyph_index = FT_Get_Char_Index( face, ucs4text[n] );
- /* Retrieve kerning distance and move pen position */
- if ( use_kerning && previous&& glyph_index )
- {
- FT_Vector delta;
- FT_Get_Kerning( face,
- previous,
- glyph_index,
- ft_kerning_default, //FT_KERNING_DEFAULT,
- &delta );
- /* Transform this kerning distance into rotated space */
- pen.x += (int) (((double) delta.x)*cos(angle));
- pen.y += (int) (((double) delta.x)*( sin(angle)));
- }
- /* Set transform */
- FT_Set_Transform( face, &matrix, &pen );
- /*set char size*/
- if (error) {
- std::cerr << " PNGwriter::plot_text_utf8 - ERROR **: FreeType: Set char size error." << std::endl;
- delete[] ucs4text;
- return;
- }
- /* Retrieve glyph index from character code */
- glyph_index = FT_Get_Char_Index( face, ucs4text[n] );
- /* Load glyph image into the slot (erase previous one) */
- error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT );
- if (error) {
- std::cerr << " PNGwriter::plot_text_utf8 - ERROR **: FreeType: Could not load glyph (in loop). (FreeType error " << std::hex << error <<")." << std::endl;
- std::cerr.copyfmt(std::ios(NULL));
- delete[] ucs4text;
- return;
- }
- /* Convert to an anti-aliased bitmap */
- error = FT_Render_Glyph( face->glyph, ft_render_mode_normal );
- if (error) {
- std::cerr << " PNGwriter::plot_text_utf8 - ERROR **: FreeType: Render glyph error." << std::endl;
- delete[] ucs4text;
- return;
- }
- /* Now, draw to our target surface */
- my_draw_bitmap( &slot->bitmap,
- slot->bitmap_left,
- y_start + slot->bitmap_top,
- red,
- green,
- blue );
- /* Advance to the next position */
- pen.x += slot->advance.x;
- pen.y += slot->advance.y;
- /* record current glyph index */
- previous = glyph_index;
- }
- /* Free the face and the library objects */
- FT_Done_Face ( face );
- FT_Done_FreeType( library );
- delete[] ucs4text;
- }
- void pngwriter::plot_text(pngwriterfont &font, int fontsize, int x_start, int y_start, double angle, char * text, int red, int green, int blue)
- {
- plot_text( font, fontsize, x_start, y_start, angle, text, ((double) red)/65535.0, ((double) green)/65535.0, ((double) blue)/65535.0 );
- }
- void pngwriter::plot_text( char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, int red, int green, int blue)
- {
- plot_text( face_path, fontsize, x_start, y_start, angle, text, ((double) red)/65535.0, ((double) green)/65535.0, ((double) blue)/65535.0 );
- }
- void pngwriter::plot_text_utf8( char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, int red, int green, int blue)
- {
- plot_text_utf8( face_path, fontsize, x_start, y_start, angle, text, ((double) red)/65535.0, ((double) green)/65535.0, ((double) blue)/65535.0 );
- }
- void pngwriter::my_draw_bitmap( FT_Bitmap * bitmap, int x, int y, double red, double green, double blue)
- {
- double temp;
- for(unsigned int j = 1u; j < bitmap->rows + 1u; j++)
- {
- for(unsigned int i = 1u; i < bitmap->width + 1u; i++)
- {
- temp = (double)(bitmap->buffer[(j-1u)*bitmap->width + (i-1u)] )/255.0;
- if(temp)
- {
- this->plot(x + i,
- y - j,
- temp*red + (1-temp)*(this->dread(x+i,y-j,1)),
- temp*green + (1-temp)*(this->dread(x+i,y-j,2)),
- temp*blue + (1-temp)*(this->dread(x+i,y-j,3))
- );
- }
- }
- }
- }
- //////////// Get text width
- //put in freetype section
- int pngwriter::get_text_width(char* fontPath, int fontsize, char * text)
- {
- pngwriterfont font(font);
- return get_text_width(font, fontsize, text);
- }
- int pngwriter::get_text_width(pngwriterfont& font, int fontsize, char * text)
- {
- FT_Matrix matrix; // transformation matrix
- FT_Vector pen;
- FT_UInt glyph_index;
- FT_Error error;
- FT_Bool use_kerning;
- FT_UInt previous = 0;
- /* Set up transformation Matrix */
- matrix.xx = (FT_Fixed)( 1.0*0x10000); /* It would make more sense to do this (below), but, bizzarely, */
- matrix.xy = (FT_Fixed)( 0.0*0x10000); /* if one does, FT_Load_Glyph fails consistently. */
- matrix.yx = (FT_Fixed)( 0.0*0x10000); // matrix.yx = - matrix.xy;
- matrix.yy = (FT_Fixed)( 1.0*0x10000); // matrix.yy = matrix.xx;
- /* Place starting coordinates in adequate form. */
- pen.x = 0;
- pen.y = 0;
- /*Count the length of the string */
- int num_chars = strlen(text);
- /* Set the Char size */
- error = FT_Set_Char_Size(font.getFontFace(), /* handle to face object */
- 0, /* char_width in 1/64th of points */
- fontsize*64, /* char_height in 1/64th of points */
- 100, /* horizontal device resolution */
- 100 ); /* vertical device resolution */
- /* A way of accesing the glyph directly */
- FT_GlyphSlot slot = font.getFontFace()->glyph; // a small shortcut
- /* Does the font file support kerning? */
- use_kerning = FT_HAS_KERNING( font.getFontFace() );
- int n;
- for ( n = 0; n < num_chars; n++ )
- {
- /* Convert character code to glyph index */
- glyph_index = FT_Get_Char_Index( font.getFontFace(), text[n] );
- /* Retrieve kerning distance and move pen position */
- if ( use_kerning && previous&& glyph_index )
- {
- FT_Vector delta;
- FT_Get_Kerning( font.getFontFace(),
- previous,
- glyph_index,
- ft_kerning_default, //FT_KERNING_DEFAULT,
- &delta );
- /* Transform this kerning distance into rotated space */
- pen.x += (int) ( delta.x);
- pen.y += 0;
- }
- /* Set transform */
- FT_Set_Transform( font.getFontFace(), &matrix, &pen );
- /*set char size*/
- if (error) { std::cerr << " PNGwriter::get_text_width - ERROR **: FreeType: Set char size error." << std::endl; return 0; }
- /* Retrieve glyph index from character code */
- glyph_index = FT_Get_Char_Index( font.getFontFace(), text[n] );
- /* Load glyph image into the slot (erase previous one) */
- error = FT_Load_Glyph( font.getFontFace(), glyph_index, FT_LOAD_DEFAULT );
- if (error) {
- std::cerr << " PNGwriter::get_text_width - ERROR **: FreeType: Could not load glyph (in loop). (FreeType error " << std::hex << error <<")." << std::endl;
- std::cerr.copyfmt(std::ios(NULL));
- return 0;
- }
- /* Convert to an anti-aliased bitmap */
- // error = FT_Render_Glyph( face->glyph, FT_RENDER_MODE_NORMAL );
- error = FT_Render_Glyph( font.getFontFace()->glyph, ft_render_mode_normal );
- if (error) { std::cerr << " PNGwriter::get_text_width - ERROR **: FreeType: Render glyph error." << std::endl; return 0;}
- /* Now, draw to our target surface */
- /* my_draw_bitmap( &slot->bitmap,
- slot->bitmap_left,
- slot->bitmap_top,
- red,
- green,
- blue );
- */
- /* Advance to the next position */
- pen.x += slot->advance.x;
- // std::cout << ((double) pen.x)/64.0 << std::endl;
- pen.y += slot->advance.y;
- /* record current glyph index */
- previous = glyph_index;
- }
- return (int)( ((double)pen.x)/64.0 );
- }
- int pngwriter::get_text_width_utf8(char * face_path, int fontsize, char * text)
- {
- FT_Library library;
- FT_Face face;
- FT_Matrix matrix; // transformation matrix
- FT_Vector pen;
- FT_UInt glyph_index;
- FT_Error error;
- FT_Bool use_kerning;
- FT_UInt previous = 0;
- /* Set up transformation Matrix */
- matrix.xx = (FT_Fixed)( 0x10000); /* It would make more sense to do this (below), but, bizzarely, */
- matrix.xy = (FT_Fixed)( 0*0x10000); /* if one does, FT_Load_Glyph fails consistently. */
- matrix.yx = (FT_Fixed)( 0*0x10000); // matrix.yx = - matrix.xy;
- matrix.yy = (FT_Fixed)( 0x10000); // matrix.yy = matrix.xx;
- /* Place starting coordinates in adequate form. */
- pen.x = 0 ;
- pen.y = 0;
- /*Count the length of the string */
- int num_bytes=0;
- while(text[num_bytes]!=0)
- {
- num_bytes++;
- }
- /*
- std::cout << "Num bytes is: "<< num_bytes << std::endl;
- */
- //The array of ucs4 glyph indexes, which will by at most the number of bytes in the utf-8 file.
- long * ucs4text;
- ucs4text = new long[num_bytes+1];
- unsigned char u,v,w,x,y;
- int num_chars=0;
- long iii=0;
- while(iii<num_bytes)
- {
- unsigned char const z = text[iii];
- if(z<=127)
- {
- ucs4text[num_chars] = z;
- }
- if((192<=z)&&(z<=223))
- {
- iii++; y = text[iii];
- ucs4text[num_chars] = (z-192)*64 + (y -128);
- }
- if((224<=z)&&(z<=239))
- {
- iii++; y = text[iii];
- iii++; x = text[iii];
- ucs4text[num_chars] = (z-224)*4096 + (y -128)*64 + (x-128);
- }
- if((240<=z)&&(z<=247))
- {
- iii++; y = text[iii];
- iii++; x = text[iii];
- iii++; w = text[iii];
- ucs4text[num_chars] = (z-240)*262144 + (y -128)*4096 + (x-128)*64 + (w-128);
- }
- if((248<=z)&&(z<=251))
- {
- iii++; y = text[iii];
- iii++; x = text[iii];
- iii++; w = text[iii];
- iii++; v = text[iii];
- ucs4text[num_chars] = (z-248)*16777216 + (y -128)*262144 + (x-128)*4096 + (w-128)*64 +(v-128);
- }
- if((252==z)||(z==253))
- {
- iii++; y = text[iii];
- iii++; x = text[iii];
- iii++; w = text[iii];
- iii++; v = text[iii];
- u = text[iii];
- ucs4text[num_chars] = (z-252)*1073741824 + (y -128)*16777216 + (x-128)*262144 + (w-128)*4096 +(v-128)*64 + (u-128);
- }
- if((z==254)||(z==255))
- {
- std::cerr << " PNGwriter::get_text_width_utf8 - ERROR **: Problem with character: invalid UTF-8 data."<< std::endl;
- }
- // std::cerr << "\nProblem at " << iii << ".\n";
- //
- iii++;
- num_chars++;
- }
- // num_chars now contains the number of characters in the string.
- /*
- std::cout << "Num chars is: "<< num_chars << std::endl;
- */
- /* Initialize FT Library object */
- error = FT_Init_FreeType( &library );
- if (error) {
- std::cerr << " PNGwriter::get_text_width_utf8 - ERROR **: FreeType: Could not init Library." << std::endl;
- delete[] ucs4text;
- return 0;
- }
- /* Initialize FT face object */
- error = FT_New_Face( library,face_path,0,&face );
- if ( error == FT_Err_Unknown_File_Format ) {
- std::cerr << " PNGwriter::get_text_width_utf8 - ERROR **: FreeType: Font was opened, but type not supported." << std::endl;
- delete[] ucs4text;
- return 0;
- } else if (error) {
- std::cerr << " PNGwriter::plot_text - ERROR **: FreeType: Could not find or load font file." << std::endl;
- delete[] ucs4text;
- return 0;
- }
- /* Set the Char size */
- error = FT_Set_Char_Size( face, /* handle to face object */
- 0, /* char_width in 1/64th of points */
- fontsize*64, /* char_height in 1/64th of points */
- 100, /* horizontal device resolution */
- 100 ); /* vertical device resolution */
- /* A way of accesing the glyph directly */
- FT_GlyphSlot slot = face->glyph; // a small shortcut
- /* Does the font file support kerning? */
- use_kerning = FT_HAS_KERNING( face );
- int n;
- for ( n = 0; n < num_chars; n++ )
- {
- /* Convert character code to glyph index */
- glyph_index = FT_Get_Char_Index( face, ucs4text[n] );
- /* Retrieve kerning distance and move pen position */
- if ( use_kerning && previous&& glyph_index )
- {
- FT_Vector delta;
- FT_Get_Kerning( face,
- previous,
- glyph_index,
- ft_kerning_default, //FT_KERNING_DEFAULT,
- &delta );
- /* Transform this kerning distance into rotated space */
- pen.x += (int) (delta.x);
- pen.y += 0;
- }
- /* Set transform */
- FT_Set_Transform( face, &matrix, &pen );
- /*set char size*/
- if (error) {
- std::cerr << " PNGwriter::get_text_width_utf8 - ERROR **: FreeType: Set char size error." << std::endl;
- delete[] ucs4text;
- return 0;
- }
- /* Retrieve glyph index from character code */
- glyph_index = FT_Get_Char_Index( face, ucs4text[n] );
- /* Load glyph image into the slot (erase previous one) */
- error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT );
- if (error) {
- std::cerr << " PNGwriter::get_text_width_utf8 - ERROR **: FreeType: Could not load glyph (in loop). (FreeType error " << std::hex << error <<")." << std::endl;
- std::cerr.copyfmt(std::ios(NULL));
- delete[] ucs4text;
- return 0;
- }
- /* Convert to an anti-aliased bitmap */
- error = FT_Render_Glyph( face->glyph, ft_render_mode_normal );
- if (error) {
- std::cerr << " PNGwriter::get_text_width_utf8 - ERROR **: FreeType: Render glyph error." << std::endl;
- delete[] ucs4text;
- return 0;
- }
- /* Now, draw to our target surface */
- /* my_draw_bitmap( &slot->bitmap,
- slot->bitmap_left,
- y_start + slot->bitmap_top,
- red,
- green,
- blue );
- */
- /* Advance to the next position */
- pen.x += slot->advance.x;
- pen.y += slot->advance.y;
- /* record current glyph index */
- previous = glyph_index;
- }
- /* Free the face and the library objects */
- FT_Done_Face ( face );
- FT_Done_FreeType( library );
- delete[] ucs4text;
- return (int) (((double) pen.x)/64.0);
- }
- ///////////////
- #endif
- #ifdef NO_FREETYPE
- void pngwriter::plot_text( char *, int, int, int, double, char *, int, int, int )
- {
- std::cerr << " PNGwriter::plot_text - ERROR **: PNGwriter was compiled without Freetype support! Recompile PNGwriter with Freetype support (once you have Freetype installed, that is. Websites: www.freetype.org and pngwriter.sourceforge.net)." << std::endl;
- return;
- }
- void pngwriter::plot_text( char *, int, int, int, double, char *, double, double, double )
- {
- std::cerr << " PNGwriter::plot_text - ERROR **: PNGwriter was compiled without Freetype support! Recompile PNGwriter with Freetype support (once you have Freetype installed, that is. Websites: www.freetype.org and pngwriter.sourceforge.net)." << std::endl;
- return;
- }
- void pngwriter::plot_text_utf8( char *, int, int, int, double, char *, int, int, int )
- {
- std::cerr << " PNGwriter::plot_text_utf8 - ERROR **: PNGwriter was compiled without Freetype support! Recompile PNGwriter with Freetype support (once you have Freetype installed, that is. Websites: www.freetype.org and pngwriter.sourceforge.net)." << std::endl;
- return;
- }
- void pngwriter::plot_text_utf8( char *, int, int, int, double, char *, double, double, double)
- {
- std::cerr << " PNGwriter::plot_text_utf8 - ERROR **: PNGwriter was compiled without Freetype support! Recompile PNGwriter with Freetype support (once you have Freetype installed, that is. Websites: www.freetype.org and pngwriter.sourceforge.net)." << std::endl;
- return;
- }
- //////////// Get text width
- int pngwriter::get_text_width(char *, int, char *)
- {
- std::cerr << " PNGwriter::get_text_width - ERROR **: PNGwriter was compiled without Freetype support! Recompile PNGwriter with Freetype support (once you have Freetype installed, that is. Websites: www.freetype.org and pngwriter.sourceforge.net)." << std::endl;
- return 0;
- }
- int pngwriter::get_text_width_utf8(char *, int, char *)
- {
- std::cerr << " PNGwriter::get_text_width_utf8 - ERROR **: PNGwriter was compiled without Freetype support! Recompile PNGwriter with Freetype support (once you have Freetype installed, that is. Websites: www.freetype.org and pngwriter.sourceforge.net)." << std::endl;
- return 0;
- }
- ///////////////
- #endif
- /////////////////////////////////////
- int pngwriter::bilinear_interpolation_read(double x, double y, int colour) const
- {
- int inty, intx;
- inty = (int) ceil(y);
- intx = (int) ceil(x);
- //inty = (int) floor(y) +1;
- // intx = (int) floor(x) +1;
- //
- bool attop, atright;
- attop = inty==this->height_;
- atright = intx==this->width_;
- /*
- if( intx==this->width_ +1)
- {
- intx--;
- // std::cout << "intx--" << std::endl;
- }
- */
- /*
- if(inty == this->height_ +1)
- {
- inty--;
- // std::cout << "inty--" << std::endl;
- }
- */
- if( (!attop)&&(!atright) )
- {
- double f,g,f1,g1;
- f = 1.0 + x - ((double) intx);
- g = 1.0 + y - ((double) inty);
- f1 = 1.0 - f;
- g1 = 1.0 - g;
- return (int) (
- f1*g1*this->read(intx, inty,colour)
- + f*g1*this->read(intx+1,inty,colour)
- +f1*g*this->read(intx,inty+1,colour)
- + f*g*(this->read(intx+1,inty+1,colour))
- );
- }
- if( (atright)&&(!attop))
- {
- double f,g,f1,g1;
- f = 1.0 + x - ((double) intx);
- g = 1.0 + y - ((double) inty);
- f1 = 1.0 - f;
- g1 = 1.0 - g;
- return (int) (
- f1*g1*this->read(intx, inty,colour)
- + f*g1*( 2*(this->read(intx,inty,colour)) - (this->read(intx-1,inty,colour)) )
- +f1*g*this->read(intx,inty+1,colour)
- + f*g*(2*(this->read(intx,inty+1,colour)) - (this->read(intx-1,inty+1,colour)))
- );
- }
- if((attop)&&(!atright))
- {
- double f,g,f1,g1;
- f = 1.0 + x - ((double) intx);
- g = 1.0 + y - ((double) inty);
- f1 = 1.0 - f;
- g1 = 1.0 - g;
- return (int) (
- f1*g1*this->read(intx, inty,colour)
- + f*g1*this->read(intx+1,inty,colour)
- +f1*g*( 2*(this->read(intx,inty,colour)) - this->read(intx,inty-1,colour) )
- + f*g*( 2*(this->read(intx+1,inty,colour)) - this->read(intx+1,inty-1,colour))
- );
- }
- double f,g,f1,g1;
- f = 1.0 + x - ((double) intx);
- g = 1.0 + y - ((double) inty);
- f1 = 1.0 - f;
- g1 = 1.0 - g;
- return (int) (
- f1*g1*this->read(intx, inty,colour)
- + f*g1*( 2*(this->read(intx,inty,colour)) - (this->read(intx-1,inty,colour)) )
- +f1*g*( 2*(this->read(intx,inty,colour)) - this->read(intx,inty-1,colour) )
- + f*g*( 2*( 2*(this->read(intx,inty,colour)) - (this->read(intx-1,inty,colour)) ) - ( 2*(this->read(intx,inty-1,colour)) - (this->read(intx-1,inty-1,colour)) ))
- );
- /*
- return (int) (
- f1*g1*this->read(intx, inty,colour)
- + f*g1*this->read(intx+1,inty,colour)
- +f1*g*this->read(intx,inty+1,colour)
- + f*g*this->read(intx+1, inty+1,colour)
- );
- * */
- }
- double pngwriter::bilinear_interpolation_dread(double x, double y, int colour) const
- {
- return double(this->bilinear_interpolation_read(x,y,colour))/65535.0;
- }
- void pngwriter::plot_blend(int x, int y, double opacity, int red, int green, int blue)
- {
- this->plot(x, y,
- (int)( opacity*red + this->read(x,y,1)*(1.0-opacity)),
- (int)( opacity*green + this->read(x,y,2)*(1.0-opacity)),
- (int)( opacity*blue + this->read(x,y,3)*(1.0-opacity))
- );
- }
- void pngwriter::plot_blend(int x, int y, double opacity, double red, double green, double blue)
- {
- this->plot_blend(x, y, opacity, (int) (65535*red), (int) (65535*green), (int) (65535*blue));
- }
- void pngwriter::invert(void)
- {
- // int temp1, temp2, temp3;
- double temp11, temp22, temp33;
- for(int jjj = 1; jjj <= (this->height_); jjj++)
- {
- for(int iii = 1; iii <= (this->width_); iii++)
- {
- /* temp11 = (this->read(iii,jjj,1));
- temp22 = (this->read(iii,jjj,2));
- temp33 = (this->read(iii,jjj,3));
- *
- this->plot(iii,jjj,
- ((double)(65535 - temp11))/65535.0,
- ((double)(65535 - temp22))/65535.0,
- ((double)(65535 - temp33))/65535.0
- );
- *
- */
- temp11 = (this->read(iii,jjj,1));
- temp22 = (this->read(iii,jjj,2));
- temp33 = (this->read(iii,jjj,3));
- this->plot(iii,jjj,
- (int)(65535 - temp11),
- (int)(65535 - temp22),
- (int)(65535 - temp33)
- );
- }
- }
- }
- void pngwriter::resize(int width, int height)
- {
- for (int jjj = 0; jjj < height_; jjj++) free(graph_[jjj]);
- free(graph_);
- width_ = width;
- height_ = height;
- backgroundcolour_ = 0;
- graph_ = (png_bytepp)malloc(height_ * sizeof(png_bytep));
- if(graph_ == NULL)
- {
- std::cerr << " PNGwriter::resize - ERROR **: Not able to allocate memory for image." << std::endl;
- }
- for (int kkkk = 0; kkkk < height_; kkkk++)
- {
- graph_[kkkk] = (png_bytep)malloc(6*width_ * sizeof(png_byte));
- if(graph_[kkkk] == NULL)
- {
- std::cerr << " PNGwriter::resize - ERROR **: Not able to allocate memory for image." << std::endl;
- }
- }
- if(graph_ == NULL)
- {
- std::cerr << " PNGwriter::resize - ERROR **: Not able to allocate memory for image." << std::endl;
- }
- int tempindex;
- for(int vhhh = 0; vhhh<height_;vhhh++)
- {
- for(int hhh = 0; hhh<width_;hhh++)
- {
- //graph_[vhhh][6*hhh + i] where i goes from 0 to 5
- tempindex = 6*hhh;
- graph_[vhhh][tempindex] = (char) floor(((double)backgroundcolour_)/256);
- graph_[vhhh][tempindex+1] = (char)(backgroundcolour_%256);
- graph_[vhhh][tempindex+2] = (char) floor(((double)backgroundcolour_)/256);
- graph_[vhhh][tempindex+3] = (char)(backgroundcolour_%256);
- graph_[vhhh][tempindex+4] = (char) floor(((double)backgroundcolour_)/256);
- graph_[vhhh][tempindex+5] = (char)(backgroundcolour_%256);
- }
- }
- }
- void pngwriter::boundary_fill(int xstart, int ystart, double boundary_red,double boundary_green,double boundary_blue,double fill_red, double fill_green, double fill_blue)
- {
- if( (
- (this->dread(xstart,ystart,1) != boundary_red) ||
- (this->dread(xstart,ystart,2) != boundary_green) ||
- (this->dread(xstart,ystart,3) != boundary_blue)
- )
- &&
- (
- (this->dread(xstart,ystart,1) != fill_red) ||
- (this->dread(xstart,ystart,2) != fill_green) ||
- (this->dread(xstart,ystart,3) != fill_blue)
- )
- &&
- (xstart >0)&&(xstart <= width_)&&(ystart >0)&&(ystart <= height_)
- )
- {
- this->plot(xstart, ystart, fill_red, fill_green, fill_blue);
- boundary_fill(xstart+1, ystart, boundary_red, boundary_green, boundary_blue, fill_red, fill_green, fill_blue) ;
- boundary_fill(xstart, ystart+1, boundary_red, boundary_green, boundary_blue, fill_red, fill_green, fill_blue) ;
- boundary_fill(xstart, ystart-1, boundary_red, boundary_green, boundary_blue, fill_red, fill_green, fill_blue) ;
- boundary_fill(xstart-1, ystart, boundary_red, boundary_green, boundary_blue, fill_red, fill_green, fill_blue) ;
- }
- }
- //no int version needed
- void pngwriter::flood_fill_internal(int xstart, int ystart, double start_red, double start_green, double start_blue, double fill_red, double fill_green, double fill_blue)
- {
- if( (
- (this->dread(xstart,ystart,1) == start_red) &&
- (this->dread(xstart,ystart,2) == start_green) &&
- (this->dread(xstart,ystart,3) == start_blue)
- )
- &&
- (
- (this->dread(xstart,ystart,1) != fill_red) ||
- (this->dread(xstart,ystart,2) != fill_green) ||
- (this->dread(xstart,ystart,3) != fill_blue)
- )
- &&
- (xstart >0)&&(xstart <= width_)&&(ystart >0)&&(ystart <= height_)
- )
- {
- this->plot(xstart, ystart, fill_red, fill_green, fill_blue);
- flood_fill_internal( xstart+1, ystart, start_red, start_green, start_blue, fill_red, fill_green, fill_blue);
- flood_fill_internal( xstart-1, ystart, start_red, start_green, start_blue, fill_red, fill_green, fill_blue);
- flood_fill_internal( xstart, ystart+1, start_red, start_green, start_blue, fill_red, fill_green, fill_blue);
- flood_fill_internal( xstart, ystart-1, start_red, start_green, start_blue, fill_red, fill_green, fill_blue);
- }
- }
- //int version
- void pngwriter::boundary_fill(int xstart, int ystart, int boundary_red,int boundary_green,int boundary_blue,int fill_red, int fill_green, int fill_blue)
- {
- this->boundary_fill( xstart, ystart,
- ((double) boundary_red)/65535.0,
- ((double) boundary_green)/65535.0,
- ((double) boundary_blue)/65535.0,
- ((double) fill_red)/65535.0,
- ((double) fill_green)/65535.0,
- ((double) fill_blue)/65535.0
- );
- }
- void pngwriter::flood_fill(int xstart, int ystart, double fill_red, double fill_green, double fill_blue)
- {
- flood_fill_internal( xstart, ystart, this->dread(xstart,ystart,1),this->dread(xstart,ystart,2),this->dread(xstart,ystart,3), fill_red, fill_green, fill_blue);
- }
- //int version
- void pngwriter::flood_fill(int xstart, int ystart, int fill_red, int fill_green, int fill_blue)
- {
- this->flood_fill( xstart, ystart,
- ((double) fill_red)/65535.0,
- ((double) fill_green)/65535.0,
- ((double) fill_blue)/65535.0
- );
- }
- void pngwriter::polygon( int * points, int number_of_points, double red, double green, double blue)
- {
- if( (number_of_points<1)||(points ==NULL))
- {
- std::cerr << " PNGwriter::polygon - ERROR **: Number of points is zero or negative, or array is NULL." << std::endl;
- return;
- }
- for(int k=0;k< number_of_points-1; k++)
- {
- this->line(points[2*k],points[2*k+1],points[2*k+2],points[2*k+3], red, green, blue);
- }
- }
- //int version
- void pngwriter::polygon( int * points, int number_of_points, int red, int green, int blue)
- {
- this->polygon(points, number_of_points,
- ((double) red)/65535.0,
- ((double) green)/65535.0,
- ((double) blue)/65535.0
- );
- }
- void pngwriter::plotCMYK(int x, int y, double cyan, double magenta, double yellow, double black)
- {
- /*CMYK to RGB:
- * -----------
- * red = 255 - minimum(255,((cyan/255) * (255 - black) + black))
- * green = 255 - minimum(255,((magenta/255) * (255 - black) + black))
- * blue = 255 - minimum(255,((yellow/255) * (255 - black) + black))
- * */
- if(cyan<0.0)
- {
- cyan = 0.0;
- }
- if(magenta<0.0)
- {
- magenta = 0.0;
- }
- if(yellow<0.0)
- {
- yellow = 0.0;
- }
- if(black<0.0)
- {
- black = 0.0;
- }
- if(cyan>1.0)
- {
- cyan = 1.0;
- }
- if(magenta>1.0)
- {
- magenta = 1.0;
- }
- if(yellow>1.0)
- {
- yellow = 1.0;
- }
- if(black>1.0)
- {
- black = 1.0;
- }
- double red, green, blue, minr, ming, minb, iblack;
- iblack = 1.0 - black;
- minr = 1.0;
- ming = 1.0;
- minb = 1.0;
- if( (cyan*iblack + black)<1.0 )
- {
- minr = cyan*iblack + black;
- }
- if( (magenta*iblack + black)<1.0 )
- {
- ming = magenta*iblack + black;
- }
- if( (yellow*iblack + black)<1.0 )
- {
- minb = yellow*iblack + black;
- }
- red = 1.0 - minr;
- green = 1.0 - ming;
- blue = 1.0 - minb;
- this->plot(x,y,red, green, blue);
- }
- //int version
- void pngwriter::plotCMYK(int x, int y, int cyan, int magenta, int yellow, int black)
- {
- this->plotCMYK( x, y,
- ((double) cyan)/65535.0,
- ((double) magenta)/65535.0,
- ((double) yellow)/65535.0,
- ((double) black)/65535.0
- );
- }
- double pngwriter::dreadCMYK(int x, int y, int colour) const
- {
- /*
- * Black = minimum(1-Red,1-Green,1-Blue)
- * Cyan = (1-Red-Black)/(1-Black)
- * Magenta = (1-Green-Black)/(1-Black)
- * Yellow = (1-Blue-Black)/(1-Black)
- *
- * */
- double black, red, green, blue, ired, igreen, iblue, iblack;
- //add error detection here
- // not much to detect, really
- red = this->dread(x, y, 1);
- green = this->dread(x, y, 2);
- blue = this->dread(x, y, 3);
- ired = 1.0 - red;
- igreen = 1.0 - green;
- iblue = 1.0 - blue;
- black = ired;
- //black is the mimimum of inverse RGB colours, and if they are all equal, it is the inverse of red.
- if( (igreen<ired)&&(igreen<iblue) )
- {
- black = igreen;
- }
- if( (iblue<igreen)&&(iblue<ired) )
- {
- black = iblue;
- }
- iblack = 1.0 - black;
- switch( colour )
- {
- case 1: return ((ired-black)/iblack);
- case 2: return ((igreen-black)/iblack);
- case 3: return ((iblue-black)/iblack);
- case 4: return black;
- default:
- std::cerr << " PNGwriter::dreadCMYK - WARNING **: Invalid argument: should be 1, 2, 3 or 4, is "
- << colour << std::endl;
- return 0.0;
- }
- }
- int pngwriter::readCMYK(int x, int y, int colour) const
- {
- /*
- * Black = minimum(1-Red,1-Green,1-Blue)
- * Cyan = (1-Red-Black)/(1-Black)
- * Magenta = (1-Green-Black)/(1-Black)
- * Yellow = (1-Blue-Black)/(1-Black)
- *
- * */
- double black, red, green, blue, ired, igreen, iblue, iblack;
- //add error detection here
- // not much to detect, really
- red = this->dread(x, y, 1);
- green = this->dread(x, y, 2);
- blue = this->dread(x, y, 3);
- ired = 1.0 - red;
- igreen = 1.0 - green;
- iblue = 1.0 - blue;
- black = ired;
- //black is the mimimum of inverse RGB colours, and if they are all equal, it is the inverse of red.
- if( (igreen<ired)&&(igreen<iblue) )
- {
- black = igreen;
- }
- if( (iblue<igreen)&&(iblue<ired) )
- {
- black = iblue;
- }
- iblack = 1.0 - black;
- switch( colour )
- {
- case 1: return (int)( ((ired-black)/(iblack))*65535);
- case 2: return (int)( ((igreen-black)/(iblack))*65535);
- case 3: return (int)( ((iblue-black)/(iblack))*65535);
- case 4: return (int)( (black)*65535);
- default:
- std::cerr << " PNGwriter::readCMYK - WARNING **: Invalid argument: should be 1, 2, 3 or 4, is "
- << colour << std::endl;
- return 0;
- }
- }
- void pngwriter::scale_k(double k)
- {
- if(k <= 0.0)
- {
- std::cerr << " PNGwriter::scale_k - ERROR **: scale_k() called with negative or zero scale factor. Was: " << k << "." << std::endl;
- }
- // Calculate the new scaled height and width
- int scaledh, scaledw;
- scaledw = (int) ceil(k*width_);
- scaledh = (int) ceil(k*height_);
- // Create image storage.
- pngwriter temp(scaledw,scaledh,0,"temp");
- int red, green, blue;
- double spacingx = ((double)width_)/(2*scaledw);
- double spacingy = ((double)height_)/(2*scaledh);
- double readx, ready;
- for(int y = 1; y <= scaledh; y++)
- {
- for(int x = 1; x<= scaledw; x++)
- {
- readx = (2*x-1)*spacingx;
- ready = (2*y-1)*spacingy;
- red = this->bilinear_interpolation_read(readx, ready, 1);
- green = this->bilinear_interpolation_read(readx, ready, 2);
- blue = this->bilinear_interpolation_read(readx, ready, 3);
- temp.plot(x, y, red, green, blue);
- }
- }
- // From here on, the process is the same for all scale functions.
- //Get data out of temp and into this's storage.
- //Resize this instance
- // Delete current storage.
- for (int jjj = 0; jjj < height_; jjj++) free(graph_[jjj]);
- free(graph_);
- //New image will have bit depth 16, regardless of original bit depth.
- bit_depth_ = 16;
- // New width and height will be the scaled width and height
- width_ = scaledw;
- height_ = scaledh;
- backgroundcolour_ = 0;
- graph_ = (png_bytepp)malloc(height_ * sizeof(png_bytep));
- if(graph_ == NULL)
- {
- std::cerr << " PNGwriter::scale_k - ERROR **: Not able to allocate memory for image." << std::endl;
- }
- for (int kkkk = 0; kkkk < height_; kkkk++)
- {
- graph_[kkkk] = (png_bytep)malloc(6*width_ * sizeof(png_byte));
- if(graph_[kkkk] == NULL)
- {
- std::cerr << " PNGwriter::scale_k - ERROR **: Not able to allocate memory for image." << std::endl;
- }
- }
- if(graph_ == NULL)
- {
- std::cerr << " PNGwriter::scale_k - ERROR **: Not able to allocate memory for image." << std::endl;
- }
- //This instance now has a new, resized storage space.
- //Copy the temp date into this's storage.
- int tempindex;
- for(int vhhh = 0; vhhh<height_;vhhh++)
- {
- for(int hhh = 0; hhh<width_;hhh++)
- {
- tempindex=6*hhh;
- graph_[vhhh][tempindex] = temp.graph_[vhhh][tempindex];
- graph_[vhhh][tempindex+1] = temp.graph_[vhhh][tempindex+1];
- graph_[vhhh][tempindex+2] = temp.graph_[vhhh][tempindex+2];
- graph_[vhhh][tempindex+3] = temp.graph_[vhhh][tempindex+3];
- graph_[vhhh][tempindex+4] = temp.graph_[vhhh][tempindex+4];
- graph_[vhhh][tempindex+5] = temp.graph_[vhhh][tempindex+5];
- }
- }
- // this should now contain the new, scaled image data.
- //
- }
- void pngwriter::scale_kxky(double kx, double ky)
- {
- if((kx <= 0.0)||(ky <= 0.0))
- {
- std::cerr << " PNGwriter::scale_kxky - ERROR **: scale_kxky() called with negative or zero scale factor. Was: " << kx << ", " << ky << "." << std::endl;
- }
- int scaledh, scaledw;
- scaledw = (int) ceil(kx*width_);
- scaledh = (int) ceil(ky*height_);
- pngwriter temp(scaledw, scaledh, 0, "temp");
- int red, green, blue;
- double spacingx = ((double)width_)/(2*scaledw);
- double spacingy = ((double)height_)/(2*scaledh);
- double readx, ready;
- for(int y = 1; y <= scaledh; y++)
- {
- for(int x = 1; x<= scaledw; x++)
- {
- readx = (2*x-1)*spacingx;
- ready = (2*y-1)*spacingy;
- red = this->bilinear_interpolation_read(readx, ready, 1);
- green = this->bilinear_interpolation_read(readx, ready, 2);
- blue = this->bilinear_interpolation_read(readx, ready, 3);
- temp.plot(x, y, red, green, blue);
- }
- }
- // From here on, the process is the same for all scale functions.
- //Get data out of temp and into this's storage.
- //Resize this instance
- // Delete current storage.
- for (int jjj = 0; jjj < height_; jjj++) free(graph_[jjj]);
- free(graph_);
- //New image will have bit depth 16, regardless of original bit depth.
- bit_depth_ = 16;
- // New width and height will be the scaled width and height
- width_ = scaledw;
- height_ = scaledh;
- backgroundcolour_ = 0;
- graph_ = (png_bytepp)malloc(height_ * sizeof(png_bytep));
- if(graph_ == NULL)
- {
- std::cerr << " PNGwriter::scale_kxky - ERROR **: Not able to allocate memory for image." << std::endl;
- }
- for (int kkkk = 0; kkkk < height_; kkkk++)
- {
- graph_[kkkk] = (png_bytep)malloc(6*width_ * sizeof(png_byte));
- if(graph_[kkkk] == NULL)
- {
- std::cerr << " PNGwriter::scale_kxky - ERROR **: Not able to allocate memory for image." << std::endl;
- }
- }
- if(graph_ == NULL)
- {
- std::cerr << " PNGwriter::scale_kxky - ERROR **: Not able to allocate memory for image." << std::endl;
- }
- //This instance now has a new, resized storage space.
- //Copy the temp date into this's storage.
- int tempindex;
- for(int vhhh = 0; vhhh<height_;vhhh++)
- {
- for(int hhh = 0; hhh<width_;hhh++)
- {
- tempindex=6*hhh;
- graph_[vhhh][tempindex] = temp.graph_[vhhh][tempindex];
- graph_[vhhh][tempindex+1] = temp.graph_[vhhh][tempindex+1];
- graph_[vhhh][tempindex+2] = temp.graph_[vhhh][tempindex+2];
- graph_[vhhh][tempindex+3] = temp.graph_[vhhh][tempindex+3];
- graph_[vhhh][tempindex+4] = temp.graph_[vhhh][tempindex+4];
- graph_[vhhh][tempindex+5] = temp.graph_[vhhh][tempindex+5];
- }
- }
- // this should now contain the new, scaled image data.
- //
- //
- }
- void pngwriter::scale_wh(int finalwidth, int finalheight)
- {
- if((finalwidth <= 0)||(finalheight <= 0))
- {
- std::cerr << " PNGwriter::scale_wh - ERROR **: Negative or zero final width or height not allowed." << std::endl;
- }
- pngwriter temp(finalwidth, finalheight, 0, "temp");
- int red, green, blue;
- double spacingx = ((double)width_)/(2*finalwidth);
- double spacingy = ((double)height_)/(2*finalheight);
- double readx, ready;
- for(int y = 1; y <= finalheight; y++)
- {
- for(int x = 1; x<= finalwidth; x++)
- {
- readx = (2*x-1)*spacingx;
- ready = (2*y-1)*spacingy;
- red = this->bilinear_interpolation_read(readx, ready, 1);
- green = this->bilinear_interpolation_read(readx, ready, 2);
- blue = this->bilinear_interpolation_read(readx, ready, 3);
- temp.plot(x, y, red, green, blue);
- }
- }
- // From here on, the process is the same for all scale functions.
- //Get data out of temp and into this's storage.
- //Resize this instance
- // Delete current storage.
- for (int jjj = 0; jjj < height_; jjj++) free(graph_[jjj]);
- free(graph_);
- //New image will have bit depth 16, regardless of original bit depth.
- bit_depth_ = 16;
- // New width and height will be the scaled width and height
- width_ = finalwidth;
- height_ = finalheight;
- backgroundcolour_ = 0;
- graph_ = (png_bytepp)malloc(height_ * sizeof(png_bytep));
- if(graph_ == NULL)
- {
- std::cerr << " PNGwriter::scale_wh - ERROR **: Not able to allocate memory for image." << std::endl;
- }
- for (int kkkk = 0; kkkk < height_; kkkk++)
- {
- graph_[kkkk] = (png_bytep)malloc(6*width_ * sizeof(png_byte));
- if(graph_[kkkk] == NULL)
- {
- std::cerr << " PNGwriter::scale_wh - ERROR **: Not able to allocate memory for image." << std::endl;
- }
- }
- if(graph_ == NULL)
- {
- std::cerr << " PNGwriter::scale_wh - ERROR **: Not able to allocate memory for image." << std::endl;
- }
- //This instance now has a new, resized storage space.
- //Copy the temp date into this's storage.
- int tempindex;
- for(int vhhh = 0; vhhh<height_;vhhh++)
- {
- for(int hhh = 0; hhh<width_;hhh++)
- {
- tempindex=6*hhh;
- graph_[vhhh][tempindex] = temp.graph_[vhhh][tempindex];
- graph_[vhhh][tempindex+1] = temp.graph_[vhhh][tempindex+1];
- graph_[vhhh][tempindex+2] = temp.graph_[vhhh][tempindex+2];
- graph_[vhhh][tempindex+3] = temp.graph_[vhhh][tempindex+3];
- graph_[vhhh][tempindex+4] = temp.graph_[vhhh][tempindex+4];
- graph_[vhhh][tempindex+5] = temp.graph_[vhhh][tempindex+5];
- }
- }
- // this should now contain the new, scaled image data.
- //
- //
- }
- // Blended functions
- //
- void pngwriter::plotHSV_blend(int x, int y, double opacity, double hue, double saturation, double value)
- {
- double red,green,blue;
- double *redp;
- double *greenp;
- double *bluep;
- redp = &red;
- greenp = &green;
- bluep = &blue;
- HSVtoRGB(redp,greenp,bluep,hue,saturation,value);
- plot_blend(x,y,opacity, red,green,blue);
- }
- void pngwriter::plotHSV_blend(int x, int y, double opacity, int hue, int saturation, int value)
- {
- plotHSV_blend(x, y, opacity, double(hue)/65535.0, double(saturation)/65535.0, double(value)/65535.0);
- }
- void pngwriter::line_blend(int xfrom, int yfrom, int xto, int yto, double opacity, int red, int green,int blue)
- {
- // Bresenham Algorithm.
- //
- int dy = yto - yfrom;
- int dx = xto - xfrom;
- int stepx, stepy;
- if (dy < 0)
- {
- dy = -dy; stepy = -1;
- }
- else
- {
- stepy = 1;
- }
- if (dx < 0)
- {
- dx = -dx; stepx = -1;
- }
- else
- {
- stepx = 1;
- }
- dy <<= 1; // dy is now 2*dy
- dx <<= 1; // dx is now 2*dx
- this->plot_blend(xfrom,yfrom,opacity, red,green,blue);
- if (dx > dy)
- {
- int fraction = dy - (dx >> 1);
- while (xfrom != xto)
- {
- if (fraction >= 0)
- {
- yfrom += stepy;
- fraction -= dx;
- }
- xfrom += stepx;
- fraction += dy;
- this->plot_blend(xfrom,yfrom,opacity, red,green,blue);
- }
- }
- else
- {
- int fraction = dx - (dy >> 1);
- while (yfrom != yto)
- {
- if (fraction >= 0)
- {
- xfrom += stepx;
- fraction -= dy;
- }
- yfrom += stepy;
- fraction += dx;
- this->plot_blend(xfrom,yfrom, opacity, red,green,blue);
- }
- }
- }
- void pngwriter::line_blend(int xfrom, int yfrom, int xto, int yto, double opacity, double red, double green,double blue)
- {
- this->line_blend( xfrom,
- yfrom,
- xto,
- yto,
- opacity,
- int (red*65535),
- int (green*65535),
- int (blue*65535)
- );
- }
- void pngwriter::square_blend(int xfrom, int yfrom, int xto, int yto, double opacity, int red, int green,int blue)
- {
- this->line_blend(xfrom, yfrom, xfrom, yto, opacity, red, green, blue);
- this->line_blend(xto, yfrom, xto, yto, opacity, red, green, blue);
- this->line_blend(xfrom, yfrom, xto, yfrom, opacity, red, green, blue);
- this->line_blend(xfrom, yto, xto, yto, opacity, red, green, blue);
- }
- void pngwriter::square_blend(int xfrom, int yfrom, int xto, int yto, double opacity, double red, double green,double blue)
- {
- this->square_blend( xfrom, yfrom, xto, yto, opacity, int(red*65535), int(green*65535), int(blue*65535));
- }
- void pngwriter::filledsquare_blend(int xfrom, int yfrom, int xto, int yto, double opacity, int red, int green,int blue)
- {
- for(int caca = xfrom; caca <xto+1; caca++)
- {
- this->line_blend(caca, yfrom, caca, yto, opacity, red, green, blue);
- }
- }
- void pngwriter::filledsquare_blend(int xfrom, int yfrom, int xto, int yto, double opacity, double red, double green,double blue)
- {
- this->filledsquare_blend( xfrom, yfrom, xto, yto, opacity, int(red*65535), int(green*65535), int(blue*65535));
- }
- void pngwriter::circle_aux_blend(int xcentre, int ycentre, int x, int y, double opacity, int red, int green, int blue)
- {
- if (x == 0)
- {
- this->plot_blend( xcentre, ycentre + y, opacity, red, green, blue);
- this->plot_blend( xcentre, ycentre - y, opacity, red, green, blue);
- this->plot_blend( xcentre + y, ycentre, opacity, red, green, blue);
- this->plot_blend( xcentre - y, ycentre, opacity, red, green, blue);
- }
- else
- if (x == y)
- {
- this->plot_blend( xcentre + x, ycentre + y, opacity, red, green, blue);
- this->plot_blend( xcentre - x, ycentre + y, opacity, red, green, blue);
- this->plot_blend( xcentre + x, ycentre - y, opacity, red, green, blue);
- this->plot_blend( xcentre - x, ycentre - y, opacity, red, green, blue);
- }
- else
- if (x < y)
- {
- this->plot_blend( xcentre + x, ycentre + y, opacity, red, green, blue);
- this->plot_blend( xcentre - x, ycentre + y, opacity, red, green, blue);
- this->plot_blend( xcentre + x, ycentre - y, opacity, red, green, blue);
- this->plot_blend( xcentre - x, ycentre - y, opacity, red, green, blue);
- this->plot_blend( xcentre + y, ycentre + x, opacity, red, green, blue);
- this->plot_blend( xcentre - y, ycentre + x, opacity, red, green, blue);
- this->plot_blend( xcentre + y, ycentre - x, opacity, red, green, blue);
- this->plot_blend( xcentre - y, ycentre - x, opacity, red, green, blue);
- }
- }
- //
- void pngwriter::circle_blend(int xcentre, int ycentre, int radius, double opacity, int red, int green, int blue)
- {
- int x = 0;
- int y = radius;
- int p = (5 - radius*4)/4;
- circle_aux_blend(xcentre, ycentre, x, y, opacity, red, green, blue);
- while (x < y)
- {
- x++;
- if (p < 0)
- {
- p += 2*x+1;
- }
- else
- {
- y--;
- p += 2*(x-y)+1;
- }
- circle_aux_blend(xcentre, ycentre, x, y, opacity, red, green, blue);
- }
- }
- void pngwriter::circle_blend(int xcentre, int ycentre, int radius, double opacity, double red, double green, double blue)
- {
- this->circle_blend(xcentre,ycentre,radius, opacity, int(red*65535), int(green*65535), int(blue*65535));
- }
- void pngwriter::filledcircle_blend(int xcentre, int ycentre, int radius, double opacity, int red, int green, int blue)
- {
- for(int jjj = ycentre-radius; jjj< ycentre+radius+1; jjj++)
- {
- this->line_blend(xcentre - int(sqrt((double)(radius*radius) - (-ycentre + jjj)*(-ycentre + jjj ))), jjj,
- xcentre + int(sqrt((double)(radius*radius) - (-ycentre + jjj)*(-ycentre + jjj ))),jjj, opacity, red,green,blue);
- }
- }
- void pngwriter::filledcircle_blend(int xcentre, int ycentre, int radius, double opacity, double red, double green, double blue)
- {
- this->filledcircle_blend( xcentre, ycentre, radius, opacity, int(red*65535), int(green*65535), int(blue*65535));
- }
- void pngwriter::bezier_blend( int startPtX, int startPtY,
- int startControlX, int startControlY,
- int endPtX, int endPtY,
- int endControlX, int endControlY,
- double opacity,
- double red, double green, double blue)
- {
- double cx = 3.0*(startControlX - startPtX);
- double bx = 3.0*(endControlX - startControlX) - cx;
- double ax = double(endPtX - startPtX - cx - bx);
- double cy = 3.0*(startControlY - startPtY);
- double by = 3.0*(endControlY - startControlY) - cy;
- double ay = double(endPtY - startPtY - cy - by);
- double x,y;
- x = startPtX;
- y = startPtY;
- for(double t = 0.0; t<=1.005; t += 0.005)
- {
- double const newx = startPtX + t*(double(cx) + t*(double(bx) + t*(double(ax))));
- double const newy = startPtY + t*(double(cy) + t*(double(by) + t*(double(ay))));
- this->line_blend(int(x),int(y),int(newx),int(newy),opacity, red,green,blue);
- x = newx;
- y = newy;
- }
- }
- void pngwriter::bezier_blend( int startPtX, int startPtY,
- int startControlX, int startControlY,
- int endPtX, int endPtY,
- int endControlX, int endControlY,
- double opacity,
- int red, int green, int blue)
- {
- this->bezier_blend( startPtX, startPtY,
- startControlX, startControlY,
- endPtX, endPtY,
- endControlX, endControlY,
- opacity,
- double(red)/65535.0, double(green)/65535.0, double(blue)/65535.0);
- }
- /////////////////////////////
- #ifndef NO_FREETYPE
- // Freetype-based text rendering functions.
- ///////////////////////////////////////////
- void pngwriter::plot_text_blend( char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double opacity, double red, double green, double blue)
- {
- FT_Library library;
- FT_Face face;
- FT_Matrix matrix; // transformation matrix
- FT_Vector pen;
- FT_UInt glyph_index;
- FT_Error error;
- FT_Bool use_kerning;
- FT_UInt previous = 0;
- /* Set up transformation Matrix */
- matrix.xx = (FT_Fixed)( cos(angle)*0x10000); /* It would make more sense to do this (below), but, bizzarely, */
- matrix.xy = (FT_Fixed)(-sin(angle)*0x10000); /* if one does, FT_Load_Glyph fails consistently. */
- matrix.yx = (FT_Fixed)( sin(angle)*0x10000); // matrix.yx = - matrix.xy;
- matrix.yy = (FT_Fixed)( cos(angle)*0x10000); // matrix.yy = matrix.xx;
- /* Place starting coordinates in adequate form. */
- pen.x = x_start*64 ;
- pen.y = (int)(y_start/64.0);
- /*Count the length of the string */
- int num_chars = strlen(text);
- /* Initialize FT Library object */
- error = FT_Init_FreeType( &library );
- if (error) { std::cerr << " PNGwriter::plot_text_blend - ERROR **: FreeType: Could not init Library."<< std::endl; return;}
- /* Initialize FT face object */
- error = FT_New_Face( library,face_path,0,&face );
- if ( error == FT_Err_Unknown_File_Format ) { std::cerr << " PNGwriter::plot_text_blend - ERROR **: FreeType: Font was opened, but type not supported."<< std::endl; return; } else if (error){ std::cerr << " PNGwriter::plot_text - ERROR **: FreeType: Could not find or load font file."<< std::endl; return; }
- /* Set the Char size */
- error = FT_Set_Char_Size( face, /* handle to face object */
- 0, /* char_width in 1/64th of points */
- fontsize*64, /* char_height in 1/64th of points */
- 100, /* horizontal device resolution */
- 100 ); /* vertical device resolution */
- /* A way of accesing the glyph directly */
- FT_GlyphSlot slot = face->glyph; // a small shortcut
- /* Does the font file support kerning? */
- use_kerning = FT_HAS_KERNING( face );
- int n;
- for ( n = 0; n < num_chars; n++ )
- {
- /* Convert character code to glyph index */
- glyph_index = FT_Get_Char_Index( face, text[n] );
- /* Retrieve kerning distance and move pen position */
- if ( use_kerning && previous&& glyph_index )
- {
- FT_Vector delta;
- FT_Get_Kerning( face,
- previous,
- glyph_index,
- ft_kerning_default, //FT_KERNING_DEFAULT,
- &delta );
- /* Transform this kerning distance into rotated space */
- pen.x += (int) (((double) delta.x)*cos(angle));
- pen.y += (int) (((double) delta.x)*( sin(angle)));
- }
- /* Set transform */
- FT_Set_Transform( face, &matrix, &pen );
- /*set char size*/
- if (error) { std::cerr << " PNGwriter::plot_text_blend - ERROR **: FreeType: Set char size error." << std::endl; return;}
- /* Retrieve glyph index from character code */
- glyph_index = FT_Get_Char_Index( face, text[n] );
- /* Load glyph image into the slot (erase previous one) */
- error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT );
- if (error) {
- std::cerr << " PNGwriter::plot_text_blend - ERROR **: FreeType: Could not load glyph (in loop). (FreeType error " << std::hex << error <<")." << std::endl;
- std::cerr.copyfmt(std::ios(NULL));
- return;
- }
- /* Convert to an anti-aliased bitmap */
- // error = FT_Render_Glyph( face->glyph, FT_RENDER_MODE_NORMAL );
- error = FT_Render_Glyph( face->glyph, ft_render_mode_normal );
- if (error) { std::cerr << " PNGwriter::plot_text_blend - ERROR **: FreeType: Render glyph error." << std::endl; return;}
- /* Now, draw to our target surface */
- my_draw_bitmap_blend( &slot->bitmap,
- slot->bitmap_left,
- y_start + slot->bitmap_top,
- opacity,
- red,
- green,
- blue );
- /* Advance to the next position */
- pen.x += slot->advance.x;
- pen.y += slot->advance.y;
- /* record current glyph index */
- previous = glyph_index;
- }
- /* Free the face and the library objects */
- FT_Done_Face ( face );
- FT_Done_FreeType( library );
- }
- void pngwriter::plot_text_utf8_blend( char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double opacity, double red, double green, double blue)
- {
- FT_Library library;
- FT_Face face;
- FT_Matrix matrix; // transformation matrix
- FT_Vector pen;
- FT_UInt glyph_index;
- FT_Error error;
- FT_Bool use_kerning;
- FT_UInt previous = 0;
- /* Set up transformation Matrix */
- matrix.xx = (FT_Fixed)( cos(angle)*0x10000); /* It would make more sense to do this (below), but, bizzarely, */
- matrix.xy = (FT_Fixed)(-sin(angle)*0x10000); /* if one does, FT_Load_Glyph fails consistently. */
- matrix.yx = (FT_Fixed)( sin(angle)*0x10000); // matrix.yx = - matrix.xy;
- matrix.yy = (FT_Fixed)( cos(angle)*0x10000); // matrix.yy = matrix.xx;
- /* Place starting coordinates in adequate form. */
- pen.x = x_start*64 ;
- pen.y = (int)(y_start/64.0);
- /*Count the length of the string */
- int num_bytes=0;
- while(text[num_bytes]!=0)
- {
- num_bytes++;
- }
- /*
- std::cout << "Num bytes is: "<< num_bytes << std::endl;
- */
- //The array of ucs4 glyph indexes, which will by at most the number of bytes in the utf-8 file.
- long * ucs4text;
- ucs4text = new long[num_bytes+1];
- unsigned char u,v,w,x,y;
- int num_chars=0;
- long iii=0;
- while(iii<num_bytes)
- {
- unsigned char const z = text[iii];
- if(z<=127)
- {
- ucs4text[num_chars] = z;
- }
- if((192<=z)&&(z<=223))
- {
- iii++; y = text[iii];
- ucs4text[num_chars] = (z-192)*64 + (y -128);
- }
- if((224<=z)&&(z<=239))
- {
- iii++; y = text[iii];
- iii++; x = text[iii];
- ucs4text[num_chars] = (z-224)*4096 + (y -128)*64 + (x-128);
- }
- if((240<=z)&&(z<=247))
- {
- iii++; y = text[iii];
- iii++; x = text[iii];
- iii++; w = text[iii];
- ucs4text[num_chars] = (z-240)*262144 + (y -128)*4096 + (x-128)*64 + (w-128);
- }
- if((248<=z)&&(z<=251))
- {
- iii++; y = text[iii];
- iii++; x = text[iii];
- iii++; w = text[iii];
- iii++; v = text[iii];
- ucs4text[num_chars] = (z-248)*16777216 + (y -128)*262144 + (x-128)*4096 + (w-128)*64 +(v-128);
- }
- if((252==z)||(z==253))
- {
- iii++; y = text[iii];
- iii++; x = text[iii];
- iii++; w = text[iii];
- iii++; v = text[iii];
- u = text[iii];
- ucs4text[num_chars] = (z-252)*1073741824 + (y -128)*16777216 + (x-128)*262144 + (w-128)*4096 +(v-128)*64 + (u-128);
- }
- if((z==254)||(z==255))
- {
- std::cerr << " PNGwriter::plot_text_utf8_blend - ERROR **: Problem with character: invalid UTF-8 data."<< std::endl;
- }
- // std::cerr << "\nProblem at " << iii << ".\n";
- //
- iii++;
- num_chars++;
- }
- // num_chars now contains the number of characters in the string.
- /*
- std::cout << "Num chars is: "<< num_chars << std::endl;
- */
- /* Initialize FT Library object */
- error = FT_Init_FreeType( &library );
- if (error) {
- std::cerr << " PNGwriter::plot_text_utf8_blend - ERROR **: FreeType: Could not init Library." << std::endl;
- delete[] ucs4text;
- return;
- }
- /* Initialize FT face object */
- error = FT_New_Face( library,face_path,0,&face );
- if ( error == FT_Err_Unknown_File_Format ) {
- std::cerr << " PNGwriter::plot_text_utf8_blend - ERROR **: FreeType: Font was opened, but type not supported." << std::endl;
- delete[] ucs4text;
- return;
- } else if (error) {
- std::cerr << " PNGwriter::plot_text - ERROR **: FreeType: Could not find or load font file." << std::endl;
- delete[] ucs4text;
- return;
- }
- /* Set the Char size */
- error = FT_Set_Char_Size( face, /* handle to face object */
- 0, /* char_width in 1/64th of points */
- fontsize*64, /* char_height in 1/64th of points */
- 100, /* horizontal device resolution */
- 100 ); /* vertical device resolution */
- /* A way of accesing the glyph directly */
- FT_GlyphSlot slot = face->glyph; // a small shortcut
- /* Does the font file support kerning? */
- use_kerning = FT_HAS_KERNING( face );
- int n;
- for ( n = 0; n < num_chars; n++ )
- {
- /* Convert character code to glyph index */
- glyph_index = FT_Get_Char_Index( face, ucs4text[n] );
- /* Retrieve kerning distance and move pen position */
- if ( use_kerning && previous&& glyph_index )
- {
- FT_Vector delta;
- FT_Get_Kerning( face,
- previous,
- glyph_index,
- ft_kerning_default, //FT_KERNING_DEFAULT,
- &delta );
- /* Transform this kerning distance into rotated space */
- pen.x += (int) (((double) delta.x)*cos(angle));
- pen.y += (int) (((double) delta.x)*( sin(angle)));
- }
- /* Set transform */
- FT_Set_Transform( face, &matrix, &pen );
- /*set char size*/
- if (error) {
- std::cerr << " PNGwriter::plot_text_utf8_blend - ERROR **: FreeType: Set char size error." << std::endl;
- delete[] ucs4text;
- return;
- }
- /* Retrieve glyph index from character code */
- glyph_index = FT_Get_Char_Index( face, ucs4text[n] );
- /* Load glyph image into the slot (erase previous one) */
- error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT );
- if (error) {
- std::cerr << " PNGwriter::plot_text_utf8_blend - ERROR **: FreeType: Could not load glyph (in loop). (FreeType error " << std::hex << error <<")." << std::endl;
- std::cout.copyfmt(std::ios(NULL));
- delete[] ucs4text;
- return;
- }
- /* Convert to an anti-aliased bitmap */
- error = FT_Render_Glyph( face->glyph, ft_render_mode_normal );
- if (error) {
- std::cerr << " PNGwriter::plot_text_utf8_blend - ERROR **: FreeType: Render glyph error." << std::endl;
- delete[] ucs4text;
- return;
- }
- /* Now, draw to our target surface */
- my_draw_bitmap_blend( &slot->bitmap,
- slot->bitmap_left,
- y_start + slot->bitmap_top,
- opacity,
- red,
- green,
- blue );
- /* Advance to the next position */
- pen.x += slot->advance.x;
- pen.y += slot->advance.y;
- /* record current glyph index */
- previous = glyph_index;
- }
- /* Free the face and the library objects */
- FT_Done_Face ( face );
- FT_Done_FreeType( library );
- delete[] ucs4text;
- }
- void pngwriter::plot_text_blend( char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double opacity, int red, int green, int blue)
- {
- plot_text_blend( face_path, fontsize, x_start, y_start, angle, text, opacity, ((double) red)/65535.0, ((double) green)/65535.0, ((double) blue)/65535.0 );
- }
- void pngwriter::plot_text_utf8_blend( char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double opacity, int red, int green, int blue)
- {
- plot_text_utf8_blend( face_path, fontsize, x_start, y_start, angle, text, opacity, ((double) red)/65535.0, ((double) green)/65535.0, ((double) blue)/65535.0 );
- }
- void pngwriter::my_draw_bitmap_blend( FT_Bitmap * bitmap, int x, int y, double opacity, double red, double green, double blue)
- {
- double temp;
- for(unsigned int j = 1u; j < bitmap->rows + 1u; j++)
- {
- for(unsigned int i = 1u; i < bitmap->width + 1u; i++)
- {
- temp = (double)(bitmap->buffer[(j-1u)*bitmap->width + (i-1u)] )/255.0;
- if(temp)
- {
- this->plot_blend(x + i,
- y - j,
- opacity,
- temp*red + (1-temp)*(this->dread(x+i,y-j,1)),
- temp*green + (1-temp)*(this->dread(x+i,y-j,2)),
- temp*blue + (1-temp)*(this->dread(x+i,y-j,3))
- );
- }
- }
- }
- }
- #endif
- #ifdef NO_FREETYPE
- void pngwriter::plot_text_blend( char *, int, int, int, double, char *, double, int, int, int )
- {
- std::cerr << " PNGwriter::plot_text_blend - ERROR **: PNGwriter was compiled without Freetype support! Recompile PNGwriter with Freetype support (once you have Freetype installed, that is. Websites: www.freetype.org and pngwriter.sourceforge.net)." << std::endl;
- return;
- }
- void pngwriter::plot_text_blend( char *, int, int, int, double, char *, double, double, double, double )
- {
- std::cerr << " PNGwriter::plot_text_blend - ERROR **: PNGwriter was compiled without Freetype support! Recompile PNGwriter with Freetype support (once you have Freetype installed, that is. Websites: www.freetype.org and pngwriter.sourceforge.net)." << std::endl;
- return;
- }
- void pngwriter::plot_text_utf8_blend( char *, int, int, int, double, char *, double, int, int, int )
- {
- std::cerr << " PNGwriter::plot_text_utf8_blend - ERROR **: PNGwriter was compiled without Freetype support! Recompile PNGwriter with Freetype support (once you have Freetype installed, that is. Websites: www.freetype.org and pngwriter.sourceforge.net)." << std::endl;
- return;
- }
- void pngwriter::plot_text_utf8_blend( char *, int, int, int, double, char *, double, double, double, double )
- {
- std::cerr << " PNGwriter::plot_text_utf8_blend - ERROR **: PNGwriter was compiled without Freetype support! Recompile PNGwriter with Freetype support (once you have Freetype installed, that is. Websites: www.freetype.org and pngwriter.sourceforge.net)." << std::endl;
- return;
- }
- #endif
- ///////////////////////////
- void pngwriter::boundary_fill_blend(int xstart, int ystart, double opacity, double boundary_red,double boundary_green,double boundary_blue,double fill_red, double fill_green, double fill_blue)
- {
- if( (
- (this->dread(xstart,ystart,1) != boundary_red) ||
- (this->dread(xstart,ystart,2) != boundary_green) ||
- (this->dread(xstart,ystart,3) != boundary_blue)
- )
- &&
- (
- (this->dread(xstart,ystart,1) != fill_red) ||
- (this->dread(xstart,ystart,2) != fill_green) ||
- (this->dread(xstart,ystart,3) != fill_blue)
- )
- &&
- (xstart >0)&&(xstart <= width_)&&(ystart >0)&&(ystart <= height_)
- )
- {
- this->plot_blend(xstart, ystart, opacity, fill_red, fill_green, fill_blue);
- boundary_fill_blend(xstart+1, ystart, opacity, boundary_red, boundary_green, boundary_blue, fill_red, fill_green, fill_blue) ;
- boundary_fill_blend(xstart, ystart+1, opacity, boundary_red, boundary_green, boundary_blue, fill_red, fill_green, fill_blue) ;
- boundary_fill_blend(xstart, ystart-1, opacity, boundary_red, boundary_green, boundary_blue, fill_red, fill_green, fill_blue) ;
- boundary_fill_blend(xstart-1, ystart, opacity, boundary_red, boundary_green, boundary_blue, fill_red, fill_green, fill_blue) ;
- }
- }
- //no int version needed
- void pngwriter::flood_fill_internal_blend(int xstart, int ystart, double opacity, double start_red, double start_green, double start_blue, double fill_red, double fill_green, double fill_blue)
- {
- if( (
- (this->dread(xstart,ystart,1) == start_red) &&
- (this->dread(xstart,ystart,2) == start_green) &&
- (this->dread(xstart,ystart,3) == start_blue)
- )
- &&
- (
- (this->dread(xstart,ystart,1) != fill_red) ||
- (this->dread(xstart,ystart,2) != fill_green) ||
- (this->dread(xstart,ystart,3) != fill_blue)
- )
- &&
- (xstart >0)&&(xstart <= width_)&&(ystart >0)&&(ystart <= height_)
- )
- {
- this->plot_blend(xstart, ystart, opacity, fill_red, fill_green, fill_blue);
- flood_fill_internal_blend( xstart+1, ystart, opacity, start_red, start_green, start_blue, fill_red, fill_green, fill_blue);
- flood_fill_internal_blend( xstart-1, ystart,opacity, start_red, start_green, start_blue, fill_red, fill_green, fill_blue);
- flood_fill_internal_blend( xstart, ystart+1, opacity, start_red, start_green, start_blue, fill_red, fill_green, fill_blue);
- flood_fill_internal_blend( xstart, ystart-1, opacity, start_red, start_green, start_blue, fill_red, fill_green, fill_blue);
- }
- }
- //int version
- void pngwriter::boundary_fill_blend(int xstart, int ystart, double opacity, int boundary_red,int boundary_green,int boundary_blue,int fill_red, int fill_green, int fill_blue)
- {
- this->boundary_fill_blend( xstart, ystart,
- opacity,
- ((double) boundary_red)/65535.0,
- ((double) boundary_green)/65535.0,
- ((double) boundary_blue)/65535.0,
- ((double) fill_red)/65535.0,
- ((double) fill_green)/65535.0,
- ((double) fill_blue)/65535.0
- );
- }
- void pngwriter::flood_fill_blend(int xstart, int ystart, double opacity, double fill_red, double fill_green, double fill_blue)
- {
- flood_fill_internal_blend( xstart, ystart, opacity, this->dread(xstart,ystart,1),this->dread(xstart,ystart,2),this->dread(xstart,ystart,3), fill_red, fill_green, fill_blue);
- }
- //int version
- void pngwriter::flood_fill_blend(int xstart, int ystart, double opacity, int fill_red, int fill_green, int fill_blue)
- {
- this->flood_fill_blend( xstart, ystart,
- opacity,
- ((double) fill_red)/65535.0,
- ((double) fill_green)/65535.0,
- ((double) fill_blue)/65535.0
- );
- }
- void pngwriter::polygon_blend( int * points, int number_of_points, double opacity, double red, double green, double blue)
- {
- if( (number_of_points<1)||(points ==NULL))
- {
- std::cerr << " PNGwriter::polygon_blend - ERROR **: Number of points is zero or negative, or array is NULL." << std::endl;
- return;
- }
- for(int k=0;k< number_of_points-1; k++)
- {
- this->line_blend(points[2*k],points[2*k+1],points[2*k+2],points[2*k+3], opacity, red, green, blue);
- }
- }
- //int version
- void pngwriter::polygon_blend( int * points, int number_of_points, double opacity, int red, int green, int blue)
- {
- this->polygon_blend(points, number_of_points,
- opacity,
- ((double) red)/65535.0,
- ((double) green)/65535.0,
- ((double) blue)/65535.0
- );
- }
- void pngwriter::plotCMYK_blend(int x, int y, double opacity, double cyan, double magenta, double yellow, double black)
- {
- /*CMYK to RGB:
- * -----------
- * red = 255 - minimum(255,((cyan/255) * (255 - black) + black))
- * green = 255 - minimum(255,((magenta/255) * (255 - black) + black))
- * blue = 255 - minimum(255,((yellow/255) * (255 - black) + black))
- * */
- if(cyan<0.0)
- {
- cyan = 0.0;
- }
- if(magenta<0.0)
- {
- magenta = 0.0;
- }
- if(yellow<0.0)
- {
- yellow = 0.0;
- }
- if(black<0.0)
- {
- black = 0.0;
- }
- if(cyan>1.0)
- {
- cyan = 1.0;
- }
- if(magenta>1.0)
- {
- magenta = 1.0;
- }
- if(yellow>1.0)
- {
- yellow = 1.0;
- }
- if(black>1.0)
- {
- black = 1.0;
- }
- double red, green, blue, minr, ming, minb, iblack;
- iblack = 1.0 - black;
- minr = 1.0;
- ming = 1.0;
- minb = 1.0;
- if( (cyan*iblack + black)<1.0 )
- {
- minr = cyan*iblack + black;
- }
- if( (magenta*iblack + black)<1.0 )
- {
- ming = magenta*iblack + black;
- }
- if( (yellow*iblack + black)<1.0 )
- {
- minb = yellow*iblack + black;
- }
- red = 1.0 - minr;
- green = 1.0 - ming;
- blue = 1.0 - minb;
- this->plot_blend(x,y,opacity, red, green, blue);
- }
- //int version
- void pngwriter::plotCMYK_blend(int x, int y, double opacity, int cyan, int magenta, int yellow, int black)
- {
- this->plotCMYK_blend( x, y,
- opacity,
- ((double) cyan)/65535.0,
- ((double) magenta)/65535.0,
- ((double) yellow)/65535.0,
- ((double) black)/65535.0
- );
- }
- void pngwriter::laplacian(double k, double offset)
- {
- // Create image storage.
- pngwriter temp(width_,height_,0,"temp");
- double red, green, blue;
- for(int y = 1; y <= height_; y++)
- {
- for(int x = 1; x <= width_; x++)
- {
- red =
- 8.0*this->dread(x,y,1) -
- ( this->dread(x+1, y-1, 1) +
- this->dread(x, y-1, 1) +
- this->dread(x-1, y-1, 1) +
- this->dread(x-1, y, 1) +
- this->dread(x+1, y, 1) +
- this->dread(x+1, y+1, 1) +
- this->dread(x, y+1, 1) +
- this->dread(x-1, y+1, 1) );
- green =
- 8.0*this->dread(x,y,2) -
- ( this->dread(x+1, y-1, 2) +
- this->dread(x, y-1, 2) +
- this->dread(x-1, y-1, 2) +
- this->dread(x-1, y, 2) +
- this->dread(x+1, y, 2) +
- this->dread(x+1, y+1, 2) +
- this->dread(x, y+1, 2) +
- this->dread(x-1, y+1, 2));
- blue =
- 8.0*this->dread(x,y,3) -
- ( this->dread(x+1, y-1, 3) +
- this->dread(x, y-1, 3) +
- this->dread(x-1, y-1, 3) +
- this->dread(x-1, y, 3) +
- this->dread(x+1, y, 3) +
- this->dread(x+1, y+1, 3) +
- this->dread(x, y+1, 3) +
- this->dread(x-1, y+1, 3));
- temp.plot(x,y,offset+k*red,offset+k*green,offset+k*blue);
- }
- }
- for(int yy = 1; yy <= height_; yy++)
- {
- for(int xx = 1; xx <= width_; xx++)
- {
- this->plot(xx,yy, temp.read(xx,yy,1), temp.read(xx,yy,2), temp.read(xx,yy,3));
- }
- }
- }
- // drwatop(), drawbottom() and filledtriangle() were contributed by Gurkan Sengun
- // ( <gurkan@linuks.mine.nu>, http://www.linuks.mine.nu/ )
- void pngwriter::drawtop(long x1,long y1,long x2,long y2,long x3, int red, int green, int blue)
- {
- // avoid division by zero
- long dy = 1;
- if(y2!=y1)
- dy=y2-y1;
- // This swaps x2 and x3
- // if(x2>x3) x2^=x3^=x2^=x3;
- if(x2>x3)
- {
- x2^=x3;
- x3^=x2;
- x2^=x3;
- }
- long posl = x1*256;
- long posr = posl;
- long cl=((x2-x1)*256)/dy;
- long cr=((x3-x1)*256)/dy;
- for(int y=y1; y<=y2; y++)
- {
- this->line(posl/256, y, posr/256, y, red, green, blue);
- posl+=cl;
- posr+=cr;
- }
- }
- // drwatop(), drawbottom() and filledtriangle() were contributed by Gurkan Sengun
- // ( <gurkan@linuks.mine.nu>, http://www.linuks.mine.nu/ )
- void pngwriter::drawbottom(long x1,long y1,long x2,long x3,long y3, int red, int green, int blue)
- {
- //Swap x1 and x2
- //if(x1>x2) x2^=x1^=x2^=x1;
- if(x1>x2)
- {
- x2^=x1;
- x1^=x2;
- x2^=x1;
- }
- long posl=x1*256;
- long posr=x2*256;
- long cl=((x3-x1)*256)/(y3-y1);
- long cr=((x3-x2)*256)/(y3-y1);
- for(int y=y1; y<=y3; y++)
- {
- this->line(posl/256, y, posr/256, y, red, green, blue);
- posl+=cl;
- posr+=cr;
- }
- }
- // drwatop(), drawbottom() and filledtriangle() were contributed by Gurkan Sengun
- // ( <gurkan@linuks.mine.nu>, http://www.linuks.mine.nu/ )
- void pngwriter::filledtriangle(int x1,int y1,int x2,int y2,int x3,int y3, int red, int green, int blue)
- {
- if((x1==x2 && x2==x3) || (y1==y2 && y2==y3)) return;
- if(y2<y1)
- {
- // x2^=x1^=x2^=x1;
- x2^=x1;
- x1^=x2;
- x2^=x1;
- // y2^=y1^=y2^=y1;
- y2^=y1;
- y1^=y2;
- y2^=y1;
- }
- if(y3<y1)
- {
- //x3^=x1^=x3^=x1;
- x3^=x1;
- x1^=x3;
- x3^=x1;
- //y3^=y1^=y3^=y1;
- y3^=y1;
- y1^=y3;
- y3^=y1;
- }
- if(y3<y2)
- {
- //x2^=x3^=x2^=x3;
- x2^=x3;
- x3^=x2;
- x2^=x3;
- //y2^=y3^=y2^=y3;
- y2^=y3;
- y3^=y2;
- y2^=y3;
- }
- if(y2==y3)
- {
- this->drawtop(x1, y1, x2, y2, x3, red, green, blue);
- }
- else
- {
- if(y1==y3 || y1==y2)
- {
- this->drawbottom(x1, y1, x2, x3, y3, red, green, blue);
- }
- else
- {
- int new_x = x1 + (int)((double)(y2-y1)*(double)(x3-x1)/(double)(y3-y1));
- this->drawtop(x1, y1, new_x, y2, x2, red, green, blue);
- this->drawbottom(x2, y2, new_x, x3, y3, red, green, blue);
- }
- }
- }
- //Double (bug found by Dave Wilks. Was: (int) red*65535, should have been (int) (red*65535).
- void pngwriter::filledtriangle(int x1,int y1,int x2,int y2,int x3,int y3, double red, double green, double blue)
- {
- this->filledtriangle(x1, y1, x2, y2, x3, y3, (int) (red*65535), (int) (green*65535), (int) (blue*65535));
- }
- //Blend, double. (bug found by Dave Wilks. Was: (int) red*65535, should have been (int) (red*65535).
- void pngwriter::filledtriangle_blend(int x1,int y1,int x2,int y2,int x3,int y3, double opacity, double red, double green, double blue)
- {
- this->filledtriangle_blend( x1, y1, x2, y2, x3, y3, opacity, (int) (red*65535), (int) (green*65535), (int) (blue*65535));
- }
- //Blend, int
- void pngwriter::filledtriangle_blend(int x1,int y1,int x2,int y2,int x3,int y3, double opacity, int red, int green, int blue)
- {
- if((x1==x2 && x2==x3) || (y1==y2 && y2==y3)) return;
- /*if(y2<y1)
- {
- x2^=x1^=x2^=x1;
- y2^=y1^=y2^=y1;
- }
- if(y3<y1)
- {
- x3^=x1^=x3^=x1;
- y3^=y1^=y3^=y1;
- }
- if(y3<y2)
- {
- x2^=x3^=x2^=x3;
- y2^=y3^=y2^=y3;
- }
- */
- if(y2<y1)
- {
- // x2^=x1^=x2^=x1;
- x2^=x1;
- x1^=x2;
- x2^=x1;
- // y2^=y1^=y2^=y1;
- y2^=y1;
- y1^=y2;
- y2^=y1;
- }
- if(y3<y1)
- {
- //x3^=x1^=x3^=x1;
- x3^=x1;
- x1^=x3;
- x3^=x1;
- //y3^=y1^=y3^=y1;
- y3^=y1;
- y1^=y3;
- y3^=y1;
- }
- if(y3<y2)
- {
- //x2^=x3^=x2^=x3;
- x2^=x3;
- x3^=x2;
- x2^=x3;
- //y2^=y3^=y2^=y3;
- y2^=y3;
- y3^=y2;
- y2^=y3;
- }
- if(y2==y3)
- {
- this->drawtop_blend(x1, y1, x2, y2, x3, opacity, red, green, blue);
- }
- else
- {
- if(y1==y3 || y1==y2)
- {
- this->drawbottom_blend(x1, y1, x2, x3, y3, opacity, red, green, blue);
- }
- else
- {
- int new_x = x1 + (int)((double)(y2-y1)*(double)(x3-x1)/(double)(y3-y1));
- this->drawtop_blend(x1, y1, new_x, y2, x2, opacity, red, green, blue);
- this->drawbottom_blend(x2, y2, new_x, x3, y3, opacity, red, green, blue);
- }
- }
- }
- //Blend, int
- void pngwriter::drawbottom_blend(long x1,long y1,long x2,long x3,long y3, double opacity, int red, int green, int blue)
- {
- //Swap x1 and x2
- if(x1>x2)
- {
- x2^=x1;
- x1^=x2;
- x2^=x1;
- }
- long posl=x1*256;
- long posr=x2*256;
- long cl=((x3-x1)*256)/(y3-y1);
- long cr=((x3-x2)*256)/(y3-y1);
- for(int y=y1; y<y3; y++)
- {
- this->line_blend(posl/256, y, posr/256, y, opacity, red, green, blue);
- posl+=cl;
- posr+=cr;
- }
- }
- //Blend, int
- void pngwriter::drawtop_blend(long x1,long y1,long x2,long y2,long x3, double opacity, int red, int green, int blue)
- {
- // This swaps x2 and x3
- if(x2>x3)
- {
- x2^=x3;
- x3^=x2;
- x2^=x3;
- }
- long posl = x1*256;
- long posr = posl;
- long cl=((x2-x1)*256)/(y2-y1);
- long cr=((x3-x1)*256)/(y2-y1);
- for(int y=y1; y<y2; y++)
- {
- this->line_blend(posl/256, y, posr/256, y, opacity, red, green, blue);
- posl+=cl;
- posr+=cr;
- }
- }
- void pngwriter::triangle(int x1, int y1, int x2, int y2, int x3, int y3, int red, int green, int blue)
- {
- this->line(x1, y1, x2, y2, red, green, blue);
- this->line(x2, y2, x3, y3, red, green, blue);
- this->line(x3, y3, x1, y1, red, green, blue);
- }
- void pngwriter::triangle(int x1, int y1, int x2, int y2, int x3, int y3, double red, double green, double blue)
- {
- this->line(x1, y1, x2, y2, int(65535*red), int(65535*green), int(65535*blue));
- this->line(x2, y2, x3, y3, int(65535*red), int(65535*green), int(65535*blue));
- this->line(x3, y3, x1, y1, int(65535*red), int(65535*green), int(65535*blue));
- }
- void pngwriter::arrow( int x1,int y1,int x2,int y2,int size, double head_angle, double red, double green, double blue)
- {
- this->line(x1, y1, x2, y2, red, green, blue);
- // double th = 3.141592653589793 + (head_angle)*3.141592653589793/180.0; //degrees
- double th = 3.141592653589793 + head_angle;
- double costh = cos(th);
- double sinth = sin(th);
- double t1, t2, r;
- t1 = ((x2-x1)*costh - (y2-y1)*sinth);
- t2 = ((x2-x1)*sinth + (y2-y1)*costh);
- r = sqrt(t1*t1 + t2*t2);
- double advancex = size*t1/r;
- double advancey = size*t2/r;
- this->line(x2, y2, int(x2 + advancex), int(y2 + advancey), red, green, blue);
- t1 = (x2-x1)*costh + (y2-y1)*sinth;
- t2 = (y2-y1)*costh - (x2-x1)*sinth;
- advancex = size*t1/r;
- advancey = size*t2/r;
- this->line(x2, y2, int(x2 + advancex), int(y2 + advancey), red, green, blue);
- }
- void pngwriter::filledarrow( int x1,int y1,int x2,int y2,int size, double head_angle, double red, double green, double blue)
- {
- int p1x, p2x, p3x, p1y, p2y, p3y;
- this->line(x1, y1, x2, y2, red, green, blue);
- double th = 3.141592653589793 + head_angle;
- double costh = cos(th);
- double sinth = sin(th);
- double t11, t12, t21, t22, r1, r2;
- t11 = ((x2-x1)*costh - (y2-y1)*sinth);
- t21 = ((x2-x1)*sinth + (y2-y1)*costh);
- t12 = (x2-x1)*costh + (y2-y1)*sinth;
- t22 = (y2-y1)*costh - (x2-x1)*sinth;
- r1 = sqrt(t11*t11 + t21*t21);
- r2 = sqrt(t12*t12 + t22*t22);
- double advancex1 = size*t11/r1;
- double advancey1 = size*t21/r1;
- double advancex2 = size*t12/r2;
- double advancey2 = size*t22/r2;
- p1x = x2;
- p1y = y2;
- p2x = int(x2 + advancex1);
- p2y = int(y2 + advancey1);
- p3x = int(x2 + advancex2);
- p3y = int(y2 + advancey2);
- this->filledtriangle( p1x, p1y, p2x, p2y, p3x, p3y, red, green, blue);
- }
- void pngwriter::arrow( int x1,int y1,int x2,int y2,int size, double head_angle, int red, int green, int blue)
- {
- this->arrow( x1, y1, x2, y2, size, head_angle, (double (red))/65535.0, (double (green))/65535.0, (double (blue))/65535.0 );
- }
- void pngwriter::filledarrow( int x1,int y1,int x2,int y2,int size, double head_angle, int red, int green, int blue)
- {
- this->filledarrow( x1, y1, x2, y2, size, head_angle, (double (red))/65535.0, (double (green))/65535.0, (double (blue))/65535.0 );
- }
- void pngwriter::cross( int x, int y, int xwidth, int yheight, int red, int green, int blue)
- {
- this->line(int(x - xwidth/2.0), y, int(x + xwidth/2.0), y, red, green, blue);
- this->line(x, int(y - yheight/2.0), x, int(y + yheight/2.0), red, green, blue);
- }
- void pngwriter::maltesecross( int x, int y, int xwidth, int yheight, int x_bar_height, int y_bar_width, int red, int green, int blue)
- {
- this->line(int(x - xwidth/2.0), y, int(x + xwidth/2.0), y, red, green, blue);
- this->line(x, int(y - yheight/2.0), x, int(y + yheight/2.0), red, green, blue);
- // Bars on ends of vertical line
- this->line(int(x - y_bar_width/2.0), int(y + yheight/2.0), int(x + y_bar_width/2.0), int(y + yheight/2.0), red, green, blue);
- this->line(int(x - y_bar_width/2.0), int(y - yheight/2.0), int(x + y_bar_width/2.0), int(y - yheight/2.0), red, green, blue);
- // Bars on ends of horizontal line.
- this->line(int(x - xwidth/2.0), int(y - x_bar_height/2.0), int(x - xwidth/2.0), int(y + x_bar_height/2.0), red, green, blue);
- this->line(int(x + xwidth/2.0), int(y - x_bar_height/2.0), int(x + xwidth/2.0), int(y + x_bar_height/2.0), red, green, blue);
- }
- void pngwriter::cross( int x, int y, int xwidth, int yheight, double red, double green, double blue)
- {
- this->cross( x, y, xwidth, yheight, int(65535*red), int(65535*green), int(65535*blue));
- }
- void pngwriter::maltesecross( int x, int y, int xwidth, int yheight, int x_bar_height, int y_bar_width, double red, double green, double blue)
- {
- this->maltesecross( x, y, xwidth, yheight, x_bar_height, y_bar_width, int(65535*red), int(65535*green), int(65535*blue));
- }
- void pngwriter::filleddiamond( int x, int y, int width, int height, int red, int green, int blue)
- {
- this->filledtriangle( int(x - width/2.0), y, x, y, x, int(y + height/2.0), red, green, blue);
- this->filledtriangle( int(x + width/2.0), y, x, y, x, int(y + height/2.0), red, green, blue);
- this->filledtriangle( int(x - width/2.0), y, x, y, x, int(y - height/2.0), red, green, blue);
- this->filledtriangle( int(x + width/2.0), y, x, y, x, int(y - height/2.0), red, green, blue);
- }
- void pngwriter::diamond( int x, int y, int width, int height, int red, int green, int blue)
- {
- this->line( int(x - width/2.0), y, x, int(y + height/2.0), red, green, blue);
- this->line( int(x + width/2.0), y, x, int(y + height/2.0), red, green, blue);
- this->line( int(x - width/2.0), y, x, int(y - height/2.0), red, green, blue);
- this->line( int(x + width/2.0), y, x, int(y - height/2.0), red, green, blue);
- }
- void pngwriter::filleddiamond( int x, int y, int width, int height, double red, double green, double blue)
- {
- this->filleddiamond( x, y, width, height, int(red*65535), int(green*65535), int(blue*65535) );
- }
- void pngwriter::diamond( int x, int y, int width, int height, double red, double green, double blue)
- {
- this->diamond( x, y, width, height, int(red*65535), int(green*65535), int(blue*65535) );
- }
|