LIBPOLYMNIA
ibuf-imp_.h
[詳解]
1 /**************************************************************************
2  *
3  * ibuf-imp_.h
4  * by oZ/acy
5  * (c) 2002-2016 oZ/acy. ALL RIGHTS RESERVED.
6  *
7  * implement of Image BUFfer template
8  * 畫像バッファクラステンプレート實裝部分
9  *
10  * 履歴
11  * 2016.2.26 ellipse()内の不使用變數の宣言を削除
12  */
13 #include <stack>
14 #include <cstring>
15 #include <cstdlib>
16 
17 
18 namespace polymnia{
19 
20 namespace imp_{
21 
22 /*----------------------------
23 * class Clip
24 * クリッピング處理用クラス
25 *---------------------------*/
26 class Clip_
27 {
28 public:
29  int sx, sy;
30  int w, h;
31  int dx, dy;
32 
33 private:
34  bool flag_;
35 
36 public:
37  Clip_(int ssx, int ssy, int ww, int hh, int ddx, int ddy, const Rect& mask);
38  operator bool() const { return flag_; }
39 };
40 
41 
42 }//end of namespace polymnia::imp_
43 }//end of namespace polymnia
44 
45 
46 
47 
48 /*=========================================
49 * ImageBuffer<C_>::blt()
50 * 轉送
51 *========================================*/
52 template<class C_>
53 inline
54 void
56  int dx, int dy, const polymnia::ImageBuffer<C_>* src, int sx, int sy,
57  int w, int h)
58 {
59  Rect rect(0, 0, w_ - 1, h_ - 1);
60  blt(dx, dy, src, sx, sy, w, h, rect);
61 }
62 
63 template<class C_>
64 inline
65 void
67  int dx, int dy, const polymnia::ImageBuffer<C_>* src, int sx, int sy,
68  int w, int h, const polymnia::Rect& mk)
69 {
70  imp_::Clip_ clip(sx, sy, w, h, dx, dy, mk);
71 
72  if (clip)
73  {
74  int dp = clip.dx + clip.dy * offset_;
75  int sp = clip.sx + clip.sy * src->offset_;
76  for (int i=0; i<clip.h; i++, dp+=offset_, sp+=src->offset_)
77  std::memcpy(&(buf_[dp]), &(src->buf_[sp]), clip.w * sizeof(C_));
78  }
79 }
80 
81 
82 template<class C_>
83 inline
84 void
86  int dx, int dy, const polymnia::ImageBuffer<C_>* src, int sx, int sy,
87  int w, int h, const C_& tcol)
88 {
89  Rect rect(0, 0, w_ - 1, h_ - 1);
90  blt(dx, dy, src, sx, sy, w, h, tcol, rect);
91 }
92 
93 template<class C_>
94 inline
95 void
97  int dx, int dy, const polymnia::ImageBuffer<C_>* src, int sx, int sy,
98  int w, int h, const C_& tcol, const polymnia::Rect& mk)
99 {
100  imp_::Clip_ clip(sx, sy, w, h, dx, dy, mk);
101 
102  if (clip)
103  {
104  int dp = clip.dx + clip.dy * offset_;
105  int sp = clip.sx + clip.sy * src->offset_;
106  for (int i = 0; i < clip.h; i++, dp += offset_, sp += src->offset_)
107  for (int j = 0; j < clip.w; j++)
108  {
109  if (src->buf_[sp + j] != tcol)
110  buf_[dp + j] = src->buf_[sp + j];
111  }
112  }
113 }
114 
115 
116 
117 template<class C_> template<class C2_>
118 inline
119 void
121  int dx,int dy, const polymnia::ImageBuffer<C2_>* src,
122  int sx, int sy, int w, int h)
123 {
124  Rect rect(0, 0, w_ - 1, h_ - 1);
125  blt(dx, dy, src, sx, sy, w, h, rect);
126 }
127 
128 template<class C_> template<class C2_>
129 inline
130 void
132  int dx, int dy, const polymnia::ImageBuffer<C2_>* src, int sx, int sy,
133  int w, int h, const polymnia::Rect& mk)
134 {
135  imp_::Clip_ clip(sx, sy, w, h, dx, dy, mk);
136 
137  if (clip)
138  {
139  const C2_* b = src->buffer();
140  int dp = clip.dx + clip.dy * offset_;
141  int sp = clip.sx + clip.sy * src->offset();
142  for (int j=0; j<clip.h; j++, dp+=offset_, sp+=src->offset())
143  for (int i=0; i<clip.w; i++)
144  buf_[dp + i] = b[sp + i];
145  }
146 }
147 
148 
149 template<class C_> template<class C2_>
150 inline
151 void
153  int dx,int dy, const polymnia::ImageBuffer<C2_>* src, int sx, int sy,
154  int w, int h, const C2_& tcol)
155 {
156  Rect rect(0, 0, w_ - 1, h_ - 1);
157  blt(dx, dy, src, sx, sy, w, h, tcol, rect);
158 }
159 
160 template<class C_> template<class C2_>
161 inline
162 void
164  int dx, int dy, const polymnia::ImageBuffer<C2_>* src, int sx, int sy,
165  int w, int h, const C2_& tcol, const polymnia::Rect& mk)
166 {
167  imp_::Clip_ clip(sx, sy, w, h, dx, dy, mk);
168 
169  if (clip)
170  {
171  const C2_* b = src->buffer();
172  int dp = clip.dx + clip.dy * offset_;
173  int sp = clip.sx + clip.sy * src->offset();
174  for (int j = 0; j < clip.h; j++, dp += offset_, sp += src->offset())
175  for (int i = 0; i < clip.w; i++)
176  if (b[sp + i] != tcol)
177  buf_[dp + i] = b[sp + i];
178  }
179 }
180 
181 
182 /*===============================================
183 * ImageBuffer<C_>::clear()
184 * 指定した色で全域をクリア
185 *==============================================*/
186 template<class C_>
187 inline void polymnia::ImageBuffer<C_>::clear(const C_& col)
188 {
189  int dp = 0;
190  for (int j = 0; j < h_; j++, dp += offset_)
191  for (int i = 0; i < w_; i++)
192  buf_[dp + i] = col;
193 }
194 
195 
196 
197 /*===============================================
198 * ImageBuffer<C>::addEffect()
199 * 畫像に効果處理をかける
200 *==============================================*/
201 /*
202 template<class C_>
203 inline void polymnia::ImageBuffer<C_>::addEffect(
204  const typename polymnia::ImageBuffer<C_>::Effecter& efc)
205 {
206  C_* src = new C_[h_ * offset_];
207  std::memcpy(src, buf_, sizeof(C_) * h_ * offset_);
208  efc(buf_, src, w_, h_, offset_);
209  delete[] src;
210 }
211 */
212 
213 
214 /*==========================================================
215 * ImageBuffer<C>::line()
216 * 直線を引く
217 * (Bresenham's Algorithm 參考: C MAGAZINE Dec. 2000)
218 *=========================================================*/
219 template<class C_>
220 inline
221 void
222 polymnia::ImageBuffer<C_>::line(int x1, int y1, int x2, int y2, const C_& col)
223 {
224  int dx, dy, sx, sy;
225 
226  dx = x2 - x1;
227  dy = y2 - y1;
228 
229  if (dx < 0)
230  {
231  sx = -1;
232  dx = -dx;
233  }
234  else if (dx == 0)
235  sx = 0;
236  else
237  sx = 1;
238 
239  if (dy < 0)
240  {
241  sy = -1;
242  dy = -dy;
243  }
244  else if (dy == 0)
245  sy = 0;
246  else
247  sy = 1;
248 
249  int xx1 = x1;
250  int xx2 = x2;
251  int yy1 = y1;
252  int yy2 = y2;
253 
254  int e, i, p, q;
255 
256  if (dx >= dy)
257  {
258  e = -dx;
259  int lx = (dx + 1) / 2;
260 
261  p = x1 + y1 * offset_;
262  q = x2 + y2 * offset_;
263 
264  for (i = 0; i < lx; i++)
265  {
266  if (xx1 >= 0 && xx1 < w_ && yy1 >= 0 && yy1 < h_)
267  buf_[p] = col;
268  if (xx2 >= 0 && xx2 < w_ && yy2 >= 0 && yy2 < h_)
269  buf_[q] = col;
270 
271  p += sx;
272  q -= sx;
273  xx1 += sx;
274  xx2 -= sx;
275  e += 2 * dy;
276  if (e >= 0)
277  {
278  if (sy > 0)
279  {
280  p += offset_;
281  q -= offset_;
282  yy1++;
283  yy2--;
284  }
285  else if (sy < 0)
286  {
287  p -= offset_;
288  q += offset_;
289  yy1--;
290  yy2++;
291  }
292 
293  e -= 2 * dx;
294  }
295  }
296 
297  if (!(dx % 2) && xx1 >= 0 && xx1 < w_ && yy1 >= 0 && yy1 < h_)
298  buf_[p] = col;
299  }
300  else
301  {
302  e = -dy;
303  int ly = (dy + 1) / 2;
304  p = x1 + y1 * offset_;
305  q = x2 + y2 * offset_;
306 
307  for (i = 0; i < ly; i++)
308  {
309  if (xx1 >= 0 && xx1 < w_ && yy1 >= 0 && yy1 < h_)
310  buf_[p] = col;
311  if (xx2 >= 0 && xx2 < w_ && yy2 >= 0 && yy2 < h_)
312  buf_[q] = col;
313 
314  if(sy > 0)
315  {
316  p += offset_;
317  q -= offset_;
318  yy1++;
319  yy2--;
320  }
321  else if (sy < 0)
322  {
323  p -= offset_;
324  q += offset_;
325  yy1--;
326  yy2++;
327  }
328 
329  e += 2 * dx;
330  if (e >= 0)
331  {
332  p += sx;
333  q -= sx;
334  xx1 += sx;
335  xx2 -= sx;
336  e -= 2 * dy;
337  }
338  }
339 
340  if (!(dy % 2) && xx1 >= 0 && xx1 < w_ && yy1 >= 0 && yy1 < h_)
341  buf_[p] = col;
342  }
343 }
344 
345 
346 /*===============================================
347 * ImageBuffer<C_>::box()
348 * 長方形を描く
349 *==============================================*/
350 template<class C_>
351 inline
352 void
354  int x1, int y1, int x2, int y2, const C_& col, bool fl)
355 {
356  // 座標の簡単化
357  if (x1>x2)
358  std::swap(x1, x2);
359  if (y1>y2)
360  std::swap(y1, y2);
361 
362  // 全部が範圍外なら return
363  if (x1>=w_ || x2<0 || y1>=h_ || y2<0)
364  return;
365 
366  // 範圍内に切りつめた値
367  int xx1, xx2, yy1, yy2;
368 
369  if (x1<0)
370  xx1 = 0;
371  else
372  xx1 = x1;
373 
374  if (x2>=w_)
375  xx2 = w_-1;
376  else
377  xx2 = x2;
378 
379  if (y1<0)
380  yy1 = 0;
381  else
382  yy1 = y1;
383 
384  if (y2>=h_)
385  yy2 = h_-1;
386  else
387  yy2 = y2;
388 
389  if (fl)
390  { // 塗り潰し
391  int i, j;
392  int p = yy1 * offset_;
393  //int w = xx2 - xx1;
394  for (i=yy1; i<=yy2; i++, p+=offset_)
395  for (j=xx1; j<=xx2; j++)
396  buf_[p+j] = col;
397  }
398  else
399  {
400  int i, p, q;
401 
402  // 横枠を描く
403  p = xx1 + y1*offset_;
404  q = xx1 + y2*offset_;
405  if (y1>=0)
406  {
407  if (y2<h_)
408  for (i=xx1; i<=xx2; i++,p++,q++)
409  buf_[p] = buf_[q] = col;
410  else
411  for (i=xx1; i<=xx2; i++,p++)
412  buf_[p] = col;
413  }
414  else
415  {
416  if (y2<h_)
417  for (i=xx1; i<=xx2; i++,q++)
418  buf_[q] = col;
419  }
420 
421  // 縦枠を描く
422  p = x1 + yy1*offset_;
423  q = x2 + yy1*offset_;
424  if (x1>=0)
425  {
426  if (x2<w_)
427  for (i=yy1; i<=yy2; i++, p+=offset_, q+=offset_)
428  buf_[p] = buf_[q] = col;
429  else
430  for (i=yy1; i<=yy2; i++,p+=offset_)
431  buf_[p] = col;
432  }
433  else
434  {
435  if (x2<w_)
436  for (i=yy1; i<=yy2; i++,q+=offset_)
437  buf_[q] = col;
438  }
439  }
440 }
441 
442 
443 /*============================================
444 * ImageBuffer<C>::ellipse()
445 * 楕円の描畫 (他のアルゴリズムを要檢討?)
446 *===========================================*/
447 /* 1 2
448  * 3 4
449  * 5 6 <-- コメント中で用いた番号
450  * 7 8
451  */
452 template<class C_>
453 inline
454 void
456  int x, int y, int a, int b, const C_& col, bool fl)
457 {
458  if (a==0 || b==0)
459  return;
460 
461  int ytp, ytm;
462 
463  a = std::abs(a);
464  b = std::abs(b);
465 
466  int p = 0;
467  int q, e;
468  if (a < b)
469  {
470  e = 2 - 3 * b;
471  q = b;
472  }
473  else
474  {
475  e = 2 - 3 * a;
476  q = a;
477  }
478 
479  while (p <= q)
480  {
481  if (e < 0)
482  e += (p << 2) + 6;
483  else
484  {
485  e += ((p - q) << 2) + 10;
486  q--;
487  }
488 
489  int s, t, s2, t2;
490  if (a < b)
491  {
492  s = p * a / b; // 1, 2, 7, 8
493  t = q;
494 
495  s2 = q * a / b; // 3, 4, 5, 6
496  t2 = p;
497  }
498  else
499  {
500  s = p;
501  t = q * b / a;
502 
503  s2 = q;
504  t2 = p * b / a;
505  }
506 
507  p++;
508 
509 
510  if (x - s < w_ && x + s >= 0 && y - t < h_ && y + t >= 0)
511  {
512  if (fl)
513  {
514  int i = (x - s < 0) ? 0 : x-s;
515  int j = (x + s + 1 >= w_) ? w_-1 : x + s + 1;
516  if (y + t < h_)
517  {
518  int ytp = (y + t) * offset_;
519 
520  if (y - t >= 0)
521  { // 1=>2, 7=>8
522  int ytm = (y - t) * offset_;
523  for ( ; i < j; ++i)
524  buf_[i + ytp] = buf_[i + ytm] = col;
525  }
526  else
527  { // 1=>2
528  for ( ; i < j; ++i)
529  buf_[i + ytp] = col;
530  }
531  }
532  else
533  {
534  if (y - t >= 0)
535  { //7->8
536  int ytm = (y - t) * offset_;
537  for ( ; i < j; i++)
538  buf_[i + ytm] = col;
539  }
540  }
541  }
542  else
543  {
544  bool xs1 = (x - s) >= 0;
545  bool xs2 = (x + s) < w_;
546 
547  if (y + t < h_)
548  {
549  ytp = (y + t) * offset_;
550  if (xs1)
551  buf_[x - s + ytp] = col; //1
552  if (xs2)
553  buf_[x + s + ytp] = col; //2
554  }
555  if (y - t >= 0)
556  {
557  ytm = (y - t) * offset_;
558  if (xs1)
559  buf_[x - s + ytm] = col; //7
560  if (xs2)
561  buf_[x + s + ytm] = col; //8
562  }
563  }
564  }
565 
566 
567  if (x - s2 < w_ && x + s2 >= 0 && y - t2 < h_ && y + t2 >= 0)
568  {
569  if (fl)
570  {
571  int i = (x - s2 < 0) ? 0 : x - s2;
572  int j = (x + s2 + 1 >= w_) ? w_ - 1 : x + s2 + 1;
573  if (y + t2 < h_)
574  {
575  int ytp = (y + t2) * offset_;
576 
577  if (y - t2 >= 0)
578  { // 3=>4, 5=>6
579  int ytm = (y - t2) * offset_;
580  for ( ; i < j; ++i)
581  buf_[i + ytp] = buf_[i + ytm] = col;
582  }
583  else
584  { // 3=>4
585  for ( ; i < j; ++i)
586  buf_[i + ytp] = col;
587  }
588  }
589  else
590  {
591  if (y - t2 >= 0)
592  { //5=>6
593  int ytm = (y - t2) * offset_;
594  for ( ; i < j; i++)
595  buf_[i + ytm] = col;
596  }
597  }
598  }
599  else
600  {
601  bool xs1 = (x - s2) >= 0;
602  bool xs2 = (x + s2) < w_;
603 
604  if (y + t2 < h_)
605  {
606  ytp = (y + t2) * offset_;
607  if (xs1)
608  buf_[x - s2 + ytp] = col; //3
609  if (xs2)
610  buf_[x + s2 + ytp] = col; //4
611  }
612  if (y - t2 >= 0)
613  {
614  ytm = (y - t2) * offset_;
615  if (xs1)
616  buf_[x - s2 + ytm] = col; //5
617  if (xs2)
618  buf_[x + s2 + ytm] = col; //6
619  }
620  }
621  }
622 
623  }// while
624 }
625 
626 
627 /*====================================================
628 * ImageBuffer<C>::paintFill()
629 * 所謂塗り潰し
630 *===================================================*/
631 template<class C_>
632 inline void polymnia::ImageBuffer<C_>::paintFill(int x, int y, const C_& col)
633 {
634  if (x < 0 || y < 0 || x >= w_ || y >= h_)
635  return;
636 
637  std::stack<int> p_stc;
638  unsigned pos = x + y*offset_;
639 
640  p_stc.push(pos);
641  C_ p_col = buf_[pos];
642  if (p_col==col)
643  return;
644 
645  while (!p_stc.empty())
646  {
647  int pt = p_stc.top();
648  p_stc.pop();
649 
650  int xx = pt % offset_;
651  int yy = pt / offset_;
652 
653  bool ful, fur;
654  if (yy > 0 && buf_[pt-offset_]==p_col)
655  {
656  p_stc.push(pt-offset_);
657  ful = fur = true;
658  }
659  else
660  ful = fur = false;
661 
662  bool fdl, fdr;
663  if (yy < h_ - 1 && buf_[pt+offset_]==p_col)
664  {
665  p_stc.push(pt+offset_);
666  fdl = fdr = true;
667  }
668  else
669  fdl = fdr = false;
670 
671 
672  int L = pt - 1;
673  int l = xx - 1;
674  int R = pt + 1;
675  int r = xx + 1;
676 
677  buf_[pt] = col;
678 
679  while (l >= 0 && buf_[L]==p_col)
680  {
681  if (L-offset_ >= 0)
682  {
683  if (ful && buf_[L-offset_] != p_col)
684  ful = false;
685  else if (!ful && buf_[L-offset_] == p_col)
686  {
687  ful = true;
688  p_stc.push(L-offset_);
689  }
690  }
691 
692  if (L+offset_ < h_*offset_)
693  {
694  if (fdl && buf_[L+offset_] != p_col)
695  fdl = false;
696  else if (!fdl && buf_[L+offset_] == p_col)
697  {
698  fdl = true;
699  p_stc.push(L+offset_);
700  }
701  }
702 
703  buf_[L] = col;
704  --L;
705  --l;
706  }
707 
708  while (r < w_ && buf_[R]==p_col)
709  {
710  if (R-offset_ >= 0)
711  {
712  if (fur)
713  fur = false;
714  else if (buf_[R-offset_]==p_col)
715  {
716  fur = true;
717  p_stc.push(R - offset_);
718  }
719  }
720 
721  if (R+offset_ < h_*offset_)
722  {
723  if (fdr && buf_[R+offset_] != p_col)
724  fdr = false;
725  else if (!fdr && buf_[R+offset_] == p_col)
726  {
727  fdr = true;
728  p_stc.push(R + offset_);
729  }
730  }
731 
732  buf_[R] = col;
733  ++R;
734  ++r;
735  }
736  }
737 }
738 
739 
740 
741 //eof
Definition: dibio.h:20
Definition: ibuf-imp_.h:26
int dy
Definition: ibuf-imp_.h:31
int offset_
オフセット 水平方向の1ラインのバッファサイズ
Definition: ibuf.h:106
int h
Definition: ibuf-imp_.h:30
void blt(int dx, int dy, const polymnia::ImageBuffer< C_ > *src, int sx, int sy, int w, int h)
轉送
Definition: ibuf-imp_.h:55
void paintFill(int x, int y, const C_ &col)
塗り潰し
Definition: ibuf-imp_.h:632
Clip_(int ssx, int ssy, int ww, int hh, int ddx, int ddy, const Rect &mask)
Definition: ibuf.cpp:14
int w
Definition: ibuf-imp_.h:30
void line(int x1, int y1, int x2, int y2, const C_ &col)
直線を描畫
Definition: ibuf-imp_.h:222
int sx
Definition: ibuf-imp_.h:29
int dx
Definition: ibuf-imp_.h:31
void ellipse(int x, int y, int a, int b, const C_ &col, bool fl=false)
楕圓を描畫
Definition: ibuf-imp_.h:455
長方形を表す構造體
Definition: ibuf.h:41
int sy
Definition: ibuf-imp_.h:29
C_ * buffer() noexcept
バッファの先頭アドレスを取得
Definition: ibuf.h:126
void box(int x1, int y1, int x2, int y2, const C_ &col, bool fl=false)
長方形を描畫
Definition: ibuf-imp_.h:353
void clear(const C_ &col)
バッファ全體の塗り潰し
Definition: ibuf-imp_.h:187
int offset() const noexcept
オフセットを取得
Definition: ibuf.h:123
C_ * buf_
畫像バッファ
Definition: ibuf.h:103
畫像バッファ基底クラステンプレート
Definition: ibuf.h:23