pngwriter.cc (139365B)
1 //********** pngwriter.cc ********************************************** 2 // Author: Paul Blackburn 3 // 4 // Email: individual61@users.sourceforge.net 5 // 6 // Version: 0.5.4 (19 / II / 2009) 7 // 8 // Description: Library that allows plotting a 48 bit 9 // PNG image pixel by pixel, which can 10 // then be opened with a graphics program. 11 // 12 // License: GNU General Public License 13 // Copyright 2002, 2003, 2004, 2005, 2006, 2007, 14 // 2008, 2009 Paul Blackburn 15 // 16 // Website: Main: http://pngwriter.sourceforge.net/ 17 // Sourceforge.net: http://sourceforge.net/projects/pngwriter/ 18 // Freshmeat.net: http://freshmeat.net/projects/pngwriter/ 19 // 20 // Documentation: The header file (pngwriter.h) is commented, but for a 21 // quick reference document, and support, 22 // take a look at the website. 23 // 24 //************************************************************************* 25 26 /* 27 * This program is free software; you can redistribute it and/or modify 28 * it under the terms of the GNU General Public License as published by 29 * the Free Software Foundation; either version 2 of the License, or 30 * (at your option) any later version. 31 * 32 * This program is distributed in the hope that it will be useful, 33 * but WITHOUT ANY WARRANTY; without even the implied warranty of 34 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 35 * GNU General Public License for more details. 36 * 37 * You should have received a copy of the GNU General Public License 38 * along with this program; if not, write to the Free Software 39 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 40 * 41 * */ 42 43 #include "pngwriter.h" 44 45 // Default Constructor 46 //////////////////////////////////////////////////////////////////////////// 47 pngwriter::pngwriter() 48 { 49 50 filename_ = new char[255]; 51 textauthor_ = new char[255]; 52 textdescription_ = new char[255]; 53 texttitle_ = new char[255]; 54 textsoftware_ = new char[255]; 55 56 strcpy(filename_, "out.png"); 57 width_ = 250; 58 height_ = 250; 59 backgroundcolour_ = 65535; 60 compressionlevel_ = -2; 61 filegamma_ = 0.5; 62 transformation_ = 0; 63 64 strcpy(textauthor_, "PNGwriter Author: Paul Blackburn"); 65 strcpy(textdescription_, "http://pngwriter.sourceforge.net/"); 66 strcpy(textsoftware_, "PNGwriter: An easy to use graphics library."); 67 strcpy(texttitle_, "out.png"); 68 69 int kkkk; 70 71 bit_depth_ = 16; //Default bit depth for new images 72 colortype_=2; 73 screengamma_ = 2.2; 74 75 graph_ = (png_bytepp)malloc(height_ * sizeof(png_bytep)); 76 if(graph_ == NULL) 77 { 78 std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl; 79 } 80 81 for (kkkk = 0; kkkk < height_; kkkk++) 82 { 83 graph_[kkkk] = (png_bytep)malloc(6*width_ * sizeof(png_byte)); 84 if(graph_[kkkk] == NULL) 85 { 86 std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl; 87 } 88 } 89 90 if(graph_ == NULL) 91 { 92 std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl; 93 } 94 95 int tempindex; 96 for(int hhh = 0; hhh<width_;hhh++) 97 { 98 for(int vhhh = 0; vhhh<height_;vhhh++) 99 { 100 //graph_[vhhh][6*hhh + i] where i goes from 0 to 5 101 tempindex = 6*hhh; 102 graph_[vhhh][tempindex] = (char) floor(((double)backgroundcolour_)/256); 103 graph_[vhhh][tempindex+1] = (char)(backgroundcolour_%256); 104 graph_[vhhh][tempindex+2] = (char) floor(((double)backgroundcolour_)/256); 105 graph_[vhhh][tempindex+3] = (char)(backgroundcolour_%256); 106 graph_[vhhh][tempindex+4] = (char) floor(((double)backgroundcolour_)/256); 107 graph_[vhhh][tempindex+5] = (char)(backgroundcolour_%256); 108 } 109 } 110 111 }; 112 113 //Copy Constructor 114 ////////////////////////////////////////////////////////////////////////// 115 pngwriter::pngwriter(const pngwriter &rhs) 116 { 117 width_ = rhs.width_; 118 height_ = rhs.height_; 119 backgroundcolour_ = rhs.backgroundcolour_; 120 compressionlevel_ = rhs.compressionlevel_; 121 filegamma_ = rhs.filegamma_; 122 transformation_ = rhs.transformation_;; 123 124 filename_ = new char[strlen(rhs.filename_)+1]; 125 textauthor_ = new char[strlen(rhs.textauthor_)+1]; 126 textdescription_ = new char[strlen(rhs.textdescription_)+1]; 127 textsoftware_ = new char[strlen(rhs.textsoftware_)+1]; 128 texttitle_ = new char[strlen(rhs.texttitle_)+1]; 129 130 strcpy(filename_, rhs.filename_); 131 strcpy(textauthor_, rhs.textauthor_); 132 strcpy(textdescription_, rhs.textdescription_); 133 strcpy(textsoftware_,rhs.textsoftware_); 134 strcpy(texttitle_, rhs.texttitle_); 135 136 int kkkk; 137 138 bit_depth_ = rhs.bit_depth_; 139 colortype_= rhs.colortype_; 140 screengamma_ = rhs.screengamma_; 141 142 graph_ = (png_bytepp)malloc(height_ * sizeof(png_bytep)); 143 if(graph_ == NULL) 144 { 145 std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl; 146 } 147 148 for (kkkk = 0; kkkk < height_; kkkk++) 149 { 150 graph_[kkkk] = (png_bytep)malloc(6*width_ * sizeof(png_byte)); 151 if(graph_[kkkk] == NULL) 152 { 153 std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl; 154 } 155 } 156 157 if(graph_ == NULL) 158 { 159 std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl; 160 } 161 int tempindex; 162 for(int hhh = 0; hhh<width_;hhh++) 163 { 164 for(int vhhh = 0; vhhh<height_;vhhh++) 165 { 166 // graph_[vhhh][6*hhh + i ] i=0 to 5 167 tempindex=6*hhh; 168 graph_[vhhh][tempindex] = rhs.graph_[vhhh][tempindex]; 169 graph_[vhhh][tempindex+1] = rhs.graph_[vhhh][tempindex+1]; 170 graph_[vhhh][tempindex+2] = rhs.graph_[vhhh][tempindex+2]; 171 graph_[vhhh][tempindex+3] = rhs.graph_[vhhh][tempindex+3]; 172 graph_[vhhh][tempindex+4] = rhs.graph_[vhhh][tempindex+4]; 173 graph_[vhhh][tempindex+5] = rhs.graph_[vhhh][tempindex+5]; 174 } 175 } 176 177 }; 178 179 //Constructor for int colour levels, char * filename 180 ////////////////////////////////////////////////////////////////////////// 181 pngwriter::pngwriter(int x, int y, int backgroundcolour, char * filename) 182 { 183 width_ = x; 184 height_ = y; 185 backgroundcolour_ = backgroundcolour; 186 compressionlevel_ = -2; 187 filegamma_ = 0.6; 188 transformation_ = 0; 189 190 textauthor_ = new char[255]; 191 textdescription_ = new char[255]; 192 texttitle_ = new char[strlen(filename)+1]; 193 textsoftware_ = new char[255]; 194 filename_ = new char[strlen(filename)+1]; 195 196 strcpy(textauthor_, "PNGwriter Author: Paul Blackburn"); 197 strcpy(textdescription_, "http://pngwriter.sourceforge.net/"); 198 strcpy(textsoftware_, "PNGwriter: An easy to use graphics library."); 199 strcpy(texttitle_, filename); 200 strcpy(filename_, filename); 201 202 if((width_<0)||(height_<0)) 203 { 204 std::cerr << " PNGwriter::pngwriter - ERROR **: Constructor called with negative height or width. Setting width and height to 1." << std::endl; 205 width_ = 1; 206 height_ = 1; 207 } 208 209 if(backgroundcolour_ >65535) 210 { 211 std::cerr << " PNGwriter::pngwriter - WARNING **: Constructor called with background colour greater than 65535. Setting to 65535."<<std::endl; 212 backgroundcolour_ = 65535; 213 } 214 215 if(backgroundcolour_ <0) 216 { 217 std::cerr << " PNGwriter::pngwriter - WARNING **: Constructor called with background colour lower than 0. Setting to 0."<<std::endl; 218 backgroundcolour_ = 0; 219 } 220 221 int kkkk; 222 223 bit_depth_ = 16; //Default bit depth for new images 224 colortype_=2; 225 screengamma_ = 2.2; 226 227 graph_ = (png_bytepp)malloc(height_ * sizeof(png_bytep)); 228 if(graph_ == NULL) 229 { 230 std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl; 231 } 232 233 for (kkkk = 0; kkkk < height_; kkkk++) 234 { 235 graph_[kkkk] = (png_bytep)malloc(6*width_ * sizeof(png_byte)); 236 if(graph_[kkkk] == NULL) 237 { 238 std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl; 239 } 240 } 241 242 if(graph_ == NULL) 243 { 244 std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl; 245 } 246 247 int tempindex; 248 for(int hhh = 0; hhh<width_;hhh++) 249 { 250 for(int vhhh = 0; vhhh<height_;vhhh++) 251 { 252 //graph_[vhhh][6*hhh + i] i = 0 to 5 253 tempindex = 6*hhh; 254 graph_[vhhh][tempindex] = (char) floor(((double)backgroundcolour_)/256); 255 graph_[vhhh][tempindex+1] = (char)(backgroundcolour_%256); 256 graph_[vhhh][tempindex+2] = (char) floor(((double)backgroundcolour_)/256); 257 graph_[vhhh][tempindex+3] = (char)(backgroundcolour_%256); 258 graph_[vhhh][tempindex+4] = (char) floor(((double)backgroundcolour_)/256); 259 graph_[vhhh][tempindex+5] = (char)(backgroundcolour_%256); 260 } 261 } 262 263 }; 264 265 //Constructor for double levels, char * filename 266 ///////////////////////////////////////////////////////////////////////// 267 pngwriter::pngwriter(int x, int y, double backgroundcolour, char * filename) 268 { 269 width_ = x; 270 height_ = y; 271 compressionlevel_ = -2; 272 filegamma_ = 0.6; 273 transformation_ = 0; 274 backgroundcolour_ = int(backgroundcolour*65535); 275 276 textauthor_ = new char[255]; 277 textdescription_ = new char[255]; 278 texttitle_ = new char[strlen(filename)+1]; 279 textsoftware_ = new char[255]; 280 filename_ = new char[strlen(filename)+1]; 281 282 strcpy(textauthor_, "PNGwriter Author: Paul Blackburn"); 283 strcpy(textdescription_, "http://pngwriter.sourceforge.net/"); 284 strcpy(textsoftware_, "PNGwriter: An easy to use graphics library."); 285 strcpy(texttitle_, filename); 286 strcpy(filename_, filename); 287 288 if((width_<0)||(height_<0)) 289 { 290 std::cerr << " PNGwriter::pngwriter - ERROR **: Constructor called with negative height or width. Setting width and height to 1." << std::endl; 291 width_ = 1; 292 height_ = 1; 293 } 294 295 if(backgroundcolour_ >65535) 296 { 297 std::cerr << " PNGwriter::pngwriter - WARNING **: Constructor called with background colour greater than 1.0. Setting to 1.0."<<std::endl; 298 backgroundcolour_ = 65535; 299 } 300 301 if(backgroundcolour_ < 0) 302 { 303 std::cerr << " PNGwriter::pngwriter - WARNING **: Constructor called with background colour lower than 0.0. Setting to 0.0."<<std::endl; 304 backgroundcolour_ = 0; 305 } 306 307 int kkkk; 308 309 bit_depth_ = 16; //Default bit depth for new images 310 colortype_=2; 311 screengamma_ = 2.2; 312 313 graph_ = (png_bytepp)malloc(height_ * sizeof(png_bytep)); 314 if(graph_ == NULL) 315 { 316 std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl; 317 } 318 319 for (kkkk = 0; kkkk < height_; kkkk++) 320 { 321 graph_[kkkk] = (png_bytep)malloc(6*width_ * sizeof(png_byte)); 322 if(graph_[kkkk] == NULL) 323 { 324 std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl; 325 } 326 } 327 328 if(graph_ == NULL) 329 { 330 std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl; 331 } 332 333 int tempindex; 334 for(int hhh = 0; hhh<width_;hhh++) 335 { 336 for(int vhhh = 0; vhhh<height_;vhhh++) 337 { 338 // graph_[vhhh][tempindex + i] where i = 0 to 5 339 tempindex = 6*hhh; 340 graph_[vhhh][tempindex] = (char) floor(((double)backgroundcolour_)/256); 341 graph_[vhhh][tempindex+1] = (char)(backgroundcolour_%256); 342 graph_[vhhh][tempindex+2] = (char) floor(((double)backgroundcolour_)/256); 343 graph_[vhhh][tempindex+3] = (char)(backgroundcolour_%256); 344 graph_[vhhh][tempindex+4] = (char) floor(((double)backgroundcolour_)/256); 345 graph_[vhhh][tempindex+5] = (char)(backgroundcolour_%256); 346 } 347 } 348 349 }; 350 351 //Destructor 352 /////////////////////////////////////// 353 pngwriter::~pngwriter() 354 { 355 delete [] filename_; 356 delete [] textauthor_; 357 delete [] textdescription_; 358 delete [] texttitle_; 359 delete [] textsoftware_; 360 361 for (int jjj = 0; jjj < height_; jjj++) free(graph_[jjj]); 362 free(graph_); 363 }; 364 365 //Constructor for int levels, const char * filename 366 ////////////////////////////////////////////////////////////// 367 pngwriter::pngwriter(int x, int y, int backgroundcolour, const char * filename) 368 { 369 width_ = x; 370 height_ = y; 371 backgroundcolour_ = backgroundcolour; 372 compressionlevel_ = -2; 373 filegamma_ = 0.6; 374 transformation_ = 0; 375 376 textauthor_ = new char[255]; 377 textdescription_ = new char[255]; 378 texttitle_ = new char[strlen(filename)+1]; 379 textsoftware_ = new char[255]; 380 filename_ = new char[strlen(filename)+1]; 381 382 strcpy(textauthor_, "PNGwriter Author: Paul Blackburn"); 383 strcpy(textdescription_, "http://pngwriter.sourceforge.net/"); 384 strcpy(textsoftware_, "PNGwriter: An easy to use graphics library."); 385 strcpy(texttitle_, filename); 386 strcpy(filename_, filename); 387 388 if((width_<0)||(height_<0)) 389 { 390 std::cerr << " PNGwriter::pngwriter - ERROR **: Constructor called with negative height or width. Setting width and height to 1." << std::endl; 391 height_ = 1; 392 width_ = 1; 393 } 394 395 if(backgroundcolour_ >65535) 396 { 397 std::cerr << " PNGwriter::pngwriter - WARNING **: Constructor called with background colour greater than 65535. Setting to 65535."<<std::endl; 398 backgroundcolour_ = 65535; 399 } 400 401 if(backgroundcolour_ <0) 402 { 403 std::cerr << " PNGwriter::pngwriter - WARNING **: Constructor called with background colour lower than 0. Setting to 0."<<std::endl; 404 backgroundcolour_ = 0; 405 } 406 407 int kkkk; 408 409 bit_depth_ = 16; //Default bit depth for new images 410 colortype_=2; 411 screengamma_ = 2.2; 412 413 graph_ = (png_bytepp)malloc(height_ * sizeof(png_bytep)); 414 if(graph_ == NULL) 415 { 416 std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl; 417 } 418 419 for (kkkk = 0; kkkk < height_; kkkk++) 420 { 421 graph_[kkkk] = (png_bytep)malloc(6*width_ * sizeof(png_byte)); 422 if(graph_[kkkk] == NULL) 423 { 424 std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl; 425 } 426 } 427 428 if(graph_ == NULL) 429 { 430 std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl; 431 } 432 433 int tempindex; 434 for(int hhh = 0; hhh<width_;hhh++) 435 { 436 for(int vhhh = 0; vhhh<height_;vhhh++) 437 { 438 //graph_[vhhh][6*hhh + i] where i = 0 to 5 439 tempindex=6*hhh; 440 graph_[vhhh][tempindex] = (char) floor(((double)backgroundcolour_)/256); 441 graph_[vhhh][tempindex+1] = (char)(backgroundcolour_%256); 442 graph_[vhhh][tempindex+2] = (char) floor(((double)backgroundcolour_)/256); 443 graph_[vhhh][tempindex+3] = (char)(backgroundcolour_%256); 444 graph_[vhhh][tempindex+4] = (char) floor(((double)backgroundcolour_)/256); 445 graph_[vhhh][tempindex+5] = (char)(backgroundcolour_%256); 446 } 447 } 448 449 }; 450 451 //Constructor for double levels, const char * filename 452 ///////////////////////////////////////////////////////////////////////// 453 pngwriter::pngwriter(int x, int y, double backgroundcolour, const char * filename) 454 { 455 width_ = x; 456 height_ = y; 457 compressionlevel_ = -2; 458 backgroundcolour_ = int(backgroundcolour*65535); 459 filegamma_ = 0.6; 460 transformation_ = 0; 461 462 textauthor_ = new char[255]; 463 textdescription_ = new char[255]; 464 texttitle_ = new char[strlen(filename)+1]; 465 textsoftware_ = new char[255]; 466 filename_ = new char[strlen(filename)+1]; 467 468 strcpy(textauthor_, "PNGwriter Author: Paul Blackburn"); 469 strcpy(textdescription_, "http://pngwriter.sourceforge.net/"); 470 strcpy(textsoftware_, "PNGwriter: An easy to use graphics library."); 471 strcpy(texttitle_, filename); 472 strcpy(filename_, filename); 473 474 if((width_<0)||(height_<0)) 475 { 476 std::cerr << " PNGwriter::pngwriter - ERROR **: Constructor called with negative height or width. Setting width and height to 1." << std::endl; 477 width_ = 1; 478 height_ = 1; 479 } 480 481 if(backgroundcolour_ >65535) 482 { 483 std::cerr << " PNGwriter::pngwriter - WARNING **: Constructor called with background colour greater than 65535. Setting to 65535."<<std::endl; 484 backgroundcolour_ = 65535; 485 } 486 487 if(backgroundcolour_ <0) 488 { 489 std::cerr << " PNGwriter::pngwriter - WARNING **: Constructor called with background colour lower than 0. Setting to 0."<<std::endl; 490 backgroundcolour_ = 0; 491 } 492 493 int kkkk; 494 495 bit_depth_ = 16; //Default bit depth for new images 496 colortype_=2; 497 screengamma_ = 2.2; 498 499 graph_ = (png_bytepp)malloc(height_ * sizeof(png_bytep)); 500 if(graph_ == NULL) 501 { 502 std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl; 503 } 504 505 for (kkkk = 0; kkkk < height_; kkkk++) 506 { 507 graph_[kkkk] = (png_bytep)malloc(6*width_ * sizeof(png_byte)); 508 if(graph_[kkkk] == NULL) 509 { 510 std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl; 511 } 512 } 513 514 if(graph_ == NULL) 515 { 516 std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl; 517 } 518 519 int tempindex; 520 for(int hhh = 0; hhh<width_;hhh++) 521 { 522 for(int vhhh = 0; vhhh<height_;vhhh++) 523 { 524 //etc 525 tempindex = 6*hhh; 526 graph_[vhhh][tempindex] = (char) floor(((double)backgroundcolour_)/256); 527 graph_[vhhh][tempindex+1] = (char)(backgroundcolour_%256); 528 graph_[vhhh][tempindex+2] = (char) floor(((double)backgroundcolour_)/256); 529 graph_[vhhh][tempindex+3] = (char)(backgroundcolour_%256); 530 graph_[vhhh][tempindex+4] = (char) floor(((double)backgroundcolour_)/256); 531 graph_[vhhh][tempindex+5] = (char)(backgroundcolour_%256); 532 } 533 } 534 535 }; 536 537 // Overloading operator = 538 ///////////////////////////////////////////////////////// 539 pngwriter & pngwriter::operator = (const pngwriter & rhs) 540 { 541 if( this==&rhs) 542 { 543 return *this; 544 } 545 546 width_ = rhs.width_; 547 height_ = rhs.height_; 548 backgroundcolour_ = rhs.backgroundcolour_; 549 compressionlevel_ = rhs.compressionlevel_; 550 filegamma_ = rhs.filegamma_; 551 transformation_ = rhs.transformation_; 552 553 filename_ = new char[strlen(rhs.filename_)+1]; 554 textauthor_ = new char[strlen(rhs.textauthor_)+1]; 555 textdescription_ = new char[strlen(rhs.textdescription_)+1]; 556 textsoftware_ = new char[strlen(rhs.textsoftware_)+1]; 557 texttitle_ = new char[strlen(rhs.texttitle_)+1]; 558 559 strcpy(textauthor_, rhs.textauthor_); 560 strcpy(textdescription_, rhs.textdescription_); 561 strcpy(textsoftware_,rhs.textsoftware_); 562 strcpy(texttitle_, rhs.texttitle_); 563 strcpy(filename_, rhs.filename_); 564 565 int kkkk; 566 567 bit_depth_ = rhs.bit_depth_; 568 colortype_= rhs.colortype_; 569 screengamma_ = rhs.screengamma_; 570 571 graph_ = (png_bytepp)malloc(height_ * sizeof(png_bytep)); 572 if(graph_ == NULL) 573 { 574 std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl; 575 } 576 577 for (kkkk = 0; kkkk < height_; kkkk++) 578 { 579 graph_[kkkk] = (png_bytep)malloc(6*width_ * sizeof(png_byte)); 580 if(graph_[kkkk] == NULL) 581 { 582 std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl; 583 } 584 } 585 586 if(graph_ == NULL) 587 { 588 std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl; 589 } 590 591 int tempindex; 592 for(int hhh = 0; hhh<width_;hhh++) 593 { 594 for(int vhhh = 0; vhhh<height_;vhhh++) 595 { 596 tempindex=6*hhh; 597 graph_[vhhh][tempindex] = rhs.graph_[vhhh][tempindex]; 598 graph_[vhhh][tempindex+1] = rhs.graph_[vhhh][tempindex+1]; 599 graph_[vhhh][tempindex+2] = rhs.graph_[vhhh][tempindex+2]; 600 graph_[vhhh][tempindex+3] = rhs.graph_[vhhh][tempindex+3]; 601 graph_[vhhh][tempindex+4] = rhs.graph_[vhhh][tempindex+4]; 602 graph_[vhhh][tempindex+5] = rhs.graph_[vhhh][tempindex+5]; 603 } 604 } 605 606 return *this; 607 } 608 609 /////////////////////////////////////////////////////////////// 610 void pngwriter::plot(int x, int y, int red, int green, int blue) 611 { 612 int tempindex; 613 614 if(red > 65535) 615 { 616 red = 65535; 617 } 618 if(green > 65535) 619 { 620 green = 65535; 621 } 622 if(blue > 65535) 623 { 624 blue = 65535; 625 } 626 627 if(red < 0) 628 { 629 red = 0; 630 } 631 if(green < 0) 632 { 633 green = 0; 634 } 635 if(blue < 0) 636 { 637 blue = 0; 638 } 639 640 if((bit_depth_ == 16)) 641 { 642 // if( (height_-y >-1) && (height_-y <height_) && (6*(x-1) >-1) && (6*(x-1)+5<6*width_) ) 643 if( (y<=height_) && (y>0) && (x>0) && (x<=width_) ) 644 { 645 //graph_[height_-y][6*(x-1) + i] where i goes from 0 to 5 646 tempindex= 6*x-6; 647 graph_[height_-y][tempindex] = (char) floor(((double)red)/256); 648 graph_[height_-y][tempindex+1] = (char)(red%256); 649 graph_[height_-y][tempindex+2] = (char) floor(((double)green)/256); 650 graph_[height_-y][tempindex+3] = (char)(green%256); 651 graph_[height_-y][tempindex+4] = (char) floor(((double)blue)/256); 652 graph_[height_-y][tempindex+5] = (char)(blue%256); 653 }; 654 655 /* 656 if(!( (height_-y >-1) && (height_-y <height_) && (6*(x-1) >-1) && (6*(x-1)+5<6*width_) )) 657 { 658 std::cerr << " PNGwriter::plot-- Plotting out of range! " << y << " " << x << std::endl; 659 } 660 */ 661 } 662 663 if((bit_depth_ == 8)) 664 { 665 // if( (height_-y >-1) && (height_-y <height_) && (3*(x-1) >-1) && (3*(x-1)+5<3*width_) ) 666 if( (y<height_+1) && (y>0) && (x>0) && (x<width_+1) ) 667 { 668 // graph_[height_-y][3*(x-1) + i] where i goes from 0 to 2 669 tempindex = 3*x-3; 670 graph_[height_-y][tempindex] = (char)(floor(((double)red)/257.0)); 671 graph_[height_-y][tempindex+1] = (char)(floor(((double)green)/257.0)); 672 graph_[height_-y][tempindex+2] = (char)(floor(((double)blue)/257.0)); 673 674 }; 675 676 /* 677 if(!( (height_-y >-1) && (height_-y <height_) && (6*(x-1) >-1) && (6*(x-1)+5<6*width_) )) 678 { 679 std::cerr << " PNGwriter::plot-- Plotting out of range! " << y << " " << x << std::endl; 680 } 681 */ 682 } 683 }; 684 685 void pngwriter::plot(int x, int y, double red, double green, double blue) 686 { 687 this->plot(x,y,int(red*65535),int(green*65535),int(blue*65535)); 688 }; 689 690 /////////////////////////////////////////////////////////////// 691 int pngwriter::read(int x, int y, int colour) 692 { 693 int temp1,temp2; 694 695 if((colour !=1)&&(colour !=2)&&(colour !=3)) 696 { 697 std::cerr << " PNGwriter::read - WARNING **: Invalid argument: should be 1, 2 or 3, is " << colour << std::endl; 698 return 0; 699 } 700 701 if( ( x>0 ) && ( x <= (this->width_) ) && ( y>0 ) && ( y <= (this->height_) ) ) 702 { 703 704 if(bit_depth_ == 16) 705 { 706 temp2=6*(x-1); 707 if(colour == 1) 708 { 709 temp1 = (graph_[(height_-y)][temp2])*256 + graph_[height_-y][temp2+1]; 710 return temp1; 711 } 712 713 if(colour == 2) 714 { 715 temp1 = (graph_[height_-y][temp2+2])*256 + graph_[height_-y][temp2+3]; 716 return temp1; 717 } 718 719 if(colour == 3) 720 { 721 temp1 = (graph_[height_-y][temp2+4])*256 + graph_[height_-y][temp2+5]; 722 return temp1; 723 } 724 } 725 726 if(bit_depth_ == 8) 727 { 728 temp2=3*(x-1); 729 if(colour == 1) 730 { 731 temp1 = graph_[height_-y][temp2]; 732 return temp1*256; 733 } 734 735 if(colour == 2) 736 { 737 temp1 = graph_[height_-y][temp2+1]; 738 return temp1*256; 739 } 740 741 if(colour == 3) 742 { 743 temp1 = graph_[height_-y][temp2+2]; 744 return temp1*256; 745 } 746 } 747 } 748 else 749 { 750 return 0; 751 } 752 753 std::cerr << " PNGwriter::read - WARNING **: Returning 0 because of bitdepth/colour type mismatch."<< std::endl; 754 return 0; 755 } 756 757 /////////////////////////////////////////////////////////////// 758 int pngwriter::read(int xxx, int yyy) 759 { 760 int temp1,temp2,temp3,temp4,temp5; 761 762 if( 763 ( xxx>0 ) && 764 ( xxx <= (this->width_) ) && 765 ( yyy>0 ) && 766 ( yyy <= (this->height_) ) 767 ) 768 { 769 if(bit_depth_ == 16) 770 { 771 // temp1 = (graph_[(height_-yyy)][6*(xxx-1)])*256 + graph_[height_-yyy][6*(xxx-1)+1]; 772 temp5=6*xxx; 773 temp1 = (graph_[(height_-yyy)][temp5-6])*256 + graph_[height_-yyy][temp5-5]; 774 temp2 = (graph_[height_-yyy][temp5-4])*256 + graph_[height_-yyy][temp5-3]; 775 temp3 = (graph_[height_-yyy][temp5-2])*256 + graph_[height_-yyy][temp5-1]; 776 temp4 = int((temp1+temp2+temp3)/3.0); 777 } 778 else if(bit_depth_ == 8) 779 { 780 // temp1 = graph_[height_-yyy][3*(xxx-1)]; 781 temp5 = 3*xxx; 782 temp1 = graph_[height_-yyy][temp5-3]; 783 temp2 = graph_[height_-yyy][temp5-2]; 784 temp3 = graph_[height_-yyy][temp5-1]; 785 temp4 = int((temp1+temp2+temp3)/3.0); 786 } 787 else 788 { 789 std::cerr << " PNGwriter::read - WARNING **: Invalid bit depth! Returning 0 as average value." << std::endl; 790 temp4 = 0; 791 } 792 793 return temp4; 794 795 } 796 else 797 { 798 return 0; 799 } 800 } 801 802 ///////////////////////////////////////////////////// 803 double pngwriter::dread(int x, int y, int colour) 804 { 805 return double(this->read(x,y,colour))/65535.0; 806 } 807 808 double pngwriter::dread(int x, int y) 809 { 810 return double(this->read(x,y))/65535.0; 811 } 812 813 /////////////////////////////////////////////////////// 814 void pngwriter::clear() 815 { 816 int pen = 0; 817 int pencil = 0; 818 int tempindex; 819 820 if(bit_depth_==16) 821 { 822 for(pen = 0; pen<width_;pen++) 823 { 824 for(pencil = 0; pencil<height_;pencil++) 825 { 826 tempindex=6*pen; 827 graph_[pencil][tempindex] = 0; 828 graph_[pencil][tempindex+1] = 0; 829 graph_[pencil][tempindex+2] = 0; 830 graph_[pencil][tempindex+3] = 0; 831 graph_[pencil][tempindex+4] = 0; 832 graph_[pencil][tempindex+5] = 0; 833 } 834 } 835 } 836 837 if(bit_depth_==8) 838 { 839 for(pen = 0; pen<width_;pen++) 840 { 841 for(pencil = 0; pencil<height_;pencil++) 842 { 843 tempindex=3*pen; 844 graph_[pencil][tempindex] = 0; 845 graph_[pencil][tempindex+1] = 0; 846 graph_[pencil][tempindex+2] = 0; 847 } 848 } 849 } 850 851 }; 852 853 ///////////////////////////////////////////////////// 854 void pngwriter::pngwriter_rename(char * newname) 855 { 856 delete [] filename_; 857 delete [] texttitle_; 858 859 filename_ = new char[strlen(newname)+1]; 860 texttitle_ = new char[strlen(newname)+1]; 861 862 strcpy(filename_,newname); 863 strcpy(texttitle_,newname); 864 }; 865 866 /////////////////////////////////////////////////////// 867 void pngwriter::pngwriter_rename(const char * newname) 868 { 869 delete [] filename_; 870 delete [] texttitle_; 871 872 filename_ = new char[strlen(newname)+1]; 873 texttitle_ = new char[strlen(newname)+1]; 874 875 strcpy(filename_,newname); 876 strcpy(texttitle_,newname); 877 }; 878 879 /////////////////////////////////////////////////////// 880 void pngwriter::pngwriter_rename(long unsigned int index) 881 { 882 char buffer[255]; 883 884 // %[flags][width][.precision][modifiers]type 885 // 886 if((index > 999999999)||(index < 0)) 887 { 888 std::cerr << " PNGwriter::pngwriter_rename - ERROR **: Numerical name is out of 0 - 999 999 999 range (" << index <<")." << std::endl; 889 return; 890 } 891 892 if( 0> sprintf(buffer, "%9.9lu.png",index)) 893 { 894 std::cerr << " PNGwriter::pngwriter_rename - ERROR **: Error creating numerical filename." << std::endl; 895 return; 896 } 897 898 delete [] filename_; 899 delete [] texttitle_; 900 901 filename_ = new char[strlen(buffer)+1]; 902 texttitle_ = new char[strlen(buffer)+1]; 903 904 strcpy(filename_,buffer); 905 strcpy(texttitle_,buffer); 906 907 }; 908 909 /////////////////////////////////////////////////////// 910 void pngwriter::settext(char * title, char * author, char * description, char * software) 911 { 912 delete [] textauthor_; 913 delete [] textdescription_; 914 delete [] texttitle_; 915 delete [] textsoftware_; 916 917 textauthor_ = new char[strlen(author)+1]; 918 textdescription_ = new char[strlen(description)+1]; 919 textsoftware_ = new char[strlen(software)+1]; 920 texttitle_ = new char[strlen(title)+1]; 921 922 strcpy(texttitle_, title); 923 strcpy(textauthor_, author); 924 strcpy(textdescription_, description); 925 strcpy(textsoftware_, software); 926 }; 927 928 /////////////////////////////////////////////////////// 929 void pngwriter::settext(const char * title, const char * author, const char * description, const char * software) 930 { 931 delete [] textauthor_; 932 delete [] textdescription_; 933 delete [] texttitle_; 934 delete [] textsoftware_; 935 936 textauthor_ = new char[strlen(author)+1]; 937 textdescription_ = new char[strlen(description)+1]; 938 textsoftware_ = new char[strlen(software)+1]; 939 texttitle_ = new char[strlen(title)+1]; 940 941 strcpy(texttitle_, title); 942 strcpy(textauthor_, author); 943 strcpy(textdescription_, description); 944 strcpy(textsoftware_, software); 945 }; 946 947 /////////////////////////////////////////////////////// 948 void pngwriter::close() 949 { 950 FILE *fp; 951 png_structp png_ptr; 952 png_infop info_ptr; 953 954 fp = fopen(filename_, "wb"); 955 if( fp == NULL) 956 { 957 std::cerr << " PNGwriter::close - ERROR **: Error creating file (fopen() returned NULL pointer)." << std::endl; 958 perror(" PNGwriter::close - ERROR **"); 959 return; 960 } 961 962 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); 963 info_ptr = png_create_info_struct(png_ptr); 964 png_init_io(png_ptr, fp); 965 if(compressionlevel_ != -2) 966 { 967 png_set_compression_level(png_ptr, compressionlevel_); 968 } 969 else 970 { 971 png_set_compression_level(png_ptr, PNGWRITER_DEFAULT_COMPRESSION); 972 } 973 974 png_set_IHDR(png_ptr, info_ptr, width_, height_, 975 bit_depth_, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, 976 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); 977 978 if(filegamma_ < 1.0e-1) 979 { 980 filegamma_ = 0.5; // Modified in 0.5.4 so as to be the same as the usual gamma. 981 } 982 983 png_set_gAMA(png_ptr, info_ptr, filegamma_); 984 985 time_t gmt; 986 png_time mod_time; 987 png_text text_ptr[5]; 988 time(&gmt); 989 png_convert_from_time_t(&mod_time, gmt); 990 png_set_tIME(png_ptr, info_ptr, &mod_time); 991 text_ptr[0].key = "Title"; 992 text_ptr[0].text = texttitle_; 993 text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE; 994 text_ptr[1].key = "Author"; 995 text_ptr[1].text = textauthor_; 996 text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE; 997 text_ptr[2].key = "Description"; 998 text_ptr[2].text = textdescription_; 999 text_ptr[2].compression = PNG_TEXT_COMPRESSION_NONE; 1000 text_ptr[3].key = "Creation Time"; 1001 text_ptr[3].text = png_convert_to_rfc1123(png_ptr, &mod_time); 1002 text_ptr[3].compression = PNG_TEXT_COMPRESSION_NONE; 1003 text_ptr[4].key = "Software"; 1004 text_ptr[4].text = textsoftware_; 1005 text_ptr[4].compression = PNG_TEXT_COMPRESSION_NONE; 1006 png_set_text(png_ptr, info_ptr, text_ptr, 5); 1007 1008 png_write_info(png_ptr, info_ptr); 1009 png_write_image(png_ptr, graph_); 1010 png_write_end(png_ptr, info_ptr); 1011 png_destroy_write_struct(&png_ptr, &info_ptr); 1012 fclose(fp); 1013 } 1014 1015 ////////////////////////////////////////////////////// 1016 void pngwriter::line(int xfrom, int yfrom, int xto, int yto, int red, int green,int blue) 1017 { 1018 // Bresenham Algorithm. 1019 // 1020 int dy = yto - yfrom; 1021 int dx = xto - xfrom; 1022 int stepx, stepy; 1023 1024 if (dy < 0) 1025 { 1026 dy = -dy; stepy = -1; 1027 } 1028 else 1029 { 1030 stepy = 1; 1031 } 1032 1033 if (dx < 0) 1034 { 1035 dx = -dx; stepx = -1; 1036 } 1037 else 1038 { 1039 stepx = 1; 1040 } 1041 dy <<= 1; // dy is now 2*dy 1042 dx <<= 1; // dx is now 2*dx 1043 1044 this->plot(xfrom,yfrom,red,green,blue); 1045 1046 if (dx > dy) 1047 { 1048 int fraction = dy - (dx >> 1); 1049 1050 while (xfrom != xto) 1051 { 1052 if (fraction >= 0) 1053 { 1054 yfrom += stepy; 1055 fraction -= dx; 1056 } 1057 xfrom += stepx; 1058 fraction += dy; 1059 this->plot(xfrom,yfrom,red,green,blue); 1060 } 1061 } 1062 else 1063 { 1064 int fraction = dx - (dy >> 1); 1065 while (yfrom != yto) 1066 { 1067 if (fraction >= 0) 1068 { 1069 xfrom += stepx; 1070 fraction -= dy; 1071 } 1072 yfrom += stepy; 1073 fraction += dx; 1074 this->plot(xfrom,yfrom,red,green,blue); 1075 } 1076 } 1077 1078 } 1079 1080 void pngwriter::line(int xfrom, int yfrom, int xto, int yto, double red, double green,double blue) 1081 { 1082 this->line( xfrom, 1083 yfrom, 1084 xto, 1085 yto, 1086 int (red*65535), 1087 int (green*65535), 1088 int (blue*65535) 1089 ); 1090 } 1091 1092 /////////////////////////////////////////////////////////////////////////////////////////// 1093 void pngwriter::square(int xfrom, int yfrom, int xto, int yto, int red, int green, int blue) 1094 { 1095 this->line(xfrom, yfrom, xfrom, yto, red, green, blue); 1096 this->line(xto, yfrom, xto, yto, red, green, blue); 1097 this->line(xfrom, yfrom, xto, yfrom, red, green, blue); 1098 this->line(xfrom, yto, xto, yto, red, green, blue); 1099 } 1100 1101 void pngwriter::square(int xfrom, int yfrom, int xto, int yto, double red, double green, double blue) 1102 { 1103 this->square( xfrom, yfrom, xto, yto, int(red*65535), int(green*65535), int(blue*65535)); 1104 } 1105 1106 ////////////////////////////////////////////////////////////////////////////////////////////////// 1107 void pngwriter::filledsquare(int xfrom, int yfrom, int xto, int yto, int red, int green, int blue) 1108 { 1109 for(int caca = xfrom; caca <xto+1; caca++) 1110 { 1111 this->line(caca, yfrom, caca, yto, red, green, blue); 1112 } 1113 } 1114 1115 void pngwriter::filledsquare(int xfrom, int yfrom, int xto, int yto, double red, double green, double blue) 1116 { 1117 this->filledsquare( xfrom, yfrom, xto, yto, int(red*65535), int(green*65535), int(blue*65535)); 1118 } 1119 1120 ////////////////////////////////////////////////////////////////////////////////////////////////// 1121 void pngwriter::circle(int xcentre, int ycentre, int radius, int red, int green, int blue) 1122 { 1123 int x = 0; 1124 int y = radius; 1125 int p = (5 - radius*4)/4; 1126 1127 circle_aux(xcentre, ycentre, x, y, red, green, blue); 1128 while (x < y) 1129 { 1130 x++; 1131 if (p < 0) 1132 { 1133 p += 2*x+1; 1134 } 1135 else 1136 { 1137 y--; 1138 p += 2*(x-y)+1; 1139 } 1140 circle_aux(xcentre, ycentre, x, y, red, green, blue); 1141 } 1142 } 1143 1144 void pngwriter::circle(int xcentre, int ycentre, int radius, double red, double green, double blue) 1145 { 1146 this->circle(xcentre,ycentre,radius, int(red*65535), int(green*65535), int(blue*65535)); 1147 } 1148 1149 //////////////////////////////////////////////////////////// 1150 1151 void pngwriter::circle_aux(int xcentre, int ycentre, int x, int y, int red, int green, int blue) 1152 { 1153 if (x == 0) 1154 { 1155 this->plot( xcentre, ycentre + y, red, green, blue); 1156 this->plot( xcentre, ycentre - y, red, green, blue); 1157 this->plot( xcentre + y, ycentre, red, green, blue); 1158 this->plot( xcentre - y, ycentre, red, green, blue); 1159 } 1160 else 1161 if (x == y) 1162 { 1163 this->plot( xcentre + x, ycentre + y, red, green, blue); 1164 this->plot( xcentre - x, ycentre + y, red, green, blue); 1165 this->plot( xcentre + x, ycentre - y, red, green, blue); 1166 this->plot( xcentre - x, ycentre - y, red, green, blue); 1167 } 1168 else 1169 if (x < y) 1170 { 1171 this->plot( xcentre + x, ycentre + y, red, green, blue); 1172 this->plot( xcentre - x, ycentre + y, red, green, blue); 1173 this->plot( xcentre + x, ycentre - y, red, green, blue); 1174 this->plot( xcentre - x, ycentre - y, red, green, blue); 1175 this->plot( xcentre + y, ycentre + x, red, green, blue); 1176 this->plot( xcentre - y, ycentre + x, red, green, blue); 1177 this->plot( xcentre + y, ycentre - x, red, green, blue); 1178 this->plot( xcentre - y, ycentre - x, red, green, blue); 1179 } 1180 1181 } 1182 1183 //////////////////////////////////////////////////////////// 1184 void pngwriter::filledcircle(int xcentre, int ycentre, int radius, int red, int green, int blue) 1185 { 1186 for(int jjj = ycentre-radius; jjj< ycentre+radius+1; jjj++) 1187 { 1188 this->line(xcentre - int(sqrt((double)(radius*radius) - (-ycentre + jjj)*(-ycentre + jjj ))), jjj, 1189 xcentre + int(sqrt((double)(radius*radius) - (-ycentre + jjj)*(-ycentre + jjj ))),jjj,red,green,blue); 1190 } 1191 } 1192 1193 void pngwriter::filledcircle(int xcentre, int ycentre, int radius, double red, double green, double blue) 1194 { 1195 this->filledcircle( xcentre, ycentre, radius, int(red*65535), int(green*65535), int(blue*65535)); 1196 } 1197 1198 ////////////////Reading routines///////////////////// 1199 ///////////////////////////////////////////////// 1200 1201 // Modified with Mikkel's patch 1202 void pngwriter::readfromfile(char * name) 1203 { 1204 FILE *fp; 1205 png_structp png_ptr; 1206 png_infop info_ptr; 1207 unsigned char **image; 1208 unsigned long width, height; 1209 int bit_depth, color_type, interlace_type; 1210 // png_uint_32 i; 1211 // 1212 fp = fopen (name,"rb"); 1213 if (fp==NULL) 1214 { 1215 std::cerr << " PNGwriter::readfromfile - ERROR **: Error opening file \"" << std::flush; 1216 std::cerr << name <<std::flush; 1217 std::cerr << "\"." << std::endl << std::flush; 1218 perror(" PNGwriter::readfromfile - ERROR **"); 1219 return; 1220 } 1221 1222 if(!check_if_png(name, &fp)) 1223 { 1224 std::cerr << " PNGwriter::readfromfile - ERROR **: Error opening file " << name << ". This may not be a valid png file. (check_if_png() failed)." << std::endl; 1225 // fp has been closed already if check_if_png() fails. 1226 return; 1227 } 1228 1229 // Code as it was before Sven's patch 1230 /* if(!read_png_info(fp, &png_ptr, &info_ptr)) 1231 { 1232 std::cerr << " PNGwriter::readfromfile - ERROR **: Error opening file " << name << ". read_png_info() failed." << std::endl; 1233 // fp has been closed already if read_png_info() fails. 1234 return; 1235 } 1236 1237 if(!read_png_image(fp, png_ptr, info_ptr, &image, &width, &height)) 1238 { 1239 std::cerr << " PNGwriter::readfromfile - ERROR **: Error opening file " << name << ". read_png_image() failed." << std::endl; 1240 // fp has been closed already if read_png_image() fails. 1241 return; 1242 } 1243 1244 //stuff should now be in image[][]. 1245 1246 */ //End of code as it was before Sven's patch. 1247 1248 //Sven's patch starts here 1249 //////////////////////////////////// 1250 1251 /* 1252 1253 if(!read_png_info(fp, &png_ptr, &info_ptr)) 1254 { 1255 1256 std::cerr << " PNGwriter::readfromfile - ERROR **: Error opening file " << name << ". read_png_info() failed." << std::endl; 1257 // fp has been closed already if read_png_info() fails. 1258 return; 1259 } 1260 1261 // UPDATE: Query info struct to get header info BEFORE reading the image 1262 1263 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); 1264 bit_depth_ = bit_depth; 1265 colortype_ = color_type; 1266 1267 if(color_type == PNG_COLOR_TYPE_PALETTE) 1268 { 1269 png_set_expand(png_ptr); 1270 png_read_update_info(png_ptr, info_ptr); 1271 } 1272 1273 if(!read_png_image(fp, png_ptr, info_ptr, &image, &width, &height)) 1274 { 1275 std::cerr << " PNGwriter::readfromfile - ERROR **: Error opening file " << name << ". read_png_image() failed." << std::endl; 1276 // fp has been closed already if read_png_image() fails. 1277 return; 1278 } 1279 1280 //stuff should now be in image[][]. 1281 */ 1282 //Sven's patch ends here. 1283 //////////////////////////////// 1284 1285 // Mikkel's patch starts here 1286 // /////////////////////////////////// 1287 1288 if(!read_png_info(fp, &png_ptr, &info_ptr)) 1289 { 1290 1291 std::cerr << " PNGwriter::readfromfile - ERROR **: Error opening file " << name << ". read_png_info() failed." << std::endl; 1292 // fp has been closed already if read_png_info() fails. 1293 return; 1294 } 1295 1296 //Input transformations 1297 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); 1298 bit_depth_ = bit_depth; 1299 colortype_ = color_type; 1300 1301 1302 // Changes palletted image to RGB 1303 if(color_type == PNG_COLOR_TYPE_PALETTE /*&& bit_depth<8*/) 1304 { 1305 // png_set_expand(png_ptr); 1306 png_set_palette_to_rgb(png_ptr); // Just an alias of png_set_expand() 1307 transformation_ = 1; 1308 } 1309 1310 // Transforms grescale images of less than 8 bits to 8 bits. 1311 if(color_type == PNG_COLOR_TYPE_GRAY && bit_depth<8) 1312 { 1313 // png_set_expand(png_ptr); 1314 png_set_gray_1_2_4_to_8(png_ptr); // Just an alias of the above. 1315 transformation_ = 1; 1316 } 1317 1318 // Completely strips the alpha channel. 1319 if(color_type & PNG_COLOR_MASK_ALPHA) 1320 { 1321 png_set_strip_alpha(png_ptr); 1322 transformation_ = 1; 1323 } 1324 1325 // Converts greyscale images to RGB. 1326 if(color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) // Used to be RGB, fixed it. 1327 { 1328 png_set_gray_to_rgb(png_ptr); 1329 transformation_ = 1; 1330 } 1331 1332 // If any of the above were applied, 1333 if(transformation_) 1334 { 1335 // png_set_gray_to_rgb(png_ptr); //Is this really needed here? 1336 1337 // After setting the transformations, libpng can update your png_info structure to reflect any transformations 1338 // you've requested with this call. This is most useful to update the info structure's rowbytes field so you can 1339 // use it to allocate your image memory. This function will also update your palette with the correct screen_gamma 1340 // and background if these have been given with the calls above. 1341 1342 png_read_update_info(png_ptr, info_ptr); 1343 1344 // Just in case any of these have changed? 1345 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); 1346 bit_depth_ = bit_depth; 1347 colortype_ = color_type; 1348 } 1349 1350 if(!read_png_image(fp, png_ptr, info_ptr, &image, &width, &height)) 1351 { 1352 std::cerr << " PNGwriter::readfromfile - ERROR **: Error opening file " << name << ". read_png_image() failed." << std::endl; 1353 // fp has been closed already if read_png_image() fails. 1354 return; 1355 } 1356 1357 //stuff should now be in image[][]. 1358 1359 // Mikkel's patch ends here 1360 // ////////////////////////////// 1361 // 1362 if( image == NULL) 1363 { 1364 std::cerr << " PNGwriter::readfromfile - ERROR **: Error opening file " << name << ". Can't assign memory (after read_png_image(), image is NULL)." << std::endl; 1365 fclose(fp); 1366 return; 1367 } 1368 1369 //First we must get rid of the image already there, and free the memory. 1370 int jjj; 1371 for (jjj = 0; jjj < height_; jjj++) free(graph_[jjj]); 1372 free(graph_); 1373 1374 //Must reassign the new size of the read image 1375 width_ = width; 1376 height_ = height; 1377 1378 //Graph now is the image. 1379 graph_ = image; 1380 1381 rowbytes_ = png_get_rowbytes(png_ptr, info_ptr); 1382 1383 // This was part of the original source, but has been moved up. 1384 /* 1385 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); 1386 bit_depth_ = bit_depth; 1387 colortype_ = color_type; 1388 */ 1389 // if(color_type == PNG_COLOR_TYPE_PALETTE /*&& bit_depth<8*/ ) 1390 /* { 1391 png_set_expand(png_ptr); 1392 } 1393 1394 if(color_type == PNG_COLOR_TYPE_GRAY && bit_depth<8) 1395 { 1396 png_set_expand(png_ptr); 1397 } 1398 1399 if(color_type & PNG_COLOR_MASK_ALPHA) 1400 { 1401 png_set_strip_alpha(png_ptr); 1402 } 1403 1404 if(color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_RGB_ALPHA) 1405 { 1406 png_set_gray_to_rgb(png_ptr); 1407 } 1408 1409 */ 1410 1411 if((bit_depth_ !=16)&&(bit_depth_ !=8)) 1412 { 1413 std::cerr << " PNGwriter::readfromfile() - WARNING **: Input file is of unsupported type (bad bit_depth). Output will be unpredictable.\n"; 1414 } 1415 1416 // Thanks to Mikkel's patch, PNGwriter should now be able to handle these color types: 1417 1418 /* 1419 color_type - describes which color/alpha channels are present. 1420 PNG_COLOR_TYPE_GRAY (bit depths 1, 2, 4, 8, 16) 1421 PNG_COLOR_TYPE_GRAY_ALPHA (bit depths 8, 16) 1422 PNG_COLOR_TYPE_PALETTE (bit depths 1, 2, 4, 8) 1423 PNG_COLOR_TYPE_RGB (bit_depths 8, 16) 1424 PNG_COLOR_TYPE_RGB_ALPHA (bit_depths 8, 16) 1425 1426 PNG_COLOR_MASK_PALETTE 1427 PNG_COLOR_MASK_COLOR 1428 1429 color types. Note that not all combinations are legal 1430 #define PNG_COLOR_TYPE_GRAY 0 1431 #define PNG_COLOR_TYPE_PALETTE (PNG_COLOR_MASK_COLOR (2) | PNG_COLOR_MASK_PALETTE (1) ) 1432 #define PNG_COLOR_TYPE_RGB (PNG_COLOR_MASK_COLOR (2) ) 1433 #define PNG_COLOR_TYPE_RGB_ALPHA (PNG_COLOR_MASK_COLOR (2) | PNG_COLOR_MASK_ALPHA (4) ) 1434 #define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA (4) ) 1435 1436 aliases 1437 #define PNG_COLOR_TYPE_RGBA PNG_COLOR_TYPE_RGB_ALPHA 1438 #define PNG_COLOR_TYPE_GA PNG_COLOR_TYPE_GRAY_ALPHA 1439 1440 These describe the color_type field in png_info. 1441 color type masks 1442 #define PNG_COLOR_MASK_PALETTE 1 1443 #define PNG_COLOR_MASK_COLOR 2 1444 #define PNG_COLOR_MASK_ALPHA 4 1445 1446 1447 */ 1448 1449 1450 if(colortype_ !=2) 1451 { 1452 std::cerr << " PNGwriter::readfromfile() - WARNING **: Input file is of unsupported type (bad color_type). Output will be unpredictable.\n"; 1453 } 1454 1455 screengamma_ = 2.2; 1456 double file_gamma,screen_gamma; 1457 screen_gamma = screengamma_; 1458 if (png_get_gAMA(png_ptr, info_ptr, &file_gamma)) 1459 { 1460 png_set_gamma(png_ptr,screen_gamma,file_gamma); 1461 } 1462 else 1463 { 1464 png_set_gamma(png_ptr, screen_gamma,0.45); 1465 } 1466 1467 filegamma_ = file_gamma; 1468 1469 fclose(fp); 1470 } 1471 1472 /////////////////////////////////////////////////////// 1473 1474 void pngwriter::readfromfile(const char * name) 1475 { 1476 this->readfromfile((char *)(name)); 1477 } 1478 1479 ///////////////////////////////////////////////////////// 1480 int pngwriter::check_if_png(char *file_name, FILE **fp) 1481 { 1482 char sig[PNG_BYTES_TO_CHECK]; 1483 1484 if ( /*(*fp = fopen(file_name, "rb")) */ *fp == NULL) // Fixed 10 10 04 1485 { 1486 // exit(EXIT_FAILURE); 1487 std::cerr << " PNGwriter::check_if_png - ERROR **: Could not open file " << file_name << " to read." << std::endl; 1488 perror(" PNGwriter::check_if_png - ERROR **"); 1489 return 0; 1490 } 1491 1492 if (fread(sig, 1, PNG_BYTES_TO_CHECK, *fp) != PNG_BYTES_TO_CHECK) 1493 { 1494 //exit(EXIT_FAILURE); 1495 std::cerr << " PNGwriter::check_if_png - ERROR **: File " << file_name << " does not appear to be a valid PNG file." << std::endl; 1496 perror(" PNGwriter::check_if_png - ERROR **"); 1497 fclose(*fp); 1498 return 0; 1499 } 1500 1501 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)*/ ) 1502 { 1503 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; 1504 fclose(*fp); 1505 return 0; 1506 } 1507 1508 1509 1510 return 1; //Success 1511 } 1512 1513 /////////////////////////////////////////////////////// 1514 int pngwriter::read_png_info(FILE *fp, png_structp *png_ptr, png_infop *info_ptr) 1515 { 1516 *png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); 1517 if (*png_ptr == NULL) 1518 { 1519 std::cerr << " PNGwriter::read_png_info - ERROR **: Could not create read_struct." << std::endl; 1520 fclose(fp); 1521 return 0; 1522 //exit(EXIT_FAILURE); 1523 } 1524 *info_ptr = png_create_info_struct(*png_ptr); 1525 if (*info_ptr == NULL) 1526 { 1527 png_destroy_read_struct(png_ptr, (png_infopp)NULL, (png_infopp)NULL); 1528 std::cerr << " PNGwriter::read_png_info - ERROR **: Could not create info_struct." << std::endl; 1529 //exit(EXIT_FAILURE); 1530 fclose(fp); 1531 return 0; 1532 } 1533 if (setjmp((*png_ptr)->jmpbuf)) /*(setjmp(png_jmpbuf(*png_ptr)) )*////////////////////////////////////// 1534 { 1535 png_destroy_read_struct(png_ptr, info_ptr, (png_infopp)NULL); 1536 std::cerr << " PNGwriter::read_png_info - ERROR **: This file may be a corrupted PNG file. (setjmp(*png_ptr)->jmpbf) failed)." << std::endl; 1537 fclose(fp); 1538 return 0; 1539 //exit(EXIT_FAILURE); 1540 } 1541 png_init_io(*png_ptr, fp); 1542 png_set_sig_bytes(*png_ptr, PNG_BYTES_TO_CHECK); 1543 png_read_info(*png_ptr, *info_ptr); 1544 1545 return 1; 1546 } 1547 1548 //////////////////////////////////////////////////////////// 1549 int pngwriter::read_png_image(FILE *fp, png_structp png_ptr, png_infop info_ptr, 1550 png_bytepp *image, png_uint_32 *width, png_uint_32 *height) 1551 { 1552 unsigned int i,j; 1553 1554 *width = png_get_image_width(png_ptr, info_ptr); 1555 *height = png_get_image_height(png_ptr, info_ptr); 1556 1557 if( width == NULL) 1558 { 1559 std::cerr << " PNGwriter::read_png_image - ERROR **: png_get_image_width() returned NULL pointer." << std::endl; 1560 fclose(fp); 1561 return 0; 1562 } 1563 1564 if( height == NULL) 1565 { 1566 std::cerr << " PNGwriter::read_png_image - ERROR **: png_get_image_height() returned NULL pointer." << std::endl; 1567 fclose(fp); 1568 return 0; 1569 } 1570 1571 if ((*image = (png_bytepp)malloc(*height * sizeof(png_bytep))) == NULL) 1572 { 1573 std::cerr << " PNGwriter::read_png_image - ERROR **: Could not allocate memory for reading image." << std::endl; 1574 fclose(fp); 1575 return 0; 1576 //exit(EXIT_FAILURE); 1577 } 1578 for (i = 0; i < *height; i++) 1579 { 1580 (*image)[i] = (png_bytep)malloc(png_get_rowbytes(png_ptr, info_ptr)); 1581 if ((*image)[i] == NULL) 1582 { 1583 for (j = 0; j < i; j++) free((*image)[j]); 1584 free(*image); 1585 fclose(fp); 1586 std::cerr << " PNGwriter::read_png_image - ERROR **: Could not allocate memory for reading image." << std::endl; 1587 return 0; 1588 //exit(EXIT_FAILURE); 1589 } 1590 } 1591 png_read_image(png_ptr, *image); 1592 1593 return 1; 1594 } 1595 1596 /////////////////////////////////// 1597 int pngwriter::getheight(void) 1598 { 1599 return height_; 1600 } 1601 1602 int pngwriter::getwidth(void) 1603 { 1604 return width_; 1605 } 1606 1607 1608 int pngwriter::getbitdepth(void) 1609 { 1610 return bit_depth_; 1611 } 1612 1613 int pngwriter::getcolortype(void) 1614 { 1615 return colortype_; 1616 } 1617 1618 double pngwriter::getgamma(void) 1619 { 1620 return filegamma_; 1621 } 1622 1623 void pngwriter::setgamma(double gamma) 1624 { 1625 filegamma_ = gamma; 1626 } 1627 1628 // The algorithms HSVtoRGB and RGBtoHSV were found at http://www.cs.rit.edu/~ncs/ 1629 // which is a page that belongs to Nan C. Schaller, though 1630 // these algorithms appear to be the work of Eugene Vishnevsky. 1631 ////////////////////////////////////////////// 1632 void pngwriter::HSVtoRGB( double *r, double *g, double *b, double h, double s, double v ) 1633 { 1634 // r,g,b values are from 0 to 1 1635 // h = [0,1], s = [0,1], v = [0,1] 1636 // if s == 0, then h = -1 (undefined) 1637 // 1638 h = h*360.0; 1639 1640 int i; 1641 double f, p, q, t; 1642 if( s == 0 ) 1643 { 1644 // achromatic (grey) 1645 *r = *g = *b = v; 1646 return; 1647 } 1648 1649 h /= 60; // sector 0 to 5 1650 i = int(floor( h )); 1651 f = h - i; // factorial part of h 1652 p = v * ( 1 - s ); 1653 q = v * ( 1 - s * f ); 1654 t = v * ( 1 - s * ( 1 - f ) ); 1655 1656 switch( i ) 1657 { 1658 case 0: 1659 *r = v; 1660 *g = t; 1661 *b = p; 1662 break; 1663 case 1: 1664 *r = q; 1665 *g = v; 1666 *b = p; 1667 break; 1668 case 2: 1669 *r = p; 1670 *g = v; 1671 *b = t; 1672 break; 1673 case 3: 1674 *r = p; 1675 *g = q; 1676 *b = v; 1677 break; 1678 case 4: 1679 *r = t; 1680 *g = p; 1681 *b = v; 1682 break; 1683 default: // case 5: 1684 *r = v; 1685 *g = p; 1686 *b = q; 1687 break; 1688 } 1689 } 1690 1691 void pngwriter::RGBtoHSV( float r, float g, float b, float *h, float *s, float *v ) 1692 { 1693 1694 float min=0.0; //These values are not used. 1695 float max=1.0; 1696 float delta; 1697 1698 if( (r>=g)&&(r>=b) ) 1699 { 1700 max = r; 1701 } 1702 if( (g>=r)&&(g>=b) ) 1703 { 1704 max = g; 1705 } 1706 if( (b>=g)&&(b>=r) ) 1707 { 1708 max = b; 1709 } 1710 1711 if( (r<=g)&&(r<=b) ) 1712 { 1713 min = r; 1714 } 1715 if( (g<=r)&&(g<=b) ) 1716 { 1717 min = g; 1718 } 1719 if( (b<=g)&&(b<=r) ) 1720 { 1721 min = b; 1722 } 1723 1724 *v = max; // v 1725 1726 delta = max - min; 1727 1728 if( max != 0 ) 1729 *s = delta / max; // s 1730 else 1731 { 1732 1733 r = g = b = 0; // s = 0, v is undefined 1734 *s = 0; 1735 *h = -1; 1736 return; 1737 } 1738 1739 if( r == max ) 1740 *h = ( g - b ) / delta; // between yellow & magenta 1741 else if( g == max ) 1742 *h = 2 + ( b - r ) / delta; // between cyan & yellow 1743 else 1744 *h = 4 + ( r - g ) / delta; // between magenta & cyan 1745 1746 *h *= 60; // degrees 1747 if( *h < 0 ) 1748 *h += 360; 1749 1750 } 1751 1752 // 1753 ////////////////////////////////////////////////////////////////////////////////// 1754 void pngwriter::plotHSV(int x, int y, double hue, double saturation, double value) 1755 { 1756 double red,green,blue; 1757 double *redp; 1758 double *greenp; 1759 double *bluep; 1760 1761 redp = &red; 1762 greenp = &green; 1763 bluep = &blue; 1764 1765 HSVtoRGB(redp,greenp,bluep,hue,saturation,value); 1766 plot(x,y,red,green,blue); 1767 } 1768 1769 void pngwriter::plotHSV(int x, int y, int hue, int saturation, int value) 1770 { 1771 plotHSV(x, y, double(hue)/65535.0, double(saturation)/65535.0, double(value)/65535.0); 1772 } 1773 1774 // 1775 ////////////////////////////////////////////////////////////////////////////////// 1776 double pngwriter::dreadHSV(int x, int y, int colour) 1777 { 1778 if( (x>0)&&(x<=width_)&&(y>0)&&(y<=height_) ) 1779 { 1780 1781 float * huep; 1782 float * saturationp; 1783 float * valuep; 1784 float red,green,blue; 1785 float hue, saturation, value; 1786 1787 red = float(dread(x,y,1)); 1788 green = float(dread(x,y,2)); 1789 blue = float(dread(x,y,3)); 1790 1791 huep = &hue; 1792 saturationp = &saturation; 1793 valuep = &value; 1794 1795 RGBtoHSV( red, green, blue, huep, saturationp, valuep ); 1796 1797 if(colour == 1) 1798 { 1799 return double(hue)/360.0; 1800 } 1801 1802 else if(colour == 2) 1803 { 1804 return saturation; 1805 } 1806 1807 else if(colour == 3) 1808 { 1809 return value; 1810 } 1811 1812 std::cerr << " PNGwriter::dreadHSV - ERROR **: Called with wrong colour argument: should be 1, 2 or 3; was: " << colour << "." << std::endl; 1813 } 1814 return 0.0; 1815 } 1816 1817 // 1818 ////////////////////////////////////////////////////////////////////////////////// 1819 int pngwriter::readHSV(int x, int y, int colour) 1820 { 1821 if( (x>0)&&(x<=width_)&&(y>0)&&(y<=height_) ) 1822 { 1823 1824 float * huep; 1825 float * saturationp; 1826 float * valuep; 1827 float red,green,blue; 1828 float hue, saturation, value; 1829 1830 red = float(dread(x,y,1)); 1831 green = float(dread(x,y,2)); 1832 blue = float(dread(x,y,3)); 1833 1834 huep = &hue; 1835 saturationp = &saturation; 1836 valuep = &value; 1837 1838 RGBtoHSV( red, green, blue, huep, saturationp, valuep ); 1839 1840 if(colour == 1) 1841 { 1842 return int(65535*(double(hue)/360.0)); 1843 } 1844 1845 else if(colour == 2) 1846 { 1847 return int(65535*saturation); 1848 } 1849 1850 else if(colour == 3) 1851 { 1852 return int(65535*value); 1853 } 1854 1855 std::cerr << " PNGwriter::readHSV - ERROR **: Called with wrong colour argument: should be 1, 2 or 3; was: " << colour << "." << std::endl; 1856 return 0; 1857 } 1858 else 1859 { 1860 return 0; 1861 } 1862 } 1863 1864 void pngwriter::setcompressionlevel(int level) 1865 { 1866 if( (level < -1)||(level > 9) ) 1867 { 1868 std::cerr << " PNGwriter::setcompressionlevel - ERROR **: Called with wrong compression level: should be -1 to 9, was: " << level << "." << std::endl; 1869 } 1870 compressionlevel_ = level; 1871 } 1872 1873 // An implementation of a Bezier curve. 1874 void pngwriter::bezier( int startPtX, int startPtY, 1875 int startControlX, int startControlY, 1876 int endPtX, int endPtY, 1877 int endControlX, int endControlY, 1878 double red, double green, double blue) 1879 { 1880 1881 double cx = 3.0*(startControlX - startPtX); 1882 double bx = 3.0*(endControlX - startControlX) - cx; 1883 double ax = double(endPtX - startPtX - cx - bx); 1884 1885 double cy = 3.0*(startControlY - startPtY); 1886 double by = 3.0*(endControlY - startControlY) - cy; 1887 double ay = double(endPtY - startPtY - cy - by); 1888 1889 double x,y,newx,newy; 1890 x = startPtX; 1891 y = startPtY; 1892 1893 for(double t = 0.0; t<=1.005; t += 0.005) 1894 { 1895 newx = startPtX + t*(double(cx) + t*(double(bx) + t*(double(ax)))); 1896 newy = startPtY + t*(double(cy) + t*(double(by) + t*(double(ay)))); 1897 this->line(int(x),int(y),int(newx),int(newy),red,green,blue); 1898 x = newx; 1899 y = newy; 1900 } 1901 } 1902 1903 //int version of bezier 1904 void pngwriter::bezier( int startPtX, int startPtY, 1905 int startControlX, int startControlY, 1906 int endPtX, int endPtY, 1907 int endControlX, int endControlY, 1908 int red, int green, int blue) 1909 { 1910 this->bezier( startPtX, startPtY, 1911 startControlX, startControlY, 1912 endPtX, endPtY, 1913 endControlX, endControlY, 1914 double(red)/65535.0, double(green)/65535.0, double(blue)/65535.0); 1915 } 1916 1917 /* 1918 int pngwriter::getcompressionlevel(void) 1919 { 1920 return png_get_compression_level(png_ptr); 1921 } 1922 */ 1923 1924 double pngwriter::version(void) 1925 { 1926 const char *a = "Jeramy Webb (jeramyw@gmail.com), Mike Heller (mkheller@gmail.com)"; // For their generosity ;-) 1927 char b = a[27]; 1928 b++; 1929 return (PNGWRITER_VERSION); 1930 } 1931 1932 void pngwriter::write_png(void) 1933 { 1934 this->close(); 1935 } 1936 1937 #ifndef NO_FREETYPE 1938 1939 // Freetype-based text rendering functions. 1940 /////////////////////////////////////////// 1941 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) 1942 { 1943 FT_Library library; 1944 FT_Face face; 1945 FT_Matrix matrix; // transformation matrix 1946 FT_Vector pen; 1947 1948 FT_UInt glyph_index; 1949 FT_Error error; 1950 1951 FT_Bool use_kerning; 1952 FT_UInt previous = 0; 1953 1954 /* Set up transformation Matrix */ 1955 matrix.xx = (FT_Fixed)( cos(angle)*0x10000); /* It would make more sense to do this (below), but, bizzarely, */ 1956 matrix.xy = (FT_Fixed)(-sin(angle)*0x10000); /* if one does, FT_Load_Glyph fails consistently. */ 1957 matrix.yx = (FT_Fixed)( sin(angle)*0x10000); // matrix.yx = - matrix.xy; 1958 matrix.yy = (FT_Fixed)( cos(angle)*0x10000); // matrix.yy = matrix.xx; 1959 1960 /* Place starting coordinates in adequate form. */ 1961 pen.x = x_start*64 ; 1962 pen.y = (int)(y_start/64.0); 1963 1964 /*Count the length of the string */ 1965 int num_chars = strlen(text); 1966 1967 /* Initialize FT Library object */ 1968 error = FT_Init_FreeType( &library ); 1969 if (error) { std::cerr << " PNGwriter::plot_text - ERROR **: FreeType: Could not init Library."<< std::endl; return;} 1970 1971 /* Initialize FT face object */ 1972 error = FT_New_Face( library,face_path,0,&face ); 1973 if ( error == FT_Err_Unknown_File_Format ) { std::cerr << " PNGwriter::plot_text - 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; } 1974 1975 /* Set the Char size */ 1976 error = FT_Set_Char_Size( face, /* handle to face object */ 1977 0, /* char_width in 1/64th of points */ 1978 fontsize*64, /* char_height in 1/64th of points */ 1979 100, /* horizontal device resolution */ 1980 100 ); /* vertical device resolution */ 1981 1982 /* A way of accesing the glyph directly */ 1983 FT_GlyphSlot slot = face->glyph; // a small shortcut 1984 1985 /* Does the font file support kerning? */ 1986 use_kerning = FT_HAS_KERNING( face ); 1987 1988 int n; 1989 for ( n = 0; n < num_chars; n++ ) 1990 { 1991 /* Convert character code to glyph index */ 1992 glyph_index = FT_Get_Char_Index( face, text[n] ); 1993 1994 /* Retrieve kerning distance and move pen position */ 1995 if ( use_kerning && previous&& glyph_index ) 1996 { 1997 FT_Vector delta; 1998 FT_Get_Kerning( face, 1999 previous, 2000 glyph_index, 2001 ft_kerning_default, //FT_KERNING_DEFAULT, 2002 &delta ); 2003 2004 /* Transform this kerning distance into rotated space */ 2005 pen.x += (int) (((double) delta.x)*cos(angle)); 2006 pen.y += (int) (((double) delta.x)*( sin(angle))); 2007 } 2008 2009 /* Set transform */ 2010 FT_Set_Transform( face, &matrix, &pen ); 2011 2012 /*set char size*/ 2013 2014 if (error) { std::cerr << " PNGwriter::plot_text - ERROR **: FreeType: Set char size error." << std::endl; return;}; 2015 2016 /* Retrieve glyph index from character code */ 2017 glyph_index = FT_Get_Char_Index( face, text[n] ); 2018 2019 /* Load glyph image into the slot (erase previous one) */ 2020 error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT ); 2021 if (error) { std::cerr << " PNGwriter::plot_text - ERROR **: FreeType: Could not load glyph (in loop). (FreeType error "<< std::hex << error <<")." << std::endl; return;} 2022 2023 /* Convert to an anti-aliased bitmap */ 2024 // error = FT_Render_Glyph( face->glyph, FT_RENDER_MODE_NORMAL ); 2025 error = FT_Render_Glyph( face->glyph, ft_render_mode_normal ); 2026 if (error) { std::cerr << " PNGwriter::plot_text - ERROR **: FreeType: Render glyph error." << std::endl; return;} 2027 2028 /* Now, draw to our target surface */ 2029 my_draw_bitmap( &slot->bitmap, 2030 slot->bitmap_left, 2031 y_start + slot->bitmap_top, 2032 red, 2033 green, 2034 blue ); 2035 2036 /* Advance to the next position */ 2037 pen.x += slot->advance.x; 2038 pen.y += slot->advance.y; 2039 2040 /* record current glyph index */ 2041 previous = glyph_index; 2042 } 2043 2044 /* Free the face and the library objects */ 2045 FT_Done_Face ( face ); 2046 FT_Done_FreeType( library ); 2047 } 2048 2049 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) 2050 { 2051 FT_Library library; 2052 FT_Face face; 2053 FT_Matrix matrix; // transformation matrix 2054 FT_Vector pen; 2055 2056 FT_UInt glyph_index; 2057 FT_Error error; 2058 2059 FT_Bool use_kerning; 2060 FT_UInt previous = 0; 2061 2062 /* Set up transformation Matrix */ 2063 matrix.xx = (FT_Fixed)( cos(angle)*0x10000); /* It would make more sense to do this (below), but, bizzarely, */ 2064 matrix.xy = (FT_Fixed)(-sin(angle)*0x10000); /* if one does, FT_Load_Glyph fails consistently. */ 2065 matrix.yx = (FT_Fixed)( sin(angle)*0x10000); // matrix.yx = - matrix.xy; 2066 matrix.yy = (FT_Fixed)( cos(angle)*0x10000); // matrix.yy = matrix.xx; 2067 2068 /* Place starting coordinates in adequate form. */ 2069 pen.x = x_start*64 ; 2070 pen.y = (int)(y_start/64.0); 2071 2072 /*Count the length of the string */ 2073 int num_bytes=0; 2074 while(text[num_bytes]!=0) 2075 { 2076 num_bytes++; 2077 } 2078 2079 /* 2080 std::cout << "Num bytes is: "<< num_bytes << std::endl; 2081 */ 2082 2083 //The array of ucs4 glyph indexes, which will by at most the number of bytes in the utf-8 file. 2084 long * ucs4text; 2085 ucs4text = new long[num_bytes+1]; 2086 2087 unsigned char u,v,w,x,y,z; 2088 2089 int num_chars=0; 2090 2091 long iii=0; 2092 2093 while(iii<num_bytes) 2094 { 2095 z = text[iii]; 2096 2097 if(z<=127) 2098 { 2099 ucs4text[num_chars] = z; 2100 } 2101 2102 if((192<=z)&&(z<=223)) 2103 { 2104 iii++; y = text[iii]; 2105 ucs4text[num_chars] = (z-192)*64 + (y -128); 2106 } 2107 2108 if((224<=z)&&(z<=239)) 2109 { 2110 iii++; y = text[iii]; 2111 iii++; x = text[iii]; 2112 ucs4text[num_chars] = (z-224)*4096 + (y -128)*64 + (x-128); 2113 } 2114 2115 if((240<=z)&&(z<=247)) 2116 { 2117 iii++; y = text[iii]; 2118 iii++; x = text[iii]; 2119 iii++; w = text[iii]; 2120 ucs4text[num_chars] = (z-240)*262144 + (y -128)*4096 + (x-128)*64 + (w-128); 2121 } 2122 2123 if((248<=z)&&(z<=251)) 2124 { 2125 iii++; y = text[iii]; 2126 iii++; x = text[iii]; 2127 iii++; w = text[iii]; 2128 iii++; v = text[iii]; 2129 ucs4text[num_chars] = (z-248)*16777216 + (y -128)*262144 + (x-128)*4096 + (w-128)*64 +(v-128); 2130 } 2131 2132 if((252==z)||(z==253)) 2133 { 2134 iii++; y = text[iii]; 2135 iii++; x = text[iii]; 2136 iii++; w = text[iii]; 2137 iii++; v = text[iii]; 2138 u = text[iii]; 2139 ucs4text[num_chars] = (z-252)*1073741824 + (y -128)*16777216 + (x-128)*262144 + (w-128)*4096 +(v-128)*64 + (u-128); 2140 } 2141 2142 if((z==254)||(z==255)) 2143 { 2144 std::cerr << " PNGwriter::plot_text_utf8 - ERROR **: Problem with character: invalid UTF-8 data."<< std::endl; 2145 } 2146 // std::cerr << "\nProblem at " << iii << ".\n"; 2147 // 2148 iii++; 2149 num_chars++; 2150 } 2151 2152 // num_chars now contains the number of characters in the string. 2153 /* 2154 std::cout << "Num chars is: "<< num_chars << std::endl; 2155 */ 2156 2157 /* Initialize FT Library object */ 2158 error = FT_Init_FreeType( &library ); 2159 if (error) { std::cerr << " PNGwriter::plot_text_utf8 - ERROR **: FreeType: Could not init Library."<< std::endl; return;} 2160 2161 /* Initialize FT face object */ 2162 error = FT_New_Face( library,face_path,0,&face ); 2163 if ( error == FT_Err_Unknown_File_Format ) { std::cerr << " PNGwriter::plot_text_utf8 - 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; } 2164 2165 /* Set the Char size */ 2166 error = FT_Set_Char_Size( face, /* handle to face object */ 2167 0, /* char_width in 1/64th of points */ 2168 fontsize*64, /* char_height in 1/64th of points */ 2169 100, /* horizontal device resolution */ 2170 100 ); /* vertical device resolution */ 2171 2172 /* A way of accesing the glyph directly */ 2173 FT_GlyphSlot slot = face->glyph; // a small shortcut 2174 2175 /* Does the font file support kerning? */ 2176 use_kerning = FT_HAS_KERNING( face ); 2177 2178 int n; 2179 for ( n = 0; n < num_chars; n++ ) 2180 { 2181 /* Convert character code to glyph index */ 2182 glyph_index = FT_Get_Char_Index( face, ucs4text[n] ); 2183 2184 /* Retrieve kerning distance and move pen position */ 2185 if ( use_kerning && previous&& glyph_index ) 2186 { 2187 FT_Vector delta; 2188 FT_Get_Kerning( face, 2189 previous, 2190 glyph_index, 2191 ft_kerning_default, //FT_KERNING_DEFAULT, 2192 &delta ); 2193 2194 /* Transform this kerning distance into rotated space */ 2195 pen.x += (int) (((double) delta.x)*cos(angle)); 2196 pen.y += (int) (((double) delta.x)*( sin(angle))); 2197 } 2198 2199 /* Set transform */ 2200 FT_Set_Transform( face, &matrix, &pen ); 2201 2202 /*set char size*/ 2203 2204 if (error) { std::cerr << " PNGwriter::plot_text_utf8 - ERROR **: FreeType: Set char size error." << std::endl; return;}; 2205 2206 /* Retrieve glyph index from character code */ 2207 glyph_index = FT_Get_Char_Index( face, ucs4text[n] ); 2208 2209 /* Load glyph image into the slot (erase previous one) */ 2210 error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT ); 2211 if (error) { std::cerr << " PNGwriter::plot_text_utf8 - ERROR **: FreeType: Could not load glyph (in loop). (FreeType error "<< std::hex << error <<")." << std::endl; return;} 2212 2213 /* Convert to an anti-aliased bitmap */ 2214 error = FT_Render_Glyph( face->glyph, ft_render_mode_normal ); 2215 if (error) { std::cerr << " PNGwriter::plot_text_utf8 - ERROR **: FreeType: Render glyph error." << std::endl; return;} 2216 2217 /* Now, draw to our target surface */ 2218 my_draw_bitmap( &slot->bitmap, 2219 slot->bitmap_left, 2220 y_start + slot->bitmap_top, 2221 red, 2222 green, 2223 blue ); 2224 2225 /* Advance to the next position */ 2226 pen.x += slot->advance.x; 2227 pen.y += slot->advance.y; 2228 2229 /* record current glyph index */ 2230 previous = glyph_index; 2231 } 2232 2233 /* Free the face and the library objects */ 2234 FT_Done_Face ( face ); 2235 FT_Done_FreeType( library ); 2236 2237 delete[] ucs4text; 2238 } 2239 2240 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) 2241 { 2242 plot_text( face_path, fontsize, x_start, y_start, angle, text, ((double) red)/65535.0, ((double) green)/65535.0, ((double) blue)/65535.0 ); 2243 } 2244 2245 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) 2246 { 2247 plot_text_utf8( face_path, fontsize, x_start, y_start, angle, text, ((double) red)/65535.0, ((double) green)/65535.0, ((double) blue)/65535.0 ); 2248 } 2249 2250 void pngwriter::my_draw_bitmap( FT_Bitmap * bitmap, int x, int y, double red, double green, double blue) 2251 { 2252 double temp; 2253 for(int j=1; j<bitmap->rows+1; j++) 2254 { 2255 for(int i=1; i< bitmap->width + 1; i++) 2256 { 2257 temp = (double)(bitmap->buffer[(j-1)*bitmap->width + (i-1)] )/255.0; 2258 2259 if(temp) 2260 { 2261 this->plot(x + i, 2262 y - j, 2263 temp*red + (1-temp)*(this->dread(x+i,y-j,1)), 2264 temp*green + (1-temp)*(this->dread(x+i,y-j,2)), 2265 temp*blue + (1-temp)*(this->dread(x+i,y-j,3)) 2266 ); 2267 } 2268 } 2269 } 2270 } 2271 2272 2273 2274 //////////// Get text width 2275 2276 //put in freetype section 2277 2278 int pngwriter::get_text_width(char * face_path, int fontsize, char * text) 2279 { 2280 2281 FT_Library library; 2282 FT_Face face; 2283 FT_Matrix matrix; // transformation matrix 2284 FT_Vector pen; 2285 2286 FT_UInt glyph_index; 2287 FT_Error error; 2288 2289 FT_Bool use_kerning; 2290 FT_UInt previous = 0; 2291 2292 /* Set up transformation Matrix */ 2293 matrix.xx = (FT_Fixed)( 1.0*0x10000); /* It would make more sense to do this (below), but, bizzarely, */ 2294 matrix.xy = (FT_Fixed)( 0.0*0x10000); /* if one does, FT_Load_Glyph fails consistently. */ 2295 matrix.yx = (FT_Fixed)( 0.0*0x10000); // matrix.yx = - matrix.xy; 2296 matrix.yy = (FT_Fixed)( 1.0*0x10000); // matrix.yy = matrix.xx; 2297 2298 /* Place starting coordinates in adequate form. */ 2299 pen.x = 0; 2300 pen.y = 0; 2301 2302 /*Count the length of the string */ 2303 int num_chars = strlen(text); 2304 2305 /* Initialize FT Library object */ 2306 error = FT_Init_FreeType( &library ); 2307 if (error) { std::cerr << " PNGwriter::get_text_width - ERROR **: FreeType: Could not init Library."<< std::endl; return 0;} 2308 2309 /* Initialize FT face object */ 2310 error = FT_New_Face( library,face_path,0,&face ); 2311 if ( error == FT_Err_Unknown_File_Format ) { std::cerr << " PNGwriter::get_text_width - ERROR **: FreeType: Font was opened, but type not supported."<< std::endl; return 0; } else if (error){ std::cerr << " PNGwriter::get_text_width - ERROR **: FreeType: Could not find or load font file." << std::endl; return 0; } 2312 2313 /* Set the Char size */ 2314 error = FT_Set_Char_Size( face, /* handle to face object */ 2315 0, /* char_width in 1/64th of points */ 2316 fontsize*64, /* char_height in 1/64th of points */ 2317 100, /* horizontal device resolution */ 2318 100 ); /* vertical device resolution */ 2319 2320 /* A way of accesing the glyph directly */ 2321 FT_GlyphSlot slot = face->glyph; // a small shortcut 2322 2323 /* Does the font file support kerning? */ 2324 use_kerning = FT_HAS_KERNING( face ); 2325 2326 int n; 2327 for ( n = 0; n < num_chars; n++ ) 2328 { 2329 /* Convert character code to glyph index */ 2330 glyph_index = FT_Get_Char_Index( face, text[n] ); 2331 2332 /* Retrieve kerning distance and move pen position */ 2333 if ( use_kerning && previous&& glyph_index ) 2334 { 2335 FT_Vector delta; 2336 FT_Get_Kerning( face, 2337 previous, 2338 glyph_index, 2339 ft_kerning_default, //FT_KERNING_DEFAULT, 2340 &delta ); 2341 2342 /* Transform this kerning distance into rotated space */ 2343 pen.x += (int) ( delta.x); 2344 pen.y += 0; 2345 } 2346 2347 /* Set transform */ 2348 FT_Set_Transform( face, &matrix, &pen ); 2349 2350 /*set char size*/ 2351 2352 if (error) { std::cerr << " PNGwriter::get_text_width - ERROR **: FreeType: Set char size error." << std::endl; return 0;}; 2353 2354 /* Retrieve glyph index from character code */ 2355 glyph_index = FT_Get_Char_Index( face, text[n] ); 2356 2357 /* Load glyph image into the slot (erase previous one) */ 2358 error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT ); 2359 if (error) { std::cerr << " PNGwriter::get_text_width - ERROR **: FreeType: Could not load glyph (in loop). (FreeType error "<< std::hex << error <<")." << std::endl; return 0;} 2360 2361 /* Convert to an anti-aliased bitmap */ 2362 // error = FT_Render_Glyph( face->glyph, FT_RENDER_MODE_NORMAL ); 2363 error = FT_Render_Glyph( face->glyph, ft_render_mode_normal ); 2364 if (error) { std::cerr << " PNGwriter::get_text_width - ERROR **: FreeType: Render glyph error." << std::endl; return 0;} 2365 2366 /* Now, draw to our target surface */ 2367 /* my_draw_bitmap( &slot->bitmap, 2368 slot->bitmap_left, 2369 slot->bitmap_top, 2370 red, 2371 green, 2372 blue ); 2373 */ 2374 /* Advance to the next position */ 2375 pen.x += slot->advance.x; 2376 // std::cout << ((double) pen.x)/64.0 << std::endl; 2377 pen.y += slot->advance.y; 2378 2379 /* record current glyph index */ 2380 previous = glyph_index; 2381 } 2382 2383 2384 /* Free the face and the library objects */ 2385 FT_Done_Face ( face ); 2386 FT_Done_FreeType( library ); 2387 2388 return (int)( ((double)pen.x)/64.0 ); 2389 } 2390 2391 2392 int pngwriter::get_text_width_utf8(char * face_path, int fontsize, char * text) 2393 { 2394 FT_Library library; 2395 FT_Face face; 2396 FT_Matrix matrix; // transformation matrix 2397 FT_Vector pen; 2398 2399 FT_UInt glyph_index; 2400 FT_Error error; 2401 2402 FT_Bool use_kerning; 2403 FT_UInt previous = 0; 2404 2405 /* Set up transformation Matrix */ 2406 matrix.xx = (FT_Fixed)( 0x10000); /* It would make more sense to do this (below), but, bizzarely, */ 2407 matrix.xy = (FT_Fixed)( 0*0x10000); /* if one does, FT_Load_Glyph fails consistently. */ 2408 matrix.yx = (FT_Fixed)( 0*0x10000); // matrix.yx = - matrix.xy; 2409 matrix.yy = (FT_Fixed)( 0x10000); // matrix.yy = matrix.xx; 2410 2411 /* Place starting coordinates in adequate form. */ 2412 pen.x = 0 ; 2413 pen.y = 0; 2414 2415 /*Count the length of the string */ 2416 int num_bytes=0; 2417 while(text[num_bytes]!=0) 2418 { 2419 num_bytes++; 2420 } 2421 2422 /* 2423 std::cout << "Num bytes is: "<< num_bytes << std::endl; 2424 */ 2425 2426 //The array of ucs4 glyph indexes, which will by at most the number of bytes in the utf-8 file. 2427 long * ucs4text; 2428 ucs4text = new long[num_bytes+1]; 2429 2430 unsigned char u,v,w,x,y,z; 2431 2432 int num_chars=0; 2433 2434 long iii=0; 2435 2436 while(iii<num_bytes) 2437 { 2438 z = text[iii]; 2439 2440 if(z<=127) 2441 { 2442 ucs4text[num_chars] = z; 2443 } 2444 2445 if((192<=z)&&(z<=223)) 2446 { 2447 iii++; y = text[iii]; 2448 ucs4text[num_chars] = (z-192)*64 + (y -128); 2449 } 2450 2451 if((224<=z)&&(z<=239)) 2452 { 2453 iii++; y = text[iii]; 2454 iii++; x = text[iii]; 2455 ucs4text[num_chars] = (z-224)*4096 + (y -128)*64 + (x-128); 2456 } 2457 2458 if((240<=z)&&(z<=247)) 2459 { 2460 iii++; y = text[iii]; 2461 iii++; x = text[iii]; 2462 iii++; w = text[iii]; 2463 ucs4text[num_chars] = (z-240)*262144 + (y -128)*4096 + (x-128)*64 + (w-128); 2464 } 2465 2466 if((248<=z)&&(z<=251)) 2467 { 2468 iii++; y = text[iii]; 2469 iii++; x = text[iii]; 2470 iii++; w = text[iii]; 2471 iii++; v = text[iii]; 2472 ucs4text[num_chars] = (z-248)*16777216 + (y -128)*262144 + (x-128)*4096 + (w-128)*64 +(v-128); 2473 } 2474 2475 if((252==z)||(z==253)) 2476 { 2477 iii++; y = text[iii]; 2478 iii++; x = text[iii]; 2479 iii++; w = text[iii]; 2480 iii++; v = text[iii]; 2481 u = text[iii]; 2482 ucs4text[num_chars] = (z-252)*1073741824 + (y -128)*16777216 + (x-128)*262144 + (w-128)*4096 +(v-128)*64 + (u-128); 2483 } 2484 2485 if((z==254)||(z==255)) 2486 { 2487 std::cerr << " PNGwriter::get_text_width_utf8 - ERROR **: Problem with character: invalid UTF-8 data."<< std::endl; 2488 } 2489 // std::cerr << "\nProblem at " << iii << ".\n"; 2490 // 2491 iii++; 2492 num_chars++; 2493 } 2494 2495 // num_chars now contains the number of characters in the string. 2496 /* 2497 std::cout << "Num chars is: "<< num_chars << std::endl; 2498 */ 2499 2500 /* Initialize FT Library object */ 2501 error = FT_Init_FreeType( &library ); 2502 if (error) { std::cerr << " PNGwriter::get_text_width_utf8 - ERROR **: FreeType: Could not init Library."<< std::endl; return 0;} 2503 2504 /* Initialize FT face object */ 2505 error = FT_New_Face( library,face_path,0,&face ); 2506 if ( error == FT_Err_Unknown_File_Format ) { std::cerr << " PNGwriter::get_text_width_utf8 - ERROR **: FreeType: Font was opened, but type not supported."<< std::endl; return 0; } else if (error){ std::cerr << " PNGwriter::plot_text - ERROR **: FreeType: Could not find or load font file."<< std::endl; return 0; } 2507 2508 /* Set the Char size */ 2509 error = FT_Set_Char_Size( face, /* handle to face object */ 2510 0, /* char_width in 1/64th of points */ 2511 fontsize*64, /* char_height in 1/64th of points */ 2512 100, /* horizontal device resolution */ 2513 100 ); /* vertical device resolution */ 2514 2515 /* A way of accesing the glyph directly */ 2516 FT_GlyphSlot slot = face->glyph; // a small shortcut 2517 2518 /* Does the font file support kerning? */ 2519 use_kerning = FT_HAS_KERNING( face ); 2520 2521 int n; 2522 for ( n = 0; n < num_chars; n++ ) 2523 { 2524 /* Convert character code to glyph index */ 2525 glyph_index = FT_Get_Char_Index( face, ucs4text[n] ); 2526 2527 /* Retrieve kerning distance and move pen position */ 2528 if ( use_kerning && previous&& glyph_index ) 2529 { 2530 FT_Vector delta; 2531 FT_Get_Kerning( face, 2532 previous, 2533 glyph_index, 2534 ft_kerning_default, //FT_KERNING_DEFAULT, 2535 &delta ); 2536 2537 /* Transform this kerning distance into rotated space */ 2538 pen.x += (int) (delta.x); 2539 pen.y += 0; 2540 } 2541 2542 /* Set transform */ 2543 FT_Set_Transform( face, &matrix, &pen ); 2544 2545 /*set char size*/ 2546 2547 if (error) { std::cerr << " PNGwriter::get_text_width_utf8 - ERROR **: FreeType: Set char size error." << std::endl; return 0;}; 2548 2549 /* Retrieve glyph index from character code */ 2550 glyph_index = FT_Get_Char_Index( face, ucs4text[n] ); 2551 2552 /* Load glyph image into the slot (erase previous one) */ 2553 error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT ); 2554 if (error) { std::cerr << " PNGwriter::get_text_width_utf8 - ERROR **: FreeType: Could not load glyph (in loop). (FreeType error "<< std::hex << error <<")." << std::endl; return 0;} 2555 2556 /* Convert to an anti-aliased bitmap */ 2557 error = FT_Render_Glyph( face->glyph, ft_render_mode_normal ); 2558 if (error) { std::cerr << " PNGwriter::get_text_width_utf8 - ERROR **: FreeType: Render glyph error." << std::endl; return 0;} 2559 2560 /* Now, draw to our target surface */ 2561 /* my_draw_bitmap( &slot->bitmap, 2562 slot->bitmap_left, 2563 y_start + slot->bitmap_top, 2564 red, 2565 green, 2566 blue ); 2567 */ 2568 /* Advance to the next position */ 2569 pen.x += slot->advance.x; 2570 pen.y += slot->advance.y; 2571 2572 /* record current glyph index */ 2573 previous = glyph_index; 2574 } 2575 2576 /* Free the face and the library objects */ 2577 FT_Done_Face ( face ); 2578 FT_Done_FreeType( library ); 2579 2580 delete[] ucs4text; 2581 2582 return (int) (((double) pen.x)/64.0); 2583 } 2584 2585 /////////////// 2586 #endif 2587 #ifdef NO_FREETYPE 2588 2589 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) 2590 { 2591 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; 2592 return; 2593 } 2594 2595 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) 2596 { 2597 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; 2598 return; 2599 2600 } 2601 2602 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) 2603 { 2604 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; 2605 return; 2606 } 2607 2608 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) 2609 { 2610 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; 2611 return; 2612 } 2613 2614 //////////// Get text width 2615 int pngwriter::get_text_width(char * face_path, int fontsize, char * text) 2616 { 2617 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; 2618 return 0; 2619 } 2620 2621 2622 int pngwriter::get_text_width_utf8(char * face_path, int fontsize, char * text) 2623 { 2624 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; 2625 return 0; 2626 } 2627 2628 /////////////// 2629 #endif 2630 2631 ///////////////////////////////////// 2632 int pngwriter::bilinear_interpolation_read(double x, double y, int colour) 2633 { 2634 2635 int inty, intx; 2636 inty = (int) ceil(y); 2637 intx = (int) ceil(x); 2638 2639 //inty = (int) floor(y) +1; 2640 // intx = (int) floor(x) +1; 2641 // 2642 bool attop, atright; 2643 attop = inty==this->height_; 2644 atright = intx==this->width_; 2645 /* 2646 if( intx==this->width_ +1) 2647 { 2648 intx--; 2649 // std::cout << "intx--" << std::endl; 2650 2651 } 2652 */ 2653 /* 2654 if(inty == this->height_ +1) 2655 { 2656 inty--; 2657 // std::cout << "inty--" << std::endl; 2658 } 2659 */ 2660 2661 if( (!attop)&&(!atright) ) 2662 { 2663 2664 double f,g,f1,g1; 2665 f = 1.0 + x - ((double) intx); 2666 g = 1.0 + y - ((double) inty); 2667 f1 = 1.0 - f; 2668 g1 = 1.0 - g; 2669 2670 return (int) ( 2671 f1*g1*this->read(intx, inty,colour) 2672 + f*g1*this->read(intx+1,inty,colour) 2673 +f1*g*this->read(intx,inty+1,colour) 2674 + f*g*(this->read(intx+1,inty+1,colour)) 2675 ); 2676 } 2677 2678 if( (atright)&&(!attop)) 2679 { 2680 2681 double f,g,f1,g1; 2682 f = 1.0 + x - ((double) intx); 2683 g = 1.0 + y - ((double) inty); 2684 f1 = 1.0 - f; 2685 g1 = 1.0 - g; 2686 2687 return (int) ( 2688 f1*g1*this->read(intx, inty,colour) 2689 + f*g1*( 2*(this->read(intx,inty,colour)) - (this->read(intx-1,inty,colour)) ) 2690 +f1*g*this->read(intx,inty+1,colour) 2691 + f*g*(2*(this->read(intx,inty+1,colour)) - (this->read(intx-1,inty+1,colour))) 2692 ); 2693 } 2694 2695 if((attop)&&(!atright)) 2696 { 2697 double f,g,f1,g1; 2698 f = 1.0 + x - ((double) intx); 2699 g = 1.0 + y - ((double) inty); 2700 f1 = 1.0 - f; 2701 g1 = 1.0 - g; 2702 2703 return (int) ( 2704 f1*g1*this->read(intx, inty,colour) 2705 + f*g1*this->read(intx+1,inty,colour) 2706 +f1*g*( 2*(this->read(intx,inty,colour)) - this->read(intx,inty-1,colour) ) 2707 + f*g*( 2*(this->read(intx+1,inty,colour)) - this->read(intx+1,inty-1,colour)) 2708 ); 2709 } 2710 2711 double f,g,f1,g1; 2712 f = 1.0 + x - ((double) intx); 2713 g = 1.0 + y - ((double) inty); 2714 f1 = 1.0 - f; 2715 g1 = 1.0 - g; 2716 2717 return (int) ( 2718 f1*g1*this->read(intx, inty,colour) 2719 + f*g1*( 2*(this->read(intx,inty,colour)) - (this->read(intx-1,inty,colour)) ) 2720 +f1*g*( 2*(this->read(intx,inty,colour)) - this->read(intx,inty-1,colour) ) 2721 + 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)) )) 2722 ); 2723 2724 /* 2725 return (int) ( 2726 f1*g1*this->read(intx, inty,colour) 2727 + f*g1*this->read(intx+1,inty,colour) 2728 +f1*g*this->read(intx,inty+1,colour) 2729 + f*g*this->read(intx+1, inty+1,colour) 2730 ); 2731 * */ 2732 2733 }; 2734 2735 double pngwriter::bilinear_interpolation_dread(double x, double y, int colour) 2736 { 2737 return double(this->bilinear_interpolation_read(x,y,colour))/65535.0; 2738 }; 2739 2740 void pngwriter::plot_blend(int x, int y, double opacity, int red, int green, int blue) 2741 { 2742 this->plot(x, y, 2743 (int)( opacity*red + this->read(x,y,1)*(1.0-opacity)), 2744 (int)( opacity*green + this->read(x,y,2)*(1.0-opacity)), 2745 (int)( opacity*blue + this->read(x,y,3)*(1.0-opacity)) 2746 ); 2747 }; 2748 2749 void pngwriter::plot_blend(int x, int y, double opacity, double red, double green, double blue) 2750 { 2751 this->plot_blend(x, y, opacity, (int) (65535*red), (int) (65535*green), (int) (65535*blue)); 2752 }; 2753 2754 void pngwriter::invert(void) 2755 { 2756 // int temp1, temp2, temp3; 2757 double temp11, temp22, temp33; 2758 2759 for(int jjj = 1; jjj <= (this->height_); jjj++) 2760 { 2761 for(int iii = 1; iii <= (this->width_); iii++) 2762 { 2763 /* temp11 = (this->read(iii,jjj,1)); 2764 temp22 = (this->read(iii,jjj,2)); 2765 temp33 = (this->read(iii,jjj,3)); 2766 * 2767 this->plot(iii,jjj, 2768 ((double)(65535 - temp11))/65535.0, 2769 ((double)(65535 - temp22))/65535.0, 2770 ((double)(65535 - temp33))/65535.0 2771 ); 2772 * 2773 */ 2774 temp11 = (this->read(iii,jjj,1)); 2775 temp22 = (this->read(iii,jjj,2)); 2776 temp33 = (this->read(iii,jjj,3)); 2777 2778 this->plot(iii,jjj, 2779 (int)(65535 - temp11), 2780 (int)(65535 - temp22), 2781 (int)(65535 - temp33) 2782 ); 2783 2784 } 2785 } 2786 } 2787 2788 void pngwriter::resize(int width, int height) 2789 { 2790 2791 for (int jjj = 0; jjj < height_; jjj++) free(graph_[jjj]); 2792 free(graph_); 2793 2794 width_ = width; 2795 height_ = height; 2796 backgroundcolour_ = 0; 2797 2798 graph_ = (png_bytepp)malloc(height_ * sizeof(png_bytep)); 2799 if(graph_ == NULL) 2800 { 2801 std::cerr << " PNGwriter::resize - ERROR **: Not able to allocate memory for image." << std::endl; 2802 } 2803 2804 for (int kkkk = 0; kkkk < height_; kkkk++) 2805 { 2806 graph_[kkkk] = (png_bytep)malloc(6*width_ * sizeof(png_byte)); 2807 if(graph_[kkkk] == NULL) 2808 { 2809 std::cerr << " PNGwriter::resize - ERROR **: Not able to allocate memory for image." << std::endl; 2810 } 2811 } 2812 2813 if(graph_ == NULL) 2814 { 2815 std::cerr << " PNGwriter::resize - ERROR **: Not able to allocate memory for image." << std::endl; 2816 } 2817 2818 int tempindex; 2819 for(int hhh = 0; hhh<width_;hhh++) 2820 { 2821 for(int vhhh = 0; vhhh<height_;vhhh++) 2822 { 2823 //graph_[vhhh][6*hhh + i] where i goes from 0 to 5 2824 tempindex = 6*hhh; 2825 graph_[vhhh][tempindex] = (char) floor(((double)backgroundcolour_)/256); 2826 graph_[vhhh][tempindex+1] = (char)(backgroundcolour_%256); 2827 graph_[vhhh][tempindex+2] = (char) floor(((double)backgroundcolour_)/256); 2828 graph_[vhhh][tempindex+3] = (char)(backgroundcolour_%256); 2829 graph_[vhhh][tempindex+4] = (char) floor(((double)backgroundcolour_)/256); 2830 graph_[vhhh][tempindex+5] = (char)(backgroundcolour_%256); 2831 } 2832 } 2833 } 2834 2835 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) 2836 { 2837 if( ( 2838 (this->dread(xstart,ystart,1) != boundary_red) || 2839 (this->dread(xstart,ystart,2) != boundary_green) || 2840 (this->dread(xstart,ystart,3) != boundary_blue) 2841 ) 2842 && 2843 ( 2844 (this->dread(xstart,ystart,1) != fill_red) || 2845 (this->dread(xstart,ystart,2) != fill_green) || 2846 (this->dread(xstart,ystart,3) != fill_blue) 2847 ) 2848 && 2849 (xstart >0)&&(xstart <= width_)&&(ystart >0)&&(ystart <= height_) 2850 ) 2851 { 2852 this->plot(xstart, ystart, fill_red, fill_green, fill_blue); 2853 boundary_fill(xstart+1, ystart, boundary_red, boundary_green, boundary_blue, fill_red, fill_green, fill_blue) ; 2854 boundary_fill(xstart, ystart+1, boundary_red, boundary_green, boundary_blue, fill_red, fill_green, fill_blue) ; 2855 boundary_fill(xstart, ystart-1, boundary_red, boundary_green, boundary_blue, fill_red, fill_green, fill_blue) ; 2856 boundary_fill(xstart-1, ystart, boundary_red, boundary_green, boundary_blue, fill_red, fill_green, fill_blue) ; 2857 } 2858 } 2859 2860 //no int version needed 2861 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) 2862 { 2863 if( ( 2864 (this->dread(xstart,ystart,1) == start_red) && 2865 (this->dread(xstart,ystart,2) == start_green) && 2866 (this->dread(xstart,ystart,3) == start_blue) 2867 ) 2868 && 2869 ( 2870 (this->dread(xstart,ystart,1) != fill_red) || 2871 (this->dread(xstart,ystart,2) != fill_green) || 2872 (this->dread(xstart,ystart,3) != fill_blue) 2873 ) 2874 && 2875 (xstart >0)&&(xstart <= width_)&&(ystart >0)&&(ystart <= height_) 2876 ) 2877 { 2878 this->plot(xstart, ystart, fill_red, fill_green, fill_blue); 2879 flood_fill_internal( xstart+1, ystart, start_red, start_green, start_blue, fill_red, fill_green, fill_blue); 2880 flood_fill_internal( xstart-1, ystart, start_red, start_green, start_blue, fill_red, fill_green, fill_blue); 2881 flood_fill_internal( xstart, ystart+1, start_red, start_green, start_blue, fill_red, fill_green, fill_blue); 2882 flood_fill_internal( xstart, ystart-1, start_red, start_green, start_blue, fill_red, fill_green, fill_blue); 2883 } 2884 2885 } 2886 2887 //int version 2888 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) 2889 { 2890 2891 this->boundary_fill( xstart, ystart, 2892 ((double) boundary_red)/65535.0, 2893 ((double) boundary_green)/65535.0, 2894 ((double) boundary_blue)/65535.0, 2895 ((double) fill_red)/65535.0, 2896 ((double) fill_green)/65535.0, 2897 ((double) fill_blue)/65535.0 2898 ); 2899 } 2900 2901 void pngwriter::flood_fill(int xstart, int ystart, double fill_red, double fill_green, double fill_blue) 2902 { 2903 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); 2904 } 2905 2906 //int version 2907 void pngwriter::flood_fill(int xstart, int ystart, int fill_red, int fill_green, int fill_blue) 2908 { 2909 this->flood_fill( xstart, ystart, 2910 ((double) fill_red)/65535.0, 2911 ((double) fill_green)/65535.0, 2912 ((double) fill_blue)/65535.0 2913 ); 2914 } 2915 2916 void pngwriter::polygon( int * points, int number_of_points, double red, double green, double blue) 2917 { 2918 if( (number_of_points<1)||(points ==NULL)) 2919 { 2920 std::cerr << " PNGwriter::polygon - ERROR **: Number of points is zero or negative, or array is NULL." << std::endl; 2921 return; 2922 } 2923 2924 for(int k=0;k< number_of_points-1; k++) 2925 { 2926 this->line(points[2*k],points[2*k+1],points[2*k+2],points[2*k+3], red, green, blue); 2927 } 2928 } 2929 2930 //int version 2931 void pngwriter::polygon( int * points, int number_of_points, int red, int green, int blue) 2932 { 2933 this->polygon(points, number_of_points, 2934 ((double) red)/65535.0, 2935 ((double) green)/65535.0, 2936 ((double) blue)/65535.0 2937 ); 2938 } 2939 2940 void pngwriter::plotCMYK(int x, int y, double cyan, double magenta, double yellow, double black) 2941 { 2942 /*CMYK to RGB: 2943 * ----------- 2944 * red = 255 - minimum(255,((cyan/255) * (255 - black) + black)) 2945 * green = 255 - minimum(255,((magenta/255) * (255 - black) + black)) 2946 * blue = 255 - minimum(255,((yellow/255) * (255 - black) + black)) 2947 * */ 2948 2949 if(cyan<0.0) 2950 { 2951 cyan = 0.0; 2952 } 2953 if(magenta<0.0) 2954 { 2955 magenta = 0.0; 2956 } 2957 if(yellow<0.0) 2958 { 2959 yellow = 0.0; 2960 } 2961 if(black<0.0) 2962 { 2963 black = 0.0; 2964 } 2965 2966 if(cyan>1.0) 2967 { 2968 cyan = 1.0; 2969 } 2970 if(magenta>1.0) 2971 { 2972 magenta = 1.0; 2973 } 2974 if(yellow>1.0) 2975 { 2976 yellow = 1.0; 2977 } 2978 if(black>1.0) 2979 { 2980 black = 1.0; 2981 } 2982 2983 double red, green, blue, minr, ming, minb, iblack; 2984 2985 iblack = 1.0 - black; 2986 2987 minr = 1.0; 2988 ming = 1.0; 2989 minb = 1.0; 2990 2991 if( (cyan*iblack + black)<1.0 ) 2992 { 2993 minr = cyan*iblack + black; 2994 } 2995 2996 if( (magenta*iblack + black)<1.0 ) 2997 { 2998 ming = magenta*iblack + black; 2999 } 3000 3001 if( (yellow*iblack + black)<1.0 ) 3002 { 3003 minb = yellow*iblack + black; 3004 } 3005 3006 red = 1.0 - minr; 3007 green = 1.0 - ming; 3008 blue = 1.0 - minb; 3009 3010 this->plot(x,y,red, green, blue); 3011 3012 } 3013 3014 //int version 3015 void pngwriter::plotCMYK(int x, int y, int cyan, int magenta, int yellow, int black) 3016 { 3017 this->plotCMYK( x, y, 3018 ((double) cyan)/65535.0, 3019 ((double) magenta)/65535.0, 3020 ((double) yellow)/65535.0, 3021 ((double) black)/65535.0 3022 ); 3023 } 3024 3025 double pngwriter::dreadCMYK(int x, int y, int colour) 3026 { 3027 /* 3028 * Black = minimum(1-Red,1-Green,1-Blue) 3029 * Cyan = (1-Red-Black)/(1-Black) 3030 * Magenta = (1-Green-Black)/(1-Black) 3031 * Yellow = (1-Blue-Black)/(1-Black) 3032 * 3033 * */ 3034 if((colour !=1)&&(colour !=2)&&(colour !=3)&&(colour !=4)) 3035 { 3036 std::cerr << " PNGwriter::dreadCMYK - WARNING **: Invalid argument: should be 1, 2, 3 or 4, is " << colour << std::endl; 3037 return 0; 3038 } 3039 3040 double black, red, green, blue, ired, igreen, iblue, iblack; 3041 //add error detection here 3042 // not much to detect, really 3043 red = this->dread(x, y, 1); 3044 green = this->dread(x, y, 2); 3045 blue = this->dread(x, y, 3); 3046 3047 ired = 1.0 - red; 3048 igreen = 1.0 - green; 3049 iblue = 1.0 - blue; 3050 3051 black = ired; 3052 3053 //black is the mimimum of inverse RGB colours, and if they are all equal, it is the inverse of red. 3054 if( (igreen<ired)&&(igreen<iblue) ) 3055 { 3056 black = igreen; 3057 } 3058 3059 if( (iblue<igreen)&&(iblue<ired) ) 3060 { 3061 black = iblue; 3062 } 3063 3064 iblack = 1.0 - black; 3065 3066 if(colour == 1) 3067 { 3068 return ((ired-black)/(iblack)); 3069 } 3070 3071 if(colour == 2) 3072 { 3073 return ((igreen-black)/(iblack)); 3074 } 3075 3076 if(colour == 3) 3077 { 3078 return ((iblue-black)/(iblack)); 3079 } 3080 3081 if(colour == 4) 3082 { 3083 return black; 3084 } 3085 3086 return 0.0; 3087 } 3088 3089 int pngwriter::readCMYK(int x, int y, int colour) 3090 { 3091 /* 3092 * Black = minimum(1-Red,1-Green,1-Blue) 3093 * Cyan = (1-Red-Black)/(1-Black) 3094 * Magenta = (1-Green-Black)/(1-Black) 3095 * Yellow = (1-Blue-Black)/(1-Black) 3096 * 3097 * */ 3098 if((colour !=1)&&(colour !=2)&&(colour !=3)&&(colour !=4)) 3099 { 3100 std::cerr << " PNGwriter::readCMYK - WARNING **: Invalid argument: should be 1, 2, 3 or 4, is " << colour << std::endl; 3101 return 0; 3102 } 3103 3104 double black, red, green, blue, ired, igreen, iblue, iblack; 3105 //add error detection here 3106 // not much to detect, really 3107 red = this->dread(x, y, 1); 3108 green = this->dread(x, y, 2); 3109 blue = this->dread(x, y, 3); 3110 3111 ired = 1.0 - red; 3112 igreen = 1.0 - green; 3113 iblue = 1.0 - blue; 3114 3115 black = ired; 3116 3117 //black is the mimimum of inverse RGB colours, and if they are all equal, it is the inverse of red. 3118 if( (igreen<ired)&&(igreen<iblue) ) 3119 { 3120 black = igreen; 3121 } 3122 3123 if( (iblue<igreen)&&(iblue<ired) ) 3124 { 3125 black = iblue; 3126 } 3127 3128 iblack = 1.0 - black; 3129 3130 if(colour == 1) 3131 { 3132 return (int)( ((ired-black)/(iblack))*65535); 3133 } 3134 3135 if(colour == 2) 3136 { 3137 return (int)( ((igreen-black)/(iblack))*65535); 3138 } 3139 3140 if(colour == 3) 3141 { 3142 return (int)( ((iblue-black)/(iblack))*65535); 3143 } 3144 3145 if(colour == 4) 3146 { 3147 return (int)( (black)*65535); 3148 } 3149 3150 return 0; 3151 3152 } 3153 3154 void pngwriter::scale_k(double k) 3155 { 3156 if(k <= 0.0) 3157 { 3158 std::cerr << " PNGwriter::scale_k - ERROR **: scale_k() called with negative or zero scale factor. Was: " << k << "." << std::endl; 3159 } 3160 3161 // Calculate the new scaled height and width 3162 int scaledh, scaledw; 3163 scaledw = (int) ceil(k*width_); 3164 scaledh = (int) ceil(k*height_); 3165 3166 // Create image storage. 3167 pngwriter temp(scaledw,scaledh,0,"temp"); 3168 3169 int red, green, blue; 3170 3171 double spacingx = ((double)width_)/(2*scaledw); 3172 double spacingy = ((double)height_)/(2*scaledh); 3173 3174 double readx, ready; 3175 3176 for(int x = 1; x<= scaledw; x++) 3177 { 3178 for(int y = 1; y <= scaledh; y++) 3179 { 3180 readx = (2*x-1)*spacingx; 3181 ready = (2*y-1)*spacingy; 3182 red = this->bilinear_interpolation_read(readx, ready, 1); 3183 green = this->bilinear_interpolation_read(readx, ready, 2); 3184 blue = this->bilinear_interpolation_read(readx, ready, 3); 3185 temp.plot(x, y, red, green, blue); 3186 3187 } 3188 } 3189 3190 // From here on, the process is the same for all scale functions. 3191 //Get data out of temp and into this's storage. 3192 3193 //Resize this instance 3194 // Delete current storage. 3195 for (int jjj = 0; jjj < height_; jjj++) free(graph_[jjj]); 3196 free(graph_); 3197 3198 //New image will have bit depth 16, regardless of original bit depth. 3199 bit_depth_ = 16; 3200 3201 // New width and height will be the scaled width and height 3202 width_ = scaledw; 3203 height_ = scaledh; 3204 backgroundcolour_ = 0; 3205 3206 graph_ = (png_bytepp)malloc(height_ * sizeof(png_bytep)); 3207 if(graph_ == NULL) 3208 { 3209 std::cerr << " PNGwriter::scale_k - ERROR **: Not able to allocate memory for image." << std::endl; 3210 } 3211 3212 for (int kkkk = 0; kkkk < height_; kkkk++) 3213 { 3214 graph_[kkkk] = (png_bytep)malloc(6*width_ * sizeof(png_byte)); 3215 if(graph_[kkkk] == NULL) 3216 { 3217 std::cerr << " PNGwriter::scale_k - ERROR **: Not able to allocate memory for image." << std::endl; 3218 } 3219 } 3220 3221 if(graph_ == NULL) 3222 { 3223 std::cerr << " PNGwriter::scale_k - ERROR **: Not able to allocate memory for image." << std::endl; 3224 } 3225 3226 //This instance now has a new, resized storage space. 3227 3228 //Copy the temp date into this's storage. 3229 int tempindex; 3230 for(int hhh = 0; hhh<width_;hhh++) 3231 { 3232 for(int vhhh = 0; vhhh<height_;vhhh++) 3233 { 3234 tempindex=6*hhh; 3235 graph_[vhhh][tempindex] = temp.graph_[vhhh][tempindex]; 3236 graph_[vhhh][tempindex+1] = temp.graph_[vhhh][tempindex+1]; 3237 graph_[vhhh][tempindex+2] = temp.graph_[vhhh][tempindex+2]; 3238 graph_[vhhh][tempindex+3] = temp.graph_[vhhh][tempindex+3]; 3239 graph_[vhhh][tempindex+4] = temp.graph_[vhhh][tempindex+4]; 3240 graph_[vhhh][tempindex+5] = temp.graph_[vhhh][tempindex+5]; 3241 } 3242 } 3243 3244 // this should now contain the new, scaled image data. 3245 // 3246 } 3247 3248 void pngwriter::scale_kxky(double kx, double ky) 3249 { 3250 if((kx <= 0.0)||(ky <= 0.0)) 3251 { 3252 std::cerr << " PNGwriter::scale_kxky - ERROR **: scale_kxky() called with negative or zero scale factor. Was: " << kx << ", " << ky << "." << std::endl; 3253 } 3254 3255 int scaledh, scaledw; 3256 scaledw = (int) ceil(kx*width_); 3257 scaledh = (int) ceil(ky*height_); 3258 3259 pngwriter temp(scaledw, scaledh, 0, "temp"); 3260 3261 int red, green, blue; 3262 3263 double spacingx = ((double)width_)/(2*scaledw); 3264 double spacingy = ((double)height_)/(2*scaledh); 3265 3266 double readx, ready; 3267 3268 for(int x = 1; x<= scaledw; x++) 3269 { 3270 for(int y = 1; y <= scaledh; y++) 3271 { 3272 readx = (2*x-1)*spacingx; 3273 ready = (2*y-1)*spacingy; 3274 red = this->bilinear_interpolation_read(readx, ready, 1); 3275 green = this->bilinear_interpolation_read(readx, ready, 2); 3276 blue = this->bilinear_interpolation_read(readx, ready, 3); 3277 temp.plot(x, y, red, green, blue); 3278 3279 } 3280 } 3281 // From here on, the process is the same for all scale functions. 3282 //Get data out of temp and into this's storage. 3283 3284 //Resize this instance 3285 // Delete current storage. 3286 for (int jjj = 0; jjj < height_; jjj++) free(graph_[jjj]); 3287 free(graph_); 3288 3289 //New image will have bit depth 16, regardless of original bit depth. 3290 bit_depth_ = 16; 3291 3292 // New width and height will be the scaled width and height 3293 width_ = scaledw; 3294 height_ = scaledh; 3295 backgroundcolour_ = 0; 3296 3297 graph_ = (png_bytepp)malloc(height_ * sizeof(png_bytep)); 3298 if(graph_ == NULL) 3299 { 3300 std::cerr << " PNGwriter::scale_kxky - ERROR **: Not able to allocate memory for image." << std::endl; 3301 } 3302 3303 for (int kkkk = 0; kkkk < height_; kkkk++) 3304 { 3305 graph_[kkkk] = (png_bytep)malloc(6*width_ * sizeof(png_byte)); 3306 if(graph_[kkkk] == NULL) 3307 { 3308 std::cerr << " PNGwriter::scale_kxky - ERROR **: Not able to allocate memory for image." << std::endl; 3309 } 3310 } 3311 3312 if(graph_ == NULL) 3313 { 3314 std::cerr << " PNGwriter::scale_kxky - ERROR **: Not able to allocate memory for image." << std::endl; 3315 } 3316 3317 //This instance now has a new, resized storage space. 3318 3319 //Copy the temp date into this's storage. 3320 int tempindex; 3321 for(int hhh = 0; hhh<width_;hhh++) 3322 { 3323 for(int vhhh = 0; vhhh<height_;vhhh++) 3324 { 3325 tempindex=6*hhh; 3326 graph_[vhhh][tempindex] = temp.graph_[vhhh][tempindex]; 3327 graph_[vhhh][tempindex+1] = temp.graph_[vhhh][tempindex+1]; 3328 graph_[vhhh][tempindex+2] = temp.graph_[vhhh][tempindex+2]; 3329 graph_[vhhh][tempindex+3] = temp.graph_[vhhh][tempindex+3]; 3330 graph_[vhhh][tempindex+4] = temp.graph_[vhhh][tempindex+4]; 3331 graph_[vhhh][tempindex+5] = temp.graph_[vhhh][tempindex+5]; 3332 } 3333 } 3334 3335 // this should now contain the new, scaled image data. 3336 // 3337 // 3338 } 3339 3340 void pngwriter::scale_wh(int finalwidth, int finalheight) 3341 { 3342 if((finalwidth <= 0)||(finalheight <= 0)) 3343 { 3344 std::cerr << " PNGwriter::scale_wh - ERROR **: Negative or zero final width or height not allowed." << std::endl; 3345 } 3346 3347 double kx; 3348 double ky; 3349 3350 kx = ((double)finalwidth)/((double)width_); 3351 ky = ((double)finalheight)/((double)height_); 3352 3353 pngwriter temp(finalwidth, finalheight, 0, "temp"); 3354 3355 int red, green, blue; 3356 3357 double spacingx = ((double)width_)/(2*finalwidth); 3358 double spacingy = ((double)height_)/(2*finalheight); 3359 3360 double readx, ready; 3361 3362 for(int x = 1; x<= finalwidth; x++) 3363 { 3364 for(int y = 1; y <= finalheight; y++) 3365 { 3366 readx = (2*x-1)*spacingx; 3367 ready = (2*y-1)*spacingy; 3368 red = this->bilinear_interpolation_read(readx, ready, 1); 3369 green = this->bilinear_interpolation_read(readx, ready, 2); 3370 blue = this->bilinear_interpolation_read(readx, ready, 3); 3371 temp.plot(x, y, red, green, blue); 3372 3373 } 3374 } 3375 3376 // From here on, the process is the same for all scale functions. 3377 //Get data out of temp and into this's storage. 3378 3379 //Resize this instance 3380 // Delete current storage. 3381 for (int jjj = 0; jjj < height_; jjj++) free(graph_[jjj]); 3382 free(graph_); 3383 3384 //New image will have bit depth 16, regardless of original bit depth. 3385 bit_depth_ = 16; 3386 3387 // New width and height will be the scaled width and height 3388 width_ = finalwidth; 3389 height_ = finalheight; 3390 backgroundcolour_ = 0; 3391 3392 graph_ = (png_bytepp)malloc(height_ * sizeof(png_bytep)); 3393 if(graph_ == NULL) 3394 { 3395 std::cerr << " PNGwriter::scale_wh - ERROR **: Not able to allocate memory for image." << std::endl; 3396 } 3397 3398 for (int kkkk = 0; kkkk < height_; kkkk++) 3399 { 3400 graph_[kkkk] = (png_bytep)malloc(6*width_ * sizeof(png_byte)); 3401 if(graph_[kkkk] == NULL) 3402 { 3403 std::cerr << " PNGwriter::scale_wh - ERROR **: Not able to allocate memory for image." << std::endl; 3404 } 3405 } 3406 3407 if(graph_ == NULL) 3408 { 3409 std::cerr << " PNGwriter::scale_wh - ERROR **: Not able to allocate memory for image." << std::endl; 3410 } 3411 3412 //This instance now has a new, resized storage space. 3413 3414 //Copy the temp date into this's storage. 3415 int tempindex; 3416 for(int hhh = 0; hhh<width_;hhh++) 3417 { 3418 for(int vhhh = 0; vhhh<height_;vhhh++) 3419 { 3420 tempindex=6*hhh; 3421 graph_[vhhh][tempindex] = temp.graph_[vhhh][tempindex]; 3422 graph_[vhhh][tempindex+1] = temp.graph_[vhhh][tempindex+1]; 3423 graph_[vhhh][tempindex+2] = temp.graph_[vhhh][tempindex+2]; 3424 graph_[vhhh][tempindex+3] = temp.graph_[vhhh][tempindex+3]; 3425 graph_[vhhh][tempindex+4] = temp.graph_[vhhh][tempindex+4]; 3426 graph_[vhhh][tempindex+5] = temp.graph_[vhhh][tempindex+5]; 3427 } 3428 } 3429 3430 // this should now contain the new, scaled image data. 3431 // 3432 // 3433 } 3434 3435 // Blended functions 3436 // 3437 void pngwriter::plotHSV_blend(int x, int y, double opacity, double hue, double saturation, double value) 3438 { 3439 double red,green,blue; 3440 double *redp; 3441 double *greenp; 3442 double *bluep; 3443 3444 redp = &red; 3445 greenp = &green; 3446 bluep = &blue; 3447 3448 HSVtoRGB(redp,greenp,bluep,hue,saturation,value); 3449 plot_blend(x,y,opacity, red,green,blue); 3450 3451 } 3452 3453 void pngwriter::plotHSV_blend(int x, int y, double opacity, int hue, int saturation, int value) 3454 { 3455 plotHSV_blend(x, y, opacity, double(hue)/65535.0, double(saturation)/65535.0, double(value)/65535.0); 3456 } 3457 3458 void pngwriter::line_blend(int xfrom, int yfrom, int xto, int yto, double opacity, int red, int green,int blue) 3459 { 3460 // Bresenham Algorithm. 3461 // 3462 int dy = yto - yfrom; 3463 int dx = xto - xfrom; 3464 int stepx, stepy; 3465 3466 if (dy < 0) 3467 { 3468 dy = -dy; stepy = -1; 3469 } 3470 else 3471 { 3472 stepy = 1; 3473 } 3474 3475 if (dx < 0) 3476 { 3477 dx = -dx; stepx = -1; 3478 } 3479 else 3480 { 3481 stepx = 1; 3482 } 3483 dy <<= 1; // dy is now 2*dy 3484 dx <<= 1; // dx is now 2*dx 3485 3486 this->plot_blend(xfrom,yfrom,opacity, red,green,blue); 3487 3488 if (dx > dy) 3489 { 3490 int fraction = dy - (dx >> 1); 3491 3492 while (xfrom != xto) 3493 { 3494 if (fraction >= 0) 3495 { 3496 yfrom += stepy; 3497 fraction -= dx; 3498 } 3499 xfrom += stepx; 3500 fraction += dy; 3501 this->plot_blend(xfrom,yfrom,opacity, red,green,blue); 3502 } 3503 } 3504 else 3505 { 3506 int fraction = dx - (dy >> 1); 3507 while (yfrom != yto) 3508 { 3509 if (fraction >= 0) 3510 { 3511 xfrom += stepx; 3512 fraction -= dy; 3513 } 3514 yfrom += stepy; 3515 fraction += dx; 3516 this->plot_blend(xfrom,yfrom, opacity, red,green,blue); 3517 } 3518 } 3519 3520 } 3521 3522 void pngwriter::line_blend(int xfrom, int yfrom, int xto, int yto, double opacity, double red, double green,double blue) 3523 { 3524 this->line_blend( xfrom, 3525 yfrom, 3526 xto, 3527 yto, 3528 opacity, 3529 int (red*65535), 3530 int (green*65535), 3531 int (blue*65535) 3532 ); 3533 3534 } 3535 3536 void pngwriter::square_blend(int xfrom, int yfrom, int xto, int yto, double opacity, int red, int green,int blue) 3537 { 3538 this->line_blend(xfrom, yfrom, xfrom, yto, opacity, red, green, blue); 3539 this->line_blend(xto, yfrom, xto, yto, opacity, red, green, blue); 3540 this->line_blend(xfrom, yfrom, xto, yfrom, opacity, red, green, blue); 3541 this->line_blend(xfrom, yto, xto, yto, opacity, red, green, blue); 3542 } 3543 3544 void pngwriter::square_blend(int xfrom, int yfrom, int xto, int yto, double opacity, double red, double green,double blue) 3545 { 3546 this->square_blend( xfrom, yfrom, xto, yto, opacity, int(red*65535), int(green*65535), int(blue*65535)); 3547 } 3548 3549 void pngwriter::filledsquare_blend(int xfrom, int yfrom, int xto, int yto, double opacity, int red, int green,int blue) 3550 { 3551 for(int caca = xfrom; caca <xto+1; caca++) 3552 { 3553 this->line_blend(caca, yfrom, caca, yto, opacity, red, green, blue); 3554 } 3555 3556 } 3557 3558 void pngwriter::filledsquare_blend(int xfrom, int yfrom, int xto, int yto, double opacity, double red, double green,double blue) 3559 { 3560 this->filledsquare_blend( xfrom, yfrom, xto, yto, opacity, int(red*65535), int(green*65535), int(blue*65535)); 3561 } 3562 3563 void pngwriter::circle_aux_blend(int xcentre, int ycentre, int x, int y, double opacity, int red, int green, int blue) 3564 { 3565 if (x == 0) 3566 { 3567 this->plot_blend( xcentre, ycentre + y, opacity, red, green, blue); 3568 this->plot_blend( xcentre, ycentre - y, opacity, red, green, blue); 3569 this->plot_blend( xcentre + y, ycentre, opacity, red, green, blue); 3570 this->plot_blend( xcentre - y, ycentre, opacity, red, green, blue); 3571 } 3572 else 3573 if (x == y) 3574 { 3575 this->plot_blend( xcentre + x, ycentre + y, opacity, red, green, blue); 3576 this->plot_blend( xcentre - x, ycentre + y, opacity, red, green, blue); 3577 this->plot_blend( xcentre + x, ycentre - y, opacity, red, green, blue); 3578 this->plot_blend( xcentre - x, ycentre - y, opacity, red, green, blue); 3579 } 3580 else 3581 if (x < y) 3582 { 3583 this->plot_blend( xcentre + x, ycentre + y, opacity, red, green, blue); 3584 this->plot_blend( xcentre - x, ycentre + y, opacity, red, green, blue); 3585 this->plot_blend( xcentre + x, ycentre - y, opacity, red, green, blue); 3586 this->plot_blend( xcentre - x, ycentre - y, opacity, red, green, blue); 3587 this->plot_blend( xcentre + y, ycentre + x, opacity, red, green, blue); 3588 this->plot_blend( xcentre - y, ycentre + x, opacity, red, green, blue); 3589 this->plot_blend( xcentre + y, ycentre - x, opacity, red, green, blue); 3590 this->plot_blend( xcentre - y, ycentre - x, opacity, red, green, blue); 3591 } 3592 3593 } 3594 // 3595 3596 void pngwriter::circle_blend(int xcentre, int ycentre, int radius, double opacity, int red, int green, int blue) 3597 { 3598 int x = 0; 3599 int y = radius; 3600 int p = (5 - radius*4)/4; 3601 3602 circle_aux_blend(xcentre, ycentre, x, y, opacity, red, green, blue); 3603 while (x < y) 3604 { 3605 x++; 3606 if (p < 0) 3607 { 3608 p += 2*x+1; 3609 } 3610 else 3611 { 3612 y--; 3613 p += 2*(x-y)+1; 3614 } 3615 circle_aux_blend(xcentre, ycentre, x, y, opacity, red, green, blue); 3616 } 3617 3618 } 3619 3620 void pngwriter::circle_blend(int xcentre, int ycentre, int radius, double opacity, double red, double green, double blue) 3621 { 3622 this->circle_blend(xcentre,ycentre,radius, opacity, int(red*65535), int(green*65535), int(blue*65535)); 3623 } 3624 3625 void pngwriter::filledcircle_blend(int xcentre, int ycentre, int radius, double opacity, int red, int green, int blue) 3626 { 3627 for(int jjj = ycentre-radius; jjj< ycentre+radius+1; jjj++) 3628 { 3629 this->line_blend(xcentre - int(sqrt((double)(radius*radius) - (-ycentre + jjj)*(-ycentre + jjj ))), jjj, 3630 xcentre + int(sqrt((double)(radius*radius) - (-ycentre + jjj)*(-ycentre + jjj ))),jjj, opacity, red,green,blue); 3631 } 3632 3633 } 3634 3635 void pngwriter::filledcircle_blend(int xcentre, int ycentre, int radius, double opacity, double red, double green, double blue) 3636 { 3637 this->filledcircle_blend( xcentre, ycentre, radius, opacity, int(red*65535), int(green*65535), int(blue*65535)); 3638 } 3639 3640 void pngwriter::bezier_blend( int startPtX, int startPtY, 3641 int startControlX, int startControlY, 3642 int endPtX, int endPtY, 3643 int endControlX, int endControlY, 3644 double opacity, 3645 double red, double green, double blue) 3646 { 3647 3648 double cx = 3.0*(startControlX - startPtX); 3649 double bx = 3.0*(endControlX - startControlX) - cx; 3650 double ax = double(endPtX - startPtX - cx - bx); 3651 3652 double cy = 3.0*(startControlY - startPtY); 3653 double by = 3.0*(endControlY - startControlY) - cy; 3654 double ay = double(endPtY - startPtY - cy - by); 3655 3656 double x,y,newx,newy; 3657 x = startPtX; 3658 y = startPtY; 3659 3660 for(double t = 0.0; t<=1.005; t += 0.005) 3661 { 3662 newx = startPtX + t*(double(cx) + t*(double(bx) + t*(double(ax)))); 3663 newy = startPtY + t*(double(cy) + t*(double(by) + t*(double(ay)))); 3664 this->line_blend(int(x),int(y),int(newx),int(newy),opacity, red,green,blue); 3665 x = newx; 3666 y = newy; 3667 } 3668 } 3669 3670 void pngwriter::bezier_blend( int startPtX, int startPtY, 3671 int startControlX, int startControlY, 3672 int endPtX, int endPtY, 3673 int endControlX, int endControlY, 3674 double opacity, 3675 int red, int green, int blue) 3676 { 3677 this->bezier_blend( startPtX, startPtY, 3678 startControlX, startControlY, 3679 endPtX, endPtY, 3680 endControlX, endControlY, 3681 opacity, 3682 double(red)/65535.0, double(green)/65535.0, double(blue)/65535.0); 3683 3684 } 3685 3686 ///////////////////////////// 3687 #ifndef NO_FREETYPE 3688 3689 // Freetype-based text rendering functions. 3690 /////////////////////////////////////////// 3691 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) 3692 { 3693 FT_Library library; 3694 FT_Face face; 3695 FT_Matrix matrix; // transformation matrix 3696 FT_Vector pen; 3697 3698 FT_UInt glyph_index; 3699 FT_Error error; 3700 3701 FT_Bool use_kerning; 3702 FT_UInt previous = 0; 3703 3704 /* Set up transformation Matrix */ 3705 matrix.xx = (FT_Fixed)( cos(angle)*0x10000); /* It would make more sense to do this (below), but, bizzarely, */ 3706 matrix.xy = (FT_Fixed)(-sin(angle)*0x10000); /* if one does, FT_Load_Glyph fails consistently. */ 3707 matrix.yx = (FT_Fixed)( sin(angle)*0x10000); // matrix.yx = - matrix.xy; 3708 matrix.yy = (FT_Fixed)( cos(angle)*0x10000); // matrix.yy = matrix.xx; 3709 3710 /* Place starting coordinates in adequate form. */ 3711 pen.x = x_start*64 ; 3712 pen.y = (int)(y_start/64.0); 3713 3714 /*Count the length of the string */ 3715 int num_chars = strlen(text); 3716 3717 /* Initialize FT Library object */ 3718 error = FT_Init_FreeType( &library ); 3719 if (error) { std::cerr << " PNGwriter::plot_text_blend - ERROR **: FreeType: Could not init Library."<< std::endl; return;} 3720 3721 /* Initialize FT face object */ 3722 error = FT_New_Face( library,face_path,0,&face ); 3723 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; } 3724 3725 /* Set the Char size */ 3726 error = FT_Set_Char_Size( face, /* handle to face object */ 3727 0, /* char_width in 1/64th of points */ 3728 fontsize*64, /* char_height in 1/64th of points */ 3729 100, /* horizontal device resolution */ 3730 100 ); /* vertical device resolution */ 3731 3732 /* A way of accesing the glyph directly */ 3733 FT_GlyphSlot slot = face->glyph; // a small shortcut 3734 3735 /* Does the font file support kerning? */ 3736 use_kerning = FT_HAS_KERNING( face ); 3737 3738 int n; 3739 for ( n = 0; n < num_chars; n++ ) 3740 { 3741 /* Convert character code to glyph index */ 3742 glyph_index = FT_Get_Char_Index( face, text[n] ); 3743 3744 /* Retrieve kerning distance and move pen position */ 3745 if ( use_kerning && previous&& glyph_index ) 3746 { 3747 FT_Vector delta; 3748 FT_Get_Kerning( face, 3749 previous, 3750 glyph_index, 3751 ft_kerning_default, //FT_KERNING_DEFAULT, 3752 &delta ); 3753 3754 /* Transform this kerning distance into rotated space */ 3755 pen.x += (int) (((double) delta.x)*cos(angle)); 3756 pen.y += (int) (((double) delta.x)*( sin(angle))); 3757 } 3758 3759 /* Set transform */ 3760 FT_Set_Transform( face, &matrix, &pen ); 3761 3762 /*set char size*/ 3763 3764 if (error) { std::cerr << " PNGwriter::plot_text_blend - ERROR **: FreeType: Set char size error." << std::endl; return;}; 3765 3766 /* Retrieve glyph index from character code */ 3767 glyph_index = FT_Get_Char_Index( face, text[n] ); 3768 3769 /* Load glyph image into the slot (erase previous one) */ 3770 error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT ); 3771 if (error) { std::cerr << " PNGwriter::plot_text_blend - ERROR **: FreeType: Could not load glyph (in loop). (FreeType error "<< std::hex << error <<")." << std::endl; return;} 3772 3773 /* Convert to an anti-aliased bitmap */ 3774 // error = FT_Render_Glyph( face->glyph, FT_RENDER_MODE_NORMAL ); 3775 error = FT_Render_Glyph( face->glyph, ft_render_mode_normal ); 3776 if (error) { std::cerr << " PNGwriter::plot_text_blend - ERROR **: FreeType: Render glyph error." << std::endl; return;} 3777 3778 /* Now, draw to our target surface */ 3779 my_draw_bitmap_blend( &slot->bitmap, 3780 slot->bitmap_left, 3781 y_start + slot->bitmap_top, 3782 opacity, 3783 red, 3784 green, 3785 blue ); 3786 3787 /* Advance to the next position */ 3788 pen.x += slot->advance.x; 3789 pen.y += slot->advance.y; 3790 3791 /* record current glyph index */ 3792 previous = glyph_index; 3793 } 3794 3795 /* Free the face and the library objects */ 3796 FT_Done_Face ( face ); 3797 FT_Done_FreeType( library ); 3798 } 3799 3800 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) 3801 { 3802 FT_Library library; 3803 FT_Face face; 3804 FT_Matrix matrix; // transformation matrix 3805 FT_Vector pen; 3806 3807 FT_UInt glyph_index; 3808 FT_Error error; 3809 3810 FT_Bool use_kerning; 3811 FT_UInt previous = 0; 3812 3813 /* Set up transformation Matrix */ 3814 matrix.xx = (FT_Fixed)( cos(angle)*0x10000); /* It would make more sense to do this (below), but, bizzarely, */ 3815 matrix.xy = (FT_Fixed)(-sin(angle)*0x10000); /* if one does, FT_Load_Glyph fails consistently. */ 3816 matrix.yx = (FT_Fixed)( sin(angle)*0x10000); // matrix.yx = - matrix.xy; 3817 matrix.yy = (FT_Fixed)( cos(angle)*0x10000); // matrix.yy = matrix.xx; 3818 3819 /* Place starting coordinates in adequate form. */ 3820 pen.x = x_start*64 ; 3821 pen.y = (int)(y_start/64.0); 3822 3823 /*Count the length of the string */ 3824 int num_bytes=0; 3825 while(text[num_bytes]!=0) 3826 { 3827 num_bytes++; 3828 } 3829 3830 /* 3831 std::cout << "Num bytes is: "<< num_bytes << std::endl; 3832 */ 3833 3834 //The array of ucs4 glyph indexes, which will by at most the number of bytes in the utf-8 file. 3835 long * ucs4text; 3836 ucs4text = new long[num_bytes+1]; 3837 3838 unsigned char u,v,w,x,y,z; 3839 3840 int num_chars=0; 3841 3842 long iii=0; 3843 3844 while(iii<num_bytes) 3845 { 3846 z = text[iii]; 3847 3848 if(z<=127) 3849 { 3850 ucs4text[num_chars] = z; 3851 } 3852 3853 if((192<=z)&&(z<=223)) 3854 { 3855 iii++; y = text[iii]; 3856 ucs4text[num_chars] = (z-192)*64 + (y -128); 3857 } 3858 3859 if((224<=z)&&(z<=239)) 3860 { 3861 iii++; y = text[iii]; 3862 iii++; x = text[iii]; 3863 ucs4text[num_chars] = (z-224)*4096 + (y -128)*64 + (x-128); 3864 } 3865 3866 if((240<=z)&&(z<=247)) 3867 { 3868 iii++; y = text[iii]; 3869 iii++; x = text[iii]; 3870 iii++; w = text[iii]; 3871 ucs4text[num_chars] = (z-240)*262144 + (y -128)*4096 + (x-128)*64 + (w-128); 3872 } 3873 3874 if((248<=z)&&(z<=251)) 3875 { 3876 iii++; y = text[iii]; 3877 iii++; x = text[iii]; 3878 iii++; w = text[iii]; 3879 iii++; v = text[iii]; 3880 ucs4text[num_chars] = (z-248)*16777216 + (y -128)*262144 + (x-128)*4096 + (w-128)*64 +(v-128); 3881 } 3882 3883 if((252==z)||(z==253)) 3884 { 3885 iii++; y = text[iii]; 3886 iii++; x = text[iii]; 3887 iii++; w = text[iii]; 3888 iii++; v = text[iii]; 3889 u = text[iii]; 3890 ucs4text[num_chars] = (z-252)*1073741824 + (y -128)*16777216 + (x-128)*262144 + (w-128)*4096 +(v-128)*64 + (u-128); 3891 } 3892 3893 if((z==254)||(z==255)) 3894 { 3895 std::cerr << " PNGwriter::plot_text_utf8_blend - ERROR **: Problem with character: invalid UTF-8 data."<< std::endl; 3896 } 3897 // std::cerr << "\nProblem at " << iii << ".\n"; 3898 // 3899 iii++; 3900 num_chars++; 3901 } 3902 3903 // num_chars now contains the number of characters in the string. 3904 /* 3905 std::cout << "Num chars is: "<< num_chars << std::endl; 3906 */ 3907 3908 /* Initialize FT Library object */ 3909 error = FT_Init_FreeType( &library ); 3910 if (error) { std::cerr << " PNGwriter::plot_text_utf8_blend - ERROR **: FreeType: Could not init Library."<< std::endl; return;} 3911 3912 /* Initialize FT face object */ 3913 error = FT_New_Face( library,face_path,0,&face ); 3914 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; return; } else if (error){ std::cerr << " PNGwriter::plot_text - ERROR **: FreeType: Could not find or load font file."<< std::endl; return; } 3915 3916 /* Set the Char size */ 3917 error = FT_Set_Char_Size( face, /* handle to face object */ 3918 0, /* char_width in 1/64th of points */ 3919 fontsize*64, /* char_height in 1/64th of points */ 3920 100, /* horizontal device resolution */ 3921 100 ); /* vertical device resolution */ 3922 3923 /* A way of accesing the glyph directly */ 3924 FT_GlyphSlot slot = face->glyph; // a small shortcut 3925 3926 /* Does the font file support kerning? */ 3927 use_kerning = FT_HAS_KERNING( face ); 3928 3929 int n; 3930 for ( n = 0; n < num_chars; n++ ) 3931 { 3932 /* Convert character code to glyph index */ 3933 glyph_index = FT_Get_Char_Index( face, ucs4text[n] ); 3934 3935 /* Retrieve kerning distance and move pen position */ 3936 if ( use_kerning && previous&& glyph_index ) 3937 { 3938 FT_Vector delta; 3939 FT_Get_Kerning( face, 3940 previous, 3941 glyph_index, 3942 ft_kerning_default, //FT_KERNING_DEFAULT, 3943 &delta ); 3944 3945 /* Transform this kerning distance into rotated space */ 3946 pen.x += (int) (((double) delta.x)*cos(angle)); 3947 pen.y += (int) (((double) delta.x)*( sin(angle))); 3948 } 3949 3950 /* Set transform */ 3951 FT_Set_Transform( face, &matrix, &pen ); 3952 3953 /*set char size*/ 3954 3955 if (error) { std::cerr << " PNGwriter::plot_text_utf8_blend - ERROR **: FreeType: Set char size error." << std::endl; return;}; 3956 3957 /* Retrieve glyph index from character code */ 3958 glyph_index = FT_Get_Char_Index( face, ucs4text[n] ); 3959 3960 /* Load glyph image into the slot (erase previous one) */ 3961 error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT ); 3962 if (error) { std::cerr << " PNGwriter::plot_text_utf8_blend - ERROR **: FreeType: Could not load glyph (in loop). (FreeType error "<< std::hex << error <<")." << std::endl; return;} 3963 3964 /* Convert to an anti-aliased bitmap */ 3965 error = FT_Render_Glyph( face->glyph, ft_render_mode_normal ); 3966 if (error) { std::cerr << " PNGwriter::plot_text_utf8_blend - ERROR **: FreeType: Render glyph error." << std::endl; return;} 3967 3968 /* Now, draw to our target surface */ 3969 my_draw_bitmap_blend( &slot->bitmap, 3970 slot->bitmap_left, 3971 y_start + slot->bitmap_top, 3972 opacity, 3973 red, 3974 green, 3975 blue ); 3976 3977 /* Advance to the next position */ 3978 pen.x += slot->advance.x; 3979 pen.y += slot->advance.y; 3980 3981 /* record current glyph index */ 3982 previous = glyph_index; 3983 } 3984 3985 /* Free the face and the library objects */ 3986 FT_Done_Face ( face ); 3987 FT_Done_FreeType( library ); 3988 3989 delete[] ucs4text; 3990 } 3991 3992 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) 3993 { 3994 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 ); 3995 } 3996 3997 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) 3998 { 3999 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 ); 4000 } 4001 4002 void pngwriter::my_draw_bitmap_blend( FT_Bitmap * bitmap, int x, int y, double opacity, double red, double green, double blue) 4003 { 4004 double temp; 4005 for(int j=1; j<bitmap->rows+1; j++) 4006 { 4007 for(int i=1; i< bitmap->width + 1; i++) 4008 { 4009 temp = (double)(bitmap->buffer[(j-1)*bitmap->width + (i-1)] )/255.0; 4010 4011 if(temp) 4012 { 4013 this->plot_blend(x + i, 4014 y - j, 4015 opacity, 4016 temp*red + (1-temp)*(this->dread(x+i,y-j,1)), 4017 temp*green + (1-temp)*(this->dread(x+i,y-j,2)), 4018 temp*blue + (1-temp)*(this->dread(x+i,y-j,3)) 4019 ); 4020 } 4021 } 4022 } 4023 } 4024 4025 #endif 4026 #ifdef NO_FREETYPE 4027 4028 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) 4029 { 4030 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; 4031 return; 4032 } 4033 4034 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) 4035 { 4036 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; 4037 return; 4038 4039 } 4040 4041 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) 4042 { 4043 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; 4044 return; 4045 } 4046 4047 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) 4048 { 4049 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; 4050 return; 4051 } 4052 4053 #endif 4054 4055 /////////////////////////// 4056 4057 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) 4058 { 4059 if( ( 4060 (this->dread(xstart,ystart,1) != boundary_red) || 4061 (this->dread(xstart,ystart,2) != boundary_green) || 4062 (this->dread(xstart,ystart,3) != boundary_blue) 4063 ) 4064 && 4065 ( 4066 (this->dread(xstart,ystart,1) != fill_red) || 4067 (this->dread(xstart,ystart,2) != fill_green) || 4068 (this->dread(xstart,ystart,3) != fill_blue) 4069 ) 4070 && 4071 (xstart >0)&&(xstart <= width_)&&(ystart >0)&&(ystart <= height_) 4072 ) 4073 { 4074 this->plot_blend(xstart, ystart, opacity, fill_red, fill_green, fill_blue); 4075 boundary_fill_blend(xstart+1, ystart, opacity, boundary_red, boundary_green, boundary_blue, fill_red, fill_green, fill_blue) ; 4076 boundary_fill_blend(xstart, ystart+1, opacity, boundary_red, boundary_green, boundary_blue, fill_red, fill_green, fill_blue) ; 4077 boundary_fill_blend(xstart, ystart-1, opacity, boundary_red, boundary_green, boundary_blue, fill_red, fill_green, fill_blue) ; 4078 boundary_fill_blend(xstart-1, ystart, opacity, boundary_red, boundary_green, boundary_blue, fill_red, fill_green, fill_blue) ; 4079 } 4080 } 4081 4082 //no int version needed 4083 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) 4084 { 4085 if( ( 4086 (this->dread(xstart,ystart,1) == start_red) && 4087 (this->dread(xstart,ystart,2) == start_green) && 4088 (this->dread(xstart,ystart,3) == start_blue) 4089 ) 4090 && 4091 ( 4092 (this->dread(xstart,ystart,1) != fill_red) || 4093 (this->dread(xstart,ystart,2) != fill_green) || 4094 (this->dread(xstart,ystart,3) != fill_blue) 4095 ) 4096 && 4097 (xstart >0)&&(xstart <= width_)&&(ystart >0)&&(ystart <= height_) 4098 ) 4099 { 4100 this->plot_blend(xstart, ystart, opacity, fill_red, fill_green, fill_blue); 4101 flood_fill_internal_blend( xstart+1, ystart, opacity, start_red, start_green, start_blue, fill_red, fill_green, fill_blue); 4102 flood_fill_internal_blend( xstart-1, ystart,opacity, start_red, start_green, start_blue, fill_red, fill_green, fill_blue); 4103 flood_fill_internal_blend( xstart, ystart+1, opacity, start_red, start_green, start_blue, fill_red, fill_green, fill_blue); 4104 flood_fill_internal_blend( xstart, ystart-1, opacity, start_red, start_green, start_blue, fill_red, fill_green, fill_blue); 4105 } 4106 4107 } 4108 4109 //int version 4110 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) 4111 { 4112 4113 this->boundary_fill_blend( xstart, ystart, 4114 opacity, 4115 ((double) boundary_red)/65535.0, 4116 ((double) boundary_green)/65535.0, 4117 ((double) boundary_blue)/65535.0, 4118 ((double) fill_red)/65535.0, 4119 ((double) fill_green)/65535.0, 4120 ((double) fill_blue)/65535.0 4121 ); 4122 } 4123 4124 void pngwriter::flood_fill_blend(int xstart, int ystart, double opacity, double fill_red, double fill_green, double fill_blue) 4125 { 4126 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); 4127 } 4128 4129 //int version 4130 void pngwriter::flood_fill_blend(int xstart, int ystart, double opacity, int fill_red, int fill_green, int fill_blue) 4131 { 4132 this->flood_fill_blend( xstart, ystart, 4133 opacity, 4134 ((double) fill_red)/65535.0, 4135 ((double) fill_green)/65535.0, 4136 ((double) fill_blue)/65535.0 4137 ); 4138 } 4139 4140 void pngwriter::polygon_blend( int * points, int number_of_points, double opacity, double red, double green, double blue) 4141 { 4142 if( (number_of_points<1)||(points ==NULL)) 4143 { 4144 std::cerr << " PNGwriter::polygon_blend - ERROR **: Number of points is zero or negative, or array is NULL." << std::endl; 4145 return; 4146 } 4147 4148 for(int k=0;k< number_of_points-1; k++) 4149 { 4150 this->line_blend(points[2*k],points[2*k+1],points[2*k+2],points[2*k+3], opacity, red, green, blue); 4151 } 4152 } 4153 4154 //int version 4155 void pngwriter::polygon_blend( int * points, int number_of_points, double opacity, int red, int green, int blue) 4156 { 4157 this->polygon_blend(points, number_of_points, 4158 opacity, 4159 ((double) red)/65535.0, 4160 ((double) green)/65535.0, 4161 ((double) blue)/65535.0 4162 ); 4163 } 4164 4165 void pngwriter::plotCMYK_blend(int x, int y, double opacity, double cyan, double magenta, double yellow, double black) 4166 { 4167 /*CMYK to RGB: 4168 * ----------- 4169 * red = 255 - minimum(255,((cyan/255) * (255 - black) + black)) 4170 * green = 255 - minimum(255,((magenta/255) * (255 - black) + black)) 4171 * blue = 255 - minimum(255,((yellow/255) * (255 - black) + black)) 4172 * */ 4173 4174 if(cyan<0.0) 4175 { 4176 cyan = 0.0; 4177 } 4178 if(magenta<0.0) 4179 { 4180 magenta = 0.0; 4181 } 4182 if(yellow<0.0) 4183 { 4184 yellow = 0.0; 4185 } 4186 if(black<0.0) 4187 { 4188 black = 0.0; 4189 } 4190 4191 if(cyan>1.0) 4192 { 4193 cyan = 1.0; 4194 } 4195 if(magenta>1.0) 4196 { 4197 magenta = 1.0; 4198 } 4199 if(yellow>1.0) 4200 { 4201 yellow = 1.0; 4202 } 4203 if(black>1.0) 4204 { 4205 black = 1.0; 4206 } 4207 4208 double red, green, blue, minr, ming, minb, iblack; 4209 4210 iblack = 1.0 - black; 4211 4212 minr = 1.0; 4213 ming = 1.0; 4214 minb = 1.0; 4215 4216 if( (cyan*iblack + black)<1.0 ) 4217 { 4218 minr = cyan*iblack + black; 4219 } 4220 4221 if( (magenta*iblack + black)<1.0 ) 4222 { 4223 ming = magenta*iblack + black; 4224 } 4225 4226 if( (yellow*iblack + black)<1.0 ) 4227 { 4228 minb = yellow*iblack + black; 4229 } 4230 4231 red = 1.0 - minr; 4232 green = 1.0 - ming; 4233 blue = 1.0 - minb; 4234 4235 this->plot_blend(x,y,opacity, red, green, blue); 4236 4237 } 4238 4239 //int version 4240 void pngwriter::plotCMYK_blend(int x, int y, double opacity, int cyan, int magenta, int yellow, int black) 4241 { 4242 this->plotCMYK_blend( x, y, 4243 opacity, 4244 ((double) cyan)/65535.0, 4245 ((double) magenta)/65535.0, 4246 ((double) yellow)/65535.0, 4247 ((double) black)/65535.0 4248 ); 4249 } 4250 4251 void pngwriter::laplacian(double k, double offset) 4252 { 4253 4254 // Create image storage. 4255 pngwriter temp(width_,height_,0,"temp"); 4256 4257 double red, green, blue; 4258 4259 for(int x = 1; x <= width_; x++) 4260 { 4261 for(int y = 1; y <= height_; y++) 4262 { 4263 red = 4264 8.0*this->dread(x,y,1) - 4265 ( this->dread(x+1, y-1, 1) + 4266 this->dread(x, y-1, 1) + 4267 this->dread(x-1, y-1, 1) + 4268 this->dread(x-1, y, 1) + 4269 this->dread(x+1, y, 1) + 4270 this->dread(x+1, y+1, 1) + 4271 this->dread(x, y+1, 1) + 4272 this->dread(x-1, y+1, 1) ); 4273 4274 green = 4275 8.0*this->dread(x,y,2) - 4276 ( this->dread(x+1, y-1, 2) + 4277 this->dread(x, y-1, 2) + 4278 this->dread(x-1, y-1, 2) + 4279 this->dread(x-1, y, 2) + 4280 this->dread(x+1, y, 2) + 4281 this->dread(x+1, y+1, 2) + 4282 this->dread(x, y+1, 2) + 4283 this->dread(x-1, y+1, 2)); 4284 4285 blue = 4286 8.0*this->dread(x,y,3) - 4287 ( this->dread(x+1, y-1, 3) + 4288 this->dread(x, y-1, 3) + 4289 this->dread(x-1, y-1, 3) + 4290 this->dread(x-1, y, 3) + 4291 this->dread(x+1, y, 3) + 4292 this->dread(x+1, y+1, 3) + 4293 this->dread(x, y+1, 3) + 4294 this->dread(x-1, y+1, 3)); 4295 4296 temp.plot(x,y,offset+k*red,offset+k*green,offset+k*blue); 4297 4298 } 4299 } 4300 4301 for(int xx = 1; xx <= width_; xx++) 4302 { 4303 for(int yy = 1; yy <= height_; yy++) 4304 { 4305 this->plot(xx,yy, temp.read(xx,yy,1), temp.read(xx,yy,2), temp.read(xx,yy,3)); 4306 } 4307 } 4308 } 4309 4310 4311 4312 // drwatop(), drawbottom() and filledtriangle() were contributed by Gurkan Sengun 4313 // ( <gurkan@linuks.mine.nu>, http://www.linuks.mine.nu/ ) 4314 void pngwriter::drawtop(long x1,long y1,long x2,long y2,long x3, int red, int green, int blue) 4315 { 4316 // This swaps x2 and x3 4317 // if(x2>x3) x2^=x3^=x2^=x3; 4318 if(x2>x3) 4319 { 4320 x2^=x3; 4321 x3^=x2; 4322 x2^=x3; 4323 } 4324 4325 long posl = x1*256; 4326 long posr = posl; 4327 4328 long cl=((x2-x1)*256)/(y2-y1); 4329 long cr=((x3-x1)*256)/(y2-y1); 4330 4331 for(int y=y1; y<y2; y++) 4332 { 4333 this->line(posl/256, y, posr/256, y, red, green, blue); 4334 posl+=cl; 4335 posr+=cr; 4336 } 4337 } 4338 4339 // drwatop(), drawbottom() and filledtriangle() were contributed by Gurkan Sengun 4340 // ( <gurkan@linuks.mine.nu>, http://www.linuks.mine.nu/ ) 4341 void pngwriter::drawbottom(long x1,long y1,long x2,long x3,long y3, int red, int green, int blue) 4342 { 4343 //Swap x1 and x2 4344 //if(x1>x2) x2^=x1^=x2^=x1; 4345 if(x1>x2) 4346 { 4347 x2^=x1; 4348 x1^=x2; 4349 x2^=x1; 4350 } 4351 4352 long posl=x1*256; 4353 long posr=x2*256; 4354 4355 long cl=((x3-x1)*256)/(y3-y1); 4356 long cr=((x3-x2)*256)/(y3-y1); 4357 4358 for(int y=y1; y<y3; y++) 4359 { 4360 this->line(posl/256, y, posr/256, y, red, green, blue); 4361 4362 posl+=cl; 4363 posr+=cr; 4364 } 4365 } 4366 4367 // drwatop(), drawbottom() and filledtriangle() were contributed by Gurkan Sengun 4368 // ( <gurkan@linuks.mine.nu>, http://www.linuks.mine.nu/ ) 4369 void pngwriter::filledtriangle(int x1,int y1,int x2,int y2,int x3,int y3, int red, int green, int blue) 4370 { 4371 if((x1==x2 && x2==x3) || (y1==y2 && y2==y3)) return; 4372 4373 if(y2<y1) 4374 { 4375 // x2^=x1^=x2^=x1; 4376 x2^=x1; 4377 x1^=x2; 4378 x2^=x1; 4379 // y2^=y1^=y2^=y1; 4380 y2^=y1; 4381 y1^=x2; 4382 y2^=y1; 4383 } 4384 4385 if(y3<y1) 4386 { 4387 //x3^=x1^=x3^=x1; 4388 x3^=x1; 4389 x1^=x3; 4390 x3^=x1; 4391 //y3^=y1^=y3^=y1; 4392 y3^=y1; 4393 y1^=y3; 4394 y3^=y1; 4395 } 4396 4397 if(y3<y2) 4398 { 4399 //x2^=x3^=x2^=x3; 4400 x2^=x3; 4401 x3^=x2; 4402 x2^=x3; 4403 //y2^=y3^=y2^=y3; 4404 y2^=y3; 4405 y3^=y2; 4406 y2^=y3; 4407 } 4408 4409 if(y2==y3) 4410 { 4411 this->drawtop(x1, y1, x2, y2, x3, red, green, blue); 4412 } 4413 else 4414 { 4415 if(y1==y3 || y1==y2) 4416 { 4417 this->drawbottom(x1, y1, x2, x3, y3, red, green, blue); 4418 } 4419 else 4420 { 4421 int new_x = x1 + (int)((double)(y2-y1)*(double)(x3-x1)/(double)(y3-y1)); 4422 this->drawtop(x1, y1, new_x, y2, x2, red, green, blue); 4423 this->drawbottom(x2, y2, new_x, x3, y3, red, green, blue); 4424 } 4425 } 4426 4427 } 4428 4429 //Double (bug found by Dave Wilks. Was: (int) red*65535, should have been (int) (red*65535). 4430 void pngwriter::filledtriangle(int x1,int y1,int x2,int y2,int x3,int y3, double red, double green, double blue) 4431 { 4432 this->filledtriangle(x1, y1, x2, y2, x3, y3, (int) (red*65535), (int) (green*65535), (int) (blue*65535)); 4433 } 4434 4435 //Blend, double. (bug found by Dave Wilks. Was: (int) red*65535, should have been (int) (red*65535). 4436 void pngwriter::filledtriangle_blend(int x1,int y1,int x2,int y2,int x3,int y3, double opacity, double red, double green, double blue) 4437 { 4438 this->filledtriangle_blend( x1, y1, x2, y2, x3, y3, opacity, (int) (red*65535), (int) (green*65535), (int) (blue*65535)); 4439 } 4440 4441 //Blend, int 4442 void pngwriter::filledtriangle_blend(int x1,int y1,int x2,int y2,int x3,int y3, double opacity, int red, int green, int blue) 4443 { 4444 if((x1==x2 && x2==x3) || (y1==y2 && y2==y3)) return; 4445 4446 /*if(y2<y1) 4447 { 4448 x2^=x1^=x2^=x1; 4449 y2^=y1^=y2^=y1; 4450 } 4451 4452 if(y3<y1) 4453 { 4454 x3^=x1^=x3^=x1; 4455 y3^=y1^=y3^=y1; 4456 } 4457 4458 if(y3<y2) 4459 { 4460 x2^=x3^=x2^=x3; 4461 y2^=y3^=y2^=y3; 4462 } 4463 */ 4464 4465 if(y2<y1) 4466 { 4467 // x2^=x1^=x2^=x1; 4468 x2^=x1; 4469 x1^=x2; 4470 x2^=x1; 4471 // y2^=y1^=y2^=y1; 4472 y2^=y1; 4473 y1^=x2; 4474 y2^=y1; 4475 } 4476 4477 if(y3<y1) 4478 { 4479 //x3^=x1^=x3^=x1; 4480 x3^=x1; 4481 x1^=x3; 4482 x3^=x1; 4483 //y3^=y1^=y3^=y1; 4484 y3^=y1; 4485 y1^=y3; 4486 y3^=y1; 4487 } 4488 4489 if(y3<y2) 4490 { 4491 //x2^=x3^=x2^=x3; 4492 x2^=x3; 4493 x3^=x2; 4494 x2^=x3; 4495 //y2^=y3^=y2^=y3; 4496 y2^=y3; 4497 y3^=y2; 4498 y2^=y3; 4499 } 4500 4501 4502 if(y2==y3) 4503 { 4504 this->drawtop_blend(x1, y1, x2, y2, x3, opacity, red, green, blue); 4505 } 4506 else 4507 { 4508 if(y1==y3 || y1==y2) 4509 { 4510 this->drawbottom_blend(x1, y1, x2, x3, y3, opacity, red, green, blue); 4511 } 4512 else 4513 { 4514 int new_x = x1 + (int)((double)(y2-y1)*(double)(x3-x1)/(double)(y3-y1)); 4515 this->drawtop_blend(x1, y1, new_x, y2, x2, opacity, red, green, blue); 4516 this->drawbottom_blend(x2, y2, new_x, x3, y3, opacity, red, green, blue); 4517 } 4518 } 4519 4520 } 4521 4522 //Blend, int 4523 void pngwriter::drawbottom_blend(long x1,long y1,long x2,long x3,long y3, double opacity, int red, int green, int blue) 4524 { 4525 //Swap x1 and x2 4526 if(x1>x2) 4527 { 4528 x2^=x1; 4529 x1^=x2; 4530 x2^=x1; 4531 } 4532 4533 long posl=x1*256; 4534 long posr=x2*256; 4535 4536 long cl=((x3-x1)*256)/(y3-y1); 4537 long cr=((x3-x2)*256)/(y3-y1); 4538 4539 for(int y=y1; y<y3; y++) 4540 { 4541 this->line_blend(posl/256, y, posr/256, y, opacity, red, green, blue); 4542 4543 posl+=cl; 4544 posr+=cr; 4545 } 4546 4547 } 4548 4549 //Blend, int 4550 void pngwriter::drawtop_blend(long x1,long y1,long x2,long y2,long x3, double opacity, int red, int green, int blue) 4551 { 4552 // This swaps x2 and x3 4553 if(x2>x3) 4554 { 4555 x2^=x3; 4556 x3^=x2; 4557 x2^=x3; 4558 } 4559 4560 long posl = x1*256; 4561 long posr = posl; 4562 4563 long cl=((x2-x1)*256)/(y2-y1); 4564 long cr=((x3-x1)*256)/(y2-y1); 4565 4566 for(int y=y1; y<y2; y++) 4567 { 4568 this->line_blend(posl/256, y, posr/256, y, opacity, red, green, blue); 4569 posl+=cl; 4570 posr+=cr; 4571 } 4572 4573 } 4574 4575 void pngwriter::triangle(int x1, int y1, int x2, int y2, int x3, int y3, int red, int green, int blue) 4576 { 4577 this->line(x1, y1, x2, y2, red, green, blue); 4578 this->line(x2, y2, x3, y3, red, green, blue); 4579 this->line(x3, y3, x1, y1, red, green, blue); 4580 } 4581 4582 void pngwriter::triangle(int x1, int y1, int x2, int y2, int x3, int y3, double red, double green, double blue) 4583 { 4584 4585 this->line(x1, y1, x2, y2, ((int)65535*red), ((int)65535*green), ((int)65535*blue)); 4586 this->line(x2, y2, x3, y3, ((int)65535*red), ((int)65535*green), ((int)65535*blue)); 4587 this->line(x3, y3, x1, y1, ((int)65535*red), ((int)65535*green), ((int)65535*blue)); 4588 4589 } 4590 4591 4592 4593 4594 4595 void pngwriter::arrow( int x1,int y1,int x2,int y2,int size, double head_angle, double red, double green, double blue) 4596 { 4597 4598 this->line(x1, y1, x2, y2, red, green, blue); 4599 // double th = 3.141592653589793 + (head_angle)*3.141592653589793/180.0; //degrees 4600 double th = 3.141592653589793 + head_angle; 4601 double costh = cos(th); 4602 double sinth = sin(th); 4603 double t1, t2, r; 4604 t1 = ((x2-x1)*costh - (y2-y1)*sinth); 4605 t2 = ((x2-x1)*sinth + (y2-y1)*costh); 4606 r = sqrt(t1*t1 + t2*t2); 4607 4608 double advancex = size*t1/r; 4609 double advancey = size*t2/r; 4610 this->line(x2, y2, int(x2 + advancex), int(y2 + advancey), red, green, blue); 4611 t1 = (x2-x1)*costh + (y2-y1)*sinth; 4612 t2 = (y2-y1)*costh - (x2-x1)*sinth; 4613 4614 advancex = size*t1/r; 4615 advancey = size*t2/r; 4616 this->line(x2, y2, int(x2 + advancex), int(y2 + advancey), red, green, blue); 4617 } 4618 4619 void pngwriter::filledarrow( int x1,int y1,int x2,int y2,int size, double head_angle, double red, double green, double blue) 4620 { 4621 int p1x, p2x, p3x, p1y, p2y, p3y; 4622 4623 this->line(x1, y1, x2, y2, red, green, blue); 4624 double th = 3.141592653589793 + head_angle; 4625 double costh = cos(th); 4626 double sinth = sin(th); 4627 double t11, t12, t21, t22, r1, r2; 4628 t11 = ((x2-x1)*costh - (y2-y1)*sinth); 4629 t21 = ((x2-x1)*sinth + (y2-y1)*costh); 4630 t12 = (x2-x1)*costh + (y2-y1)*sinth; 4631 t22 = (y2-y1)*costh - (x2-x1)*sinth; 4632 4633 r1 = sqrt(t11*t11 + t21*t21); 4634 r2 = sqrt(t12*t12 + t22*t22); 4635 4636 double advancex1 = size*t11/r1; 4637 double advancey1 = size*t21/r1; 4638 double advancex2 = size*t12/r2; 4639 double advancey2 = size*t22/r2; 4640 4641 p1x = x2; 4642 p1y = y2; 4643 4644 p2x = int(x2 + advancex1); 4645 p2y = int(y2 + advancey1); 4646 4647 p3x = int(x2 + advancex2); 4648 p3y = int(y2 + advancey2); 4649 4650 4651 this->filledtriangle( p1x, p1y, p2x, p2y, p3x, p3y, red, green, blue); 4652 4653 } 4654 4655 void pngwriter::arrow( int x1,int y1,int x2,int y2,int size, double head_angle, int red, int green, int blue) 4656 { 4657 this->arrow( x1, y1, x2, y2, size, head_angle, (double (red))/65535.0, (double (green))/65535.0, (double (blue))/65535.0 ); 4658 } 4659 4660 void pngwriter::filledarrow( int x1,int y1,int x2,int y2,int size, double head_angle, int red, int green, int blue) 4661 { 4662 this->filledarrow( x1, y1, x2, y2, size, head_angle, (double (red))/65535.0, (double (green))/65535.0, (double (blue))/65535.0 ); 4663 } 4664 4665 4666 void pngwriter::cross( int x, int y, int xwidth, int yheight, int red, int green, int blue) 4667 { 4668 this->line(int(x - xwidth/2.0), y, int(x + xwidth/2.0), y, red, green, blue); 4669 this->line(x, int(y - yheight/2.0), x, int(y + yheight/2.0), red, green, blue); 4670 } 4671 4672 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) 4673 { 4674 this->line(int(x - xwidth/2.0), y, int(x + xwidth/2.0), y, red, green, blue); 4675 this->line(x, int(y - yheight/2.0), x, int(y + yheight/2.0), red, green, blue); 4676 // Bars on ends of vertical line 4677 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); 4678 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); 4679 // Bars on ends of horizontal line. 4680 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); 4681 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); 4682 } 4683 4684 void pngwriter::cross( int x, int y, int xwidth, int yheight, double red, double green, double blue) 4685 { 4686 this->cross( x, y, xwidth, yheight, int(65535*red), int(65535*green), int(65535*blue)); 4687 } 4688 4689 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) 4690 { 4691 this->maltesecross( x, y, xwidth, yheight, x_bar_height, y_bar_width, int(65535*red), int(65535*green), int(65535*blue)); 4692 } 4693 4694 4695 void pngwriter::filleddiamond( int x, int y, int width, int height, int red, int green, int blue) 4696 { 4697 this->filledtriangle( int(x - width/2.0), y, x, y, x, int(y + height/2.0), red, green, blue); 4698 this->filledtriangle( int(x + width/2.0), y, x, y, x, int(y + height/2.0), red, green, blue); 4699 this->filledtriangle( int(x - width/2.0), y, x, y, x, int(y - height/2.0), red, green, blue); 4700 this->filledtriangle( int(x + width/2.0), y, x, y, x, int(y - height/2.0), red, green, blue); 4701 } 4702 4703 void pngwriter::diamond( int x, int y, int width, int height, int red, int green, int blue) 4704 { 4705 this->line( int(x - width/2.0), y, x, int(y + height/2.0), red, green, blue); 4706 this->line( int(x + width/2.0), y, x, int(y + height/2.0), red, green, blue); 4707 this->line( int(x - width/2.0), y, x, int(y - height/2.0), red, green, blue); 4708 this->line( int(x + width/2.0), y, x, int(y - height/2.0), red, green, blue); 4709 } 4710 4711 4712 void pngwriter::filleddiamond( int x, int y, int width, int height, double red, double green, double blue) 4713 { 4714 this->filleddiamond( x, y, width, height, int(red*65535), int(green*65535), int(blue*65535) ); 4715 } 4716 4717 void pngwriter::diamond( int x, int y, int width, int height, double red, double green, double blue) 4718 { 4719 this->diamond( x, y, width, height, int(red*65535), int(green*65535), int(blue*65535) ); 4720 } 4721