Update upstream

This commit is contained in:
2023-12-02 11:03:24 -08:00
parent 84ea557696
commit d472f6348d
129 changed files with 17814 additions and 14162 deletions

View File

@ -42,10 +42,6 @@
#define LOAD_PROC "file-dds-load"
#define SAVE_PROC "file-dds-save"
#define DECODE_YCOCG_PROC "color-decode-ycocg"
#define DECODE_YCOCG_SCALED_PROC "color-decode-ycocg-scaled"
#define DECODE_ALPHA_EXP_PROC "color-decode-alpha-exp"
typedef struct _Dds Dds;
typedef struct _DdsClass DdsClass;
@ -86,15 +82,6 @@ static PikaValueArray * dds_save (PikaProcedure *procedure,
PikaMetadata *metadata,
PikaProcedureConfig *config,
gpointer run_data);
#if 0
static PikaValueArray * dds_decode (PikaProcedure *procedure,
PikaRunMode run_mode,
PikaImage *image,
gint n_drawables,
PikaDrawable **drawables,
PikaProcedureConfig *config,
gpointer run_data);
#endif
G_DEFINE_TYPE (Dds, dds, PIKA_TYPE_PLUG_IN)
@ -125,11 +112,6 @@ dds_query_procedures (PikaPlugIn *plug_in)
list = g_list_append (list, g_strdup (LOAD_PROC));
list = g_list_append (list, g_strdup (SAVE_PROC));
#if 0
list = g_list_append (list, g_strdup (DECODE_YCOCG_PROC));
list = g_list_append (list, g_strdup (DECODE_YCOCG_SCALED_PROC));
list = g_list_append (list, g_strdup (DECODE_ALPHA_EXP_PROC));
#endif
return list;
}
@ -170,10 +152,10 @@ dds_create_procedure (PikaPlugIn *plug_in,
TRUE,
G_PARAM_READWRITE);
PIKA_PROC_ARG_BOOLEAN (procedure, "decode-images",
_("Automatically decode YCoCg/AE_xp images when detected"),
_("Decode YCoCg/AExp images when detected"),
TRUE,
PIKA_PROC_ARG_BOOLEAN (procedure, "flip-image",
_("Flip image _vertically"),
_("Flip the image vertically on import"),
FALSE,
G_PARAM_READWRITE);
}
else if (! strcmp (name, SAVE_PROC))
@ -249,13 +231,17 @@ dds_create_procedure (PikaPlugIn *plug_in,
"default",
G_PARAM_READWRITE);
PIKA_PROC_ARG_INT (procedure, "save-type",
"Save type",
"How to save the image (0 = selected layer, "
"1 = cube map, 2 = volume map, 3 = texture array, "
"4 = all visible layers)",
0, 4, DDS_SAVE_SELECTED_LAYER,
G_PARAM_READWRITE);
PIKA_PROC_ARG_CHOICE (procedure, "save-type",
_("Sav_e type"),
_("How to save the image"),
pika_choice_new_with_values ("layer", DDS_SAVE_SELECTED_LAYER, _("Selected layer"), NULL,
"canvas", DDS_SAVE_VISIBLE_LAYERS, _("All visible layers"), NULL,
"cube", DDS_SAVE_CUBEMAP, _("As cube map"), NULL,
"volume", DDS_SAVE_VOLUMEMAP, _("As volume map"), NULL,
"array", DDS_SAVE_ARRAY, _("As texture array"), NULL,
NULL),
"layer",
G_PARAM_READWRITE);
PIKA_PROC_ARG_BOOLEAN (procedure, "flip-image",
_("Flip image _vertically on export"),
@ -276,26 +262,29 @@ dds_create_procedure (PikaPlugIn *plug_in,
0, 255, 0,
G_PARAM_READWRITE);
PIKA_PROC_ARG_INT (procedure, "mipmaps",
"Mipmaps",
"How to handle mipmaps (0 = No mipmaps, "
"1 = Generate mipmaps, "
"2 = Use existing mipmaps (layers)",
0, 2, DDS_MIPMAP_NONE,
G_PARAM_READWRITE);
PIKA_PROC_ARG_CHOICE (procedure, "mipmaps",
_("_Mipmaps"),
_("How to handle mipmaps"),
pika_choice_new_with_values ("none", DDS_MIPMAP_NONE, _("No mipmaps"), NULL,
"generate", DDS_MIPMAP_GENERATE, _("Generate mipmaps"), NULL,
"existing", DDS_MIPMAP_EXISTING, _("Use existing mipmaps"), NULL,
NULL),
"none",
G_PARAM_READWRITE);
PIKA_PROC_ARG_CHOICE (procedure, "mipmap-filter",
_("F_ilter"),
_("Filtering to use when generating mipmaps"),
pika_choice_new_with_values ("default", DDS_MIPMAP_FILTER_DEFAULT, _("Default"), NULL,
"nearest", DDS_MIPMAP_FILTER_NEAREST, _("Nearest"), NULL,
"box", DDS_MIPMAP_FILTER_BOX, _("Box"), NULL,
"triangle", DDS_MIPMAP_FILTER_TRIANGLE, _("Triangle"), NULL,
"quadratic", DDS_MIPMAP_FILTER_QUADRATIC, _("Quadratic"), NULL,
"bspline", DDS_MIPMAP_FILTER_BSPLINE, _("B-Spline"), NULL,
"mitchell", DDS_MIPMAP_FILTER_MITCHELL, _("Mitchell"), NULL,
"lanczos", DDS_MIPMAP_FILTER_LANCZOS, _("Lanczos"), NULL,
"kaiser", DDS_MIPMAP_FILTER_KAISER, _("Kaiser"), NULL,
pika_choice_new_with_values ("default", DDS_MIPMAP_FILTER_DEFAULT, _("Default"), NULL,
"nearest", DDS_MIPMAP_FILTER_NEAREST, _("Nearest"), NULL,
"box", DDS_MIPMAP_FILTER_BOX, _("Box"), NULL,
"triangle", DDS_MIPMAP_FILTER_TRIANGLE, _("Triangle"), NULL,
"quadratic", DDS_MIPMAP_FILTER_QUADRATIC, _("Quadratic"), NULL,
"bspline", DDS_MIPMAP_FILTER_BSPLINE, _("B-Spline"), NULL,
"mitchell", DDS_MIPMAP_FILTER_MITCHELL, _("Mitchell"), NULL,
"catrom", DDS_MIPMAP_FILTER_CATROM, _("Catmull-Rom"), NULL,
"lanczos", DDS_MIPMAP_FILTER_LANCZOS, _("Lanczos"), NULL,
"kaiser", DDS_MIPMAP_FILTER_KAISER, _("Kaiser"), NULL,
NULL),
"default",
G_PARAM_READWRITE);
@ -343,78 +332,6 @@ dds_create_procedure (PikaPlugIn *plug_in,
0.0, 1.0, 0.5,
G_PARAM_READWRITE);
}
#if 0
else if (! strcmp (name, DECODE_YCOCG_PROC))
{
procedure = pika_image_procedure_new (plug_in, name,
PIKA_PDB_PROC_TYPE_PLUGIN,
dds_decode, NULL, NULL);
pika_procedure_set_image_types (procedure, "RGBA");
pika_procedure_set_sensitivity_mask (procedure,
PIKA_PROCEDURE_SENSITIVE_DRAWABLE);
pika_procedure_set_menu_label (procedure, _("Decode YCoCg"));
/* pika_procedure_add_menu_path (procedure, "<Image>/Filters/Colors"); */
pika_procedure_set_documentation (procedure,
_("Converts YCoCg encoded pixels to RGB"),
_("Converts YCoCg encoded pixels to RGB"),
name);
pika_procedure_set_attribution (procedure,
"Shawn Kirst",
"Shawn Kirst",
"2008");
}
else if (! strcmp (name, DECODE_YCOCG_SCALED_PROC))
{
procedure = pika_image_procedure_new (plug_in, name,
PIKA_PDB_PROC_TYPE_PLUGIN,
dds_decode, NULL, NULL);
pika_procedure_set_image_types (procedure, "RGBA");
pika_procedure_set_sensitivity_mask (procedure,
PIKA_PROCEDURE_SENSITIVE_DRAWABLE);
pika_procedure_set_menu_label (procedure, _("Decode YCoCg (scaled)"));
/* pika_procedure_add_menu_path (procedure, "<Image>/Filters/Colors"); */
pika_procedure_set_documentation (procedure,
_("Converts YCoCg (scaled) encoded "
"pixels to RGB"),
_("Converts YCoCg (scaled) encoded "
"pixels to RGB"),
name);
pika_procedure_set_attribution (procedure,
"Shawn Kirst",
"Shawn Kirst",
"2008");
}
else if (! strcmp (name, DECODE_ALPHA_EXP_PROC))
{
procedure = pika_image_procedure_new (plug_in, name,
PIKA_PDB_PROC_TYPE_PLUGIN,
dds_decode, NULL, NULL);
pika_procedure_set_image_types (procedure, "RGBA");
pika_procedure_set_sensitivity_mask (procedure,
PIKA_PROCEDURE_SENSITIVE_DRAWABLE);
pika_procedure_set_menu_label (procedure, _("Decode Alpha exponent"));
/* pika_procedure_add_menu_path (procedure, "<Image>/Filters/Colors"); */
pika_procedure_set_documentation (procedure,
_("Converts alpha exponent encoded "
"pixels to RGB",
_("Converts alpha exponent encoded "
"pixels to RGB"),
name);
pika_procedure_set_attribution (procedure,
"Shawn Kirst",
"Shawn Kirst",
"2008");
}
#endif
return procedure;
}
@ -436,7 +353,7 @@ dds_load (PikaProcedure *procedure,
gegl_init (NULL, NULL);
status = read_dds (file, &image, run_mode == PIKA_RUN_INTERACTIVE,
procedure, G_OBJECT (config), &error);
procedure, config, &error);
if (status != PIKA_PDB_SUCCESS)
return pika_procedure_new_return_values (procedure, status, error);
@ -520,53 +437,3 @@ dds_save (PikaProcedure *procedure,
return pika_procedure_new_return_values (procedure, status, error);
}
#if 0
static PikaValueArray *
dds_decode (PikaProcedure *procedure,
PikaRunMode run_mode,
PikaImage *image,
gint n_drawables,
PikaDrawable **drawables,
PikaProcedureConfig *config,
gpointer run_data)
{
const gchar *name = pika_procedure_get_name (procedure);
PikaDrawable *drawable,
if (n_drawables != 1)
{
GError *error = NULL;
g_set_error (&error, PIKA_PLUG_IN_ERROR, 0,
_("Procedure '%s' only works with one drawable."),
name);
return pika_procedure_new_return_values (procedure,
PIKA_PDB_EXECUTION_ERROR,
error);
}
else
{
drawable = drawables[0];
}
if (! strcmp (name, DECODE_YCOCG_PROC))
{
decode_ycocg_image (drawable, TRUE);
}
else if (! strcmp (name, DECODE_YCOCG_SCALED_PROC))
{
decode_ycocg_scaled_image (drawable, TRUE);
}
else if (! strcmp (name, DECODE_ALPHA_EXP_PROC))
{
decode_alpha_exp_image (drawable, TRUE);
}
if (run_mode != PIKA_RUN_NONINTERACTIVE)
pika_displays_flush ();
return pika_procedure_new_return_values (procedure, PIKA_PDB_SUCCESS, NULL);
}
#endif

View File

@ -21,6 +21,7 @@
#ifndef __DDS_H__
#define __DDS_H__
#define DDS_PLUGIN_VERSION_MAJOR 3
#define DDS_PLUGIN_VERSION_MINOR 9
#define DDS_PLUGIN_VERSION_REVISION 92
@ -101,6 +102,7 @@ typedef enum
DDS_MIPMAP_FILTER_QUADRATIC,
DDS_MIPMAP_FILTER_BSPLINE,
DDS_MIPMAP_FILTER_MITCHELL,
DDS_MIPMAP_FILTER_CATROM,
DDS_MIPMAP_FILTER_LANCZOS,
DDS_MIPMAP_FILTER_KAISER,
DDS_MIPMAP_FILTER_MAX
@ -115,6 +117,7 @@ typedef enum
DDS_MIPMAP_WRAP_MAX
} DDS_MIPMAP_WRAP;
#define DDS_HEADERSIZE 128
#define DDS_HEADERSIZE_DX10 20
@ -122,18 +125,43 @@ typedef enum
#define DDSD_HEIGHT 0x00000002
#define DDSD_WIDTH 0x00000004
#define DDSD_PITCH 0x00000008
#define DDSD_BACKBUFFERCOUNT 0x00000020
#define DDSD_ZBUFFERBITDEPTH 0x00000040
#define DDSD_ALPHABITDEPTH 0x00000080
#define DDSD_LPSURFACE 0x00000800
#define DDSD_PIXELFORMAT 0x00001000
#define DDSD_CKDESTOVERLAY 0x00002000
#define DDSD_CKDESTBLT 0x00004000
#define DDSD_CKSRCOVERLAY 0x00008000
#define DDSD_CKSRCBLT 0x00010000
#define DDSD_MIPMAPCOUNT 0x00020000
#define DDSD_REFRESHRATE 0x00040000
#define DDSD_LINEARSIZE 0x00080000
#define DDSD_TEXTURESTAGE 0x00100000
#define DDSD_FVF 0x00200000
#define DDSD_SRCVBHANDLE 0x00400000
#define DDSD_DEPTH 0x00800000
#define DDPF_ALPHAPIXELS 0x00000001
#define DDPF_ALPHA 0x00000002
#define DDPF_FOURCC 0x00000004
#define DDPF_PALETTEINDEXED4 0x00000008
#define DDPF_PALETTEINDEXEDTO8 0x00000010
#define DDPF_PALETTEINDEXED8 0x00000020
#define DDPF_RGB 0x00000040
#define DDPF_COMPRESSED 0x00000080
#define DDPF_RGBTOYUV 0x00000100
#define DDPF_YUV 0x00000200
#define DDPF_ZBUFFER 0x00000400
#define DDPF_PALETTEINDEXED1 0x00000800
#define DDPF_PALETTEINDEXED2 0x00001000
#define DDPF_ZPIXELS 0x00002000
#define DDPF_STENCILBUFFER 0x00004000
#define DDPF_ALPHAPREMULT 0x00008000
#define DDPF_LUMINANCE 0x00020000
#define DDPF_NORMAL 0x80000000 // nvidia specific
#define DDPF_BUMPLUMINANCE 0x00040000
#define DDPF_BUMPDUDV 0x00080000
#define DDPF_NORMAL 0x80000000 /* NVidia specific */
#define DDSCAPS_COMPLEX 0x00000008
#define DDSCAPS_TEXTURE 0x00001000
@ -159,6 +187,7 @@ typedef enum
#define D3D10_RESOURCE_DIMENSION_TEXTURE2D 3
#define D3D10_RESOURCE_DIMENSION_TEXTURE3D 4
typedef struct
{
unsigned int size;
@ -192,8 +221,8 @@ typedef struct
{
struct
{
unsigned int magic1; // FOURCC "PIKA"
unsigned int magic2; // FOURCC "-DDS"
unsigned int magic1; /* FOURCC "PIKA" */
unsigned int magic2; /* FOURCC "-DDS" */
unsigned int version;
unsigned int extra_fourcc;
} pika_dds_special;
@ -204,6 +233,7 @@ typedef struct
unsigned int reserved2;
} dds_header_t;
typedef enum
{
DXGI_FORMAT_UNKNOWN = 0,
@ -334,4 +364,70 @@ typedef struct
unsigned int reserved;
} dds_header_dx10_t;
/* Format values that can be found in the FOURCC field */
typedef enum _D3DFORMAT {
D3DFMT_R8G8B8 = 20,
D3DFMT_A8R8G8B8 = 21,
D3DFMT_X8R8G8B8 = 22,
D3DFMT_R5G6B5 = 23,
D3DFMT_X1R5G5B5 = 24,
D3DFMT_A1R5G5B5 = 25,
D3DFMT_A4R4G4B4 = 26,
D3DFMT_R3G3B2 = 27,
D3DFMT_A8 = 28,
D3DFMT_A8R3G3B2 = 29,
D3DFMT_X4R4G4B4 = 30,
D3DFMT_A2B10G10R10 = 31,
D3DFMT_A8B8G8R8 = 32,
D3DFMT_X8B8G8R8 = 33,
D3DFMT_G16R16 = 34,
D3DFMT_A2R10G10B10 = 35,
D3DFMT_A16B16G16R16 = 36,
D3DFMT_A8P8 = 40,
D3DFMT_P8 = 41,
D3DFMT_L8 = 50,
D3DFMT_A8L8 = 51,
D3DFMT_A4L4 = 52,
D3DFMT_V8U8 = 60,
D3DFMT_L6V5U5 = 61,
D3DFMT_X8L8V8U8 = 62,
D3DFMT_Q8W8V8U8 = 63,
D3DFMT_V16U16 = 64,
D3DFMT_A2W10V10U10 = 67,
D3DFMT_D16_LOCKABLE = 70,
D3DFMT_D32 = 71,
D3DFMT_D15S1 = 73,
D3DFMT_D24S8 = 75,
D3DFMT_D24X8 = 77,
D3DFMT_D24X4S4 = 79,
D3DFMT_D16 = 80,
D3DFMT_L16 = 81,
D3DFMT_D32F_LOCKABLE = 82,
D3DFMT_D24FS8 = 83,
D3DFMT_D32_LOCKABLE = 84,
D3DFMT_S8_LOCKABLE = 85,
D3DFMT_VERTEXDATA = 100,
D3DFMT_INDEX16 = 101,
D3DFMT_INDEX32 = 102,
D3DFMT_Q16W16V16U16 = 110,
D3DFMT_R16F = 111,
D3DFMT_G16R16F = 112,
D3DFMT_A16B16G16R16F = 113,
D3DFMT_R32F = 114,
D3DFMT_G32R32F = 115,
D3DFMT_A32B32G32R32F = 116,
D3DFMT_CxV8U8 = 117,
D3DFMT_A1 = 118,
D3DFMT_A2B10G10R10_XR_BIAS = 119,
D3DFMT_BINARYBUFFER = 199,
} D3DFORMAT;
#endif /* __DDS_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -22,12 +22,12 @@
#define __DDSREAD_H__
extern PikaPDBStatusType read_dds (GFile *file,
PikaImage **image,
gboolean interactive,
PikaProcedure *procedure,
GObject *config,
GError **error);
extern PikaPDBStatusType read_dds (GFile *file,
PikaImage **image,
gboolean interactive,
PikaProcedure *procedure,
PikaProcedureConfig *config,
GError **error);
#endif /* __DDSREAD_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -34,11 +34,14 @@
#include <math.h>
#include <glib.h>
#include <libpika/pika.h>
#include "dds.h"
#include "dxt.h"
#include "endian_rw.h"
#include "mipmap.h"
#include "imath.h"
#include "mipmap.h"
#include "misc.h"
#include "vec.h"
#include "dxt_tables.h"
@ -757,181 +760,6 @@ encode_color_block (unsigned char *dst,
PUTL32(dst + 4, indices);
}
static void
get_min_max_YCoCg (const unsigned char *block,
unsigned char *mincolor,
unsigned char *maxcolor)
{
int i;
mincolor[2] = mincolor[1] = 255;
maxcolor[2] = maxcolor[1] = 0;
for (i = 0; i < 16; ++i)
{
if (block[4 * i + 2] < mincolor[2]) mincolor[2] = block[4 * i + 2];
if (block[4 * i + 1] < mincolor[1]) mincolor[1] = block[4 * i + 1];
if (block[4 * i + 2] > maxcolor[2]) maxcolor[2] = block[4 * i + 2];
if (block[4 * i + 1] > maxcolor[1]) maxcolor[1] = block[4 * i + 1];
}
}
static void
scale_YCoCg (unsigned char *block,
unsigned char *mincolor,
unsigned char *maxcolor)
{
const int s0 = 128 / 2 - 1;
const int s1 = 128 / 4 - 1;
int m0, m1, m2, m3;
int mask0, mask1, scale;
int i;
m0 = abs(mincolor[2] - 128);
m1 = abs(mincolor[1] - 128);
m2 = abs(maxcolor[2] - 128);
m3 = abs(maxcolor[1] - 128);
if (m1 > m0) m0 = m1;
if (m3 > m2) m2 = m3;
if (m2 > m0) m0 = m2;
mask0 = -(m0 <= s0);
mask1 = -(m0 <= s1);
scale = 1 + (1 & mask0) + (2 & mask1);
mincolor[2] = (mincolor[2] - 128) * scale + 128;
mincolor[1] = (mincolor[1] - 128) * scale + 128;
mincolor[0] = (scale - 1) << 3;
maxcolor[2] = (maxcolor[2] - 128) * scale + 128;
maxcolor[1] = (maxcolor[1] - 128) * scale + 128;
maxcolor[0] = (scale - 1) << 3;
for (i = 0; i < 16; ++i)
{
block[i * 4 + 2] = (block[i * 4 + 2] - 128) * scale + 128;
block[i * 4 + 1] = (block[i * 4 + 1] - 128) * scale + 128;
}
}
#define INSET_SHIFT 4
static void
inset_bbox_YCoCg (unsigned char *mincolor,
unsigned char *maxcolor)
{
int inset[4], mini[4], maxi[4];
inset[2] = (maxcolor[2] - mincolor[2]) - ((1 << (INSET_SHIFT - 1)) - 1);
inset[1] = (maxcolor[1] - mincolor[1]) - ((1 << (INSET_SHIFT - 1)) - 1);
mini[2] = ((mincolor[2] << INSET_SHIFT) + inset[2]) >> INSET_SHIFT;
mini[1] = ((mincolor[1] << INSET_SHIFT) + inset[1]) >> INSET_SHIFT;
maxi[2] = ((maxcolor[2] << INSET_SHIFT) - inset[2]) >> INSET_SHIFT;
maxi[1] = ((maxcolor[1] << INSET_SHIFT) - inset[1]) >> INSET_SHIFT;
mini[2] = (mini[2] >= 0) ? mini[2] : 0;
mini[1] = (mini[1] >= 0) ? mini[1] : 0;
maxi[2] = (maxi[2] <= 255) ? maxi[2] : 255;
maxi[1] = (maxi[1] <= 255) ? maxi[1] : 255;
mincolor[2] = (mini[2] & 0xf8) | (mini[2] >> 5);
mincolor[1] = (mini[1] & 0xfc) | (mini[1] >> 6);
maxcolor[2] = (maxi[2] & 0xf8) | (maxi[2] >> 5);
maxcolor[1] = (maxi[1] & 0xfc) | (maxi[1] >> 6);
}
static void
select_diagonal_YCoCg (const unsigned char *block,
unsigned char *mincolor,
unsigned char *maxcolor)
{
unsigned char mid0, mid1, side, mask, b0, b1, c0, c1;
int i;
mid0 = ((int)mincolor[2] + maxcolor[2] + 1) >> 1;
mid1 = ((int)mincolor[1] + maxcolor[1] + 1) >> 1;
side = 0;
for (i = 0; i < 16; ++i)
{
b0 = block[i * 4 + 2] >= mid0;
b1 = block[i * 4 + 1] >= mid1;
side += (b0 ^ b1);
}
mask = -(side > 8);
mask &= -(mincolor[2] != maxcolor[2]);
c0 = mincolor[1];
c1 = maxcolor[1];
c0 ^= c1;
c1 ^= c0 & mask;
c0 ^= c1;
mincolor[1] = c0;
maxcolor[1] = c1;
}
static void
encode_YCoCg_block (unsigned char *dst,
unsigned char *block)
{
unsigned char colors[4][3], *maxcolor, *mincolor;
unsigned int mask;
int c0, c1, d0, d1, d2, d3;
int b0, b1, b2, b3, b4;
int x0, x1, x2;
int i, idx;
maxcolor = &colors[0][0];
mincolor = &colors[1][0];
get_min_max_YCoCg(block, mincolor, maxcolor);
scale_YCoCg(block, mincolor, maxcolor);
inset_bbox_YCoCg(mincolor, maxcolor);
select_diagonal_YCoCg(block, mincolor, maxcolor);
lerp_rgb13(&colors[2][0], maxcolor, mincolor);
lerp_rgb13(&colors[3][0], mincolor, maxcolor);
mask = 0;
for (i = 0; i < 16; ++i)
{
c0 = block[4 * i + 2];
c1 = block[4 * i + 1];
d0 = abs(colors[0][2] - c0) + abs(colors[0][1] - c1);
d1 = abs(colors[1][2] - c0) + abs(colors[1][1] - c1);
d2 = abs(colors[2][2] - c0) + abs(colors[2][1] - c1);
d3 = abs(colors[3][2] - c0) + abs(colors[3][1] - c1);
b0 = d0 > d3;
b1 = d1 > d2;
b2 = d0 > d2;
b3 = d1 > d3;
b4 = d2 > d3;
x0 = b1 & b2;
x1 = b0 & b3;
x2 = b0 & b4;
idx = (x2 | ((x0 | x1) << 1));
mask |= idx << (2 * i);
}
PUTL16(dst + 0, pack_rgb565(maxcolor));
PUTL16(dst + 2, pack_rgb565(mincolor));
PUTL32(dst + 4, mask);
}
/* write DXT3 alpha block */
static void
encode_alpha_block_BC2 (unsigned char *dst,
@ -1288,33 +1116,35 @@ dxt_compress (unsigned char *dst,
}
static void
decode_color_block (unsigned char *block,
unsigned char *src,
int format)
decode_color_block (guchar *block,
guchar *src,
gint format)
{
int i, x, y;
unsigned char *d = block;
unsigned int indices, idx;
unsigned char colors[4][3];
unsigned short c0, c1;
guchar *d = block;
guint indices, idx;
guchar colors[4][3];
gushort c0, c1;
gint i, x, y;
c0 = GETL16(&src[0]);
c1 = GETL16(&src[2]);
c0 = GETL16 (&src[0]);
c1 = GETL16 (&src[2]);
unpack_rgb565(colors[0], c0);
unpack_rgb565(colors[1], c1);
unpack_rgb565 (colors[0], c0);
unpack_rgb565 (colors[1], c1);
if ((c0 > c1) || (format == DDS_COMPRESS_BC3))
{
lerp_rgb13(colors[2], colors[0], colors[1]);
lerp_rgb13(colors[3], colors[1], colors[0]);
/* Four-color mode */
lerp_rgb13 (colors[2], colors[0], colors[1]);
lerp_rgb13 (colors[3], colors[1], colors[0]);
}
else
{
/* Three-color mode */
for (i = 0; i < 3; ++i)
{
colors[2][i] = (colors[0][i] + colors[1][i] + 1) >> 1;
colors[3][i] = 255;
colors[3][i] = 0; /* Three-color mode index 11 is always black */
}
}

View File

@ -2,7 +2,6 @@ plugin_name = 'file-dds'
plugin_sources = [
'dds.c',
'color.c',
'ddsread.c',
'ddswrite.c',
'dxt.c',

File diff suppressed because it is too large Load Diff

View File

@ -21,55 +21,56 @@
#ifndef __MIPMAP_H__
#define __MIPMAP_H__
int get_num_mipmaps (int width,
int height);
unsigned int get_mipmapped_size (int width,
int height,
int bpp,
int level,
int num,
int format);
unsigned int get_volume_mipmapped_size (int width,
int height,
int depth,
int bpp,
int level,
int num,
int format);
int get_next_mipmap_dimensions (int *next_w,
int *next_h,
int curr_w,
int curr_h);
float cubic_interpolate (float a,
float b,
float c,
float d,
float x);
int generate_mipmaps (unsigned char *dst,
unsigned char *src,
unsigned int width,
unsigned int height,
int bpp,
int indexed,
int mipmaps,
int filter,
int wrap,
int gamma_correct,
float gamma,
int preserve_alpha_test_coverage,
float alpha_test_threshold);
int generate_volume_mipmaps (unsigned char *dst,
unsigned char *src,
unsigned int width,
unsigned int height,
unsigned int depth,
int bpp,
int indexed,
int mipmaps,
int filter,
int wrap,
int gamma_correct,
float gamma);
gint get_num_mipmaps (gint width,
gint height);
guint get_mipmapped_size (gint width,
gint height,
gint bpp,
gint level,
gint num,
gint format);
guint get_volume_mipmapped_size (gint width,
gint height,
gint depth,
gint bpp,
gint level,
gint num,
gint format);
gint get_next_mipmap_dimensions (gint *next_w,
gint *next_h,
gint curr_w,
gint curr_h);
gint generate_mipmaps (guchar *dst,
guchar *src,
guint width,
guint height,
gint bpp,
gint indexed,
gint mipmaps,
gint filter,
gint wrap,
gint gamma_correct,
gfloat gamma,
gint preserve_alpha_test_coverage,
gfloat alpha_test_threshold);
gint generate_volume_mipmaps (guchar *dst,
guchar *src,
guint width,
guint height,
guint depth,
gint bpp,
gint indexed,
gint mipmaps,
gint filter,
gint wrap,
gint gamma_correct,
gfloat gamma);
#endif /* __MIPMAP_H__ */

View File

@ -4,56 +4,53 @@
* Copyright (C) 2004-2012 Shawn Kirst <skirst@gmail.com>,
* with parts (C) 2003 Arne Reuter <homepage@arnereuter.de> where specified.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301, USA.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <libpika/pika.h>
#include "endian_rw.h"
#include "imath.h"
#include "misc.h"
static inline float
saturate (float a)
{
if(a < 0) a = 0;
if(a > 1) a = 1;
/*
* Decoding Functions
*/
static inline gfloat
saturate (gfloat a)
{
if (a < 0) a = 0;
if (a > 1) a = 1;
return a;
}
void
decode_ycocg_image (PikaDrawable *drawable,
gboolean shadow)
decode_ycocg (PikaDrawable *drawable)
{
GeglBuffer *buffer, *sbuffer;
const Babl *format;
unsigned char *data;
unsigned int i, w, h, num_pixels;
const float offset = 0.5f * 256.0f / 255.0f;
float Y, Co, Cg, R, G, B;
GeglBuffer *buffer;
const Babl *format;
guchar *data;
guint num_pixels;
guint i, w, h;
const gfloat offset = 0.5f * 256.0f / 255.0f;
gfloat Y, Co, Cg;
gfloat R, G, B;
buffer = pika_drawable_get_buffer (drawable);
if (shadow)
{
sbuffer = pika_drawable_get_shadow_buffer (drawable);
gegl_buffer_copy (buffer, NULL, GEGL_ABYSS_NONE, sbuffer, NULL);
g_object_unref (buffer);
buffer = sbuffer;
}
format = babl_format ("R'G'B'A u8");
w = gegl_buffer_get_width (buffer);
@ -62,46 +59,43 @@ decode_ycocg_image (PikaDrawable *drawable,
data = g_malloc (num_pixels * 4);
gegl_buffer_get (buffer, GEGL_RECTANGLE(0, 0, w, h), 1.0, format, data,
gegl_buffer_get (buffer, GEGL_RECTANGLE (0, 0, w, h), 1.0, format, data,
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
pika_progress_init ("Decoding YCoCg pixels...");
for (i = 0; i < num_pixels; ++i)
{
Y = (float)data[4 * i + 3] / 255.0f;
Co = (float)data[4 * i + 0] / 255.0f;
Cg = (float)data[4 * i + 1] / 255.0f;
Y = (gfloat) data[4 * i + 3] / 255.0f;
Co = (gfloat) data[4 * i + 0] / 255.0f;
Cg = (gfloat) data[4 * i + 1] / 255.0f;
/* convert YCoCg to RGB */
Co -= offset;
Cg -= offset;
R = saturate(Y + Co - Cg);
G = saturate(Y + Cg);
B = saturate(Y - Co - Cg);
R = saturate (Y + Co - Cg);
G = saturate (Y + Cg);
B = saturate (Y - Co - Cg);
/* copy new alpha from blue */
data[4 * i + 3] = data[4 * i + 2];
data[4 * i + 0] = (unsigned char)(R * 255.0f);
data[4 * i + 1] = (unsigned char)(G * 255.0f);
data[4 * i + 2] = (unsigned char)(B * 255.0f);
data[4 * i + 0] = (guchar) (R * 255.0f);
data[4 * i + 1] = (guchar) (G * 255.0f);
data[4 * i + 2] = (guchar) (B * 255.0f);
if ((i & 0x7fff) == 0)
pika_progress_update ((float)i / (float)num_pixels);
pika_progress_update ((gdouble) i / (gdouble) num_pixels);
}
gegl_buffer_set (buffer, GEGL_RECTANGLE(0, 0, w, h), 0, format, data,
gegl_buffer_set (buffer, GEGL_RECTANGLE (0, 0, w, h), 0, format, data,
GEGL_AUTO_ROWSTRIDE);
pika_progress_update (1.0);
gegl_buffer_flush (buffer);
if (shadow)
pika_drawable_merge_shadow (drawable, TRUE);
pika_drawable_update (drawable, 0, 0, w, h);
g_free (data);
@ -110,27 +104,19 @@ decode_ycocg_image (PikaDrawable *drawable,
}
void
decode_ycocg_scaled_image (PikaDrawable *drawable,
gboolean shadow)
decode_ycocg_scaled (PikaDrawable *drawable)
{
GeglBuffer *buffer, *sbuffer;
const Babl *format;
unsigned char *data;
unsigned int i, w, h, num_pixels;
const float offset = 0.5f * 256.0f / 255.0f;
float Y, Co, Cg, R, G, B, s;
GeglBuffer *buffer;
const Babl *format;
guchar *data;
guint num_pixels;
guint i, w, h;
const gfloat offset = 0.5f * 256.0f / 255.0f;
gfloat Y, Co, Cg;
gfloat R, G, B, s;
buffer = pika_drawable_get_buffer (drawable);
if (shadow)
{
sbuffer = pika_drawable_get_shadow_buffer (drawable);
gegl_buffer_copy (buffer, NULL, GEGL_ABYSS_NONE, sbuffer, NULL);
g_object_unref (buffer);
buffer = sbuffer;
}
format = babl_format ("R'G'B'A u8");
w = gegl_buffer_get_width (buffer);
@ -139,17 +125,17 @@ decode_ycocg_scaled_image (PikaDrawable *drawable,
data = g_malloc (num_pixels * 4);
gegl_buffer_get (buffer, GEGL_RECTANGLE(0, 0, w, h), 1.0, format, data,
gegl_buffer_get (buffer, GEGL_RECTANGLE (0, 0, w, h), 1.0, format, data,
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
pika_progress_init ("Decoding YCoCg (scaled) pixels...");
for (i = 0; i < num_pixels; ++i)
{
Y = (float)data[4 * i + 3] / 255.0f;
Co = (float)data[4 * i + 0] / 255.0f;
Cg = (float)data[4 * i + 1] / 255.0f;
s = (float)data[4 * i + 2] / 255.0f;
Y = (gfloat) data[4 * i + 3] / 255.0f;
Co = (gfloat) data[4 * i + 0] / 255.0f;
Cg = (gfloat) data[4 * i + 1] / 255.0f;
s = (gfloat) data[4 * i + 2] / 255.0f;
/* convert YCoCg to RGB */
s = 1.0f / ((255.0f / 8.0f) * s + 1.0f);
@ -157,31 +143,28 @@ decode_ycocg_scaled_image (PikaDrawable *drawable,
Co = (Co - offset) * s;
Cg = (Cg - offset) * s;
R = saturate(Y + Co - Cg);
G = saturate(Y + Cg);
B = saturate(Y - Co - Cg);
R = saturate (Y + Co - Cg);
G = saturate (Y + Cg);
B = saturate (Y - Co - Cg);
data[4 * i + 0] = (unsigned char)(R * 255.0f);
data[4 * i + 1] = (unsigned char)(G * 255.0f);
data[4 * i + 2] = (unsigned char)(B * 255.0f);
data[4 * i + 0] = (guchar) (R * 255.0f);
data[4 * i + 1] = (guchar) (G * 255.0f);
data[4 * i + 2] = (guchar) (B * 255.0f);
/* set alpha to 1 */
data[4 * i + 3] = 255;
if ((i & 0x7fff) == 0)
pika_progress_update ((float)i / (float)num_pixels);
pika_progress_update ((gdouble) i / (gdouble) num_pixels);
}
gegl_buffer_set (buffer, GEGL_RECTANGLE(0, 0, w, h), 0, format, data,
gegl_buffer_set (buffer, GEGL_RECTANGLE (0, 0, w, h), 0, format, data,
GEGL_AUTO_ROWSTRIDE);
pika_progress_update (1.0);
gegl_buffer_flush (buffer);
if (shadow)
pika_drawable_merge_shadow (drawable, TRUE);
pika_drawable_update (drawable, 0, 0, w, h);
g_free (data);
@ -190,25 +173,17 @@ decode_ycocg_scaled_image (PikaDrawable *drawable,
}
void
decode_alpha_exp_image (PikaDrawable *drawable,
gboolean shadow)
decode_alpha_exponent (PikaDrawable *drawable)
{
GeglBuffer *buffer, *sbuffer;
GeglBuffer *buffer;
const Babl *format;
unsigned char *data;
unsigned int i, w, h, num_pixels;
int R, G, B, A;
guchar *data;
guint num_pixels;
guint i, w, h;
gint R, G, B, A;
buffer = pika_drawable_get_buffer (drawable);
if (shadow)
{
sbuffer = pika_drawable_get_shadow_buffer (drawable);
gegl_buffer_copy (buffer, NULL, GEGL_ABYSS_NONE, sbuffer, NULL);
g_object_unref (buffer);
buffer = sbuffer;
}
format = babl_format ("R'G'B'A u8");
w = gegl_buffer_get_width (buffer);
@ -217,7 +192,7 @@ decode_alpha_exp_image (PikaDrawable *drawable,
data = g_malloc (num_pixels * 4);
gegl_buffer_get (buffer, GEGL_RECTANGLE(0, 0, w, h), 1.0, format, data,
gegl_buffer_get (buffer, GEGL_RECTANGLE (0, 0, w, h), 1.0, format, data,
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
pika_progress_init ("Decoding Alpha-exponent pixels...");
@ -240,22 +215,268 @@ decode_alpha_exp_image (PikaDrawable *drawable,
data[4 * i + 3] = A;
if ((i & 0x7fff) == 0)
pika_progress_update ((float)i / (float)num_pixels);
pika_progress_update ((gdouble) i / (gdouble) num_pixels);
}
gegl_buffer_set (buffer, GEGL_RECTANGLE(0, 0, w, h), 0, format, data,
gegl_buffer_set (buffer, GEGL_RECTANGLE (0, 0, w, h), 0, format, data,
GEGL_AUTO_ROWSTRIDE);
pika_progress_update (1.0);
gegl_buffer_flush (buffer);
if (shadow)
pika_drawable_merge_shadow (drawable, TRUE);
pika_drawable_update (drawable, 0, 0, w, h);
g_free (data);
g_object_unref (buffer);
}
/*
* Encoding Functions
*/
void
encode_ycocg (guchar *dst,
gint r,
gint g,
gint b)
{
gint y = ((r + (g << 1) + b) + 2) >> 2;
gint co = ((((r << 1) - (b << 1)) + 2) >> 2) + 128;
gint cg = (((-r + (g << 1) - b) + 2) >> 2) + 128;
dst[0] = 255;
dst[1] = (cg > 255 ? 255 : (cg < 0 ? 0 : cg));
dst[2] = (co > 255 ? 255 : (co < 0 ? 0 : co));
dst[3] = (y > 255 ? 255 : (y < 0 ? 0 : y));
}
void
encode_alpha_exponent (guchar *dst,
gint r,
gint g,
gint b,
gint a)
{
gfloat ar, ag, ab, aa;
ar = (gfloat) r / 255.0f;
ag = (gfloat) g / 255.0f;
ab = (gfloat) b / 255.0f;
aa = MAX (ar, MAX (ag, ab));
if (aa < 1e-04f)
{
dst[0] = b;
dst[1] = g;
dst[2] = r;
dst[3] = 255;
return;
}
ar /= aa;
ag /= aa;
ab /= aa;
r = (gint) floorf (255.0f * ar + 0.5f);
g = (gint) floorf (255.0f * ag + 0.5f);
b = (gint) floorf (255.0f * ab + 0.5f);
a = (gint) floorf (255.0f * aa + 0.5f);
dst[0] = MAX (0, MIN (255, b));
dst[1] = MAX (0, MIN (255, g));
dst[2] = MAX (0, MIN (255, r));
dst[3] = MAX (0, MIN (255, a));
}
/*
* Compression Functions
*/
static void
get_min_max_YCoCg (const guchar *block,
guchar *mincolor,
guchar *maxcolor)
{
gint i;
mincolor[2] = mincolor[1] = 255;
maxcolor[2] = maxcolor[1] = 0;
for (i = 0; i < 16; ++i)
{
if (block[4 * i + 2] < mincolor[2]) mincolor[2] = block[4 * i + 2];
if (block[4 * i + 1] < mincolor[1]) mincolor[1] = block[4 * i + 1];
if (block[4 * i + 2] > maxcolor[2]) maxcolor[2] = block[4 * i + 2];
if (block[4 * i + 1] > maxcolor[1]) maxcolor[1] = block[4 * i + 1];
}
}
static void
scale_YCoCg (guchar *block,
guchar *mincolor,
guchar *maxcolor)
{
const gint s0 = 128 / 2 - 1;
const gint s1 = 128 / 4 - 1;
gint m0, m1, m2, m3;
gint mask0, mask1, scale;
gint i;
m0 = abs (mincolor[2] - 128);
m1 = abs (mincolor[1] - 128);
m2 = abs (maxcolor[2] - 128);
m3 = abs (maxcolor[1] - 128);
if (m1 > m0) m0 = m1;
if (m3 > m2) m2 = m3;
if (m2 > m0) m0 = m2;
mask0 = -(m0 <= s0);
mask1 = -(m0 <= s1);
scale = 1 + (1 & mask0) + (2 & mask1);
mincolor[2] = (mincolor[2] - 128) * scale + 128;
mincolor[1] = (mincolor[1] - 128) * scale + 128;
mincolor[0] = (scale - 1) << 3;
maxcolor[2] = (maxcolor[2] - 128) * scale + 128;
maxcolor[1] = (maxcolor[1] - 128) * scale + 128;
maxcolor[0] = (scale - 1) << 3;
for (i = 0; i < 16; ++i)
{
block[i * 4 + 2] = (block[i * 4 + 2] - 128) * scale + 128;
block[i * 4 + 1] = (block[i * 4 + 1] - 128) * scale + 128;
}
}
#define INSET_SHIFT 4
static void
inset_bbox_YCoCg (guchar *mincolor,
guchar *maxcolor)
{
gint inset[4], mini[4], maxi[4];
inset[2] = (maxcolor[2] - mincolor[2]) - ((1 << (INSET_SHIFT - 1)) - 1);
inset[1] = (maxcolor[1] - mincolor[1]) - ((1 << (INSET_SHIFT - 1)) - 1);
mini[2] = ((mincolor[2] << INSET_SHIFT) + inset[2]) >> INSET_SHIFT;
mini[1] = ((mincolor[1] << INSET_SHIFT) + inset[1]) >> INSET_SHIFT;
maxi[2] = ((maxcolor[2] << INSET_SHIFT) - inset[2]) >> INSET_SHIFT;
maxi[1] = ((maxcolor[1] << INSET_SHIFT) - inset[1]) >> INSET_SHIFT;
mini[2] = (mini[2] >= 0) ? mini[2] : 0;
mini[1] = (mini[1] >= 0) ? mini[1] : 0;
maxi[2] = (maxi[2] <= 255) ? maxi[2] : 255;
maxi[1] = (maxi[1] <= 255) ? maxi[1] : 255;
mincolor[2] = (mini[2] & 0xf8) | (mini[2] >> 5);
mincolor[1] = (mini[1] & 0xfc) | (mini[1] >> 6);
maxcolor[2] = (maxi[2] & 0xf8) | (maxi[2] >> 5);
maxcolor[1] = (maxi[1] & 0xfc) | (maxi[1] >> 6);
}
static void
select_diagonal_YCoCg (const guchar *block,
guchar *mincolor,
guchar *maxcolor)
{
guchar mid0, mid1, side, mask, b0, b1, c0, c1;
gint i;
mid0 = ((gint) mincolor[2] + maxcolor[2] + 1) >> 1;
mid1 = ((gint) mincolor[1] + maxcolor[1] + 1) >> 1;
side = 0;
for (i = 0; i < 16; ++i)
{
b0 = block[i * 4 + 2] >= mid0;
b1 = block[i * 4 + 1] >= mid1;
side += (b0 ^ b1);
}
mask = -(side > 8);
mask &= -(mincolor[2] != maxcolor[2]);
c0 = mincolor[1];
c1 = maxcolor[1];
c0 ^= c1;
c1 ^= c0 & mask;
c0 ^= c1;
mincolor[1] = c0;
maxcolor[1] = c1;
}
void
encode_YCoCg_block (guchar *dst,
guchar *block)
{
guchar colors[4][3], *maxcolor, *mincolor;
guint mask;
gint c0, c1, d0, d1, d2, d3;
gint b0, b1, b2, b3, b4;
gint x0, x1, x2;
gint i, idx;
maxcolor = &colors[0][0];
mincolor = &colors[1][0];
get_min_max_YCoCg (block, mincolor, maxcolor);
scale_YCoCg (block, mincolor, maxcolor);
inset_bbox_YCoCg (mincolor, maxcolor);
select_diagonal_YCoCg (block, mincolor, maxcolor);
colors[2][0] = (2 * maxcolor[0] + mincolor[0]) / 3;
colors[2][1] = (2 * maxcolor[1] + mincolor[1]) / 3;
colors[2][2] = (2 * maxcolor[2] + mincolor[2]) / 3;
colors[3][0] = (2 * mincolor[0] + maxcolor[0]) / 3;
colors[3][1] = (2 * mincolor[1] + maxcolor[1]) / 3;
colors[3][2] = (2 * mincolor[2] + maxcolor[2]) / 3;
mask = 0;
for (i = 0; i < 16; ++i)
{
c0 = block[4 * i + 2];
c1 = block[4 * i + 1];
d0 = abs (colors[0][2] - c0) + abs (colors[0][1] - c1);
d1 = abs (colors[1][2] - c0) + abs (colors[1][1] - c1);
d2 = abs (colors[2][2] - c0) + abs (colors[2][1] - c1);
d3 = abs (colors[3][2] - c0) + abs (colors[3][1] - c1);
b0 = d0 > d3;
b1 = d1 > d2;
b2 = d0 > d2;
b3 = d1 > d3;
b4 = d2 > d3;
x0 = b1 & b2;
x1 = b0 & b3;
x2 = b0 & b4;
idx = (x2 | ((x0 | x1) << 1));
mask |= idx << (2 * i);
}
PUTL16 (dst + 0, (mul8bit (maxcolor[2], 31) << 11) |
(mul8bit (maxcolor[1], 63) << 5) |
(mul8bit (maxcolor[0], 31) ));
PUTL16 (dst + 2, (mul8bit (mincolor[2], 31) << 11) |
(mul8bit (mincolor[1], 63) << 5) |
(mul8bit (mincolor[0], 31) ));
PUTL32 (dst + 4, mask);
}

View File

@ -21,11 +21,26 @@
#ifndef __MISC_H__
#define __MISC_H__
void decode_ycocg_image (PikaDrawable *drawable,
gboolean shadow);
void decode_ycocg_scaled_image (PikaDrawable *drawable,
gboolean shadow);
void decode_alpha_exp_image (PikaDrawable *drawable,
gboolean shadow);
void decode_ycocg (PikaDrawable *drawable);
void decode_ycocg_scaled (PikaDrawable *drawable);
void decode_alpha_exponent (PikaDrawable *drawable);
void encode_ycocg (guchar *dst,
gint r,
gint g,
gint b);
void encode_alpha_exponent (guchar *dst,
gint r,
gint g,
gint b,
gint a);
void encode_YCoCg_block (guchar *dst,
guchar *block);
#endif /* __MISC_H__ */