| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605 |
- /********************************* 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(const char *face_path)
- {
- std::string err;
- pngwriterfont(face_path, err);
- }
- 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(face_path);
- 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)
- {
- pngwriterfont font(face_path);
- plot_text(font, fontsize, x_start, y_start, angle, text, red, green, blue);
- }
- void pngwriter::plot_text_utf8(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_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;
- */
- /* 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(), ucs4text[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_utf8 - ERROR **: FreeType: Set char size error." << std::endl;
- delete[] ucs4text;
- return;
- }
- /* Retrieve glyph index from character code */
- glyph_index = FT_Get_Char_Index(font.getFontFace(), ucs4text[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_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(font.getFontFace()->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;
- }
- 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::plot_text_utf8(pngwriterfont& font, int fontsize, int x_start, int y_start, double angle, char * text, int red, int green, int blue)
- {
- plot_text_utf8(font, 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(fontPath);
- 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)
- {
- pngwriterfont font(font);
- return get_text_width_utf8(font, fontsize, text);
- }
- int pngwriter::get_text_width_utf8(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)( 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;
- */
- /* 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(), ucs4text[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_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(font.getFontFace(), ucs4text[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_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(font.getFontFace()->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;
- }
- 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) );
- }
|