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