mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-05-18 18:58:27 +00:00
Added SDL_ClearSurface() and SDL_ReadSurfacePixelFloat()
This commit is contained in:
parent
b07bd55baf
commit
02a072a1b7
5 changed files with 246 additions and 28 deletions
|
@ -828,6 +828,25 @@ extern SDL_DECLSPEC int SDLCALL SDL_PremultiplyAlpha(int width, int height, SDL_
|
|||
*/
|
||||
extern SDL_DECLSPEC int SDLCALL SDL_PremultiplySurfaceAlpha(SDL_Surface *surface, SDL_bool linear);
|
||||
|
||||
/**
|
||||
* Clear a surface with a specific color, with floating point precision.
|
||||
*
|
||||
* This function handles all surface formats, and ignores any clip rectangle.
|
||||
*
|
||||
* If the surface is YUV, the color is assumed to be in the sRGB colorspace, otherwise the color is assumed to be in the colorspace of the suface.
|
||||
*
|
||||
* \param surface the SDL_Surface to clear.
|
||||
* \param r the red component of the pixel, normally in the range 0-1
|
||||
* \param g the green component of the pixel, normally in the range 0-1
|
||||
* \param b the blue component of the pixel, normally in the range 0-1
|
||||
* \param a the alpha component of the pixel, normally in the range 0-1
|
||||
* \returns 0 on success or a negative error code on failure; call
|
||||
* SDL_GetError() for more information.
|
||||
*
|
||||
* \since This function is available since SDL 3.0.0.
|
||||
*/
|
||||
extern SDL_DECLSPEC int SDLCALL SDL_ClearSurface(SDL_Surface *surface, float r, float g, float b, float a);
|
||||
|
||||
/**
|
||||
* Perform a fast fill of a rectangle with a specific color.
|
||||
*
|
||||
|
@ -1138,6 +1157,30 @@ extern SDL_DECLSPEC Uint32 SDLCALL SDL_MapSurfaceRGBA(SDL_Surface *surface, Uint
|
|||
*/
|
||||
extern SDL_DECLSPEC int SDLCALL SDL_ReadSurfacePixel(SDL_Surface *surface, int x, int y, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a);
|
||||
|
||||
/**
|
||||
* Retrieves a single pixel from a surface.
|
||||
*
|
||||
* This function prioritizes correctness over speed: it is suitable for unit
|
||||
* tests, but is not intended for use in a game engine.
|
||||
*
|
||||
* \param surface the surface to read.
|
||||
* \param x the horizontal coordinate, 0 <= x < width.
|
||||
* \param y the vertical coordinate, 0 <= y < height.
|
||||
* \param r a pointer filled in with the red channel, normally in the range 0-1, or NULL to ignore
|
||||
* this channel.
|
||||
* \param g a pointer filled in with the green channel, normally in the range 0-1, or NULL to
|
||||
* ignore this channel.
|
||||
* \param b a pointer filled in with the blue channel, normally in the range 0-1, or NULL to
|
||||
* ignore this channel.
|
||||
* \param a a pointer filled in with the alpha channel, normally in the range 0-1, or NULL to
|
||||
* ignore this channel.
|
||||
* \returns 0 on success or a negative error code on failure; call
|
||||
* SDL_GetError() for more information.
|
||||
*
|
||||
* \since This function is available since SDL 3.0.0.
|
||||
*/
|
||||
extern SDL_DECLSPEC int SDLCALL SDL_ReadSurfacePixelFloat(SDL_Surface *surface, int x, int y, float *r, float *g, float *b, float *a);
|
||||
|
||||
/* Ends C function definitions when using C++ */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ SDL3_0.0.0 {
|
|||
SDL_ClearComposition;
|
||||
SDL_ClearError;
|
||||
SDL_ClearProperty;
|
||||
SDL_ClearSurface;
|
||||
SDL_CloseAudioDevice;
|
||||
SDL_CloseCamera;
|
||||
SDL_CloseGamepad;
|
||||
|
@ -627,6 +628,7 @@ SDL3_0.0.0 {
|
|||
SDL_ReadS8;
|
||||
SDL_ReadStorageFile;
|
||||
SDL_ReadSurfacePixel;
|
||||
SDL_ReadSurfacePixelFloat;
|
||||
SDL_ReadU16BE;
|
||||
SDL_ReadU16LE;
|
||||
SDL_ReadU32BE;
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
#define SDL_ClearComposition SDL_ClearComposition_REAL
|
||||
#define SDL_ClearError SDL_ClearError_REAL
|
||||
#define SDL_ClearProperty SDL_ClearProperty_REAL
|
||||
#define SDL_ClearSurface SDL_ClearSurface_REAL
|
||||
#define SDL_CloseAudioDevice SDL_CloseAudioDevice_REAL
|
||||
#define SDL_CloseCamera SDL_CloseCamera_REAL
|
||||
#define SDL_CloseGamepad SDL_CloseGamepad_REAL
|
||||
|
@ -652,6 +653,7 @@
|
|||
#define SDL_ReadS8 SDL_ReadS8_REAL
|
||||
#define SDL_ReadStorageFile SDL_ReadStorageFile_REAL
|
||||
#define SDL_ReadSurfacePixel SDL_ReadSurfacePixel_REAL
|
||||
#define SDL_ReadSurfacePixelFloat SDL_ReadSurfacePixelFloat_REAL
|
||||
#define SDL_ReadU16BE SDL_ReadU16BE_REAL
|
||||
#define SDL_ReadU16LE SDL_ReadU16LE_REAL
|
||||
#define SDL_ReadU32BE SDL_ReadU32BE_REAL
|
||||
|
|
|
@ -80,6 +80,7 @@ SDL_DYNAPI_PROC(int,SDL_ClearClipboardData,(void),(),return)
|
|||
SDL_DYNAPI_PROC(int,SDL_ClearComposition,(SDL_Window *a),(a),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_ClearError,(void),(),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_ClearProperty,(SDL_PropertiesID a, const char *b),(a,b),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_ClearSurface,(SDL_Surface *a, float b, float c, float d, float e),(a,b,c,d,e),return)
|
||||
SDL_DYNAPI_PROC(void,SDL_CloseAudioDevice,(SDL_AudioDeviceID a),(a),)
|
||||
SDL_DYNAPI_PROC(void,SDL_CloseCamera,(SDL_Camera *a),(a),)
|
||||
SDL_DYNAPI_PROC(void,SDL_CloseGamepad,(SDL_Gamepad *a),(a),)
|
||||
|
@ -663,6 +664,7 @@ SDL_DYNAPI_PROC(SDL_bool,SDL_ReadS64LE,(SDL_IOStream *a, Sint64 *b),(a,b),return
|
|||
SDL_DYNAPI_PROC(SDL_bool,SDL_ReadS8,(SDL_IOStream *a, Sint8 *b),(a,b),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_ReadStorageFile,(SDL_Storage *a, const char *b, void *c, Uint64 d),(a,b,c,d),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_ReadSurfacePixel,(SDL_Surface *a, int b, int c, Uint8 *d, Uint8 *e, Uint8 *f, Uint8 *g),(a,b,c,d,e,f,g),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_ReadSurfacePixelFloat,(SDL_Surface *a, int b, int c, float *d, float *e, float *f, float *g),(a,b,c,d,e,f,g),return)
|
||||
SDL_DYNAPI_PROC(SDL_bool,SDL_ReadU16BE,(SDL_IOStream *a, Uint16 *b),(a,b),return)
|
||||
SDL_DYNAPI_PROC(SDL_bool,SDL_ReadU16LE,(SDL_IOStream *a, Uint16 *b),(a,b),return)
|
||||
SDL_DYNAPI_PROC(SDL_bool,SDL_ReadU32BE,(SDL_IOStream *a, Uint32 *b),(a,b),return)
|
||||
|
|
|
@ -1991,6 +1991,63 @@ int SDL_PremultiplySurfaceAlpha(SDL_Surface *surface, SDL_bool linear)
|
|||
return SDL_PremultiplyAlphaPixelsAndColorspace(surface->w, surface->h, surface->format, colorspace, surface->internal->props, surface->pixels, surface->pitch, surface->format, colorspace, surface->internal->props, surface->pixels, surface->pitch, linear);
|
||||
}
|
||||
|
||||
int SDL_ClearSurface(SDL_Surface *surface, float r, float g, float b, float a)
|
||||
{
|
||||
SDL_Rect clip_rect;
|
||||
int result = -1;
|
||||
|
||||
if (!SDL_SurfaceValid(surface)) {
|
||||
return SDL_InvalidParamError("surface");
|
||||
}
|
||||
|
||||
SDL_GetSurfaceClipRect(surface, &clip_rect);
|
||||
SDL_SetSurfaceClipRect(surface, NULL);
|
||||
|
||||
if (!SDL_ISPIXELFORMAT_FOURCC(surface->format) &&
|
||||
SDL_BYTESPERPIXEL(surface->format) <= sizeof(Uint32)) {
|
||||
Uint32 color;
|
||||
|
||||
color = SDL_MapSurfaceRGBA(surface,
|
||||
(Uint8)SDL_roundf(SDL_clamp(r, 0.0f, 1.0f) * 255.0f),
|
||||
(Uint8)SDL_roundf(SDL_clamp(g, 0.0f, 1.0f) * 255.0f),
|
||||
(Uint8)SDL_roundf(SDL_clamp(b, 0.0f, 1.0f) * 255.0f),
|
||||
(Uint8)SDL_roundf(SDL_clamp(a, 0.0f, 1.0f) * 255.0f));
|
||||
result = SDL_FillSurfaceRect(surface, NULL, color);
|
||||
} else if (SDL_ISPIXELFORMAT_FOURCC(surface->format)) {
|
||||
// We can't directly set an RGB value on a YUV surface
|
||||
SDL_Surface *tmp = SDL_CreateSurface(surface->w, surface->h, SDL_PIXELFORMAT_ARGB8888);
|
||||
if (!tmp) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (SDL_ClearSurface(tmp, r, g, b, a) == 0) {
|
||||
result = SDL_ConvertPixelsAndColorspace(surface->w, surface->h, tmp->format, SDL_GetSurfaceColorspace(tmp), tmp->internal->props, tmp->pixels, tmp->pitch, surface->format, SDL_GetSurfaceColorspace(surface), surface->internal->props, surface->pixels, surface->pitch);
|
||||
}
|
||||
SDL_DestroySurface(tmp);
|
||||
} else {
|
||||
// Take advantage of blit color conversion
|
||||
SDL_Surface *tmp = SDL_CreateSurface(1, 1, SDL_PIXELFORMAT_RGBA128_FLOAT);
|
||||
if (!tmp) {
|
||||
goto done;
|
||||
}
|
||||
SDL_SetSurfaceColorspace(tmp, SDL_GetSurfaceColorspace(surface));
|
||||
|
||||
float *pixels = (float *)tmp->pixels;
|
||||
pixels[0] = r;
|
||||
pixels[1] = g;
|
||||
pixels[2] = b;
|
||||
pixels[3] = a;
|
||||
|
||||
result = SDL_BlitSurfaceScaled(tmp, NULL, surface, NULL, SDL_SCALEMODE_NEAREST);
|
||||
SDL_DestroySurface(tmp);
|
||||
}
|
||||
|
||||
done:
|
||||
SDL_SetSurfaceClipRect(surface, &clip_rect);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Uint32 SDL_MapSurfaceRGB(SDL_Surface *surface, Uint8 r, Uint8 g, Uint8 b)
|
||||
{
|
||||
return SDL_MapSurfaceRGBA(surface, r, g, b, SDL_ALPHA_OPAQUE);
|
||||
|
@ -2014,7 +2071,31 @@ int SDL_ReadSurfacePixel(SDL_Surface *surface, int x, int y, Uint8 *r, Uint8 *g,
|
|||
Uint8 *p;
|
||||
int result = -1;
|
||||
|
||||
if (!surface || !surface->format || !surface->pixels) {
|
||||
if (r) {
|
||||
*r = 0;
|
||||
} else {
|
||||
r = &unused;
|
||||
}
|
||||
|
||||
if (g) {
|
||||
*g = 0;
|
||||
} else {
|
||||
g = &unused;
|
||||
}
|
||||
|
||||
if (b) {
|
||||
*b = 0;
|
||||
} else {
|
||||
b = &unused;
|
||||
}
|
||||
|
||||
if (a) {
|
||||
*a = 0;
|
||||
} else {
|
||||
a = &unused;
|
||||
}
|
||||
|
||||
if (!SDL_SurfaceValid(surface) || !surface->format || !surface->pixels) {
|
||||
return SDL_InvalidParamError("surface");
|
||||
}
|
||||
|
||||
|
@ -2026,22 +2107,6 @@ int SDL_ReadSurfacePixel(SDL_Surface *surface, int x, int y, Uint8 *r, Uint8 *g,
|
|||
return SDL_InvalidParamError("y");
|
||||
}
|
||||
|
||||
if (!r) {
|
||||
r = &unused;
|
||||
}
|
||||
|
||||
if (!g) {
|
||||
g = &unused;
|
||||
}
|
||||
|
||||
if (!b) {
|
||||
b = &unused;
|
||||
}
|
||||
|
||||
if (!a) {
|
||||
a = &unused;
|
||||
}
|
||||
|
||||
bytes_per_pixel = SDL_BYTESPERPIXEL(surface->format);
|
||||
|
||||
if (SDL_MUSTLOCK(surface)) {
|
||||
|
@ -2052,7 +2117,24 @@ int SDL_ReadSurfacePixel(SDL_Surface *surface, int x, int y, Uint8 *r, Uint8 *g,
|
|||
|
||||
p = (Uint8 *)surface->pixels + y * surface->pitch + x * bytes_per_pixel;
|
||||
|
||||
if (bytes_per_pixel > sizeof(pixel)) {
|
||||
if (bytes_per_pixel <= sizeof(pixel) && !SDL_ISPIXELFORMAT_FOURCC(surface->format)) {
|
||||
/* Fill the appropriate number of least-significant bytes of pixel,
|
||||
* leaving the most-significant bytes set to zero */
|
||||
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
SDL_memcpy(((Uint8 *)&pixel) + (sizeof(pixel) - bytes_per_pixel), p, bytes_per_pixel);
|
||||
#else
|
||||
SDL_memcpy(&pixel, p, bytes_per_pixel);
|
||||
#endif
|
||||
SDL_GetRGBA(pixel, surface->internal->format, surface->internal->palette, r, g, b, a);
|
||||
result = 0;
|
||||
} else if (SDL_ISPIXELFORMAT_FOURCC(surface->format)) {
|
||||
// FIXME: We need code to extract a single macroblock from a YUV surface
|
||||
SDL_Surface *converted = SDL_ConvertSurface(surface, SDL_PIXELFORMAT_ARGB8888);
|
||||
if (converted) {
|
||||
result = SDL_ReadSurfacePixel(converted, x, y, r, g, b, a);
|
||||
SDL_DestroySurface(converted);
|
||||
}
|
||||
} else {
|
||||
/* This is really slow, but it gets the job done */
|
||||
Uint8 rgba[4];
|
||||
SDL_Colorspace colorspace = SDL_GetSurfaceColorspace(surface);
|
||||
|
@ -2064,16 +2146,6 @@ int SDL_ReadSurfacePixel(SDL_Surface *surface, int x, int y, Uint8 *r, Uint8 *g,
|
|||
*a = rgba[3];
|
||||
result = 0;
|
||||
}
|
||||
} else {
|
||||
/* Fill the appropriate number of least-significant bytes of pixel,
|
||||
* leaving the most-significant bytes set to zero */
|
||||
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
SDL_memcpy(((Uint8 *)&pixel) + (sizeof(pixel) - bytes_per_pixel), p, bytes_per_pixel);
|
||||
#else
|
||||
SDL_memcpy(&pixel, p, bytes_per_pixel);
|
||||
#endif
|
||||
SDL_GetRGBA(pixel, surface->internal->format, surface->internal->palette, r, g, b, a);
|
||||
result = 0;
|
||||
}
|
||||
|
||||
if (SDL_MUSTLOCK(surface)) {
|
||||
|
@ -2082,6 +2154,103 @@ int SDL_ReadSurfacePixel(SDL_Surface *surface, int x, int y, Uint8 *r, Uint8 *g,
|
|||
return result;
|
||||
}
|
||||
|
||||
int SDL_ReadSurfacePixelFloat(SDL_Surface *surface, int x, int y, float *r, float *g, float *b, float *a)
|
||||
{
|
||||
float unused;
|
||||
int result = -1;
|
||||
|
||||
if (r) {
|
||||
*r = 0.0f;
|
||||
} else {
|
||||
r = &unused;
|
||||
}
|
||||
|
||||
if (g) {
|
||||
*g = 0.0f;
|
||||
} else {
|
||||
g = &unused;
|
||||
}
|
||||
|
||||
if (b) {
|
||||
*b = 0.0f;
|
||||
} else {
|
||||
b = &unused;
|
||||
}
|
||||
|
||||
if (a) {
|
||||
*a = 0.0f;
|
||||
} else {
|
||||
a = &unused;
|
||||
}
|
||||
|
||||
if (!SDL_SurfaceValid(surface) || !surface->format || !surface->pixels) {
|
||||
return SDL_InvalidParamError("surface");
|
||||
}
|
||||
|
||||
if (x < 0 || x >= surface->w) {
|
||||
return SDL_InvalidParamError("x");
|
||||
}
|
||||
|
||||
if (y < 0 || y >= surface->h) {
|
||||
return SDL_InvalidParamError("y");
|
||||
}
|
||||
|
||||
if (SDL_BYTESPERPIXEL(surface->format) <= sizeof(Uint32) && !SDL_ISPIXELFORMAT_FOURCC(surface->format)) {
|
||||
Uint8 r8, g8, b8, a8;
|
||||
|
||||
if (SDL_ReadSurfacePixel(surface, x, y, &r8, &g8, &b8, &a8) == 0) {
|
||||
*r = (float)r8 / 255.0f;
|
||||
*g = (float)g8 / 255.0f;
|
||||
*b = (float)b8 / 255.0f;
|
||||
*a = (float)a8 / 255.0f;
|
||||
result = 0;
|
||||
}
|
||||
} else if (SDL_ISPIXELFORMAT_FOURCC(surface->format)) {
|
||||
// FIXME: We need code to extract a single macroblock from a YUV surface
|
||||
SDL_Surface *converted = SDL_ConvertSurface(surface, SDL_PIXELFORMAT_ARGB8888);
|
||||
if (converted) {
|
||||
result = SDL_ReadSurfacePixelFloat(converted, x, y, r, g, b, a);
|
||||
SDL_DestroySurface(converted);
|
||||
}
|
||||
} else {
|
||||
/* This is really slow, but it gets the job done */
|
||||
float rgba[4];
|
||||
Uint8 *p;
|
||||
|
||||
if (SDL_MUSTLOCK(surface)) {
|
||||
if (SDL_LockSurface(surface) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
p = (Uint8 *)surface->pixels + y * surface->pitch + x * SDL_BYTESPERPIXEL(surface->format);
|
||||
|
||||
if (surface->format == SDL_PIXELFORMAT_RGBA128_FLOAT) {
|
||||
SDL_memcpy(rgba, p, sizeof(rgba));
|
||||
result = 0;
|
||||
} else {
|
||||
SDL_Colorspace src_colorspace = SDL_GetSurfaceColorspace(surface);
|
||||
SDL_Colorspace dst_colorspace = (src_colorspace == SDL_COLORSPACE_SRGB_LINEAR ? SDL_COLORSPACE_SRGB_LINEAR : SDL_COLORSPACE_SRGB);
|
||||
|
||||
if (SDL_ConvertPixelsAndColorspace(1, 1, surface->format, src_colorspace, surface->internal->props, p, surface->pitch, SDL_PIXELFORMAT_RGBA128_FLOAT, dst_colorspace, 0, rgba, sizeof(rgba)) == 0) {
|
||||
result = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (result == 0) {
|
||||
*r = rgba[0];
|
||||
*g = rgba[1];
|
||||
*b = rgba[2];
|
||||
*a = rgba[3];
|
||||
}
|
||||
|
||||
if (SDL_MUSTLOCK(surface)) {
|
||||
SDL_UnlockSurface(surface);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free a surface created by the above function.
|
||||
*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue