initially completed version, could use polishing
authorTony Cook <tony@develop=help.com>
Wed, 16 May 2001 03:07:47 +0000 (03:07 +0000)
committerTony Cook <tony@develop=help.com>
Wed, 16 May 2001 03:07:47 +0000 (03:07 +0000)
design/represent.txt

index 70e3ac4..f2610d3 100644 (file)
@@ -22,6 +22,8 @@ to suit special purposes, including paletted images, images kept of
 disk (think of 64k x 64k RGB images), and virtual images (where
 there's no actual image data.)
 
+=head1 IMAGE TYPES
+
 =head2 Paletted Images
 
 This is the form we've discussed the most.  The main advantage here is
@@ -97,7 +99,35 @@ pixels are writable, to avoid that extra expense.
 
 =head2 Varying Bits/Sample
 
-=head2 Implementation
+The typical Imager image could stay at 8 bits/sample, but some
+applications may need to work with images with a higher or lower
+colour resolution.  It may also be desirable to work with images where
+the sample values are floating point, eg. some FITS images.
+
+The problem with supporting floating point or a larger bit count is
+that we need an interface to get and put pixels/rows at the largest
+resolution for the high colour resolution.  Since working at this
+colour resolution for lower colour resolution images would be
+inefficient, we also want another interface at some lower bit-count.
+To reduce maintenance costs we want to limit the number of interfaces.
+
+=head1 INTERFACE CONSIDERATIONS
+
+Common interfaces are those interfaces which available for every image
+type.  These should include some common bits/sample, and some
+all-encompassing bits/sample, eg. 8 bits/sample for the common, and
+floating point for the all-encompassing.
+
+The idea is to make it possible for a given filtering function to have
+only one implementation at the all-encompassing bits/sample, while
+some other function has implementations at multiple bits/sample for
+improved speed.
+
+To reduce maintenance we want to reduce the number of common
+interfaces, both so that we don't have to write too much code for each
+image representation and so that we don't have someone trying to write
+five versions of the same code in an attempt to push efficiency to the
+limits.
 
 Since we want some function pointers to only be available for some
 images (like 'getpixindex' against paletted images), callers need to
@@ -111,12 +141,122 @@ the other topics above.
 Perhaps some method to check the writability at given pixels could be
 used to avoid expensive pixel calculations.
 
-=head2 Robustness
+We need to strike a balance between speed and maintainability.
+
+While most x86 processors have floating point performance almost as
+fast or faster than integer performance, some architectures don't,
+hence we need to support use of integer algorithms where appropriate.
 
+=head2 Robustness
 
+By preferring access via the functions we can reduce the possibility
+of incorrect access to the image data.
+
+If an image interface function pointer isn't implemented, it should be set to NULL rather than being left uninitialized.  This is so that use of the ununsed pointer results in an immediate crash rather than possibly calling the wrong function and crashing at some later point.
+
+In a debug build of Imager the image interface functions should check
+that the correct type of image pointer is being passed in.  This means
+that a caller cannot accidentally pass the wrong type of image pointer
+to an image access function.
+
+=head1 PROPOSED INTERFACE
+
+The basic interface would include:
+
+  typedef struct {
+    struct { unsigned char r,g,b,a; } rgb;
+    unsigned char channels[MAX_CHANNELS];
+    /* and others as we currently have */
+  } i_color;
+  typedef struct {
+    struct { double char r, g, b, a; } rgb;
+    double channels[MAX_CHANNELS];
+    /* and others as we currently have */
+  } i_fcolor;
+  typedef struct i_img_tag i_img;
+  typedef int (*i_f_ppix_t)(i_img *im, int x, int y, i_color *pix);
+  typedef int (*i_f_ppixf_t)(i_img *im, int x, int y, i_fcolor *pix);
+  typedef int (*i_f_plin_t)(i_img *im, int x, int r, int y, i_color *vals);
+  typedef int (*i_f_plinf_t)(i_img *im, int x, int r, int y, i_fcolor *vals);
+  typedef int (*i_f_gpix_t)(i_img *im, int x, int y, i_color *pix);
+  typedef int (*i_f_gpixf_t)(i_img *im, int x, int y, i_fcolor *pix);
+  typedef int (*i_f_glin_t)(i_img *im, int x, int r, int y, i_color *vals);
+  typedef int (*i_f_glinf_t)(i_img *im, int x, int r, int y, i_fcolor *vals);
+  typedef enum {
+    i_literal_type, /* keeps RGB values per pixel */
+    i_palette_type, /* keeps a palette index per pixel */
+  } i_img_types;
+  /* interface functions 
+  typedef int (*i_f_gpal_t)(i_img *im, int x, int r, int y, i_palidx *vals);
+  typedef int (*i_f_ppal_t)(i_img *im, int x, int r, int y, i_palidx *vals);
+  typedef int (*i_f_addcolor_t)(i_img *im, i_color *);
+  typedef int (*i_f_getcolor_t)(i_img *im, int i, i_color *);
+  typedef int (*i_f_colorcount_t)(i_img *im);
+  typedef int (*i_f_findcolor_t)(i_img *im);
+  typedef enum { 
+    /* bits per sample, not per pixel */
+    /* a paletted image might have one bit perl sample */
+    i_8_bits = 8,
+    i_16_bits = 16,
+    i_double_bits = 64
+  } i_img_bits;
+  typedef struct {
+    char *name; /* name of a given tag, might be NULL */
+    int code; /* number of a given tag, -1 if it has no meaning */
+    char *data; /* value of a given tag if it's not an int, may be NULL */
+    int idata; /* value of a given tag if data is NULL */
+  } i_img_tag;
+  typedef struct {
+    int count; /* how many tags have been set */
+    int alloc; /* how many tags have been allocated for */
+    i_img_tag *tags;
+  } i_img_tags;
+  typedef struct {
+    int channels;
+    int xsize, ysize, bytes;
+    int ch_mask;
+    i_img_bits bits;
+    i_img_type type;
+    int virtual; /* image might not keep any data, must use functions */
+    void *idata; /* renamed to force inspection of existing code */
+                /* can be NULL if virtual is non-zero */
+    i_img_tags tags;
+
+    /* interface functions */
+    i_f_ppix_t i_f_ppix;
+    i_f_ppixf_t i_f_ppixf;
+    i_f_plin_t i_f_plin;
+    i_f_plinf_t i_f_plinf;
+    i_f_gpix_t i_f_gpix;
+    i_f_gpixf_t i_f_gpixf;
+    i_f_glin_t i_f_glin;
+    i_f_glinf_t i_f_glinf;
+
+    /* only valid for type == i_palette_type */
+    i_f_gpal_t i_f_gpal;
+    i_f_ppal_t i_f_ppal;
+    i_f_addcolor_t i_f_addcolor;
+    i_f_getcolor_t i_f_getcolor;
+    i_f_colorcount_t i_f_colorcount;
+    i_f_findcolor_t i_f_findcolor;
+  } i_img;
+
+I'm using 8-bits for the base interface to remain compatible with
+existing code, and because it's a common sample size.
+
+I'm using double for the all-encompassing size since it's the biggest
+convenient type that supports floating point based-pixels.
+
+We might want to add functions to set/retrieve the whole palette at
+once, though setting the whole palette at once would make existing
+image data fairly useless.
 
 =head1 AUTHOR
 
 Tony Cook <tony@develop-help.com>
 
+=head1 HISTORY
+
+16May2001 - initially completed version, could use some polishing
+
 =cut