]> git.imager.perl.org - imager.git/blobdiff - design/represent.txt
i_img_info() (C API) no longer tries to handle a NULL image object pointer.
[imager.git] / design / represent.txt
index 70e3ac497fdee93202862a3b754c7179e1c1091f..b047a8838f2e1df91eaa78f61eab02a6325c288b 100644 (file)
@@ -9,6 +9,8 @@
   Varying Bits/Sample
   Paletted Images
   Performance
+  Robustness
+  XS Changes
 
 =head1 DESCRIPTION
 
@@ -22,6 +24,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 +101,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 +143,148 @@ 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 *msg;
+    int code;
+  } i_errmsg;
+
+  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;
+
+    i_errmsg error_stack[ERRSTK]; /* Store errors with image */
+
+    /* 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 XS CHANGES
+
+I had been considering moving the i_img object from being an
+Imager::ImgRef object to being an Imager object.  But I don't see much
+point to it, so I'll leave it the way it is now.
 
 =head1 AUTHOR
 
 Tony Cook <tony@develop-help.com>
 
+=head1 HISTORY
+
+16May2001 - initially completed version, could use some polishing
+16May2001 - Added i_error stack to the image structure.
+24May2001 - Added XS Changes section (TC)
+
 =cut