1 /*$
2 Copyright (C) 2013-2020 Azel.
3
4 This file is part of AzPainter.
5
6 AzPainter is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 AzPainter is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 $*/
19
20 /*****************************************
21 * ImageBuf8
22 *
23 * 8bit イメージ
24 *****************************************/
25 /*
26 * - 確保バッファサイズは 4byte 単位。
27 * - テクスチャ画像で使用される。
28 */
29
30
31 #include <string.h>
32
33 #include "mDef.h"
34 #include "mPixbuf.h"
35
36 #include "ImageBuf8.h"
37 #include "ImageBuf24.h"
38
39
40 #define _TOGRAY(r,g,b) ((r * 77 + g * 150 + b * 29) >> 8)
41
42
43
44 /** 解放 */
45
ImageBuf8_free(ImageBuf8 * p)46 void ImageBuf8_free(ImageBuf8 *p)
47 {
48 if(p)
49 {
50 mFree(p->buf);
51 mFree(p);
52 }
53 }
54
55 /** 作成 */
56
ImageBuf8_new(int w,int h)57 ImageBuf8 *ImageBuf8_new(int w,int h)
58 {
59 ImageBuf8 *p;
60 uint32_t size;
61
62 p = (ImageBuf8 *)mMalloc(sizeof(ImageBuf8), TRUE);
63 if(!p) return NULL;
64
65 size = (w * h + 3) & (~3);
66
67 p->buf = (uint8_t *)mMalloc(size, FALSE);
68 if(!p->buf)
69 {
70 mFree(p);
71 return NULL;
72 }
73
74 p->w = w;
75 p->h = h;
76 p->bufsize = size;
77
78 return p;
79 }
80
81 /** クリア */
82
ImageBuf8_clear(ImageBuf8 * p)83 void ImageBuf8_clear(ImageBuf8 *p)
84 {
85 memset(p->buf, 0, p->bufsize);
86 }
87
88 /** テクスチャ画像として色を取得 */
89
ImageBuf8_getPixel_forTexture(ImageBuf8 * p,int x,int y)90 uint8_t ImageBuf8_getPixel_forTexture(ImageBuf8 *p,int x,int y)
91 {
92 if(x < 0)
93 x += (-x / p->w + 1) * p->w;
94
95 if(y < 0)
96 y += (-y / p->h + 1) * p->h;
97
98 return *(p->buf + (y % p->h) * p->w + (x % p->w));
99 }
100
101 /** ImageBuf24 からテクスチャ画像として作成 */
102
ImageBuf8_createFromImageBuf24(ImageBuf24 * src)103 ImageBuf8 *ImageBuf8_createFromImageBuf24(ImageBuf24 *src)
104 {
105 ImageBuf8 *img;
106 uint8_t *pd,*ps;
107 uint32_t i;
108
109 img = ImageBuf8_new(src->w, src->h);
110 if(!img) return NULL;
111
112 //変換
113
114 pd = img->buf;
115 ps = src->buf;
116
117 for(i = src->w * src->h; i; i--, ps += 3)
118 *(pd++) = 255 - _TOGRAY(ps[0], ps[1], ps[2]);
119
120 return img;
121 }
122
123 /** ブラシ用画像として作成
124 *
125 * src が正方形でない場合は、正方形に調整される。 */
126
ImageBuf8_createFromImageBuf24_forBrush(ImageBuf24 * src)127 ImageBuf8 *ImageBuf8_createFromImageBuf24_forBrush(ImageBuf24 *src)
128 {
129 ImageBuf8 *img;
130 uint8_t *ps,*pd;
131 int sw,sh,size,pitchd,ix,iy;
132
133 //作成
134
135 sw = src->w, sh = src->h;
136
137 size = (sw < sh)? sh: sw;
138
139 img = ImageBuf8_new(size, size);
140 if(!img) return NULL;
141
142 ImageBuf8_clear(img);
143
144 //変換
145
146 pd = img->buf + ((size - sh) >> 1) * size + ((size - sw) >> 1);
147 ps = src->buf;
148 pitchd = size - sw;
149
150 for(iy = sh; iy; iy--, pd += pitchd)
151 {
152 for(ix = sw; ix; ix--, ps += 3)
153 *(pd++) = 255 - *ps;
154 }
155
156 return img;
157 }
158
159 /** mPixbuf にテクスチャプレビュー描画 */
160
ImageBuf8_drawTexturePreview(ImageBuf8 * p,mPixbuf * pixbuf,int x,int y,int w,int h)161 void ImageBuf8_drawTexturePreview(ImageBuf8 *p,mPixbuf *pixbuf,int x,int y,int w,int h)
162 {
163 mBox box;
164 int ix,iy,sw,sh,pitchd,bpp,fx,fy,fxleft;
165 uint8_t *pd,*psY;
166
167 if(!mPixbufGetClipBox_d(pixbuf, &box, x, y, w, h))
168 return;
169
170 sw = p->w, sh = p->h;
171
172 pd = mPixbufGetBufPtFast(pixbuf, box.x, box.y);
173 bpp = pixbuf->bpp;
174 pitchd = pixbuf->pitch_dir - box.w * bpp;
175
176 fxleft = (box.x - x) % sw;
177 fy = (box.y - y) % sh;
178
179 psY = p->buf + fy * sw;
180
181 //
182
183 for(iy = box.h; iy; iy--)
184 {
185 fx = fxleft;
186
187 for(ix = box.w; ix; ix--, pd += bpp)
188 {
189 (pixbuf->setbuf)(pd, mGraytoPix(255 - *(psY + fx)));
190
191 fx++;
192 if(fx == sw) fx = 0;
193 }
194
195 fy++;
196 if(fy == sh)
197 fy = 0, psY = p->buf;
198 else
199 psY += sw;
200
201 pd += pitchd;
202 }
203 }
204
205 /** mPixbuf にブラシ画像プレビュー描画
206 *
207 * 範囲内に収まるように縮小。左上寄せ。 */
208
ImageBuf8_drawBrushPreview(ImageBuf8 * p,mPixbuf * pixbuf,int x,int y,int w,int h)209 void ImageBuf8_drawBrushPreview(ImageBuf8 *p,mPixbuf *pixbuf,int x,int y,int w,int h)
210 {
211 uint8_t *pd,*psY;
212 mBox box;
213 int dsize,bpp,pitchd,finc,ix,iy,fx,fy,n;
214 uint32_t colex;
215
216 if(!mPixbufGetClipBox_d(pixbuf, &box, x, y, w, h))
217 return;
218
219 dsize = (w < h)? w: h;
220
221 pd = mPixbufGetBufPtFast(pixbuf, box.x, box.y);
222 bpp = pixbuf->bpp;
223 pitchd = pixbuf->pitch_dir - box.w * bpp;
224
225 finc = (int)((double)p->w / dsize * (1<<16) + 0.5);
226
227 colex = mGraytoPix(128);
228
229 //
230
231 for(iy = box.h, fy = 0; iy; iy--, fy += finc)
232 {
233 n = fy >> 16;
234 psY = (n < p->h)? p->buf + n * p->w: NULL;
235
236 for(ix = box.w, fx = 0; ix; ix--, fx += finc, pd += bpp)
237 {
238 n = fx >> 16;
239
240 if(!psY || n >= p->w)
241 (pixbuf->setbuf)(pd, colex);
242 else
243 (pixbuf->setbuf)(pd, mGraytoPix(255 - *(psY + n)));
244 }
245
246 pd += pitchd;
247 }
248 }
249