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 * TileImage
22 *
23 * RGBA 16bit タイプ (1pixel = 8byte)
24 *****************************************/
25 /*
26 * R-G-B-A の順で 1px ごとに並んでいる。
27 */
28
29 #include <string.h>
30 #include "mDef.h"
31
32 #include "defTileImage.h"
33 #include "TileImage_pv.h"
34 #include "TileImage_coltype.h"
35 #include "ImageBuf8.h"
36
37
38 /** 2色が同じ色か (タイルデータ上での色に置換えた時) */
39
_isSameColor(RGBAFix15 * p1,RGBAFix15 * p2)40 static mBool _isSameColor(RGBAFix15 *p1,RGBAFix15 *p2)
41 {
42 return ((p1->v64 == p2->v64) || (p1->a == 0 && p2->a == 0));
43 }
44
45 /** 2色が同じ色か (アルファ値は判定しない) */
46
_isSameRGB(RGBAFix15 * p1,RGBAFix15 * p2)47 static mBool _isSameRGB(RGBAFix15 *p1,RGBAFix15 *p2)
48 {
49 return (p1->r == p2->r && p1->g == p2->g && p1->b == p2->b);
50 }
51
52 /** タイルと px 位置からバッファ位置取得 */
53
_getPixelBufAtTile(TileImage * p,uint8_t * tile,int x,int y)54 static uint8_t *_getPixelBufAtTile(TileImage *p,uint8_t *tile,int x,int y)
55 {
56 x = (x - p->offx) & 63;
57 y = (y - p->offy) & 63;
58
59 return tile + (((y << 6) + x) << 3);
60 }
61
62 /** タイルと px 位置から色取得 */
63
_getPixelColAtTile(TileImage * p,uint8_t * tile,int x,int y,RGBAFix15 * dst)64 static void _getPixelColAtTile(TileImage *p,uint8_t *tile,int x,int y,RGBAFix15 *dst)
65 {
66 x = (x - p->offx) & 63;
67 y = (y - p->offy) & 63;
68
69 *dst = *((RGBAFix15 *)( tile + (((y << 6) + x) << 3) ));
70 }
71
72 /** 色をセット */
73
_setPixel(TileImage * p,uint8_t * buf,int x,int y,RGBAFix15 * rgb)74 static void _setPixel(TileImage *p,uint8_t *buf,int x,int y,RGBAFix15 *rgb)
75 {
76 *((RGBAFix15 *)buf) = *rgb;
77 }
78
79 /** タイルがすべて透明か */
80
_isTransparentTile(uint8_t * tile)81 static mBool _isTransparentTile(uint8_t *tile)
82 {
83 RGBAFix15 *ps = (RGBAFix15 *)tile;
84 int i;
85
86 for(i = 64 * 64; i; i--, ps++)
87 {
88 if(ps->a) return FALSE;
89 }
90
91 return TRUE;
92 }
93
94 /** ImageBufRGB16 に合成 */
95
_blendTile(TileImage * p,TileImageBlendInfo * info)96 static void _blendTile(TileImage *p,TileImageBlendInfo *info)
97 {
98 int pitchs,ix,iy,dx,dy,opacity,a;
99 RGBFix15 *pd,src,dst;
100 RGBAFix15 *ps;
101 TileImageFunc_BlendColor funcBlend;
102 ImageBuf8 *imgtex;
103
104 pd = (RGBFix15 *)info->dst;
105 ps = (RGBAFix15 *)info->tile + ((info->sy << 6) + info->sx);
106 pitchs = 64 - info->w;
107 opacity = info->opacity;
108 funcBlend = info->funcBlend;
109 imgtex = info->imgtex;
110
111 for(iy = info->h, dy = info->dy; iy; iy--, dy++)
112 {
113 for(ix = info->w, dx = info->dx; ix; ix--, dx++, ps++, pd++)
114 {
115 a = ps->a;
116 if(a == 0) continue;
117
118 if(imgtex)
119 a = a * ImageBuf8_getPixel_forTexture(imgtex, dx, dy) / 255;
120
121 a = a * opacity >> 7;
122
123 if(a)
124 {
125 //色合成
126
127 src.r = ps->r;
128 src.g = ps->g;
129 src.b = ps->b;
130
131 dst = *pd;
132
133 if((funcBlend)(&src, &dst, a))
134 *pd = src;
135 else
136 {
137 //アルファ合成
138
139 if(a == 0x8000)
140 *pd = src;
141 else
142 {
143 pd->r = ((src.r - dst.r) * a >> 15) + dst.r;
144 pd->g = ((src.g - dst.g) * a >> 15) + dst.g;
145 pd->b = ((src.b - dst.b) * a >> 15) + dst.b;
146 }
147 }
148 }
149 }
150
151 ps += pitchs;
152 pd += info->pitch_dst;
153 }
154 }
155
156 /** RGBA タイルとして取得 */
157
_getTileRGBA(TileImage * p,void * dst,uint8_t * src)158 static void _getTileRGBA(TileImage *p,void *dst,uint8_t *src)
159 {
160 memcpy(dst, src, 64 * 64 * 8);
161 }
162
163 /** RGBA タイルからセット */
164
_setTileFromRGBA(uint8_t * dst,void * src,mBool bLumtoA)165 static void _setTileFromRGBA(uint8_t *dst,void *src,mBool bLumtoA)
166 {
167 memcpy(dst, src, 64 * 64 * 8);
168 }
169
170 /** ファイル保存時用にタイル取得 */
171
_getTileForSave(uint8_t * dst,uint8_t * src)172 static void _getTileForSave(uint8_t *dst,uint8_t *src)
173 {
174 uint16_t *ps;
175 int i,j;
176
177 //BigEndian (R[64*64],G,...A)
178
179 for(j = 0; j < 4; j++)
180 {
181 ps = (uint16_t *)src + j;
182
183 for(i = 64 * 64; i; i--, dst += 2, ps += 4)
184 {
185 dst[0] = (uint8_t)(*ps >> 8);
186 dst[1] = (uint8_t)*ps;
187 }
188 }
189 }
190
191 /** ファイル保存用データからタイルセット */
192
_setTileForSave(uint8_t * dst,uint8_t * src)193 static void _setTileForSave(uint8_t *dst,uint8_t *src)
194 {
195 uint16_t *pd;
196 int i,j;
197
198 for(j = 0; j < 4; j++)
199 {
200 pd = (uint16_t *)dst + j;
201
202 for(i = 64 * 64; i; i--, pd += 4, src += 2)
203 *pd = (src[0] << 8) | src[1];
204 }
205 }
206
207 /** タイルを左右反転 */
208
_reverseHorz(uint8_t * tile)209 static void _reverseHorz(uint8_t *tile)
210 {
211 RGBAFix15 *p1,*p2,c;
212 int ix,iy;
213
214 p1 = (RGBAFix15 *)tile;
215 p2 = p1 + 63;
216
217 for(iy = 64; iy; iy--)
218 {
219 for(ix = 32; ix; ix--, p1++, p2--)
220 {
221 c = *p1;
222 *p1 = *p2;
223 *p2 = c;
224 }
225
226 p1 += 64 - 32;
227 p2 += 64 + 32;
228 }
229 }
230
231 /** タイルを上下反転 */
232
_reverseVert(uint8_t * tile)233 static void _reverseVert(uint8_t *tile)
234 {
235 RGBAFix15 *p1,*p2,c;
236 int ix,iy;
237
238 p1 = (RGBAFix15 *)tile;
239 p2 = p1 + 63 * 64;
240
241 for(iy = 32; iy; iy--, p2 -= 128)
242 {
243 for(ix = 64; ix; ix--, p1++, p2++)
244 {
245 c = *p1;
246 *p1 = *p2;
247 *p2 = c;
248 }
249 }
250 }
251
252 /** タイルを左に90度回転 */
253
_rotateLeft(uint8_t * tile)254 static void _rotateLeft(uint8_t *tile)
255 {
256 RGBAFix15 *p1,*p2,*p3,*p4,c1,c2;
257 int ix,iy;
258
259 p1 = (RGBAFix15 *)tile;
260 p2 = p1 + 63 * 64;
261 p3 = p1 + 63;
262 p4 = p2 + 63;
263
264 for(iy = 32; iy; iy--)
265 {
266 for(ix = 32; ix; ix--, p1++, p2 -= 64, p3 += 64, p4--)
267 {
268 c1 = *p1;
269 c2 = *p2;
270 *p1 = *p3;
271 *p2 = c1;
272 *p3 = *p4;
273 *p4 = c2;
274 }
275
276 p1 += 32;
277 p2 += 32 * 64 + 1;
278 p3 -= 32 * 64 + 1;
279 p4 -= 32;
280 }
281 }
282
283 /** タイルを右に90度回転 */
284
_rotateRight(uint8_t * tile)285 static void _rotateRight(uint8_t *tile)
286 {
287 RGBAFix15 *p1,*p2,*p3,*p4,c1,c3;
288 int ix,iy;
289
290 p1 = (RGBAFix15 *)tile;
291 p2 = p1 + 63 * 64;
292 p3 = p1 + 63;
293 p4 = p2 + 63;
294
295 for(iy = 32; iy; iy--)
296 {
297 for(ix = 32; ix; ix--, p1++, p2 -= 64, p3 += 64, p4--)
298 {
299 c1 = *p1;
300 c3 = *p3;
301
302 *p1 = *p2;
303 *p2 = *p4;
304 *p3 = c1;
305 *p4 = c3;
306 }
307
308 p1 += 32;
309 p2 += 32 * 64 + 1;
310 p3 -= 32 * 64 + 1;
311 p4 -= 32;
312 }
313 }
314
315 /** 関数テーブルにセット */
316
__TileImage_RGBA_setFuncTable(TileImageColtypeFuncs * p)317 void __TileImage_RGBA_setFuncTable(TileImageColtypeFuncs *p)
318 {
319 p->isSameColor = _isSameColor;
320 p->isSameRGB = _isSameRGB;
321 p->getPixelBufAtTile = _getPixelBufAtTile;
322 p->getPixelColAtTile = _getPixelColAtTile;
323 p->setPixel = _setPixel;
324 p->isTransparentTile = _isTransparentTile;
325 p->blendTile = _blendTile;
326 p->getTileRGBA = _getTileRGBA;
327 p->setTileFromRGBA = _setTileFromRGBA;
328 p->reverseHorz = _reverseHorz;
329 p->reverseVert = _reverseVert;
330 p->rotateLeft = _rotateLeft;
331 p->rotateRight = _rotateRight;
332 p->getTileForSave = _getTileForSave;
333 p->setTileForSave = _setTileForSave;
334 }
335