Main Page | Modules | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

src/main/print-dither-matrices.c

Go to the documentation of this file.
00001 /*
00002  * "$Id: print-dither-matrices.c,v 1.33 2004/05/07 19:20:31 rleigh Exp $"
00003  *
00004  *   Print plug-in driver utility functions for the GIMP.
00005  *
00006  *   Copyright 2001 Robert Krawitz (rlk@alum.mit.edu)
00007  *
00008  *   This program is free software; you can redistribute it and/or modify it
00009  *   under the terms of the GNU General Public License as published by the Free
00010  *   Software Foundation; either version 2 of the License, or (at your option)
00011  *   any later version.
00012  *
00013  *   This program is distributed in the hope that it will be useful, but
00014  *   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
00015  *   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00016  *   for more details.
00017  *
00018  *   You should have received a copy of the GNU General Public License
00019  *   along with this program; if not, write to the Free Software
00020  *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00021  *
00022  * Revision History:
00023  *
00024  *   See ChangeLog
00025  */
00026 
00027 #ifdef HAVE_CONFIG_H
00028 #include <config.h>
00029 #endif
00030 #include <gimp-print/gimp-print.h>
00031 #include "gimp-print-internal.h"
00032 #include <math.h>
00033 #include <string.h>
00034 #include <stdlib.h>
00035 #include <stdio.h>
00036 #include <assert.h>
00037 #include "dither-impl.h"
00038 
00039 #ifdef __GNUC__
00040 #define inline __inline__
00041 #endif
00042 
00043 
00044 static unsigned
00045 gcd(unsigned a, unsigned b)
00046 {
00047   unsigned tmp;
00048   if (b > a)
00049     {
00050       tmp = a;
00051       a = b;
00052       b = tmp;
00053     }
00054   while (1)
00055     {
00056       tmp = a % b;
00057       if (tmp == 0)
00058         return b;
00059       a = b;
00060       b = tmp;
00061     }
00062 }
00063 
00064 static inline int
00065 calc_ordered_point(unsigned x, unsigned y, int steps, int multiplier,
00066                    int size, const unsigned *map)
00067 {
00068   int i, j;
00069   unsigned retval = 0;
00070   int divisor = 1;
00071   int div1;
00072   for (i = 0; i < steps; i++)
00073     {
00074       int xa = (x / divisor) % size;
00075       int ya = (y / divisor) % size;
00076       unsigned base;
00077       base = map[ya + (xa * size)];
00078       div1 = 1;
00079       for (j = i; j < steps - 1; j++)
00080         div1 *= size * size;
00081       retval += base * div1;
00082       divisor *= size;
00083     }
00084   return retval * multiplier;
00085 }
00086 
00087 static int
00088 is_po2(size_t i)
00089 {
00090   if (i == 0)
00091     return 0;
00092   return (((i & (i - 1)) == 0) ? 1 : 0);
00093 }
00094 
00095 void
00096 stp_dither_matrix_iterated_init(stp_dither_matrix_impl_t *mat, size_t size,
00097                                 size_t expt, const unsigned *array)
00098 {
00099   int i;
00100   int x, y;
00101   mat->base = size;
00102   mat->exp = expt;
00103   mat->x_size = 1;
00104   for (i = 0; i < expt; i++)
00105     mat->x_size *= mat->base;
00106   mat->y_size = mat->x_size;
00107   mat->total_size = mat->x_size * mat->y_size;
00108   mat->matrix = stp_malloc(sizeof(unsigned) * mat->x_size * mat->y_size);
00109   for (x = 0; x < mat->x_size; x++)
00110     for (y = 0; y < mat->y_size; y++)
00111       {
00112         mat->matrix[x + y * mat->x_size] =
00113           calc_ordered_point(x, y, mat->exp, 1, mat->base, array);
00114         mat->matrix[x + y * mat->x_size] =
00115           (double) mat->matrix[x + y * mat->x_size] * 65536.0 /
00116           (double) (mat->x_size * mat->y_size);
00117       }
00118   mat->last_x = mat->last_x_mod = 0;
00119   mat->last_y = mat->last_y_mod = 0;
00120   mat->index = 0;
00121   mat->i_own = 1;
00122   if (is_po2(mat->x_size))
00123     mat->fast_mask = mat->x_size - 1;
00124   else
00125     mat->fast_mask = 0;
00126 }
00127 
00128 #define MATRIX_POINT(m, x, y, x_size, y_size) \
00129   ((m)[(((x) + (x_size)) % (x_size)) + ((x_size) * (((y) + (y_size)) % (y_size)))])
00130 
00131 void
00132 stp_dither_matrix_shear(stp_dither_matrix_impl_t *mat, int x_shear, int y_shear)
00133 {
00134   int i;
00135   int j;
00136   int *tmp = stp_malloc(mat->x_size * mat->y_size * sizeof(int));
00137   for (i = 0; i < mat->x_size; i++)
00138     for (j = 0; j < mat->y_size; j++)
00139       MATRIX_POINT(tmp, i, j, mat->x_size, mat->y_size) =
00140         MATRIX_POINT(mat->matrix, i, j * (x_shear + 1), mat->x_size,
00141                     mat->y_size);
00142   for (i = 0; i < mat->x_size; i++)
00143     for (j = 0; j < mat->y_size; j++)
00144       MATRIX_POINT(mat->matrix, i, j, mat->x_size, mat->y_size) =
00145         MATRIX_POINT(tmp, i * (y_shear + 1), j, mat->x_size, mat->y_size);
00146   stp_free(tmp);
00147 }
00148 
00149 int
00150 stp_dither_matrix_validate_array(const stp_array_t *array)
00151 {
00152   double low, high;
00153   const stp_sequence_t *seq = stp_array_get_sequence(array);
00154   stp_sequence_get_bounds(seq, &low, &high);
00155   if (low < 0 || high > 65535)
00156     return 0;
00157   return 1;
00158 }
00159 
00160 
00161 void
00162 stp_dither_matrix_init_from_dither_array(stp_dither_matrix_impl_t *mat,
00163                                          const stp_array_t *array,
00164                                          int transpose)
00165 {
00166   int x, y;
00167   size_t count;
00168   const unsigned short *vec;
00169   int x_size, y_size;
00170   const stp_sequence_t *seq = stp_array_get_sequence(array);
00171   stp_array_get_size(array, &x_size, &y_size);
00172 
00173   vec = stp_sequence_get_ushort_data(seq, &count);
00174   mat->base = x_size;;
00175   mat->exp = 1;
00176   mat->x_size = x_size;
00177   mat->y_size = y_size;
00178   mat->total_size = mat->x_size * mat->y_size;
00179   mat->matrix = stp_malloc(sizeof(unsigned) * mat->x_size * mat->y_size);
00180   for (x = 0; x < mat->x_size; x++)
00181     for (y = 0; y < mat->y_size; y++)
00182       {
00183         if (transpose)
00184           mat->matrix[x + y * mat->x_size] = vec[y + x * mat->y_size];
00185         else
00186           mat->matrix[x + y * mat->x_size] = vec[x + y * mat->x_size];
00187       }
00188   mat->last_x = mat->last_x_mod = 0;
00189   mat->last_y = mat->last_y_mod = 0;
00190   mat->index = 0;
00191   mat->i_own = 1;
00192   if (is_po2(mat->x_size))
00193     mat->fast_mask = mat->x_size - 1;
00194   else
00195     mat->fast_mask = 0;
00196 }
00197 
00198 
00199 void
00200 stp_dither_matrix_init(stp_dither_matrix_impl_t *mat, int x_size, int y_size,
00201                        const unsigned int *array, int transpose, int prescaled)
00202 {
00203   int x, y;
00204   mat->base = x_size;
00205   mat->exp = 1;
00206   mat->x_size = x_size;
00207   mat->y_size = y_size;
00208   mat->total_size = mat->x_size * mat->y_size;
00209   mat->matrix = stp_malloc(sizeof(unsigned) * mat->x_size * mat->y_size);
00210   for (x = 0; x < mat->x_size; x++)
00211     for (y = 0; y < mat->y_size; y++)
00212       {
00213         if (transpose)
00214           mat->matrix[x + y * mat->x_size] = array[y + x * mat->y_size];
00215         else
00216           mat->matrix[x + y * mat->x_size] = array[x + y * mat->x_size];
00217         if (!prescaled)
00218           mat->matrix[x + y * mat->x_size] =
00219             (double) mat->matrix[x + y * mat->x_size] * 65536.0 /
00220             (double) (mat->x_size * mat->y_size);
00221       }
00222   mat->last_x = mat->last_x_mod = 0;
00223   mat->last_y = mat->last_y_mod = 0;
00224   mat->index = 0;
00225   mat->i_own = 1;
00226   if (is_po2(mat->x_size))
00227     mat->fast_mask = mat->x_size - 1;
00228   else
00229     mat->fast_mask = 0;
00230 }
00231 
00232 void
00233 stp_dither_matrix_init_short(stp_dither_matrix_impl_t *mat, int x_size, int y_size,
00234                              const unsigned short *array, int transpose,
00235                              int prescaled)
00236 {
00237   int x, y;
00238   mat->base = x_size;
00239   mat->exp = 1;
00240   mat->x_size = x_size;
00241   mat->y_size = y_size;
00242   mat->total_size = mat->x_size * mat->y_size;
00243   mat->matrix = stp_malloc(sizeof(unsigned) * mat->x_size * mat->y_size);
00244   for (x = 0; x < mat->x_size; x++)
00245     for (y = 0; y < mat->y_size; y++)
00246       {
00247         if (transpose)
00248           mat->matrix[x + y * mat->x_size] = array[y + x * mat->y_size];
00249         else
00250           mat->matrix[x + y * mat->x_size] = array[x + y * mat->x_size];
00251         if (!prescaled)
00252           mat->matrix[x + y * mat->x_size] =
00253             (double) mat->matrix[x + y * mat->x_size] * 65536.0 /
00254             (double) (mat->x_size * mat->y_size);
00255       }
00256   mat->last_x = mat->last_x_mod = 0;
00257   mat->last_y = mat->last_y_mod = 0;
00258   mat->index = 0;
00259   mat->i_own = 1;
00260   if (is_po2(mat->x_size))
00261     mat->fast_mask = mat->x_size - 1;
00262   else
00263     mat->fast_mask = 0;
00264 }
00265 
00266 void
00267 stp_dither_matrix_destroy(stp_dither_matrix_impl_t *mat)
00268 {
00269   if (mat->i_own && mat->matrix)
00270     stp_free(mat->matrix);
00271   mat->matrix = NULL;
00272   mat->base = 0;
00273   mat->exp = 0;
00274   mat->x_size = 0;
00275   mat->y_size = 0;
00276   mat->total_size = 0;
00277   mat->i_own = 0;
00278 }
00279 
00280 void
00281 stp_dither_matrix_clone(const stp_dither_matrix_impl_t *src, stp_dither_matrix_impl_t *dest,
00282                         int x_offset, int y_offset)
00283 {
00284   dest->base = src->base;
00285   dest->exp = src->exp;
00286   dest->x_size = src->x_size;
00287   dest->y_size = src->y_size;
00288   dest->total_size = src->total_size;
00289   dest->matrix = src->matrix;
00290   dest->x_offset = x_offset;
00291   dest->y_offset = y_offset;
00292   dest->last_x = 0;
00293   dest->last_x_mod = dest->x_offset % dest->x_size;
00294   dest->last_y = 0;
00295   dest->last_y_mod = dest->x_size * (dest->y_offset % dest->y_size);
00296   dest->index = dest->last_x_mod + dest->last_y_mod;
00297   dest->fast_mask = src->fast_mask;
00298   dest->i_own = 0;
00299 }
00300 
00301 void
00302 stp_dither_matrix_copy(const stp_dither_matrix_impl_t *src, stp_dither_matrix_impl_t *dest)
00303 {
00304   int x;
00305   dest->base = src->base;
00306   dest->exp = src->exp;
00307   dest->x_size = src->x_size;
00308   dest->y_size = src->y_size;
00309   dest->total_size = src->total_size;
00310   dest->matrix = stp_malloc(sizeof(unsigned) * dest->x_size * dest->y_size);
00311   for (x = 0; x < dest->x_size * dest->y_size; x++)
00312     dest->matrix[x] = src->matrix[x];
00313   dest->x_offset = 0;
00314   dest->y_offset = 0;
00315   dest->last_x = 0;
00316   dest->last_x_mod = 0;
00317   dest->last_y = 0;
00318   dest->last_y_mod = 0;
00319   dest->index = 0;
00320   dest->fast_mask = src->fast_mask;
00321   dest->i_own = 1;
00322 }
00323 
00324 void
00325 stp_dither_matrix_scale_exponentially(stp_dither_matrix_impl_t *mat, double exponent)
00326 {
00327   int i;
00328   int mat_size = mat->x_size * mat->y_size;
00329   for (i = 0; i < mat_size; i++)
00330     {
00331       double dd = mat->matrix[i] / 65535.0;
00332       dd = pow(dd, exponent);
00333       mat->matrix[i] = 65535 * dd;
00334     }
00335 }
00336 
00337 void
00338 stp_dither_matrix_set_row(stp_dither_matrix_impl_t *mat, int y)
00339 {
00340   mat->last_y = y;
00341   mat->last_y_mod = mat->x_size * ((y + mat->y_offset) % mat->y_size);
00342   mat->index = mat->last_x_mod + mat->last_y_mod;
00343 }
00344 
00345 static void
00346 preinit_matrix(stp_vars_t *v)
00347 {
00348   stpi_dither_t *d = (stpi_dither_t *) stp_get_component_data(v, "Dither");
00349   int i;
00350   for (i = 0; i < CHANNEL_COUNT(d); i++)
00351     stp_dither_matrix_destroy(&(CHANNEL(d, i).dithermat));
00352   stp_dither_matrix_destroy(&(d->dither_matrix));
00353 }
00354 
00355 static void
00356 postinit_matrix(stp_vars_t *v, int x_shear, int y_shear)
00357 {
00358   stpi_dither_t *d = (stpi_dither_t *) stp_get_component_data(v, "Dither");
00359   unsigned rc = 1 + (unsigned) ceil(sqrt(CHANNEL_COUNT(d)));
00360   int i, j;
00361   int color = 0;
00362   unsigned x_n = d->dither_matrix.x_size / rc;
00363   unsigned y_n = d->dither_matrix.y_size / rc;
00364   if (x_shear || y_shear)
00365     stp_dither_matrix_shear(&(d->dither_matrix), x_shear, y_shear);
00366   for (i = 0; i < rc; i++)
00367     for (j = 0; j < rc; j++)
00368       if (color < CHANNEL_COUNT(d))
00369         {
00370           stp_dither_matrix_clone(&(d->dither_matrix),
00371                                   &(CHANNEL(d, color).dithermat),
00372                                   x_n * i, y_n * j);
00373           color++;
00374         }
00375   stp_dither_set_transition(v, d->transition);
00376 }
00377 
00378 void
00379 stp_dither_set_iterated_matrix(stp_vars_t *v, size_t edge, size_t iterations,
00380                                const unsigned *data, int prescaled,
00381                                int x_shear, int y_shear)
00382 {
00383   stpi_dither_t *d = (stpi_dither_t *) stp_get_component_data(v, "Dither");
00384   preinit_matrix(v);
00385   stp_dither_matrix_iterated_init(&(d->dither_matrix), edge, iterations, data);
00386   postinit_matrix(v, x_shear, y_shear);
00387 }
00388 
00389 void
00390 stp_dither_set_matrix(stp_vars_t *v, const stp_dither_matrix_generic_t *matrix,
00391                       int transposed, int x_shear, int y_shear)
00392 {
00393   stpi_dither_t *d = (stpi_dither_t *) stp_get_component_data(v, "Dither");
00394   int x = transposed ? matrix->y : matrix->x;
00395   int y = transposed ? matrix->x : matrix->y;
00396   preinit_matrix(v);
00397   if (matrix->bytes == 2)
00398     stp_dither_matrix_init_short(&(d->dither_matrix), x, y,
00399                                  (const unsigned short *) matrix->data,
00400                                  transposed, matrix->prescaled);
00401   else if (matrix->bytes == 4)
00402     stp_dither_matrix_init(&(d->dither_matrix), x, y,
00403                            (const unsigned *)matrix->data,
00404                            transposed, matrix->prescaled);
00405   postinit_matrix(v, x_shear, y_shear);
00406 }
00407 
00408 void
00409 stp_dither_set_matrix_from_dither_array(stp_vars_t *v,
00410                                         const stp_array_t *array,
00411                                         int transpose)
00412 {
00413   stpi_dither_t *d = (stpi_dither_t *) stp_get_component_data(v, "Dither");
00414   preinit_matrix(v);
00415   stp_dither_matrix_init_from_dither_array(&(d->dither_matrix), array, transpose);
00416   postinit_matrix(v, 0, 0);
00417 }
00418 
00419 void
00420 stp_dither_set_transition(stp_vars_t *v, double exponent)
00421 {
00422   stpi_dither_t *d = (stpi_dither_t *) stp_get_component_data(v, "Dither");
00423   unsigned rc = 1 + (unsigned) ceil(sqrt(CHANNEL_COUNT(d)));
00424   int i, j;
00425   int color = 0;
00426   unsigned x_n = d->dither_matrix.x_size / rc;
00427   unsigned y_n = d->dither_matrix.y_size / rc;
00428   for (i = 0; i < CHANNEL_COUNT(d); i++)
00429     stp_dither_matrix_destroy(&(CHANNEL(d, i).pick));
00430   stp_dither_matrix_destroy(&(d->transition_matrix));
00431   stp_dither_matrix_copy(&(d->dither_matrix), &(d->transition_matrix));
00432   d->transition = exponent;
00433   if (exponent < .999 || exponent > 1.001)
00434     stp_dither_matrix_scale_exponentially(&(d->transition_matrix), exponent);
00435   for (i = 0; i < rc; i++)
00436     for (j = 0; j < rc; j++)
00437       if (color < CHANNEL_COUNT(d))
00438         {
00439           stp_dither_matrix_clone(&(d->dither_matrix),
00440                                   &(CHANNEL(d, color).pick),
00441                                   x_n * i, y_n * j);
00442           color++;
00443         }
00444 }
00445 
00446 static stp_list_t *dither_matrix_cache = NULL;
00447 
00448 typedef struct
00449 {
00450   int x;
00451   int y;
00452   const char *filename;
00453   const stp_array_t *dither_array;
00454 } stp_xml_dither_cache_t;
00455 
00456 static stp_xml_dither_cache_t *
00457 stp_xml_dither_cache_get(int x, int y)
00458 {
00459   stp_list_item_t *ln;
00460 
00461   stp_deprintf(STP_DBG_XML,
00462                "stp_xml_dither_cache_get: lookup %dx%d... ", x, y);
00463   if (!dither_matrix_cache)
00464     {
00465       stp_deprintf(STP_DBG_XML, "cache does not exist\n");
00466       return NULL;
00467     }
00468 
00469   ln = stp_list_get_start(dither_matrix_cache);
00470 
00471   while (ln)
00472     {
00473       if (((stp_xml_dither_cache_t *) stp_list_item_get_data(ln))->x == x &&
00474           ((stp_xml_dither_cache_t *) stp_list_item_get_data(ln))->y == y)
00475         {
00476 
00477           stp_deprintf(STP_DBG_XML, "found\n");
00478 
00479           return ((stp_xml_dither_cache_t *) stp_list_item_get_data(ln));
00480         }
00481       ln = stp_list_item_next(ln);
00482     }
00483   stp_deprintf(STP_DBG_XML, "missing\n");
00484 
00485   return NULL;
00486 }
00487 
00488 static void
00489 stp_xml_dither_cache_set(int x, int y, const char *filename)
00490 {
00491   stp_xml_dither_cache_t *cacheval;
00492 
00493   assert(x && y && filename);
00494 
00495   stp_xml_init();
00496 
00497   if (dither_matrix_cache == NULL)
00498     dither_matrix_cache = stp_list_create();
00499 
00500   if (stp_xml_dither_cache_get(x, y))
00501       /* Already cached for this x and y aspect */
00502     return;
00503 
00504   cacheval = stp_malloc(sizeof(stp_xml_dither_cache_t));
00505   cacheval->x = x;
00506   cacheval->y = y;
00507   cacheval->filename = stp_strdup(filename);
00508   cacheval->dither_array = NULL;
00509 
00510   stp_list_item_create(dither_matrix_cache, NULL, (void *) cacheval);
00511 
00512   stp_deprintf(STP_DBG_XML, "stp_xml_dither_cache_set: added %dx%d\n", x, y);
00513 
00514   stp_xml_exit();
00515 
00516   return;
00517 }
00518 
00519 /*
00520  * Parse the <dither-matrix> node.
00521  */
00522 static int
00523 stp_xml_process_dither_matrix(stp_mxml_node_t *dm,     /* The dither matrix node */
00524                                const char *file)  /* Source file */
00525                                
00526 {
00527   const char *value;
00528   int x = -1;
00529   int y = -1;
00530 
00531   value = stp_mxmlElementGetAttr(dm, "x-aspect");
00532   x = stp_xmlstrtol(value);
00533 
00534   value = stp_mxmlElementGetAttr(dm, "y-aspect");
00535   y = stp_xmlstrtol(value);
00536 
00537   stp_deprintf(STP_DBG_XML,
00538                "stp_xml_process_dither_matrix: x=%d, y=%d\n", x, y);
00539 
00540   stp_xml_dither_cache_set(x, y, file);
00541   return 1;
00542 }
00543 
00544 static stp_array_t *
00545 stpi_dither_array_create_from_xmltree(stp_mxml_node_t *dm) /* Dither matrix node */
00546 {
00547   const char *stmp;
00548   stp_mxml_node_t *child;
00549   int x_aspect, y_aspect; /* Dither matrix size */
00550 
00551   /* Get x-size */
00552   stmp = stp_mxmlElementGetAttr(dm, "x-aspect");
00553   if (stmp)
00554     {
00555       x_aspect = (int) stp_xmlstrtoul(stmp);
00556     }
00557   else
00558     {
00559       stp_erprintf("stpi_dither_array_create_from_xmltree: \"x-aspect\" missing\n");
00560       goto error;
00561     }
00562   /* Get y-size */
00563   stmp = stp_mxmlElementGetAttr(dm, "y-aspect");
00564   if (stmp)
00565     {
00566       y_aspect = (int) stp_xmlstrtoul(stmp);
00567     }
00568   else
00569     {
00570       stp_erprintf("stpi_dither_array_create_from_xmltree: \"y-aspect\" missing\n");
00571       goto error;
00572     }
00573 
00574   /* Now read in the array */
00575   child = stp_mxmlFindElement(dm, dm, "array", NULL, NULL, STP_MXML_DESCEND);
00576   if (child)
00577     return stp_array_create_from_xmltree(child);
00578   else
00579     stp_erprintf("stpi_dither_array_create_from_xmltree: cannot find root\n");
00580  error:
00581   return NULL;
00582 }
00583 
00584 static stp_array_t *
00585 xml_doc_get_dither_array(stp_mxml_node_t *doc)
00586 {
00587   stp_mxml_node_t *cur;
00588   stp_mxml_node_t *xmlseq;
00589 
00590   if (doc == NULL )
00591     {
00592       fprintf(stderr,"xml_doc_get_dither_array: XML file not parsed successfully.\n");
00593       return NULL;
00594     }
00595 
00596   cur = doc->child;
00597 
00598   if (cur == NULL)
00599     {
00600       fprintf(stderr,"xml_doc_get_dither_array: empty document\n");
00601       return NULL;
00602     }
00603 
00604   xmlseq = stp_xml_get_node(cur, "gimp-print", "dither-matrix", NULL);
00605   if (xmlseq == NULL )
00606     {
00607       fprintf(stderr,"xml-doc-get-dither-array: XML file is not a dither matrix.\n");
00608       return NULL;
00609     }
00610 
00611   return stpi_dither_array_create_from_xmltree(xmlseq);
00612 }
00613 
00614 static stp_array_t *
00615 stpi_dither_array_create_from_file(const char* file)
00616 {
00617   stp_mxml_node_t *doc;
00618   stp_array_t *ret = NULL;
00619 
00620   FILE *fp = fopen(file, "r");
00621   if (!fp)
00622     {
00623       stp_erprintf("stp_curve_create_from_file: unable to open %s: %s\n",
00624                    file, strerror(errno));
00625       return NULL;
00626     }
00627 
00628   stp_xml_init();
00629 
00630   stp_deprintf(STP_DBG_XML,
00631                "stpi_dither_array_create_from_file: reading `%s'...\n", file);
00632 
00633   doc = stp_mxmlLoadFile(NULL, fp, STP_MXML_NO_CALLBACK);
00634   (void) fclose(fp);
00635 
00636   if (doc)
00637     {
00638       ret = xml_doc_get_dither_array(doc);
00639       stp_mxmlDelete(doc);
00640     }
00641 
00642   stp_xml_exit();
00643 
00644   return ret;
00645 }
00646 
00647 static stp_array_t *
00648 stp_xml_get_dither_array(int x, int y)
00649 {
00650   stp_xml_dither_cache_t *cachedval;
00651   stp_array_t *ret;
00652 
00653   cachedval = stp_xml_dither_cache_get(x, y);
00654 
00655   if (cachedval && cachedval->dither_array)
00656     return stp_array_create_copy(cachedval->dither_array);
00657 
00658   if (!cachedval)
00659     {
00660       char buf[1024];
00661       (void) sprintf(buf, "dither-matrix-%dx%d.xml", x, y);
00662       stp_xml_parse_file_named(buf);
00663       cachedval = stp_xml_dither_cache_get(x, y);
00664       if (cachedval == NULL || cachedval->filename == NULL)
00665         {
00666           return NULL;
00667         }
00668     }
00669 
00670   ret = stpi_dither_array_create_from_file(cachedval->filename);
00671 
00672   cachedval->dither_array = ret;
00673   return stp_array_create_copy(ret);
00674 }
00675 
00676 void
00677 stpi_init_dither(void)
00678 {
00679   stp_register_xml_parser("dither-matrix", stp_xml_process_dither_matrix);
00680 }
00681 
00682 stp_array_t *
00683 stp_find_standard_dither_array(int x_aspect, int y_aspect)
00684 {
00685   stp_array_t *answer;
00686   int divisor = gcd(x_aspect, y_aspect);
00687 
00688   x_aspect /= divisor;
00689   y_aspect /= divisor;
00690 
00691   if (x_aspect == 3)            /* We don't have x3 matrices */
00692     x_aspect += 1;              /* so cheat */
00693   if (y_aspect == 3)
00694     y_aspect += 1;
00695   
00696   divisor = gcd(x_aspect, y_aspect);
00697   x_aspect /= divisor;
00698   y_aspect /= divisor;
00699 
00700   answer = stp_xml_get_dither_array(x_aspect, y_aspect);
00701   if (answer)
00702     return answer;
00703   answer = stp_xml_get_dither_array(y_aspect, x_aspect);
00704   if (answer)
00705     return answer;
00706   return NULL;
00707 }

Generated on Wed Aug 25 07:56:14 2004 for libgimpprint API Reference by doxygen 1.3.6