27 #include "precompiled.h"
78 if(t->
bpp % 4 || t->
bpp > 32)
84 if(dxt != 0 && dxt != 1 && dxt !=
DXT1A && dxt != 3 && dxt != 5)
94 #define CHECK_TEX(t) RETURN_STATUS_IF_ERR(tex_validate(t))
103 const bool alpha = (flags &
TEX_ALPHA ) != 0;
104 const bool grey = (flags &
TEX_GREY ) != 0;
105 const bool dxt = (flags &
TEX_DXT ) != 0;
114 if(bpp == 8 && !alpha)
119 if(bpp == 24 && !alpha)
121 if(bpp == 32 && alpha)
136 size_t level_w = w, level_h = h;
137 const u8* level_data = pixels;
148 const size_t level_dataSize = (size_t)(
round_up(level_w, data_padding) *
round_up(level_h, data_padding) * bpp/8);
151 cb((
size_t)level, level_w, level_h, level_data, level_dataSize, cbData);
153 level_data += level_dataSize;
156 if(level_w == 1 && level_h == 1)
163 if(level_w == 0) level_w = 1;
164 if(level_h == 0) level_h = 1;
192 u8* dst = (
u8*)level_data;
198 memcpy(dst, src, level_dataSize);
203 const size_t dx = num_components, dy = dx*src_w;
211 for(
size_t y = 0; y < std::max(src_w, src_h); y += 2)
213 for(
size_t i = 0; i < num_components; i++)
215 *dst++ = (src[0]+src[dx]+1)/2;
225 for(
size_t y = 0; y < src_h; y += 2)
227 for(
size_t x = 0; x < src_w; x += 2)
229 for(
size_t i = 0; i < num_components; i++)
231 *dst++ = (src[0]+src[dx]+src[dy]+src[dx+dy]+2)/4;
242 ENSURE(dst == level_data + level_dataSize);
262 shared_ptr<u8> mipmapData;
266 t->
data = mipmapData;
296 const size_t w = t->
w, h = t->
h, bpp = t->
bpp;
297 const size_t flags = t->
flags;
311 size_t dstSize = srcSize;
318 dstSize = (srcSize / 3) * 4;
340 shared_ptr<u8> dstStorage;
344 u8* dst = (
u8*)dstStorage.get();
346 const size_t pitch = w * bpp/8;
353 src = (
const u8*)srcStorage+srcSize-pitch;
357 else if(transforms & TEX_ALPHA)
359 src = (
const u8*)srcStorage;
364 src = (
const u8*)dstStorage.get();
365 memcpy(dstStorage.get(), srcStorage, srcSize);
369 if(!(transforms & (
TEX_BGR | TEX_ALPHA)))
373 for(
size_t y = 0; y < h; y++)
375 memcpy(dst, src, pitch);
382 else if(bpp == 24 && (transforms & TEX_ALPHA) && (transforms &
TEX_BGR))
384 for(
size_t y = 0; y < h; y++)
386 for(
size_t x = 0; x < w; x++)
389 const u8 b = src[0], g = src[1], r = src[2];
390 dst[0] = r; dst[1] = g; dst[2] = b; dst[3] = 0xFF;
394 src += row_ofs - pitch;
398 else if(bpp == 24 && (transforms & TEX_ALPHA) && !(transforms & TEX_BGR))
400 for(
size_t y = 0; y < h; y++)
402 for(
size_t x = 0; x < w; x++)
405 const u8 r = src[0], g = src[1], b = src[2];
406 dst[0] = r; dst[1] = g; dst[2] = b; dst[3] = 0xFF;
410 src += row_ofs - pitch;
414 else if(bpp == 24 && !(transforms & TEX_ALPHA))
416 for(
size_t y = 0; y < h; y++)
418 for(
size_t x = 0; x < w; x++)
421 const u8 b = src[0], g = src[1], r = src[2];
422 dst[0] = r; dst[1] = g; dst[2] = b;
426 src += row_ofs - pitch;
430 else if(bpp == 32 && !(transforms & TEX_ALPHA))
432 for(
size_t y = 0; y < h; y++)
434 for(
size_t x = 0; x < w; x++)
437 const u8 b = src[0], g = src[1], r = src[2], a = src[3];
438 dst[0] = r; dst[1] = g; dst[2] = b; dst[3] = a;
442 src += row_ofs - pitch;
451 t->
data = dstStorage;
472 const size_t target_flags = t->
flags ^ transforms;
473 size_t remaining_transforms;
476 remaining_transforms = target_flags ^ t->
flags;
478 if(remaining_transforms == 0)
497 const size_t transforms = t->
flags ^ new_flags;
516 global_orientation = o;
551 if(dst_orientation == 0)
553 return (src_orientation == dst_orientation);
593 Status tex_wrap(
size_t w,
size_t h,
size_t bpp,
size_t flags,
const shared_ptr<u8>& data,
size_t ofs,
Tex* t)
651 const size_t data_padding = (t->
flags &
TEX_DXT)? 4 : 1;
652 size_t last_level_size = (size_t)(data_padding * data_padding * t->
bpp/8);
659 basetex.
ofs += size - last_level_size;
667 u8 g = basetex.
data.get()[basetex.
ofs+1];
668 u8 r = basetex.
data.get()[basetex.
ofs+2];
669 u8 a = basetex.
data.get()[basetex.
ofs+3];
670 return b + (g << 8) + (r << 16) + (a << 24);
676 size_t* ptotal_size = (
size_t*)cbData;
677 *ptotal_size += level_dataSize;
689 const size_t data_padding = (t->
flags &
TEX_DXT)? 4 : 1;
723 const size_t min_hdr_size = c->
hdr_size(0);
724 if(dataSize < min_hdr_size)
726 const size_t hdr_size = c->
hdr_size(data.get());
727 if(dataSize < hdr_size)
737 if(!t->
w || !t->
h || t->
bpp > 32)
const Status TEX_INVALID_COLOR_TYPE
size_t ofs
offset to image data in file.
Status tex_codec_for_filename(const OsPath &extension, const TexCodecVTbl **c)
Find codec that recognizes the desired output file extension.
#define UNUSED(param)
mark a function parameter as unused and avoid the corresponding compiler warning. ...
#define WARN_IF_ERR(expression)
const Status TEX_CODEC_CANNOT_HANDLE
size_t prev_level_dataSize
const int TEX_BASE_LEVEL_ONLY
special value for levels_to_skip: the callback will only be called for the base mipmap level (i...
static int global_orientation
const u8 * prev_level_data
bool tex_is_known_extension(const VfsPath &pathname)
Is the file's extension that of a texture format supported by tex_load?
Status tex_transform_to(Tex *t, size_t new_flags)
Change <t>'s pixel format (2nd version) (note: this is equivalent to tex_transform(t, t->flags^new_flags).
const Status TEX_COMPRESSED
static const StatusDefinition texStatusDefinitions[]
flags & TEX_DXT is a field indicating compression.
Status(* encode)(Tex *RESTRICT t, DynArray *RESTRICT da)
encode the texture data into the codec's file format (in memory).
indicates the image contains an alpha channel.
provides a memory range that can be expanded but doesn't waste physical memory or relocate itself...
const Status TEX_INCOMPLETE_HEADER
shared_ptr< u8 > data
file buffer or image data.
T round_up(T n, T multiple)
round number up/down to the next given multiple.
indicates the image is 8bpp greyscale.
size_t tex_hdr_size(const VfsPath &filename)
return the minimum header size (i.e.
static void create_level(size_t level, size_t level_w, size_t level_h, const u8 *RESTRICT level_data, size_t level_dataSize, void *RESTRICT cbData)
indicates B and R pixel components are exchanged.
Status tex_validate_plain_format(size_t bpp, size_t flags)
check if the given texture format is acceptable: 8bpp grey, 24bpp color or 32bpp color+alpha (BGR / u...
u32 tex_get_average_colour(const Tex *t)
return the ARGB value of the 1x1 mipmap level of the texture.
flags & TEX_ORIENTATION is a field indicating orientation, i.e.
Status(* decode)(u8 *data, size_t size, Tex *RESTRICT t)
decode the file into a Tex structure.
#define TIMER_ACCRUE(client)
Measure the time taken to execute code up until end of the current scope; bill it to the given TimerC...
Status tex_validate(const Tex *t)
Is the texture object valid and self-consistent?
static Status plain_transform(Tex *t, size_t transforms)
const Status TEX_FMT_INVALID
#define WARN_RETURN_STATUS_IF_ERR(expression)
#define ENSURE(expr)
ensure the expression <expr> evaluates to non-zero.
static Status add_mipmaps(Tex *t, size_t w, size_t h, size_t bpp, void *newData, size_t dataSize)
const Status TEX_NOT_8BIT_PRECISION
u8 * tex_get_data(const Tex *t)
rationale: since Tex is a struct, its fields are accessible to callers.
bool tex_orientations_match(size_t src_flags, size_t dst_orientation)
indicate if the two vertical orientations match.
i64 Status
Error handling system.
stores all data describing an image.
#define STATUS_ADD_DEFINITIONS(definitions)
add a module's array of StatusDefinition to the list.
void tex_set_global_orientation(int o)
Set the orientation to which all loaded images will automatically be converted (excepting file format...
Status tex_codec_transform(Tex *t, size_t transforms)
transform the texture's pixel format.
we need a special value for DXT1a to avoid having to consider flags & TEX_ALPHA to determine S3TC typ...
const Status TEX_INVALID_DATA
void tex_util_foreach_mipmap(size_t w, size_t h, size_t bpp, const u8 *pixels, int levels_to_skip, size_t data_padding, MipmapCB cb, void *RESTRICT cbData)
for a series of mipmaps stored from base to highest, call back for each level.
#define TIMER_ADD_CLIENT(id)
"allocate" a new TimerClient that will keep track of the total time billed to it, along with a descri...
static Status AllocateAligned(shared_ptr< T > &p, size_t size, size_t alignment=cacheLineSize)
const Status TEX_INVALID_LAYOUT
static void add_level_size(size_t level, size_t level_w, size_t level_h, const u8 *RESTRICT level_data, size_t level_dataSize, void *RESTRICT cbData)
static void flip_to_global_orientation(Tex *t)
Status tex_wrap(size_t w, size_t h, size_t bpp, size_t flags, const shared_ptr< u8 > &data, size_t ofs, Tex *t)
store the given image data into a Tex object; this will be as if it had been loaded via tex_load...
#define WARN_RETURN(status)
void(* MipmapCB)(size_t level, size_t level_w, size_t level_h, const u8 *RESTRICT level_data, size_t level_data_size, void *RESTRICT cbData)
callback function for each mipmap level.
Status da_free(DynArray *da)
free all memory (address space + physical) that constitutes the given array.
const Status TEX_INVALID_SIZE
#define debug_warn(expr)
display the error dialog with the given text.
size_t tex_img_size(const Tex *t)
return total byte size of the image pixels.
Status tex_transform(Tex *t, size_t transforms)
Change <t>'s pixel format.
Status da_alloc(DynArray *da, size_t max_size)
ready the DynArray object for use.
virtual method table for TexCodecs.
size_t(* hdr_size)(const u8 *file)
return size of the file header supported by this codec.
size_t flags
see TexFlags and "Format Conversion" in docs.
Status tex_codec_for_header(const u8 *file, size_t file_size, const TexCodecVTbl **c)
find codec that recognizes the header's magic field.
Status tex_decode(const shared_ptr< u8 > &data, size_t dataSize, Tex *t)
decode an in-memory texture file into texture object.
void tex_free(Tex *t)
free all resources associated with the image and make further use of it impossible.
Status tex_encode(Tex *t, const OsPath &extension, DynArray *da)
encode a texture into a memory buffer in the desired file format.
#define RETURN_STATUS_IF_ERR(expression)