|
Packit |
bc1512 |
/* This file is part of GEGL.
|
|
Packit |
bc1512 |
*
|
|
Packit |
bc1512 |
* This library is free software; you can redistribute it and/or
|
|
Packit |
bc1512 |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit |
bc1512 |
* License as published by the Free Software Foundation; either
|
|
Packit |
bc1512 |
* version 3 of the License, or (at your option) any later version.
|
|
Packit |
bc1512 |
*
|
|
Packit |
bc1512 |
* This library is distributed in the hope that it will be useful,
|
|
Packit |
bc1512 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
bc1512 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
bc1512 |
* Lesser General Public License for more details.
|
|
Packit |
bc1512 |
*
|
|
Packit |
bc1512 |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit |
bc1512 |
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
|
Packit |
bc1512 |
*
|
|
Packit |
bc1512 |
* Copyright 2006,2007 Øyvind Kolås <pippin@gimp.org>
|
|
Packit |
bc1512 |
*/
|
|
Packit |
bc1512 |
#include "config.h"
|
|
Packit |
bc1512 |
#include <glib.h>
|
|
Packit |
bc1512 |
#include <glib-object.h>
|
|
Packit |
bc1512 |
#include <string.h>
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
#include "gegl-types.h"
|
|
Packit |
bc1512 |
#include "gegl-matrix.h"
|
|
Packit |
bc1512 |
#include "gegl-buffer-types.h"
|
|
Packit |
bc1512 |
#include "gegl-buffer-private.h"
|
|
Packit |
bc1512 |
#include "gegl-tile-handler.h"
|
|
Packit |
bc1512 |
#include "gegl-tile-handler-zoom.h"
|
|
Packit |
bc1512 |
#include "gegl-tile-handler-cache.h"
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
G_DEFINE_TYPE (GeglTileHandlerZoom, gegl_tile_handler_zoom, GEGL_TYPE_TILE_HANDLER)
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
#include <babl/babl.h>
|
|
Packit |
bc1512 |
#include "gegl-tile-backend.h"
|
|
Packit |
bc1512 |
#include "gegl-tile-storage.h"
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
void gegl_tile_handler_cache_insert (GeglTileHandlerCache *cache,
|
|
Packit |
bc1512 |
GeglTile *tile,
|
|
Packit |
bc1512 |
gint x,
|
|
Packit |
bc1512 |
gint y,
|
|
Packit |
bc1512 |
gint z);
|
|
Packit |
bc1512 |
static inline void set_blank (GeglTile *dst_tile,
|
|
Packit |
bc1512 |
gint width,
|
|
Packit |
bc1512 |
gint height,
|
|
Packit |
bc1512 |
const Babl *format,
|
|
Packit |
bc1512 |
gint i,
|
|
Packit |
bc1512 |
gint j)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
guchar *dst_data = gegl_tile_get_data (dst_tile);
|
|
Packit |
bc1512 |
gint bpp = babl_format_get_bytes_per_pixel (format);
|
|
Packit |
bc1512 |
gint rowstride = width * bpp;
|
|
Packit |
bc1512 |
gint scanline;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
gint bytes = width * bpp / 2;
|
|
Packit |
bc1512 |
guchar *dst = dst_data + j * height / 2 * rowstride + i * rowstride / 2;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
for (scanline = 0; scanline < height / 2; scanline++)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
memset (dst, 0x0, bytes);
|
|
Packit |
bc1512 |
dst += rowstride;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/* fixme: make the api of this, as well as blank be the
|
|
Packit |
bc1512 |
* same as the downscale functions */
|
|
Packit |
bc1512 |
static inline void set_half_nearest (GeglTile *dst_tile,
|
|
Packit |
bc1512 |
GeglTile *src_tile,
|
|
Packit |
bc1512 |
gint width,
|
|
Packit |
bc1512 |
gint height,
|
|
Packit |
bc1512 |
const Babl *format,
|
|
Packit |
bc1512 |
gint i,
|
|
Packit |
bc1512 |
gint j)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
guchar *dst_data = gegl_tile_get_data (dst_tile);
|
|
Packit |
bc1512 |
guchar *src_data = gegl_tile_get_data (src_tile);
|
|
Packit |
bc1512 |
gint bpp = babl_format_get_bytes_per_pixel (format);
|
|
Packit |
bc1512 |
gint x, y;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
for (y = 0; y < height / 2; y++)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
guchar *dst = dst_data +
|
|
Packit |
bc1512 |
(
|
|
Packit |
bc1512 |
(
|
|
Packit |
bc1512 |
(y + j * (height / 2)) * width
|
|
Packit |
bc1512 |
) + i * (width / 2)
|
|
Packit |
bc1512 |
) * bpp;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
guchar *src = src_data + (y * 2 * width) * bpp;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
for (x = 0; x < width / 2; x++)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
memcpy (dst, src, bpp);
|
|
Packit |
bc1512 |
dst += bpp;
|
|
Packit |
bc1512 |
src += bpp * 2;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static inline void
|
|
Packit |
bc1512 |
downscale_float (gint components,
|
|
Packit |
bc1512 |
gint width,
|
|
Packit |
bc1512 |
gint height,
|
|
Packit |
bc1512 |
gint rowstride,
|
|
Packit |
bc1512 |
guchar *src_data,
|
|
Packit |
bc1512 |
guchar *dst_data)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gint y;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (!src_data || !dst_data)
|
|
Packit |
bc1512 |
return;
|
|
Packit |
bc1512 |
for (y = 0; y < height / 2; y++)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gint x;
|
|
Packit |
bc1512 |
gfloat *dst = (gfloat *) (dst_data + y * rowstride);
|
|
Packit |
bc1512 |
gfloat *src = (gfloat *) (src_data + y * 2 * rowstride);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
for (x = 0; x < width / 2; x++)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
int i;
|
|
Packit |
bc1512 |
for (i = 0; i < components; i++)
|
|
Packit |
bc1512 |
dst[i] = (src[i] +
|
|
Packit |
bc1512 |
src[i + components] +
|
|
Packit |
bc1512 |
src[i + (width * components)] +
|
|
Packit |
bc1512 |
src[i + (width + 1) * components]) /
|
|
Packit |
bc1512 |
4.0;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
dst += components;
|
|
Packit |
bc1512 |
src += components * 2;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static inline void
|
|
Packit |
bc1512 |
downscale_u8 (gint components,
|
|
Packit |
bc1512 |
gint width,
|
|
Packit |
bc1512 |
gint height,
|
|
Packit |
bc1512 |
gint rowstride,
|
|
Packit |
bc1512 |
guchar *src_data,
|
|
Packit |
bc1512 |
guchar *dst_data)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gint y;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (!src_data || !dst_data)
|
|
Packit |
bc1512 |
return;
|
|
Packit |
bc1512 |
for (y = 0; y < height / 2; y++)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gint x;
|
|
Packit |
bc1512 |
guchar *dst = dst_data + y * rowstride;
|
|
Packit |
bc1512 |
guchar *src = src_data + y * 2 * rowstride;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
for (x = 0; x < width / 2; x++)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
int i;
|
|
Packit |
bc1512 |
for (i = 0; i < components; i++)
|
|
Packit |
bc1512 |
dst[i] = (src[i] +
|
|
Packit |
bc1512 |
src[i + components] +
|
|
Packit |
bc1512 |
src[i + rowstride] +
|
|
Packit |
bc1512 |
src[i + rowstride + components]) /
|
|
Packit |
bc1512 |
4;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
dst += components;
|
|
Packit |
bc1512 |
src += components * 2;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static inline void set_half (GeglTile * dst_tile,
|
|
Packit |
bc1512 |
GeglTile * src_tile,
|
|
Packit |
bc1512 |
gint width,
|
|
Packit |
bc1512 |
gint height,
|
|
Packit |
bc1512 |
const Babl * format,
|
|
Packit |
bc1512 |
gint i,
|
|
Packit |
bc1512 |
gint j)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
guchar *dst_data = gegl_tile_get_data (dst_tile);
|
|
Packit |
bc1512 |
guchar *src_data = gegl_tile_get_data (src_tile);
|
|
Packit |
bc1512 |
gint components = babl_format_get_n_components (format);
|
|
Packit |
bc1512 |
gint bpp = babl_format_get_bytes_per_pixel (format);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (i) dst_data += bpp * width / 2;
|
|
Packit |
bc1512 |
if (j) dst_data += bpp * width * height / 2;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (babl_format_get_type (format, 0) == babl_type ("float"))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
downscale_float (components, width, height, width * bpp, src_data, dst_data);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else if (babl_format_get_type (format, 0) == babl_type ("u8"))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
downscale_u8 (components, width, height, width * bpp, src_data, dst_data);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
set_half_nearest (dst_tile, src_tile, width, height, format, i, j);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static GeglTile *
|
|
Packit |
bc1512 |
get_tile (GeglTileSource *gegl_tile_source,
|
|
Packit |
bc1512 |
gint x,
|
|
Packit |
bc1512 |
gint y,
|
|
Packit |
bc1512 |
gint z)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglTileSource *source = ((GeglTileHandler*)(gegl_tile_source))->source;
|
|
Packit |
bc1512 |
GeglTileHandlerZoom *zoom = (GeglTileHandlerZoom*)(gegl_tile_source);
|
|
Packit |
bc1512 |
GeglTile *tile = NULL;
|
|
Packit |
bc1512 |
const Babl *format = gegl_tile_backend_get_format (zoom->backend);
|
|
Packit |
bc1512 |
gint tile_width;
|
|
Packit |
bc1512 |
gint tile_height;
|
|
Packit |
bc1512 |
gint tile_size;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (source)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
tile = gegl_tile_source_get_tile (source, x, y, z);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (tile)
|
|
Packit |
bc1512 |
return tile;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (z == 0)/* at base level with no tile found->send null, and shared empty
|
|
Packit |
bc1512 |
tile will be used instead */
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
return NULL;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (z>zoom->tile_storage->seen_zoom)
|
|
Packit |
bc1512 |
zoom->tile_storage->seen_zoom = z;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_assert (zoom->backend);
|
|
Packit |
bc1512 |
g_object_get (zoom->backend, "tile-width", &tile_width,
|
|
Packit |
bc1512 |
"tile-height", &tile_height,
|
|
Packit |
bc1512 |
"tile-size", &tile_size,
|
|
Packit |
bc1512 |
NULL);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gint i, j;
|
|
Packit |
bc1512 |
GeglTile *source_tile[2][2] = { { NULL, NULL }, { NULL, NULL } };
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
for (i = 0; i < 2; i++)
|
|
Packit |
bc1512 |
for (j = 0; j < 2; j++)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
/* we get the tile from ourselves, to make successive rescales work
|
|
Packit |
bc1512 |
* correctly */
|
|
Packit |
bc1512 |
source_tile[i][j] = gegl_tile_source_get_tile (gegl_tile_source,
|
|
Packit |
bc1512 |
x * 2 + i, y * 2 + j, z - 1);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (source_tile[0][0] == NULL &&
|
|
Packit |
bc1512 |
source_tile[0][1] == NULL &&
|
|
Packit |
bc1512 |
source_tile[1][0] == NULL &&
|
|
Packit |
bc1512 |
source_tile[1][1] == NULL)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
return NULL; /* no data from level below, return NULL and let GeglTileHandlerEmpty
|
|
Packit |
bc1512 |
fill in the shared empty tile */
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_assert (tile == NULL);
|
|
Packit |
bc1512 |
if (tile == NULL)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
tile = gegl_tile_new (tile_size);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
tile->x = x;
|
|
Packit |
bc1512 |
tile->y = y;
|
|
Packit |
bc1512 |
tile->z = z;
|
|
Packit |
bc1512 |
tile->tile_storage = zoom->tile_storage;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (zoom->cache)
|
|
Packit |
bc1512 |
gegl_tile_handler_cache_insert (zoom->cache, tile, x, y, z);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
gegl_tile_lock (tile);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
for (i = 0; i < 2; i++)
|
|
Packit |
bc1512 |
for (j = 0; j < 2; j++)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
if (source_tile[i][j])
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
set_half (tile, source_tile[i][j], tile_width, tile_height, format, i, j);
|
|
Packit |
bc1512 |
gegl_tile_unref (source_tile[i][j]);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
set_blank (tile, tile_width, tile_height, format, i, j);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
gegl_tile_unlock (tile);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
return tile;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static gpointer
|
|
Packit |
bc1512 |
gegl_tile_handler_zoom_command (GeglTileSource *tile_store,
|
|
Packit |
bc1512 |
GeglTileCommand command,
|
|
Packit |
bc1512 |
gint x,
|
|
Packit |
bc1512 |
gint y,
|
|
Packit |
bc1512 |
gint z,
|
|
Packit |
bc1512 |
gpointer data)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglTileHandler *handler = (void*)tile_store;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (command == GEGL_TILE_GET)
|
|
Packit |
bc1512 |
return get_tile (tile_store, x, y, z);
|
|
Packit |
bc1512 |
else
|
|
Packit |
bc1512 |
return gegl_tile_handler_source_command (handler, command, x, y, z, data);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
gegl_tile_handler_zoom_class_init (GeglTileHandlerZoomClass *klass)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
gegl_tile_handler_zoom_init (GeglTileHandlerZoom *self)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
((GeglTileSource*)self)->command = gegl_tile_handler_zoom_command;
|
|
Packit |
bc1512 |
self->backend = NULL;
|
|
Packit |
bc1512 |
self->tile_storage = NULL;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
GeglTileHandler *
|
|
Packit |
bc1512 |
gegl_tile_handler_zoom_new (GeglTileBackend *backend,
|
|
Packit |
bc1512 |
GeglTileStorage *tile_storage,
|
|
Packit |
bc1512 |
GeglTileHandlerCache *cache)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglTileHandlerZoom *ret = g_object_new (GEGL_TYPE_TILE_HANDLER_ZOOM, NULL);
|
|
Packit |
bc1512 |
((GeglTileSource*)ret)->command = gegl_tile_handler_zoom_command;
|
|
Packit |
bc1512 |
ret->backend = backend;
|
|
Packit |
bc1512 |
ret->tile_storage = tile_storage;
|
|
Packit |
bc1512 |
ret->cache = cache;
|
|
Packit |
bc1512 |
return (void*)ret;
|
|
Packit |
bc1512 |
}
|