-
Notifications
You must be signed in to change notification settings - Fork 25
/
chunky.c
123 lines (112 loc) · 3.59 KB
/
chunky.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <ace/types.h>
#include <ace/managers/log.h>
#include <ace/utils/chunky.h>
#include <ace/utils/bitmap.h>
#include <fixmath/fix16.h>
void chunkyFromPlanar16(
const tBitMap *pBitMap, UWORD uwX, UWORD uwY, UBYTE *pOut
) {
UWORD uwChunk, uwMask;
UBYTE i, ubPx;
memset(pOut, 0, 16*sizeof(*pOut));
// From highest to lowest color idx bit
for(i = pBitMap->Depth; i--;) {
// Obtain WORD from bitplane - 16 pixels
uwChunk = ((UWORD*)(pBitMap->Planes[i]))[(pBitMap->BytesPerRow>>1)*uwY + (uwX>>4)];
uwMask = 0x8000; // Start obtaining pixel values from left
for(ubPx = 0; ubPx != 16; ++ubPx) { // Insert read pixel bit to right
pOut[ubPx] = (pOut[ubPx] << 1) | ((uwChunk & uwMask) != 0);
uwMask >>= 1; // Shift pixel mask right
}
}
}
UBYTE chunkyFromPlanar(const tBitMap *pBitMap, UWORD uwX, UWORD uwY) {
UBYTE pIndicesChunk[16];
chunkyFromPlanar16(pBitMap, uwX, uwY, pIndicesChunk);
return pIndicesChunk[uwX&0xF];
}
void chunkyToPlanar16(const UBYTE *pIn, UWORD uwX, UWORD uwY, tBitMap *pOut) {
UWORD uwPlanarBuffer = 0;
ULONG ulOffset = uwY * (pOut->BytesPerRow / 2) + (uwX / 16);
for(UBYTE ubPlane = 0; ubPlane < pOut->Depth; ++ubPlane) {
for(UBYTE ubPixel = 0; ubPixel < 16; ++ubPixel) {
uwPlanarBuffer <<= 1;
if(pIn[ubPixel] & (1<<ubPlane)) {
uwPlanarBuffer |= 1;
}
}
UWORD *pPlane = (UWORD*)(pOut->Planes[ubPlane]);
pPlane[ulOffset] = uwPlanarBuffer;
}
}
void chunkyToPlanar(UBYTE ubColor, UWORD uwX, UWORD uwY, tBitMap *pOut) {
ULONG ulOffset = uwY * (pOut->BytesPerRow / 2) + (uwX / 16);
UWORD uwMask = BV(15) >> (uwX & 0xF);
for(UBYTE ubPlane = 0; ubPlane < pOut->Depth; ++ubPlane) {
UWORD *pPlane = (UWORD*)pOut->Planes[ubPlane];
if(ubColor & 1) {
pPlane[ulOffset] |= uwMask;
}
else {
pPlane[ulOffset] &= ~uwMask;
}
ubColor >>= 1;
}
}
void chunkyRotate(
const UBYTE *pSource, UBYTE *pDest, fix16_t fSin, fix16_t fCos,
UBYTE ubBgColor, WORD wWidth, WORD wHeight
) {
fix16_t fCx, fCy;
fix16_t fHalf = fix16_one>>1;
WORD x,y;
WORD u,v;
fCx = fix16_div(fix16_from_int(wWidth), fix16_from_int(2));
fCy = fix16_div(fix16_from_int(wHeight), fix16_from_int(2));
// For each of new bitmap's pixel sample color from rotated source x,y
fix16_t fDx, fDy;
for(y = 0; y != wHeight; ++y) {
fDy = fix16_from_int(y) - fCy;
for(x = 0; x != wWidth; ++x) {
fDx = fix16_from_int(x) - fCx;
// u = round(fCos*(x-fCx) - fSin*(y-fCy) +(fCx));
// v = fix16_to_int(fSin*(x-fCx) + fCos*(y-fCy) +(fCy));
u = fix16_to_int(fix16_mul(fCos, fDx) - fix16_mul(fSin, fDy) + fCx + fHalf);
v = fix16_to_int(fix16_mul(fSin, fDx) + fix16_mul(fCos, fDy) + fCy + fHalf);
if(u < 0 || v < 0 || u >= wWidth || v >= wHeight) {
pDest[y*wWidth + x] = ubBgColor;
}
else {
pDest[y*wWidth + x] = pSource[v*wWidth + u];
}
}
}
}
void chunkyFromBitmap(
const tBitMap *pBitmap, UBYTE *pChunky,
UWORD uwSrcOffsX, UWORD uwSrcOffsY, UWORD uwWidth, UWORD uwHeight
) {
for(UWORD y = 0; y < uwHeight; ++y) {
for(UWORD x = 0; x < uwWidth; x += 16) {
chunkyFromPlanar16(
pBitmap, uwSrcOffsX + x, uwSrcOffsY + y, &pChunky[y*uwWidth + x]
);
}
}
}
void chunkyToBitmap(
const UBYTE *pChunky, tBitMap *pBitmap,
UWORD uwDstOffsX, UWORD uwDstOffsY, UWORD uwWidth, UWORD uwHeight
) {
for(UWORD y = 0; y < uwHeight; ++y) {
for(UWORD x = 0; x < uwWidth; x += 16)
chunkyToPlanar16(
&pChunky[(y*uwWidth) + x],
uwDstOffsX + x, uwDstOffsY + y,
pBitmap
);
}
}