mirror of https://github.com/mgba-emu/mgba.git
Util: Add basic mImage blit with no blending
This commit is contained in:
parent
5b18089e85
commit
cfd5572fb6
|
@ -101,11 +101,14 @@ void mImageDestroy(struct mImage*);
|
|||
|
||||
bool mImageSave(const struct mImage*, const char* path, const char* format);
|
||||
bool mImageSaveVF(const struct mImage*, struct VFile* vf, const char* format);
|
||||
|
||||
uint32_t mImageGetPixel(const struct mImage* image, unsigned x, unsigned y);
|
||||
uint32_t mImageGetPixelRaw(const struct mImage* image, unsigned x, unsigned y);
|
||||
void mImageSetPixel(struct mImage* image, unsigned x, unsigned y, uint32_t color);
|
||||
void mImageSetPixelRaw(struct mImage* image, unsigned x, unsigned y, uint32_t color);
|
||||
|
||||
void mImageBlit(struct mImage* image, const struct mImage* source, int x, int y);
|
||||
|
||||
uint32_t mColorConvert(uint32_t color, enum mColorFormat from, enum mColorFormat to);
|
||||
|
||||
#ifndef PYCPARSE
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include <mgba-util/image.h>
|
||||
|
||||
#include <mgba-util/geometry.h>
|
||||
#include <mgba-util/image/png-io.h>
|
||||
#include <mgba-util/vfs.h>
|
||||
|
||||
|
@ -317,6 +318,56 @@ void mImageSetPixel(struct mImage* image, unsigned x, unsigned y, uint32_t color
|
|||
mImageSetPixelRaw(image, x, y, mColorConvert(color, mCOLOR_ARGB8, image->format));
|
||||
}
|
||||
|
||||
void mImageBlit(struct mImage* image, const struct mImage* source, int x, int y) {
|
||||
struct mRectangle dstRect = {
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.width = image->width,
|
||||
.height = image->height
|
||||
};
|
||||
struct mRectangle srcRect = {
|
||||
.x = x,
|
||||
.y = y,
|
||||
.width = source->width,
|
||||
.height = source->height
|
||||
};
|
||||
if (!mRectangleIntersection(&srcRect, &dstRect)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int srcStartX;
|
||||
int srcStartY;
|
||||
int dstStartX;
|
||||
int dstStartY;
|
||||
|
||||
if (x < 0) {
|
||||
dstStartX = 0;
|
||||
srcStartX = -x;
|
||||
} else {
|
||||
srcStartX = 0;
|
||||
dstStartX = srcRect.x;
|
||||
}
|
||||
|
||||
if (y < 0) {
|
||||
dstStartY = 0;
|
||||
srcStartY = -y;
|
||||
} else {
|
||||
srcStartY = 0;
|
||||
dstStartY = srcRect.y;
|
||||
}
|
||||
|
||||
for (y = 0; y < srcRect.height; ++y) {
|
||||
uintptr_t srcPixel = (uintptr_t) PIXEL(source, srcStartX, srcStartY + y);
|
||||
uintptr_t dstPixel = (uintptr_t) PIXEL(image, dstStartX, dstStartY + y);
|
||||
for (x = 0; x < srcRect.width; ++x, srcPixel += source->depth, dstPixel += image->depth) {
|
||||
uint32_t color;
|
||||
GET_PIXEL(color, srcPixel, source->depth);
|
||||
color = mColorConvert(color, source->format, image->format);
|
||||
PUT_PIXEL(color, dstPixel, image->depth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t mColorConvert(uint32_t color, enum mColorFormat from, enum mColorFormat to) {
|
||||
if (from == to) {
|
||||
return color;
|
||||
|
|
|
@ -703,6 +703,287 @@ M_TEST_DEFINE(convert2x2) {
|
|||
}
|
||||
}
|
||||
|
||||
M_TEST_DEFINE(blitBoundaries) {
|
||||
static const uint32_t spriteBuffer[4] = {
|
||||
0xFF000F00, 0xFF000F01,
|
||||
0xFF000F10, 0xFF000F11
|
||||
};
|
||||
static const uint32_t canvasBuffer[9] = {
|
||||
0xFF000000, 0xFF000000, 0xFF000000,
|
||||
0xFF000000, 0xFF000000, 0xFF000000,
|
||||
0xFF000000, 0xFF000000, 0xFF000000
|
||||
};
|
||||
|
||||
struct mImage* sprite = mImageCreateFromConstBuffer(2, 2, 2, mCOLOR_XRGB8, spriteBuffer);
|
||||
struct mImage* canvas;
|
||||
|
||||
#define COMPARE(AA, BA, CA, AB, BB, CB, AC, BC, CC) \
|
||||
assert_int_equal(mImageGetPixel(canvas, 0, 0), 0xFF000000 | (AA)); \
|
||||
assert_int_equal(mImageGetPixel(canvas, 1, 0), 0xFF000000 | (BA)); \
|
||||
assert_int_equal(mImageGetPixel(canvas, 2, 0), 0xFF000000 | (CA)); \
|
||||
assert_int_equal(mImageGetPixel(canvas, 0, 1), 0xFF000000 | (AB)); \
|
||||
assert_int_equal(mImageGetPixel(canvas, 1, 1), 0xFF000000 | (BB)); \
|
||||
assert_int_equal(mImageGetPixel(canvas, 2, 1), 0xFF000000 | (CB)); \
|
||||
assert_int_equal(mImageGetPixel(canvas, 0, 2), 0xFF000000 | (AC)); \
|
||||
assert_int_equal(mImageGetPixel(canvas, 1, 2), 0xFF000000 | (BC)); \
|
||||
assert_int_equal(mImageGetPixel(canvas, 2, 2), 0xFF000000 | (CC))
|
||||
|
||||
canvas = mImageCreateFromConstBuffer(3, 3, 3, mCOLOR_XRGB8, canvasBuffer);
|
||||
mImageBlit(canvas, sprite, -2, -2);
|
||||
COMPARE(0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000);
|
||||
mImageDestroy(canvas);
|
||||
|
||||
canvas = mImageCreateFromConstBuffer(3, 3, 3, mCOLOR_XRGB8, canvasBuffer);
|
||||
mImageBlit(canvas, sprite, -1, -2);
|
||||
COMPARE(0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000);
|
||||
mImageDestroy(canvas);
|
||||
|
||||
canvas = mImageCreateFromConstBuffer(3, 3, 3, mCOLOR_XRGB8, canvasBuffer);
|
||||
mImageBlit(canvas, sprite, 0, -2);
|
||||
COMPARE(0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000);
|
||||
mImageDestroy(canvas);
|
||||
|
||||
canvas = mImageCreateFromConstBuffer(3, 3, 3, mCOLOR_XRGB8, canvasBuffer);
|
||||
mImageBlit(canvas, sprite, 1, -2);
|
||||
COMPARE(0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000);
|
||||
mImageDestroy(canvas);
|
||||
|
||||
canvas = mImageCreateFromConstBuffer(3, 3, 3, mCOLOR_XRGB8, canvasBuffer);
|
||||
mImageBlit(canvas, sprite, 2, -2);
|
||||
COMPARE(0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000);
|
||||
mImageDestroy(canvas);
|
||||
|
||||
canvas = mImageCreateFromConstBuffer(3, 3, 3, mCOLOR_XRGB8, canvasBuffer);
|
||||
mImageBlit(canvas, sprite, 3, -2);
|
||||
COMPARE(0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000);
|
||||
mImageDestroy(canvas);
|
||||
|
||||
canvas = mImageCreateFromConstBuffer(3, 3, 3, mCOLOR_XRGB8, canvasBuffer);
|
||||
mImageBlit(canvas, sprite, -2, -1);
|
||||
COMPARE(0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000);
|
||||
mImageDestroy(canvas);
|
||||
|
||||
canvas = mImageCreateFromConstBuffer(3, 3, 3, mCOLOR_XRGB8, canvasBuffer);
|
||||
mImageBlit(canvas, sprite, -1, -1);
|
||||
COMPARE(0xF11, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000);
|
||||
mImageDestroy(canvas);
|
||||
|
||||
canvas = mImageCreateFromConstBuffer(3, 3, 3, mCOLOR_XRGB8, canvasBuffer);
|
||||
mImageBlit(canvas, sprite, 0, -1);
|
||||
COMPARE(0xF10, 0xF11, 0x000,
|
||||
0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000);
|
||||
mImageDestroy(canvas);
|
||||
|
||||
canvas = mImageCreateFromConstBuffer(3, 3, 3, mCOLOR_XRGB8, canvasBuffer);
|
||||
mImageBlit(canvas, sprite, 1, -1);
|
||||
COMPARE(0x000, 0xF10, 0xF11,
|
||||
0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000);
|
||||
mImageDestroy(canvas);
|
||||
|
||||
canvas = mImageCreateFromConstBuffer(3, 3, 3, mCOLOR_XRGB8, canvasBuffer);
|
||||
mImageBlit(canvas, sprite, 2, -1);
|
||||
COMPARE(0x000, 0x000, 0xF10,
|
||||
0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000);
|
||||
mImageDestroy(canvas);
|
||||
|
||||
canvas = mImageCreateFromConstBuffer(3, 3, 3, mCOLOR_XRGB8, canvasBuffer);
|
||||
mImageBlit(canvas, sprite, 3, -1);
|
||||
COMPARE(0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000);
|
||||
mImageDestroy(canvas);
|
||||
|
||||
canvas = mImageCreateFromConstBuffer(3, 3, 3, mCOLOR_XRGB8, canvasBuffer);
|
||||
mImageBlit(canvas, sprite, -2, 0);
|
||||
COMPARE(0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000);
|
||||
mImageDestroy(canvas);
|
||||
|
||||
canvas = mImageCreateFromConstBuffer(3, 3, 3, mCOLOR_XRGB8, canvasBuffer);
|
||||
mImageBlit(canvas, sprite, -1, 0);
|
||||
COMPARE(0xF01, 0x000, 0x000,
|
||||
0xF11, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000);
|
||||
mImageDestroy(canvas);
|
||||
|
||||
canvas = mImageCreateFromConstBuffer(3, 3, 3, mCOLOR_XRGB8, canvasBuffer);
|
||||
mImageBlit(canvas, sprite, 0, 0);
|
||||
COMPARE(0xF00, 0xF01, 0x000,
|
||||
0xF10, 0xF11, 0x000,
|
||||
0x000, 0x000, 0x000);
|
||||
mImageDestroy(canvas);
|
||||
|
||||
canvas = mImageCreateFromConstBuffer(3, 3, 3, mCOLOR_XRGB8, canvasBuffer);
|
||||
mImageBlit(canvas, sprite, 1, 0);
|
||||
COMPARE(0x000, 0xF00, 0xF01,
|
||||
0x000, 0xF10, 0xF11,
|
||||
0x000, 0x000, 0x000);
|
||||
mImageDestroy(canvas);
|
||||
|
||||
canvas = mImageCreateFromConstBuffer(3, 3, 3, mCOLOR_XRGB8, canvasBuffer);
|
||||
mImageBlit(canvas, sprite, 2, 0);
|
||||
COMPARE(0x000, 0x000, 0xF00,
|
||||
0x000, 0x000, 0xF10,
|
||||
0x000, 0x000, 0x000);
|
||||
mImageDestroy(canvas);
|
||||
|
||||
canvas = mImageCreateFromConstBuffer(3, 3, 3, mCOLOR_XRGB8, canvasBuffer);
|
||||
mImageBlit(canvas, sprite, 3, 0);
|
||||
COMPARE(0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000);
|
||||
mImageDestroy(canvas);
|
||||
|
||||
canvas = mImageCreateFromConstBuffer(3, 3, 3, mCOLOR_XRGB8, canvasBuffer);
|
||||
mImageBlit(canvas, sprite, -2, 1);
|
||||
COMPARE(0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000);
|
||||
mImageDestroy(canvas);
|
||||
|
||||
canvas = mImageCreateFromConstBuffer(3, 3, 3, mCOLOR_XRGB8, canvasBuffer);
|
||||
mImageBlit(canvas, sprite, -1, 1);
|
||||
COMPARE(0x000, 0x000, 0x000,
|
||||
0xF01, 0x000, 0x000,
|
||||
0xF11, 0x000, 0x000);
|
||||
mImageDestroy(canvas);
|
||||
|
||||
canvas = mImageCreateFromConstBuffer(3, 3, 3, mCOLOR_XRGB8, canvasBuffer);
|
||||
mImageBlit(canvas, sprite, 0, 1);
|
||||
COMPARE(0x000, 0x000, 0x000,
|
||||
0xF00, 0xF01, 0x000,
|
||||
0xF10, 0xF11, 0x000);
|
||||
mImageDestroy(canvas);
|
||||
|
||||
canvas = mImageCreateFromConstBuffer(3, 3, 3, mCOLOR_XRGB8, canvasBuffer);
|
||||
mImageBlit(canvas, sprite, 1, 1);
|
||||
COMPARE(0x000, 0x000, 0x000,
|
||||
0x000, 0xF00, 0xF01,
|
||||
0x000, 0xF10, 0xF11);
|
||||
mImageDestroy(canvas);
|
||||
|
||||
canvas = mImageCreateFromConstBuffer(3, 3, 3, mCOLOR_XRGB8, canvasBuffer);
|
||||
mImageBlit(canvas, sprite, 2, 1);
|
||||
COMPARE(0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0xF00,
|
||||
0x000, 0x000, 0xF10);
|
||||
mImageDestroy(canvas);
|
||||
|
||||
canvas = mImageCreateFromConstBuffer(3, 3, 3, mCOLOR_XRGB8, canvasBuffer);
|
||||
mImageBlit(canvas, sprite, 3, 1);
|
||||
COMPARE(0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000);
|
||||
mImageDestroy(canvas);
|
||||
|
||||
canvas = mImageCreateFromConstBuffer(3, 3, 3, mCOLOR_XRGB8, canvasBuffer);
|
||||
mImageBlit(canvas, sprite, -2, 2);
|
||||
COMPARE(0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000);
|
||||
mImageDestroy(canvas);
|
||||
|
||||
canvas = mImageCreateFromConstBuffer(3, 3, 3, mCOLOR_XRGB8, canvasBuffer);
|
||||
mImageBlit(canvas, sprite, -1, 2);
|
||||
COMPARE(0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000,
|
||||
0xF01, 0x000, 0x000);
|
||||
mImageDestroy(canvas);
|
||||
|
||||
canvas = mImageCreateFromConstBuffer(3, 3, 3, mCOLOR_XRGB8, canvasBuffer);
|
||||
mImageBlit(canvas, sprite, 0, 2);
|
||||
COMPARE(0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000,
|
||||
0xF00, 0xF01, 0x000);
|
||||
mImageDestroy(canvas);
|
||||
|
||||
canvas = mImageCreateFromConstBuffer(3, 3, 3, mCOLOR_XRGB8, canvasBuffer);
|
||||
mImageBlit(canvas, sprite, 1, 2);
|
||||
COMPARE(0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000,
|
||||
0x000, 0xF00, 0xF01);
|
||||
mImageDestroy(canvas);
|
||||
|
||||
canvas = mImageCreateFromConstBuffer(3, 3, 3, mCOLOR_XRGB8, canvasBuffer);
|
||||
mImageBlit(canvas, sprite, 2, 2);
|
||||
COMPARE(0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0xF00);
|
||||
mImageDestroy(canvas);
|
||||
|
||||
canvas = mImageCreateFromConstBuffer(3, 3, 3, mCOLOR_XRGB8, canvasBuffer);
|
||||
mImageBlit(canvas, sprite, 3, 2);
|
||||
COMPARE(0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000);
|
||||
mImageDestroy(canvas);
|
||||
|
||||
canvas = mImageCreateFromConstBuffer(3, 3, 3, mCOLOR_XRGB8, canvasBuffer);
|
||||
mImageBlit(canvas, sprite, -2, 3);
|
||||
COMPARE(0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000);
|
||||
mImageDestroy(canvas);
|
||||
|
||||
canvas = mImageCreateFromConstBuffer(3, 3, 3, mCOLOR_XRGB8, canvasBuffer);
|
||||
mImageBlit(canvas, sprite, -1, 3);
|
||||
COMPARE(0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000);
|
||||
mImageDestroy(canvas);
|
||||
|
||||
canvas = mImageCreateFromConstBuffer(3, 3, 3, mCOLOR_XRGB8, canvasBuffer);
|
||||
mImageBlit(canvas, sprite, 0, 3);
|
||||
COMPARE(0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000);
|
||||
mImageDestroy(canvas);
|
||||
|
||||
canvas = mImageCreateFromConstBuffer(3, 3, 3, mCOLOR_XRGB8, canvasBuffer);
|
||||
mImageBlit(canvas, sprite, 1, 3);
|
||||
COMPARE(0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000);
|
||||
mImageDestroy(canvas);
|
||||
|
||||
canvas = mImageCreateFromConstBuffer(3, 3, 3, mCOLOR_XRGB8, canvasBuffer);
|
||||
mImageBlit(canvas, sprite, 2, 3);
|
||||
COMPARE(0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000);
|
||||
mImageDestroy(canvas);
|
||||
|
||||
canvas = mImageCreateFromConstBuffer(3, 3, 3, mCOLOR_XRGB8, canvasBuffer);
|
||||
mImageBlit(canvas, sprite, 3, 3);
|
||||
COMPARE(0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000);
|
||||
mImageDestroy(canvas);
|
||||
|
||||
#undef COMPARE
|
||||
mImageDestroy(sprite);
|
||||
}
|
||||
|
||||
M_TEST_SUITE_DEFINE(Image,
|
||||
cmocka_unit_test(zeroDim),
|
||||
cmocka_unit_test(pitchRead),
|
||||
|
@ -721,4 +1002,5 @@ M_TEST_SUITE_DEFINE(Image,
|
|||
cmocka_unit_test(convert2x1),
|
||||
cmocka_unit_test(convert1x2),
|
||||
cmocka_unit_test(convert2x2),
|
||||
cmocka_unit_test(blitBoundaries),
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue