home *** CD-ROM | disk | FTP | other *** search
/ Chip 2005 February / CMCD0205.ISO / Linux / gimp-2.2.0.tar.gz / gimp-2.2.0.tar / gimp-2.2.0 / libgimpcolor / gimpbilinear.c < prev    next >
C/C++ Source or Header  |  2003-12-05  |  6KB  |  306 lines

  1. /* LIBGIMP - The GIMP Library
  2.  * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
  3.  *
  4.  * This library is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU Lesser General Public
  6.  * License as published by the Free Software Foundation; either
  7.  * version 2 of the License, or (at your option) any later version.
  8.  *
  9.  * This library is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12.  * Library General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU Lesser General Public
  15.  * License along with this library; if not, write to the
  16.  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  17.  * Boston, MA 02111-1307, USA.
  18.  */
  19.  
  20. #include "config.h"
  21.  
  22. #include <glib.h>
  23.  
  24. #include "libgimpmath/gimpmath.h"
  25.  
  26. #include "gimpcolortypes.h"
  27.  
  28. #include "gimpbilinear.h"
  29.  
  30.  
  31. gdouble
  32. gimp_bilinear (gdouble  x,
  33.            gdouble  y,
  34.            gdouble *values)
  35. {
  36.   gdouble m0, m1;
  37.  
  38.   g_return_val_if_fail (values != NULL, 0.0);
  39.  
  40.   x = fmod (x, 1.0);
  41.   y = fmod (y, 1.0);
  42.  
  43.   if (x < 0.0)
  44.     x += 1.0;
  45.   if (y < 0.0)
  46.     y += 1.0;
  47.  
  48.   m0 = (1.0 - x) * values[0] + x * values[1];
  49.   m1 = (1.0 - x) * values[2] + x * values[3];
  50.  
  51.   return (1.0 - y) * m0 + y * m1;
  52. }
  53.  
  54. guchar
  55. gimp_bilinear_8 (gdouble x,
  56.          gdouble y,
  57.          guchar *values)
  58. {
  59.   gdouble m0, m1;
  60.  
  61.   g_return_val_if_fail (values != NULL, 0);
  62.  
  63.   x = fmod (x, 1.0);
  64.   y = fmod (y, 1.0);
  65.  
  66.   if (x < 0.0)
  67.     x += 1.0;
  68.   if (y < 0.0)
  69.     y += 1.0;
  70.  
  71.   m0 = (1.0 - x) * values[0] + x * values[1];
  72.   m1 = (1.0 - x) * values[2] + x * values[3];
  73.  
  74.   return (guchar) ((1.0 - y) * m0 + y * m1);
  75. }
  76.  
  77. guint16
  78. gimp_bilinear_16 (gdouble  x,
  79.           gdouble  y,
  80.           guint16 *values)
  81. {
  82.   gdouble m0, m1;
  83.  
  84.   g_return_val_if_fail (values != NULL, 0);
  85.  
  86.   x = fmod (x, 1.0);
  87.   y = fmod (y, 1.0);
  88.  
  89.   if (x < 0.0)
  90.     x += 1.0;
  91.   if (y < 0.0)
  92.     y += 1.0;
  93.  
  94.   m0 = (1.0 - x) * values[0] + x * values[1];
  95.   m1 = (1.0 - x) * values[2] + x * values[3];
  96.  
  97.   return (guint16) ((1.0 - y) * m0 + y * m1);
  98. }
  99.  
  100. guint32
  101. gimp_bilinear_32 (gdouble  x,
  102.           gdouble  y,
  103.           guint32 *values)
  104. {
  105.   gdouble m0, m1;
  106.  
  107.   g_return_val_if_fail (values != NULL, 0);
  108.  
  109.   x = fmod (x, 1.0);
  110.   y = fmod (y, 1.0);
  111.  
  112.   if (x < 0.0)
  113.     x += 1.0;
  114.   if (y < 0.0)
  115.     y += 1.0;
  116.  
  117.   m0 = (1.0 - x) * values[0] + x * values[1];
  118.   m1 = (1.0 - x) * values[2] + x * values[3];
  119.  
  120.   return (guint32) ((1.0 - y) * m0 + y * m1);
  121. }
  122.  
  123. GimpRGB
  124. gimp_bilinear_rgb (gdouble  x,
  125.            gdouble  y,
  126.            GimpRGB *values)
  127. {
  128.   gdouble m0, m1;
  129.   gdouble ix, iy;
  130.   GimpRGB v;
  131.  
  132.   g_return_val_if_fail (values != NULL, v);
  133.  
  134.   x = fmod(x, 1.0);
  135.   y = fmod(y, 1.0);
  136.  
  137.   if (x < 0)
  138.     x += 1.0;
  139.   if (y < 0)
  140.     y += 1.0;
  141.  
  142.   ix = 1.0 - x;
  143.   iy = 1.0 - y;
  144.  
  145.   /* Red */
  146.  
  147.   m0 = ix * values[0].r + x * values[1].r;
  148.   m1 = ix * values[2].r + x * values[3].r;
  149.  
  150.   v.r = iy * m0 + y * m1;
  151.  
  152.   /* Green */
  153.  
  154.   m0 = ix * values[0].g + x * values[1].g;
  155.   m1 = ix * values[2].g + x * values[3].g;
  156.  
  157.   v.g = iy * m0 + y * m1;
  158.  
  159.   /* Blue */
  160.  
  161.   m0 = ix * values[0].b + x * values[1].b;
  162.   m1 = ix * values[2].b + x * values[3].b;
  163.  
  164.   v.b = iy * m0 + y * m1;
  165.  
  166.   return v;
  167. }
  168.  
  169. GimpRGB
  170. gimp_bilinear_rgba (gdouble  x,
  171.             gdouble  y,
  172.             GimpRGB *values)
  173. {
  174.   gdouble m0, m1;
  175.   gdouble ix, iy;
  176.   gdouble a0, a1, a2, a3, alpha;
  177.   GimpRGB v;
  178.  
  179.   g_return_val_if_fail (values != NULL, v);
  180.  
  181.   x = fmod (x, 1.0);
  182.   y = fmod (y, 1.0);
  183.  
  184.   if (x < 0)
  185.     x += 1.0;
  186.   if (y < 0)
  187.     y += 1.0;
  188.  
  189.   ix = 1.0 - x;
  190.   iy = 1.0 - y;
  191.  
  192.   a0 = values[0].a;
  193.   a1 = values[1].a;
  194.   a2 = values[2].a;
  195.   a3 = values[3].a;
  196.  
  197.   /* Alpha */
  198.  
  199.   m0 = ix * a0 + x * a1;
  200.   m1 = ix * a2 + x * a3;
  201.  
  202.   alpha = v.a = iy * m0 + y * m1;
  203.  
  204.   if (alpha > 0)
  205.     {
  206.       /* Red */
  207.  
  208.       m0 = ix * a0 * values[0].r + x * a1 * values[1].r;
  209.       m1 = ix * a2 * values[2].r + x * a3 * values[3].r;
  210.  
  211.       v.r = (iy * m0 + y * m1)/alpha;
  212.  
  213.       /* Green */
  214.  
  215.       m0 = ix * a0 * values[0].g + x * a1 * values[1].g;
  216.       m1 = ix * a2 * values[2].g + x * a3 * values[3].g;
  217.  
  218.       v.g = (iy * m0 + y * m1)/alpha;
  219.  
  220.       /* Blue */
  221.  
  222.       m0 = ix * a0 * values[0].b + x * a1 * values[1].b;
  223.       m1 = ix * a2 * values[2].b + x * a3 * values[3].b;
  224.  
  225.       v.b = (iy * m0 + y * m1)/alpha;
  226.     }
  227.  
  228.   return v;
  229. }
  230.  
  231. /**
  232.  * gimp_bilinear_pixels_8:
  233.  * @dest: Pixel, where interpolation result is to be stored.
  234.  * @x: x-coordinate (0.0 to 1.0).
  235.  * @y: y-coordinate (0.0 to 1.0).
  236.  * @bpp: Bytes per pixel.  @dest and each @values item is an array of
  237.  *    @bpp bytes.
  238.  * @has_alpha: %TRUE if the last channel is an alpha channel.
  239.  * @values: Array of four pointers to pixels.
  240.  *
  241.  * Computes bilinear interpolation of four pixels.
  242.  *
  243.  * When @has_alpha is %FALSE, it's identical to gimp_bilinear_8() on
  244.  * each channel separately.  When @has_alpha is %TRUE, it handles
  245.  * alpha channel correctly.
  246.  *
  247.  * The pixels in @values correspond to corner x, y coordinates in the
  248.  * following order: [0,0], [1,0], [0,1], [1,1].
  249.  **/
  250. void
  251. gimp_bilinear_pixels_8 (guchar    *dest,
  252.                         gdouble    x,
  253.                         gdouble    y,
  254.                         guint      bpp,
  255.                         gboolean   has_alpha,
  256.                         guchar   **values)
  257. {
  258.   guint i;
  259.  
  260.   g_return_if_fail (dest != NULL);
  261.   g_return_if_fail (values != NULL);
  262.  
  263.   x = fmod (x, 1.0);
  264.   y = fmod (y, 1.0);
  265.  
  266.   if (x < 0.0)
  267.     x += 1.0;
  268.   if (y < 0.0)
  269.     y += 1.0;
  270.  
  271.   if (has_alpha)
  272.     {
  273.       guint   ai     = bpp - 1;
  274.       gdouble alpha0 = values[0][ai];
  275.       gdouble alpha1 = values[1][ai];
  276.       gdouble alpha2 = values[2][ai];
  277.       gdouble alpha3 = values[3][ai];
  278.       gdouble alpha  = ((1.0 - y) * ((1.0 - x) * alpha0 + x * alpha1)
  279.                         + y * ((1.0 - x) * alpha2 + x * alpha3));
  280.  
  281.       dest[ai] = (guchar) alpha;
  282.       if (dest[ai])
  283.         {
  284.           for (i = 0; i < ai; i++)
  285.             {
  286.               gdouble m0 = ((1.0 - x) * values[0][i] * alpha0
  287.                             + x * values[1][i] * alpha1);
  288.               gdouble m1 = ((1.0 - x) * values[2][i] * alpha2
  289.                             + x * values[3][i] * alpha3);
  290.  
  291.               dest[i] = (guchar) (((1.0 - y) * m0 + y * m1) / alpha);
  292.             }
  293.         }
  294.     }
  295.   else
  296.     {
  297.       for (i = 0; i < bpp; i++)
  298.         {
  299.           gdouble m0 = (1.0 - x) * values[0][i] + x * values[1][i];
  300.           gdouble m1 = (1.0 - x) * values[2][i] + x * values[3][i];
  301.  
  302.           dest[i] = (guchar) ((1.0 - y) * m0 + y * m1);
  303.         }
  304.     }
  305. }
  306.