mirror of https://github.com/GNOME/gimp.git
Consolidate YCoCg/AlphaExp code, always decode
Moves most of the code relating to YCoCg and Alpha Exponent into misc.c/h, in the interest of making the rest of the codebase cleaner. Removes the decode option from the import menu, as encoded files are always decoded now (there used to be a menu button for doing this after import, but with it gone there's no reason ever to not decode). Finally, the remaining functions in color.c were only ever called once, so these were extracted and inlined, and the empty file deleted.
This commit is contained in:
parent
30922cc266
commit
a5d1d96a38
|
@ -1,62 +0,0 @@
|
||||||
/*
|
|
||||||
* DDS GIMP plugin
|
|
||||||
*
|
|
||||||
* 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 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.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
#include <libgimp/gimp.h>
|
|
||||||
|
|
||||||
#include "color.h"
|
|
||||||
|
|
||||||
|
|
||||||
gfloat
|
|
||||||
linear_to_sRGB (gfloat c)
|
|
||||||
{
|
|
||||||
gfloat v = (gfloat) c;
|
|
||||||
|
|
||||||
if (v < 0.0f)
|
|
||||||
v = 0.0f;
|
|
||||||
else if (v > 1.0f)
|
|
||||||
v = 1.0f;
|
|
||||||
else if (v <= 0.0031308f)
|
|
||||||
v = 12.92f * v;
|
|
||||||
else
|
|
||||||
v = 1.055f * powf (v, 0.41666f) - 0.055f;
|
|
||||||
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
gfloat
|
|
||||||
sRGB_to_linear (gfloat c)
|
|
||||||
{
|
|
||||||
gfloat v = (gfloat) c;
|
|
||||||
|
|
||||||
if (v < 0.0f)
|
|
||||||
v = 0.0f;
|
|
||||||
else if (v > 1.0f)
|
|
||||||
v = 1.0f;
|
|
||||||
else if (v <= 0.04045f)
|
|
||||||
v /= 12.92f;
|
|
||||||
else
|
|
||||||
v = powf ((v + 0.055f) / 1.055f, 2.4f);
|
|
||||||
|
|
||||||
return v;
|
|
||||||
}
|
|
|
@ -1,112 +0,0 @@
|
||||||
/*
|
|
||||||
* DDS GIMP plugin
|
|
||||||
*
|
|
||||||
* 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 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.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __COLOR_H__
|
|
||||||
#define __COLOR_H__
|
|
||||||
|
|
||||||
|
|
||||||
#include "imath.h"
|
|
||||||
|
|
||||||
|
|
||||||
/* sRGB encoding & decoding */
|
|
||||||
gfloat linear_to_sRGB (gfloat c);
|
|
||||||
gfloat sRGB_to_linear (gfloat c);
|
|
||||||
|
|
||||||
|
|
||||||
/* YCoCg encoding */
|
|
||||||
static inline void
|
|
||||||
RGB_to_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));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Other color conversions */
|
|
||||||
static inline gint
|
|
||||||
rgb_to_luminance (gint r,
|
|
||||||
gint g,
|
|
||||||
gint b)
|
|
||||||
{
|
|
||||||
/* ITU-R BT.709 luma coefficients, scaled by 256 */
|
|
||||||
return ((r * 54 + g * 182 + b * 20) + 128) >> 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline gushort
|
|
||||||
pack_r5g6b5 (gint r,
|
|
||||||
gint g,
|
|
||||||
gint b)
|
|
||||||
{
|
|
||||||
return (mul8bit (r, 31) << 11) |
|
|
||||||
(mul8bit (g, 63) << 5) |
|
|
||||||
(mul8bit (b, 31) );
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline gushort
|
|
||||||
pack_rgba4 (gint r,
|
|
||||||
gint g,
|
|
||||||
gint b,
|
|
||||||
gint a)
|
|
||||||
{
|
|
||||||
return (mul8bit (a, 15) << 12) |
|
|
||||||
(mul8bit (r, 15) << 8) |
|
|
||||||
(mul8bit (g, 15) << 4) |
|
|
||||||
(mul8bit (b, 15) );
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline gushort
|
|
||||||
pack_rgb5a1 (gint r,
|
|
||||||
gint g,
|
|
||||||
gint b,
|
|
||||||
gint a)
|
|
||||||
{
|
|
||||||
return (((a >> 7) & 0x01) << 15) |
|
|
||||||
(mul8bit (r, 31) << 10) |
|
|
||||||
(mul8bit (g, 31) << 5) |
|
|
||||||
(mul8bit (b, 31) );
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline guchar
|
|
||||||
pack_r3g3b2 (gint r,
|
|
||||||
gint g,
|
|
||||||
gint b)
|
|
||||||
{
|
|
||||||
return (mul8bit (r, 7) << 5) |
|
|
||||||
(mul8bit (g, 7) << 2) |
|
|
||||||
(mul8bit (b, 3) );
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline guint
|
|
||||||
pack_rgb10a2 (gint r, gint g, gint b, gint a)
|
|
||||||
{
|
|
||||||
return ((guint) ((a >> 6) & 0x003) << 30) |
|
|
||||||
((guint) ((b << 2) & 0x3ff) << 20) |
|
|
||||||
((guint) ((g << 2) & 0x3ff) << 10) |
|
|
||||||
((guint) ((r << 2) & 0x3ff) );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* __COLOR_H__ */
|
|
|
@ -42,10 +42,6 @@
|
||||||
#define LOAD_PROC "file-dds-load"
|
#define LOAD_PROC "file-dds-load"
|
||||||
#define SAVE_PROC "file-dds-save"
|
#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 _Dds Dds;
|
||||||
typedef struct _DdsClass DdsClass;
|
typedef struct _DdsClass DdsClass;
|
||||||
|
@ -86,15 +82,6 @@ static GimpValueArray * dds_save (GimpProcedure *procedure,
|
||||||
GimpMetadata *metadata,
|
GimpMetadata *metadata,
|
||||||
GimpProcedureConfig *config,
|
GimpProcedureConfig *config,
|
||||||
gpointer run_data);
|
gpointer run_data);
|
||||||
#if 0
|
|
||||||
static GimpValueArray * dds_decode (GimpProcedure *procedure,
|
|
||||||
GimpRunMode run_mode,
|
|
||||||
GimpImage *image,
|
|
||||||
gint n_drawables,
|
|
||||||
GimpDrawable **drawables,
|
|
||||||
GimpProcedureConfig *config,
|
|
||||||
gpointer run_data);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
G_DEFINE_TYPE (Dds, dds, GIMP_TYPE_PLUG_IN)
|
G_DEFINE_TYPE (Dds, dds, GIMP_TYPE_PLUG_IN)
|
||||||
|
@ -125,11 +112,6 @@ dds_query_procedures (GimpPlugIn *plug_in)
|
||||||
|
|
||||||
list = g_list_append (list, g_strdup (LOAD_PROC));
|
list = g_list_append (list, g_strdup (LOAD_PROC));
|
||||||
list = g_list_append (list, g_strdup (SAVE_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;
|
return list;
|
||||||
}
|
}
|
||||||
|
@ -183,12 +165,6 @@ dds_create_procedure (GimpPlugIn *plug_in,
|
||||||
"to opaque black"),
|
"to opaque black"),
|
||||||
TRUE,
|
TRUE,
|
||||||
G_PARAM_READWRITE);
|
G_PARAM_READWRITE);
|
||||||
|
|
||||||
GIMP_PROC_ARG_BOOLEAN (procedure, "decode-images",
|
|
||||||
_("Automatically decode YCoCg/AE_xp images when detected"),
|
|
||||||
_("Decode YCoCg/AExp images when detected"),
|
|
||||||
TRUE,
|
|
||||||
G_PARAM_READWRITE);
|
|
||||||
}
|
}
|
||||||
else if (! strcmp (name, SAVE_PROC))
|
else if (! strcmp (name, SAVE_PROC))
|
||||||
{
|
{
|
||||||
|
@ -358,78 +334,6 @@ dds_create_procedure (GimpPlugIn *plug_in,
|
||||||
0.0, 1.0, 0.5,
|
0.0, 1.0, 0.5,
|
||||||
G_PARAM_READWRITE);
|
G_PARAM_READWRITE);
|
||||||
}
|
}
|
||||||
#if 0
|
|
||||||
else if (! strcmp (name, DECODE_YCOCG_PROC))
|
|
||||||
{
|
|
||||||
procedure = gimp_image_procedure_new (plug_in, name,
|
|
||||||
GIMP_PDB_PROC_TYPE_PLUGIN,
|
|
||||||
dds_decode, NULL, NULL);
|
|
||||||
|
|
||||||
gimp_procedure_set_image_types (procedure, "RGBA");
|
|
||||||
gimp_procedure_set_sensitivity_mask (procedure,
|
|
||||||
GIMP_PROCEDURE_SENSITIVE_DRAWABLE);
|
|
||||||
|
|
||||||
gimp_procedure_set_menu_label (procedure, _("Decode YCoCg"));
|
|
||||||
/* gimp_procedure_add_menu_path (procedure, "<Image>/Filters/Colors"); */
|
|
||||||
|
|
||||||
gimp_procedure_set_documentation (procedure,
|
|
||||||
_("Converts YCoCg encoded pixels to RGB"),
|
|
||||||
_("Converts YCoCg encoded pixels to RGB"),
|
|
||||||
name);
|
|
||||||
gimp_procedure_set_attribution (procedure,
|
|
||||||
"Shawn Kirst",
|
|
||||||
"Shawn Kirst",
|
|
||||||
"2008");
|
|
||||||
}
|
|
||||||
else if (! strcmp (name, DECODE_YCOCG_SCALED_PROC))
|
|
||||||
{
|
|
||||||
procedure = gimp_image_procedure_new (plug_in, name,
|
|
||||||
GIMP_PDB_PROC_TYPE_PLUGIN,
|
|
||||||
dds_decode, NULL, NULL);
|
|
||||||
|
|
||||||
gimp_procedure_set_image_types (procedure, "RGBA");
|
|
||||||
gimp_procedure_set_sensitivity_mask (procedure,
|
|
||||||
GIMP_PROCEDURE_SENSITIVE_DRAWABLE);
|
|
||||||
|
|
||||||
gimp_procedure_set_menu_label (procedure, _("Decode YCoCg (scaled)"));
|
|
||||||
/* gimp_procedure_add_menu_path (procedure, "<Image>/Filters/Colors"); */
|
|
||||||
|
|
||||||
gimp_procedure_set_documentation (procedure,
|
|
||||||
_("Converts YCoCg (scaled) encoded "
|
|
||||||
"pixels to RGB"),
|
|
||||||
_("Converts YCoCg (scaled) encoded "
|
|
||||||
"pixels to RGB"),
|
|
||||||
name);
|
|
||||||
gimp_procedure_set_attribution (procedure,
|
|
||||||
"Shawn Kirst",
|
|
||||||
"Shawn Kirst",
|
|
||||||
"2008");
|
|
||||||
}
|
|
||||||
else if (! strcmp (name, DECODE_ALPHA_EXP_PROC))
|
|
||||||
{
|
|
||||||
procedure = gimp_image_procedure_new (plug_in, name,
|
|
||||||
GIMP_PDB_PROC_TYPE_PLUGIN,
|
|
||||||
dds_decode, NULL, NULL);
|
|
||||||
|
|
||||||
gimp_procedure_set_image_types (procedure, "RGBA");
|
|
||||||
gimp_procedure_set_sensitivity_mask (procedure,
|
|
||||||
GIMP_PROCEDURE_SENSITIVE_DRAWABLE);
|
|
||||||
|
|
||||||
gimp_procedure_set_menu_label (procedure, _("Decode Alpha exponent"));
|
|
||||||
/* gimp_procedure_add_menu_path (procedure, "<Image>/Filters/Colors"); */
|
|
||||||
|
|
||||||
gimp_procedure_set_documentation (procedure,
|
|
||||||
_("Converts alpha exponent encoded "
|
|
||||||
"pixels to RGB",
|
|
||||||
_("Converts alpha exponent encoded "
|
|
||||||
"pixels to RGB"),
|
|
||||||
name);
|
|
||||||
gimp_procedure_set_attribution (procedure,
|
|
||||||
"Shawn Kirst",
|
|
||||||
"Shawn Kirst",
|
|
||||||
"2008");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return procedure;
|
return procedure;
|
||||||
}
|
}
|
||||||
|
@ -535,53 +439,3 @@ dds_save (GimpProcedure *procedure,
|
||||||
|
|
||||||
return gimp_procedure_new_return_values (procedure, status, error);
|
return gimp_procedure_new_return_values (procedure, status, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
static GimpValueArray *
|
|
||||||
dds_decode (GimpProcedure *procedure,
|
|
||||||
GimpRunMode run_mode,
|
|
||||||
GimpImage *image,
|
|
||||||
gint n_drawables,
|
|
||||||
GimpDrawable **drawables,
|
|
||||||
GimpProcedureConfig *config,
|
|
||||||
gpointer run_data)
|
|
||||||
{
|
|
||||||
const gchar *name = gimp_procedure_get_name (procedure);
|
|
||||||
GimpDrawable *drawable,
|
|
||||||
|
|
||||||
if (n_drawables != 1)
|
|
||||||
{
|
|
||||||
GError *error = NULL;
|
|
||||||
|
|
||||||
g_set_error (&error, GIMP_PLUG_IN_ERROR, 0,
|
|
||||||
_("Procedure '%s' only works with one drawable."),
|
|
||||||
name);
|
|
||||||
|
|
||||||
return gimp_procedure_new_return_values (procedure,
|
|
||||||
GIMP_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 != GIMP_RUN_NONINTERACTIVE)
|
|
||||||
gimp_displays_flush ();
|
|
||||||
|
|
||||||
return gimp_procedure_new_return_values (procedure, GIMP_PDB_SUCCESS, NULL);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -65,19 +65,19 @@ typedef struct
|
||||||
} dds_load_info_t;
|
} dds_load_info_t;
|
||||||
|
|
||||||
|
|
||||||
static gboolean read_header (dds_header_t *hdr,
|
static gboolean read_header (dds_header_t *hdr,
|
||||||
FILE *fp);
|
FILE *fp);
|
||||||
static gboolean read_header_dx10 (dds_header_dx10_t *hdr,
|
static gboolean read_header_dx10 (dds_header_dx10_t *hdr,
|
||||||
FILE *fp);
|
FILE *fp);
|
||||||
static gboolean validate_header (dds_header_t *hdr,
|
static gboolean validate_header (dds_header_t *hdr,
|
||||||
GError **error);
|
GError **error);
|
||||||
static gboolean setup_dxgi_format (dds_header_t *hdr,
|
static gboolean setup_dxgi_format (dds_header_t *hdr,
|
||||||
const dds_header_dx10_t *dx10hdr,
|
const dds_header_dx10_t *dx10hdr,
|
||||||
dds_load_info_t *load_info,
|
dds_load_info_t *load_info,
|
||||||
GError **error);
|
GError **error);
|
||||||
static gboolean load_layer (FILE *fp,
|
static gboolean load_layer (FILE *fp,
|
||||||
const dds_header_t *hdr,
|
const dds_header_t *hdr,
|
||||||
const dds_header_dx10_t *dx10hdr,
|
const dds_header_dx10_t *dx10hdr,
|
||||||
dds_load_info_t *load_info,
|
dds_load_info_t *load_info,
|
||||||
GimpImage *image,
|
GimpImage *image,
|
||||||
guint level,
|
guint level,
|
||||||
|
@ -85,7 +85,6 @@ static gboolean load_layer (FILE *fp,
|
||||||
guint *layer_index,
|
guint *layer_index,
|
||||||
guchar *pixels,
|
guchar *pixels,
|
||||||
guchar *buf,
|
guchar *buf,
|
||||||
gboolean decode_images,
|
|
||||||
GError **error);
|
GError **error);
|
||||||
static gboolean load_mipmaps (FILE *fp,
|
static gboolean load_mipmaps (FILE *fp,
|
||||||
const dds_header_t *hdr,
|
const dds_header_t *hdr,
|
||||||
|
@ -97,24 +96,22 @@ static gboolean load_mipmaps (FILE *fp,
|
||||||
guchar *pixels,
|
guchar *pixels,
|
||||||
guchar *buf,
|
guchar *buf,
|
||||||
gboolean read_mipmaps,
|
gboolean read_mipmaps,
|
||||||
gboolean decode_images,
|
|
||||||
GError **error);
|
GError **error);
|
||||||
static gboolean load_face (FILE *fp,
|
static gboolean load_face (FILE *fp,
|
||||||
const dds_header_t *hdr,
|
const dds_header_t *hdr,
|
||||||
const dds_header_dx10_t *dx10hdr,
|
const dds_header_dx10_t *dx10hdr,
|
||||||
dds_load_info_t *load_info,
|
dds_load_info_t *load_info,
|
||||||
GimpImage *image,
|
GimpImage *image,
|
||||||
gchar *prefix,
|
gchar *prefix,
|
||||||
guint *layer_index,
|
guint *layer_index,
|
||||||
guchar *pixels,
|
guchar *pixels,
|
||||||
guchar *buf,
|
guchar *buf,
|
||||||
gboolean read_mipmaps,
|
gboolean read_mipmaps,
|
||||||
gboolean decode_images,
|
GError **error);
|
||||||
GError **error);
|
static guchar color_bits (guint mask);
|
||||||
static guchar color_bits (guint mask);
|
static guchar color_shift (guint mask);
|
||||||
static guchar color_shift (guint mask);
|
static gboolean load_dialog (GimpProcedure *procedure,
|
||||||
static gboolean load_dialog (GimpProcedure *procedure,
|
GimpProcedureConfig *config);
|
||||||
GimpProcedureConfig *config);
|
|
||||||
|
|
||||||
|
|
||||||
/* Read DDS file */
|
/* Read DDS file */
|
||||||
|
@ -138,7 +135,6 @@ read_dds (GFile *file,
|
||||||
GimpImageBaseType type;
|
GimpImageBaseType type;
|
||||||
GimpPrecision precision;
|
GimpPrecision precision;
|
||||||
gboolean read_mipmaps;
|
gboolean read_mipmaps;
|
||||||
gboolean decode_images;
|
|
||||||
gint i, j;
|
gint i, j;
|
||||||
guint computed_pitch_or_linsize;
|
guint computed_pitch_or_linsize;
|
||||||
gboolean flip_import;
|
gboolean flip_import;
|
||||||
|
@ -156,7 +152,6 @@ read_dds (GFile *file,
|
||||||
"load-mipmaps", &read_mipmaps,
|
"load-mipmaps", &read_mipmaps,
|
||||||
"flip-image", &flip_import,
|
"flip-image", &flip_import,
|
||||||
"bc1-use-transparency", &bc1_use_transparency,
|
"bc1-use-transparency", &bc1_use_transparency,
|
||||||
"decode-images", &decode_images,
|
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
fp = g_fopen (g_file_peek_path (file), "rb");
|
fp = g_fopen (g_file_peek_path (file), "rb");
|
||||||
|
@ -629,7 +624,7 @@ read_dds (GFile *file,
|
||||||
dx10hdr.arraySize <= 1) /* Standard image texture with mipmaps */
|
dx10hdr.arraySize <= 1) /* Standard image texture with mipmaps */
|
||||||
{
|
{
|
||||||
if (! load_layer (fp, &hdr, &dx10hdr, &load_info, image, 0, "", &layer_index,
|
if (! load_layer (fp, &hdr, &dx10hdr, &load_info, image, 0, "", &layer_index,
|
||||||
pixels, buf, decode_images, error))
|
pixels, buf, error))
|
||||||
{
|
{
|
||||||
fclose (fp);
|
fclose (fp);
|
||||||
gimp_image_delete (image);
|
gimp_image_delete (image);
|
||||||
|
@ -637,7 +632,7 @@ read_dds (GFile *file,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! load_mipmaps (fp, &hdr, &dx10hdr, &load_info, image, "", &layer_index,
|
if (! load_mipmaps (fp, &hdr, &dx10hdr, &load_info, image, "", &layer_index,
|
||||||
pixels, buf, read_mipmaps, decode_images, error))
|
pixels, buf, read_mipmaps, error))
|
||||||
{
|
{
|
||||||
fclose (fp);
|
fclose (fp);
|
||||||
gimp_image_delete (image);
|
gimp_image_delete (image);
|
||||||
|
@ -648,7 +643,7 @@ read_dds (GFile *file,
|
||||||
{
|
{
|
||||||
if ((hdr.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEX) &&
|
if ((hdr.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEX) &&
|
||||||
! load_face (fp, &hdr, &dx10hdr, &load_info, image, "(positive x)",
|
! load_face (fp, &hdr, &dx10hdr, &load_info, image, "(positive x)",
|
||||||
&layer_index, pixels, buf, read_mipmaps, decode_images, error))
|
&layer_index, pixels, buf, read_mipmaps, error))
|
||||||
{
|
{
|
||||||
fclose (fp);
|
fclose (fp);
|
||||||
gimp_image_delete (image);
|
gimp_image_delete (image);
|
||||||
|
@ -657,7 +652,7 @@ read_dds (GFile *file,
|
||||||
|
|
||||||
if ((hdr.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEX) &&
|
if ((hdr.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEX) &&
|
||||||
! load_face (fp, &hdr, &dx10hdr, &load_info, image, "(negative x)",
|
! load_face (fp, &hdr, &dx10hdr, &load_info, image, "(negative x)",
|
||||||
&layer_index, pixels, buf, read_mipmaps, decode_images, error))
|
&layer_index, pixels, buf, read_mipmaps, error))
|
||||||
{
|
{
|
||||||
fclose (fp);
|
fclose (fp);
|
||||||
gimp_image_delete (image);
|
gimp_image_delete (image);
|
||||||
|
@ -666,7 +661,7 @@ read_dds (GFile *file,
|
||||||
|
|
||||||
if ((hdr.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEY) &&
|
if ((hdr.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEY) &&
|
||||||
! load_face (fp, &hdr, &dx10hdr, &load_info, image, "(positive y)",
|
! load_face (fp, &hdr, &dx10hdr, &load_info, image, "(positive y)",
|
||||||
&layer_index, pixels, buf, read_mipmaps, decode_images, error))
|
&layer_index, pixels, buf, read_mipmaps, error))
|
||||||
{
|
{
|
||||||
fclose (fp);
|
fclose (fp);
|
||||||
gimp_image_delete (image);
|
gimp_image_delete (image);
|
||||||
|
@ -675,7 +670,7 @@ read_dds (GFile *file,
|
||||||
|
|
||||||
if ((hdr.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEY) &&
|
if ((hdr.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEY) &&
|
||||||
! load_face (fp, &hdr, &dx10hdr, &load_info, image, "(negative y)",
|
! load_face (fp, &hdr, &dx10hdr, &load_info, image, "(negative y)",
|
||||||
&layer_index, pixels, buf, read_mipmaps, decode_images, error))
|
&layer_index, pixels, buf, read_mipmaps, error))
|
||||||
{
|
{
|
||||||
fclose (fp);
|
fclose (fp);
|
||||||
gimp_image_delete (image);
|
gimp_image_delete (image);
|
||||||
|
@ -684,7 +679,7 @@ read_dds (GFile *file,
|
||||||
|
|
||||||
if ((hdr.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEZ) &&
|
if ((hdr.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEZ) &&
|
||||||
! load_face (fp, &hdr, &dx10hdr, &load_info, image, "(positive z)",
|
! load_face (fp, &hdr, &dx10hdr, &load_info, image, "(positive z)",
|
||||||
&layer_index, pixels, buf, read_mipmaps, decode_images, error))
|
&layer_index, pixels, buf, read_mipmaps, error))
|
||||||
{
|
{
|
||||||
fclose (fp);
|
fclose (fp);
|
||||||
gimp_image_delete (image);
|
gimp_image_delete (image);
|
||||||
|
@ -693,7 +688,7 @@ read_dds (GFile *file,
|
||||||
|
|
||||||
if ((hdr.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEZ) &&
|
if ((hdr.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEZ) &&
|
||||||
! load_face (fp, &hdr, &dx10hdr, &load_info, image, "(negative z)",
|
! load_face (fp, &hdr, &dx10hdr, &load_info, image, "(negative z)",
|
||||||
&layer_index, pixels, buf, read_mipmaps, decode_images, error))
|
&layer_index, pixels, buf, read_mipmaps, error))
|
||||||
{
|
{
|
||||||
fclose (fp);
|
fclose (fp);
|
||||||
gimp_image_delete (image);
|
gimp_image_delete (image);
|
||||||
|
@ -711,7 +706,7 @@ read_dds (GFile *file,
|
||||||
plane = g_strdup_printf ("(z = %d)", i);
|
plane = g_strdup_printf ("(z = %d)", i);
|
||||||
|
|
||||||
if (! load_layer (fp, &hdr, &dx10hdr, &load_info, image, 0, plane,
|
if (! load_layer (fp, &hdr, &dx10hdr, &load_info, image, 0, plane,
|
||||||
&layer_index, pixels, buf, decode_images, error))
|
&layer_index, pixels, buf, error))
|
||||||
{
|
{
|
||||||
g_free (plane);
|
g_free (plane);
|
||||||
fclose (fp);
|
fclose (fp);
|
||||||
|
@ -738,7 +733,7 @@ read_dds (GFile *file,
|
||||||
plane = g_strdup_printf ("(z = %d)", i);
|
plane = g_strdup_printf ("(z = %d)", i);
|
||||||
|
|
||||||
if (! load_layer (fp, &hdr, &dx10hdr, &load_info, image, level, plane,
|
if (! load_layer (fp, &hdr, &dx10hdr, &load_info, image, level, plane,
|
||||||
&layer_index, pixels, buf, decode_images, error))
|
&layer_index, pixels, buf, error))
|
||||||
{
|
{
|
||||||
g_free (plane);
|
g_free (plane);
|
||||||
fclose (fp);
|
fclose (fp);
|
||||||
|
@ -761,7 +756,7 @@ read_dds (GFile *file,
|
||||||
elem = g_strdup_printf ("(array element %d)", i);
|
elem = g_strdup_printf ("(array element %d)", i);
|
||||||
|
|
||||||
if (! load_layer (fp, &hdr, &dx10hdr, &load_info, image, 0, elem, &layer_index,
|
if (! load_layer (fp, &hdr, &dx10hdr, &load_info, image, 0, elem, &layer_index,
|
||||||
pixels, buf, decode_images, error))
|
pixels, buf, error))
|
||||||
{
|
{
|
||||||
fclose (fp);
|
fclose (fp);
|
||||||
gimp_image_delete (image);
|
gimp_image_delete (image);
|
||||||
|
@ -769,7 +764,7 @@ read_dds (GFile *file,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! load_mipmaps (fp, &hdr, &dx10hdr, &load_info, image, elem, &layer_index,
|
if (! load_mipmaps (fp, &hdr, &dx10hdr, &load_info, image, elem, &layer_index,
|
||||||
pixels, buf, read_mipmaps, decode_images, error))
|
pixels, buf, read_mipmaps, error))
|
||||||
{
|
{
|
||||||
fclose (fp);
|
fclose (fp);
|
||||||
gimp_image_delete (image);
|
gimp_image_delete (image);
|
||||||
|
@ -1309,7 +1304,6 @@ load_layer (FILE *fp,
|
||||||
guint *layer_index,
|
guint *layer_index,
|
||||||
guchar *pixels,
|
guchar *pixels,
|
||||||
guchar *buf,
|
guchar *buf,
|
||||||
gboolean decode_images,
|
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
GeglBuffer *buffer;
|
GeglBuffer *buffer;
|
||||||
|
@ -2025,21 +2019,20 @@ load_layer (FILE *fp,
|
||||||
|
|
||||||
g_object_unref (buffer);
|
g_object_unref (buffer);
|
||||||
|
|
||||||
/* gimp dds specific. decode encoded images */
|
/* Decode files with GIMP-specific encodings */
|
||||||
if (decode_images &&
|
if (hdr->reserved.gimp_dds_special.magic1 == FOURCC ('G','I','M','P') &&
|
||||||
hdr->reserved.gimp_dds_special.magic1 == FOURCC ('G','I','M','P') &&
|
|
||||||
hdr->reserved.gimp_dds_special.magic2 == FOURCC ('-','D','D','S'))
|
hdr->reserved.gimp_dds_special.magic2 == FOURCC ('-','D','D','S'))
|
||||||
{
|
{
|
||||||
switch (hdr->reserved.gimp_dds_special.extra_fourcc)
|
switch (hdr->reserved.gimp_dds_special.extra_fourcc)
|
||||||
{
|
{
|
||||||
case FOURCC ('A','E','X','P'):
|
case FOURCC ('A','E','X','P'):
|
||||||
decode_alpha_exp_image (GIMP_DRAWABLE (layer), FALSE);
|
decode_alpha_exponent (GIMP_DRAWABLE (layer));
|
||||||
break;
|
break;
|
||||||
case FOURCC ('Y','C','G','1'):
|
case FOURCC ('Y','C','G','1'):
|
||||||
decode_ycocg_image (GIMP_DRAWABLE (layer), FALSE);
|
decode_ycocg (GIMP_DRAWABLE (layer));
|
||||||
break;
|
break;
|
||||||
case FOURCC ('Y','C','G','2'):
|
case FOURCC ('Y','C','G','2'):
|
||||||
decode_ycocg_scaled_image (GIMP_DRAWABLE (layer), FALSE);
|
decode_ycocg_scaled (GIMP_DRAWABLE (layer));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -2060,7 +2053,6 @@ load_mipmaps (FILE *fp,
|
||||||
guchar *pixels,
|
guchar *pixels,
|
||||||
guchar *buf,
|
guchar *buf,
|
||||||
gboolean read_mipmaps,
|
gboolean read_mipmaps,
|
||||||
gboolean decode_images,
|
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
guint level;
|
guint level;
|
||||||
|
@ -2072,7 +2064,7 @@ load_mipmaps (FILE *fp,
|
||||||
for (level = 1; level < hdr->num_mipmaps; ++level)
|
for (level = 1; level < hdr->num_mipmaps; ++level)
|
||||||
{
|
{
|
||||||
if (! load_layer (fp, hdr, dx10hdr, load_info, image, level, prefix, layer_index,
|
if (! load_layer (fp, hdr, dx10hdr, load_info, image, level, prefix, layer_index,
|
||||||
pixels, buf, decode_images, error))
|
pixels, buf, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2091,15 +2083,14 @@ load_face (FILE *fp,
|
||||||
guchar *pixels,
|
guchar *pixels,
|
||||||
guchar *buf,
|
guchar *buf,
|
||||||
gboolean read_mipmaps,
|
gboolean read_mipmaps,
|
||||||
gboolean decode_images,
|
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
if (! load_layer (fp, hdr, dx10hdr, load_info, image, 0, prefix,
|
if (! load_layer (fp, hdr, dx10hdr, load_info, image, 0, prefix,
|
||||||
layer_index, pixels, buf, decode_images, error))
|
layer_index, pixels, buf, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
return load_mipmaps (fp, hdr, dx10hdr, load_info, image, prefix, layer_index,
|
return load_mipmaps (fp, hdr, dx10hdr, load_info, image, prefix, layer_index,
|
||||||
pixels, buf, read_mipmaps, decode_images, error);
|
pixels, buf, read_mipmaps, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
static guchar
|
static guchar
|
||||||
|
@ -2124,7 +2115,7 @@ color_shift (guint mask)
|
||||||
if (! mask)
|
if (! mask)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
while (!((mask >> i) & 1))
|
while (! ((mask >> i) & 1))
|
||||||
++i;
|
++i;
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
|
@ -2147,7 +2138,6 @@ load_dialog (GimpProcedure *procedure,
|
||||||
"load-mipmaps",
|
"load-mipmaps",
|
||||||
"flip-image",
|
"flip-image",
|
||||||
"bc1-use-transparency",
|
"bc1-use-transparency",
|
||||||
"decode-images",
|
|
||||||
NULL);
|
NULL);
|
||||||
gtk_box_set_spacing (GTK_BOX (vbox), 8);
|
gtk_box_set_spacing (GTK_BOX (vbox), 8);
|
||||||
gtk_container_set_border_width (GTK_CONTAINER (vbox), 8);
|
gtk_container_set_border_width (GTK_CONTAINER (vbox), 8);
|
||||||
|
|
|
@ -35,13 +35,13 @@
|
||||||
|
|
||||||
#include <libgimp/stdplugins-intl.h>
|
#include <libgimp/stdplugins-intl.h>
|
||||||
|
|
||||||
#include "color.h"
|
|
||||||
#include "dds.h"
|
#include "dds.h"
|
||||||
#include "ddswrite.h"
|
#include "ddswrite.h"
|
||||||
#include "dxt.h"
|
#include "dxt.h"
|
||||||
#include "endian_rw.h"
|
#include "endian_rw.h"
|
||||||
#include "imath.h"
|
#include "imath.h"
|
||||||
#include "mipmap.h"
|
#include "mipmap.h"
|
||||||
|
#include "misc.h"
|
||||||
|
|
||||||
|
|
||||||
static gboolean write_image (FILE *fp,
|
static gboolean write_image (FILE *fp,
|
||||||
|
@ -244,7 +244,7 @@ check_cubemap (GimpImage *image)
|
||||||
(gimp_drawable_get_height (drawable) != h))
|
(gimp_drawable_get_height (drawable) != h))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
layer_name = (char *) gimp_item_get_name (GIMP_ITEM (drawable));
|
layer_name = (gchar *) gimp_item_get_name (GIMP_ITEM (drawable));
|
||||||
for (j = 0; j < 6; ++j)
|
for (j = 0; j < 6; ++j)
|
||||||
{
|
{
|
||||||
for (k = 0; k < 4; ++k)
|
for (k = 0; k < 4; ++k)
|
||||||
|
@ -608,45 +608,6 @@ swap_rb (guchar *pixels,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
alpha_exp (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));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
convert_pixels (guchar *dst,
|
convert_pixels (guchar *dst,
|
||||||
guchar *src,
|
guchar *src,
|
||||||
|
@ -729,36 +690,56 @@ convert_pixels (guchar *dst,
|
||||||
dst[4 * i + 3] = a;
|
dst[4 * i + 3] = a;
|
||||||
break;
|
break;
|
||||||
case DDS_FORMAT_R5G6B5:
|
case DDS_FORMAT_R5G6B5:
|
||||||
PUTL16 (&dst[2 * i], pack_r5g6b5 (r, g, b));
|
PUTL16 (&dst[2 * i],
|
||||||
|
(mul8bit (r, 31) << 11) |
|
||||||
|
(mul8bit (g, 63) << 5) |
|
||||||
|
(mul8bit (b, 31) ));
|
||||||
break;
|
break;
|
||||||
case DDS_FORMAT_RGBA4:
|
case DDS_FORMAT_RGBA4:
|
||||||
PUTL16 (&dst[2 * i], pack_rgba4 (r, g, b, a));
|
PUTL16 (&dst[2 * i],
|
||||||
|
(mul8bit (a, 15) << 12) |
|
||||||
|
(mul8bit (r, 15) << 8) |
|
||||||
|
(mul8bit (g, 15) << 4) |
|
||||||
|
(mul8bit (b, 15) ));
|
||||||
break;
|
break;
|
||||||
case DDS_FORMAT_RGB5A1:
|
case DDS_FORMAT_RGB5A1:
|
||||||
PUTL16 (&dst[2 * i], pack_rgb5a1 (r, g, b, a));
|
PUTL16 (&dst[2 * i],
|
||||||
|
(((a >> 7) & 0x01) << 15) |
|
||||||
|
(mul8bit (r, 31) << 10) |
|
||||||
|
(mul8bit (g, 31) << 5) |
|
||||||
|
(mul8bit (b, 31) ));
|
||||||
break;
|
break;
|
||||||
case DDS_FORMAT_RGB10A2:
|
case DDS_FORMAT_RGB10A2:
|
||||||
PUTL32 (&dst[4 * i], pack_rgb10a2 (r, g, b, a));
|
PUTL32 (&dst[4 * i],
|
||||||
|
((guint) ((a >> 6) & 0x003) << 30) |
|
||||||
|
((guint) ((b << 2) & 0x3ff) << 20) |
|
||||||
|
((guint) ((g << 2) & 0x3ff) << 10) |
|
||||||
|
((guint) ((r << 2) & 0x3ff) ));
|
||||||
break;
|
break;
|
||||||
case DDS_FORMAT_R3G3B2:
|
case DDS_FORMAT_R3G3B2:
|
||||||
dst[i] = pack_r3g3b2 (r, g, b);
|
dst[i] =
|
||||||
|
(mul8bit (r, 7) << 5) |
|
||||||
|
(mul8bit (g, 7) << 2) |
|
||||||
|
(mul8bit (b, 3) );
|
||||||
break;
|
break;
|
||||||
case DDS_FORMAT_A8:
|
case DDS_FORMAT_A8:
|
||||||
dst[i] = a;
|
dst[i] = a;
|
||||||
break;
|
break;
|
||||||
case DDS_FORMAT_L8:
|
case DDS_FORMAT_L8:
|
||||||
dst[i] = rgb_to_luminance (r, g, b);
|
dst[i] =
|
||||||
|
((r * 54 + g * 182 + b * 20) + 128) >> 8;
|
||||||
break;
|
break;
|
||||||
case DDS_FORMAT_L8A8:
|
case DDS_FORMAT_L8A8:
|
||||||
dst[2 * i + 0] = rgb_to_luminance (r, g, b);
|
dst[2 * i + 0] =
|
||||||
|
((r * 54 + g * 182 + b * 20) + 128) >> 8;
|
||||||
dst[2 * i + 1] = a;
|
dst[2 * i + 1] = a;
|
||||||
break;
|
break;
|
||||||
case DDS_FORMAT_YCOCG:
|
case DDS_FORMAT_YCOCG:
|
||||||
dst[4 * i] = a;
|
dst[4 * i] = a;
|
||||||
RGB_to_YCoCg (&dst[4 * i], r, g, b);
|
encode_ycocg (&dst[4 * i], r, g, b);
|
||||||
break;
|
break;
|
||||||
case DDS_FORMAT_AEXP:
|
case DDS_FORMAT_AEXP:
|
||||||
alpha_exp (&dst[4 * i], r, g, b, a);
|
encode_alpha_exponent (&dst[4 * i], r, g, b, a);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -34,11 +34,14 @@
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
||||||
|
#include <libgimp/gimp.h>
|
||||||
|
|
||||||
#include "dds.h"
|
#include "dds.h"
|
||||||
#include "dxt.h"
|
#include "dxt.h"
|
||||||
#include "endian_rw.h"
|
#include "endian_rw.h"
|
||||||
#include "mipmap.h"
|
|
||||||
#include "imath.h"
|
#include "imath.h"
|
||||||
|
#include "mipmap.h"
|
||||||
|
#include "misc.h"
|
||||||
#include "vec.h"
|
#include "vec.h"
|
||||||
|
|
||||||
#include "dxt_tables.h"
|
#include "dxt_tables.h"
|
||||||
|
@ -757,181 +760,6 @@ encode_color_block (unsigned char *dst,
|
||||||
PUTL32(dst + 4, indices);
|
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 */
|
/* write DXT3 alpha block */
|
||||||
static void
|
static void
|
||||||
encode_alpha_block_BC2 (unsigned char *dst,
|
encode_alpha_block_BC2 (unsigned char *dst,
|
||||||
|
|
|
@ -2,7 +2,6 @@ plugin_name = 'file-dds'
|
||||||
|
|
||||||
plugin_sources = [
|
plugin_sources = [
|
||||||
'dds.c',
|
'dds.c',
|
||||||
'color.c',
|
|
||||||
'ddsread.c',
|
'ddsread.c',
|
||||||
'ddswrite.c',
|
'ddswrite.c',
|
||||||
'dxt.c',
|
'dxt.c',
|
||||||
|
|
|
@ -36,7 +36,6 @@
|
||||||
#include "dds.h"
|
#include "dds.h"
|
||||||
#include "mipmap.h"
|
#include "mipmap.h"
|
||||||
#include "imath.h"
|
#include "imath.h"
|
||||||
#include "color.h"
|
|
||||||
|
|
||||||
|
|
||||||
typedef gfloat (*filterfunc_t) (gfloat);
|
typedef gfloat (*filterfunc_t) (gfloat);
|
||||||
|
@ -217,6 +216,23 @@ wrap_clamp (gint x,
|
||||||
* Gamma-correction
|
* Gamma-correction
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static gfloat
|
||||||
|
linear_to_sRGB (gfloat c)
|
||||||
|
{
|
||||||
|
gfloat v = (gfloat) c;
|
||||||
|
|
||||||
|
if (v < 0.0f)
|
||||||
|
v = 0.0f;
|
||||||
|
else if (v > 1.0f)
|
||||||
|
v = 1.0f;
|
||||||
|
else if (v <= 0.0031308f)
|
||||||
|
v = 12.92f * v;
|
||||||
|
else
|
||||||
|
v = 1.055f * powf (v, 0.41666f) - 0.055f;
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
static gfloat
|
static gfloat
|
||||||
linear_to_gamma (gint gc,
|
linear_to_gamma (gint gc,
|
||||||
gfloat v,
|
gfloat v,
|
||||||
|
@ -236,6 +252,24 @@ linear_to_gamma (gint gc,
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gfloat
|
||||||
|
sRGB_to_linear (gfloat c)
|
||||||
|
{
|
||||||
|
gfloat v = (gfloat) c;
|
||||||
|
|
||||||
|
if (v < 0.0f)
|
||||||
|
v = 0.0f;
|
||||||
|
else if (v > 1.0f)
|
||||||
|
v = 1.0f;
|
||||||
|
else if (v <= 0.04045f)
|
||||||
|
v /= 12.92f;
|
||||||
|
else
|
||||||
|
v = powf ((v + 0.055f) / 1.055f, 2.4f);
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
static gfloat
|
static gfloat
|
||||||
gamma_to_linear (gint gc,
|
gamma_to_linear (gint gc,
|
||||||
gfloat v,
|
gfloat v,
|
||||||
|
|
|
@ -4,56 +4,53 @@
|
||||||
* Copyright (C) 2004-2012 Shawn Kirst <skirst@gmail.com>,
|
* Copyright (C) 2004-2012 Shawn Kirst <skirst@gmail.com>,
|
||||||
* with parts (C) 2003 Arne Reuter <homepage@arnereuter.de> where specified.
|
* with parts (C) 2003 Arne Reuter <homepage@arnereuter.de> where specified.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* modify it under the terms of the GNU General Public
|
* it under the terms of the GNU General Public License as published by
|
||||||
* License as published by the Free Software Foundation; either
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
* version 2 of the License, or (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; see the file COPYING. If not, write to
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
* the Free Software Foundation, 51 Franklin Street, Fifth Floor
|
|
||||||
* Boston, MA 02110-1301, USA.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <libgimp/gimp.h>
|
#include <libgimp/gimp.h>
|
||||||
|
|
||||||
|
#include "endian_rw.h"
|
||||||
|
#include "imath.h"
|
||||||
#include "misc.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;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
decode_ycocg_image (GimpDrawable *drawable,
|
decode_ycocg (GimpDrawable *drawable)
|
||||||
gboolean shadow)
|
|
||||||
{
|
{
|
||||||
GeglBuffer *buffer, *sbuffer;
|
GeglBuffer *buffer;
|
||||||
const Babl *format;
|
const Babl *format;
|
||||||
unsigned char *data;
|
guchar *data;
|
||||||
unsigned int i, w, h, num_pixels;
|
guint num_pixels;
|
||||||
|
guint i, w, h;
|
||||||
const float offset = 0.5f * 256.0f / 255.0f;
|
const gfloat offset = 0.5f * 256.0f / 255.0f;
|
||||||
float Y, Co, Cg, R, G, B;
|
gfloat Y, Co, Cg;
|
||||||
|
gfloat R, G, B;
|
||||||
|
|
||||||
buffer = gimp_drawable_get_buffer (drawable);
|
buffer = gimp_drawable_get_buffer (drawable);
|
||||||
|
|
||||||
if (shadow)
|
|
||||||
{
|
|
||||||
sbuffer = gimp_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");
|
format = babl_format ("R'G'B'A u8");
|
||||||
|
|
||||||
w = gegl_buffer_get_width (buffer);
|
w = gegl_buffer_get_width (buffer);
|
||||||
|
@ -62,46 +59,43 @@ decode_ycocg_image (GimpDrawable *drawable,
|
||||||
|
|
||||||
data = g_malloc (num_pixels * 4);
|
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);
|
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
|
||||||
|
|
||||||
gimp_progress_init ("Decoding YCoCg pixels...");
|
gimp_progress_init ("Decoding YCoCg pixels...");
|
||||||
|
|
||||||
for (i = 0; i < num_pixels; ++i)
|
for (i = 0; i < num_pixels; ++i)
|
||||||
{
|
{
|
||||||
Y = (float)data[4 * i + 3] / 255.0f;
|
Y = (gfloat) data[4 * i + 3] / 255.0f;
|
||||||
Co = (float)data[4 * i + 0] / 255.0f;
|
Co = (gfloat) data[4 * i + 0] / 255.0f;
|
||||||
Cg = (float)data[4 * i + 1] / 255.0f;
|
Cg = (gfloat) data[4 * i + 1] / 255.0f;
|
||||||
|
|
||||||
/* convert YCoCg to RGB */
|
/* convert YCoCg to RGB */
|
||||||
Co -= offset;
|
Co -= offset;
|
||||||
Cg -= offset;
|
Cg -= offset;
|
||||||
|
|
||||||
R = saturate(Y + Co - Cg);
|
R = saturate (Y + Co - Cg);
|
||||||
G = saturate(Y + Cg);
|
G = saturate (Y + Cg);
|
||||||
B = saturate(Y - Co - Cg);
|
B = saturate (Y - Co - Cg);
|
||||||
|
|
||||||
/* copy new alpha from blue */
|
/* copy new alpha from blue */
|
||||||
data[4 * i + 3] = data[4 * i + 2];
|
data[4 * i + 3] = data[4 * i + 2];
|
||||||
|
|
||||||
data[4 * i + 0] = (unsigned char)(R * 255.0f);
|
data[4 * i + 0] = (guchar) (R * 255.0f);
|
||||||
data[4 * i + 1] = (unsigned char)(G * 255.0f);
|
data[4 * i + 1] = (guchar) (G * 255.0f);
|
||||||
data[4 * i + 2] = (unsigned char)(B * 255.0f);
|
data[4 * i + 2] = (guchar) (B * 255.0f);
|
||||||
|
|
||||||
if ((i & 0x7fff) == 0)
|
if ((i & 0x7fff) == 0)
|
||||||
gimp_progress_update ((float)i / (float)num_pixels);
|
gimp_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);
|
GEGL_AUTO_ROWSTRIDE);
|
||||||
|
|
||||||
gimp_progress_update (1.0);
|
gimp_progress_update (1.0);
|
||||||
|
|
||||||
gegl_buffer_flush (buffer);
|
gegl_buffer_flush (buffer);
|
||||||
|
|
||||||
if (shadow)
|
|
||||||
gimp_drawable_merge_shadow (drawable, TRUE);
|
|
||||||
|
|
||||||
gimp_drawable_update (drawable, 0, 0, w, h);
|
gimp_drawable_update (drawable, 0, 0, w, h);
|
||||||
|
|
||||||
g_free (data);
|
g_free (data);
|
||||||
|
@ -110,27 +104,19 @@ decode_ycocg_image (GimpDrawable *drawable,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
decode_ycocg_scaled_image (GimpDrawable *drawable,
|
decode_ycocg_scaled (GimpDrawable *drawable)
|
||||||
gboolean shadow)
|
|
||||||
{
|
{
|
||||||
GeglBuffer *buffer, *sbuffer;
|
GeglBuffer *buffer;
|
||||||
const Babl *format;
|
const Babl *format;
|
||||||
unsigned char *data;
|
guchar *data;
|
||||||
unsigned int i, w, h, num_pixels;
|
guint num_pixels;
|
||||||
|
guint i, w, h;
|
||||||
const float offset = 0.5f * 256.0f / 255.0f;
|
const gfloat offset = 0.5f * 256.0f / 255.0f;
|
||||||
float Y, Co, Cg, R, G, B, s;
|
gfloat Y, Co, Cg;
|
||||||
|
gfloat R, G, B, s;
|
||||||
|
|
||||||
buffer = gimp_drawable_get_buffer (drawable);
|
buffer = gimp_drawable_get_buffer (drawable);
|
||||||
|
|
||||||
if (shadow)
|
|
||||||
{
|
|
||||||
sbuffer = gimp_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");
|
format = babl_format ("R'G'B'A u8");
|
||||||
|
|
||||||
w = gegl_buffer_get_width (buffer);
|
w = gegl_buffer_get_width (buffer);
|
||||||
|
@ -139,17 +125,17 @@ decode_ycocg_scaled_image (GimpDrawable *drawable,
|
||||||
|
|
||||||
data = g_malloc (num_pixels * 4);
|
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);
|
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
|
||||||
|
|
||||||
gimp_progress_init ("Decoding YCoCg (scaled) pixels...");
|
gimp_progress_init ("Decoding YCoCg (scaled) pixels...");
|
||||||
|
|
||||||
for (i = 0; i < num_pixels; ++i)
|
for (i = 0; i < num_pixels; ++i)
|
||||||
{
|
{
|
||||||
Y = (float)data[4 * i + 3] / 255.0f;
|
Y = (gfloat) data[4 * i + 3] / 255.0f;
|
||||||
Co = (float)data[4 * i + 0] / 255.0f;
|
Co = (gfloat) data[4 * i + 0] / 255.0f;
|
||||||
Cg = (float)data[4 * i + 1] / 255.0f;
|
Cg = (gfloat) data[4 * i + 1] / 255.0f;
|
||||||
s = (float)data[4 * i + 2] / 255.0f;
|
s = (gfloat) data[4 * i + 2] / 255.0f;
|
||||||
|
|
||||||
/* convert YCoCg to RGB */
|
/* convert YCoCg to RGB */
|
||||||
s = 1.0f / ((255.0f / 8.0f) * s + 1.0f);
|
s = 1.0f / ((255.0f / 8.0f) * s + 1.0f);
|
||||||
|
@ -157,31 +143,28 @@ decode_ycocg_scaled_image (GimpDrawable *drawable,
|
||||||
Co = (Co - offset) * s;
|
Co = (Co - offset) * s;
|
||||||
Cg = (Cg - offset) * s;
|
Cg = (Cg - offset) * s;
|
||||||
|
|
||||||
R = saturate(Y + Co - Cg);
|
R = saturate (Y + Co - Cg);
|
||||||
G = saturate(Y + Cg);
|
G = saturate (Y + Cg);
|
||||||
B = saturate(Y - Co - Cg);
|
B = saturate (Y - Co - Cg);
|
||||||
|
|
||||||
data[4 * i + 0] = (unsigned char)(R * 255.0f);
|
data[4 * i + 0] = (guchar) (R * 255.0f);
|
||||||
data[4 * i + 1] = (unsigned char)(G * 255.0f);
|
data[4 * i + 1] = (guchar) (G * 255.0f);
|
||||||
data[4 * i + 2] = (unsigned char)(B * 255.0f);
|
data[4 * i + 2] = (guchar) (B * 255.0f);
|
||||||
|
|
||||||
/* set alpha to 1 */
|
/* set alpha to 1 */
|
||||||
data[4 * i + 3] = 255;
|
data[4 * i + 3] = 255;
|
||||||
|
|
||||||
if ((i & 0x7fff) == 0)
|
if ((i & 0x7fff) == 0)
|
||||||
gimp_progress_update ((float)i / (float)num_pixels);
|
gimp_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);
|
GEGL_AUTO_ROWSTRIDE);
|
||||||
|
|
||||||
gimp_progress_update (1.0);
|
gimp_progress_update (1.0);
|
||||||
|
|
||||||
gegl_buffer_flush (buffer);
|
gegl_buffer_flush (buffer);
|
||||||
|
|
||||||
if (shadow)
|
|
||||||
gimp_drawable_merge_shadow (drawable, TRUE);
|
|
||||||
|
|
||||||
gimp_drawable_update (drawable, 0, 0, w, h);
|
gimp_drawable_update (drawable, 0, 0, w, h);
|
||||||
|
|
||||||
g_free (data);
|
g_free (data);
|
||||||
|
@ -190,25 +173,17 @@ decode_ycocg_scaled_image (GimpDrawable *drawable,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
decode_alpha_exp_image (GimpDrawable *drawable,
|
decode_alpha_exponent (GimpDrawable *drawable)
|
||||||
gboolean shadow)
|
|
||||||
{
|
{
|
||||||
GeglBuffer *buffer, *sbuffer;
|
GeglBuffer *buffer;
|
||||||
const Babl *format;
|
const Babl *format;
|
||||||
unsigned char *data;
|
guchar *data;
|
||||||
unsigned int i, w, h, num_pixels;
|
guint num_pixels;
|
||||||
int R, G, B, A;
|
guint i, w, h;
|
||||||
|
gint R, G, B, A;
|
||||||
|
|
||||||
buffer = gimp_drawable_get_buffer (drawable);
|
buffer = gimp_drawable_get_buffer (drawable);
|
||||||
|
|
||||||
if (shadow)
|
|
||||||
{
|
|
||||||
sbuffer = gimp_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");
|
format = babl_format ("R'G'B'A u8");
|
||||||
|
|
||||||
w = gegl_buffer_get_width (buffer);
|
w = gegl_buffer_get_width (buffer);
|
||||||
|
@ -217,7 +192,7 @@ decode_alpha_exp_image (GimpDrawable *drawable,
|
||||||
|
|
||||||
data = g_malloc (num_pixels * 4);
|
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);
|
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
|
||||||
|
|
||||||
gimp_progress_init ("Decoding Alpha-exponent pixels...");
|
gimp_progress_init ("Decoding Alpha-exponent pixels...");
|
||||||
|
@ -240,22 +215,268 @@ decode_alpha_exp_image (GimpDrawable *drawable,
|
||||||
data[4 * i + 3] = A;
|
data[4 * i + 3] = A;
|
||||||
|
|
||||||
if ((i & 0x7fff) == 0)
|
if ((i & 0x7fff) == 0)
|
||||||
gimp_progress_update ((float)i / (float)num_pixels);
|
gimp_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);
|
GEGL_AUTO_ROWSTRIDE);
|
||||||
|
|
||||||
gimp_progress_update (1.0);
|
gimp_progress_update (1.0);
|
||||||
|
|
||||||
gegl_buffer_flush (buffer);
|
gegl_buffer_flush (buffer);
|
||||||
|
|
||||||
if (shadow)
|
|
||||||
gimp_drawable_merge_shadow (drawable, TRUE);
|
|
||||||
|
|
||||||
gimp_drawable_update (drawable, 0, 0, w, h);
|
gimp_drawable_update (drawable, 0, 0, w, h);
|
||||||
|
|
||||||
g_free (data);
|
g_free (data);
|
||||||
|
|
||||||
g_object_unref (buffer);
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -21,11 +21,26 @@
|
||||||
#ifndef __MISC_H__
|
#ifndef __MISC_H__
|
||||||
#define __MISC_H__
|
#define __MISC_H__
|
||||||
|
|
||||||
void decode_ycocg_image (GimpDrawable *drawable,
|
|
||||||
gboolean shadow);
|
void decode_ycocg (GimpDrawable *drawable);
|
||||||
void decode_ycocg_scaled_image (GimpDrawable *drawable,
|
|
||||||
gboolean shadow);
|
void decode_ycocg_scaled (GimpDrawable *drawable);
|
||||||
void decode_alpha_exp_image (GimpDrawable *drawable,
|
|
||||||
gboolean shadow);
|
void decode_alpha_exponent (GimpDrawable *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__ */
|
#endif /* __MISC_H__ */
|
||||||
|
|
Loading…
Reference in New Issue