Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

xform.c File Reference

#include "config.h"
#include "gifsicle.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include <errno.h>
#include <limits.h>

Go to the source code of this file.


Data Structures

struct  Gt_ColorChange

Defines

#define SCALE(d)   ((d) << 10)
#define UNSCALE(d)   ((d) >> 10)
#define SCALE_FACTOR   SCALE(1)

Typedefs

typedef Gt_ColorChange Gt_ColorChange

Functions

Gt_ColorTransformappend_color_transform (Gt_ColorTransform *list, color_transform_func func, void *data)
Gt_ColorTransformdelete_color_transforms (Gt_ColorTransform *list, color_transform_func func)
void apply_color_transforms (Gt_ColorTransform *list, Gif_Stream *gfs)
void color_change_transformer (Gif_Colormap *gfcm, void *thunk)
Gt_ColorTransformappend_color_change (Gt_ColorTransform *list, Gif_Color old_color, Gif_Color new_color)
void pipe_color_transformer (Gif_Colormap *gfcm, void *thunk)
int crop_image (Gif_Image *gfi, Gt_Crop *crop)
void flip_image (Gif_Image *gfi, int screen_width, int screen_height, int is_vert)
void rotate_image (Gif_Image *gfi, int screen_width, int screen_height, int rotation)
void scale_image (Gif_Stream *gfs, Gif_Image *gfi, double xfactor, double yfactor)
void resize_stream (Gif_Stream *gfs, int new_width, int new_height)

Define Documentation

#define SCALE      ((d) << 10)
 

Definition at line 336 of file xform.c.

#define SCALE_FACTOR   SCALE(1)
 

Definition at line 338 of file xform.c.

Referenced by scale_image().

#define UNSCALE      ((d) >> 10)
 

Definition at line 337 of file xform.c.

Referenced by scale_image().


Typedef Documentation

typedef struct Gt_ColorChange Gt_ColorChange
 


Function Documentation

Gt_ColorTransform* append_color_change Gt_ColorTransform   list,
Gif_Color    old_color,
Gif_Color    new_color
 

Definition at line 104 of file xform.c.

References append_color_transform(), color_change_transformer(), Gt_ColorTransform::data, Gt_ColorTransform::func, Gif_New, Gt_ColorChange::new_color, Gt_ColorTransform::next, Gt_ColorChange::next, and Gt_ColorChange::old_color.

00106 {
00107   Gt_ColorTransform *xform;
00108   Gt_ColorChange *change = Gif_New(Gt_ColorChange);
00109   change->old_color = old_color;
00110   change->new_color = new_color;
00111   change->next = 0;
00112   
00113   for (xform = list; xform && xform->next; xform = xform->next)
00114     ;
00115   if (!xform || xform->func != &color_change_transformer)
00116     return append_color_transform(list, &color_change_transformer, change);
00117   else {
00118     Gt_ColorChange *prev = (Gt_ColorChange *)(xform->data);
00119     while (prev->next) prev = prev->next;
00120     prev->next = change;
00121     return list;
00122   }
00123 }

Gt_ColorTransform* append_color_transform Gt_ColorTransform   list,
color_transform_func    func,
void *    data
 

Definition at line 25 of file xform.c.

References color_transform_func, Gt_ColorTransform::data, Gt_ColorTransform::func, Gif_New, and Gt_ColorTransform::next.

Referenced by append_color_change().

00027 {
00028   Gt_ColorTransform *trav;
00029   Gt_ColorTransform *xform = Gif_New(Gt_ColorTransform);
00030   xform->next = 0;
00031   xform->func = func;
00032   xform->data = data;
00033   
00034   for (trav = list; trav && trav->next; trav = trav->next)
00035     ;
00036   if (trav) {
00037     trav->next = xform;
00038     return list;
00039   } else
00040     return xform;
00041 }

void apply_color_transforms Gt_ColorTransform   list,
Gif_Stream   gfs
 

Definition at line 61 of file xform.c.

References Gt_ColorTransform::data, Gt_ColorTransform::func, Gif_Stream::global, i, Gif_Stream::images, Gt_ColorTransform::next, and Gif_Stream::nimages.

Referenced by input_stream(), and merge_and_write_frames().

00062 {
00063   int i;
00064   Gt_ColorTransform *xform;
00065   for (xform = list; xform; xform = xform->next) {
00066     if (gfs->global)
00067       xform->func(gfs->global, xform->data);
00068     for (i = 0; i < gfs->nimages; i++)
00069       if (gfs->images[i]->local)
00070         xform->func(gfs->images[i]->local, xform->data);
00071   }
00072 }

void color_change_transformer Gif_Colormap   gfcm,
void *    thunk
 

Definition at line 82 of file xform.c.

References Gif_Colormap::col, GIF_COLOREQ, Gif_Color::haspixel, i, Gif_Colormap::ncol, Gt_ColorChange::new_color, Gt_ColorChange::next, Gt_ColorChange::old_color, and Gif_Color::pixel.

Referenced by append_color_change().

00083 {
00084   int i, have;
00085   Gt_ColorChange *first_change = (Gt_ColorChange *)thunk;
00086   Gt_ColorChange *change;
00087   
00088   /* change colors named by color */
00089   for (i = 0; i < gfcm->ncol; i++)
00090     for (change = first_change; change; change = change->next) {
00091       if (!change->old_color.haspixel)
00092         have = GIF_COLOREQ(&gfcm->col[i], &change->old_color);
00093       else
00094         have = change->old_color.pixel == i;
00095       
00096       if (have) {
00097         gfcm->col[i] = change->new_color;
00098         break;                  /* ignore remaining color changes */
00099       }
00100     }
00101 }

int crop_image Gif_Image   gfi,
Gt_Crop   crop
 

Definition at line 192 of file xform.c.

References error(), Gif_DeleteArray, Gif_NewArray, Gt_Crop::h, Gif_Image::height, Gif_Image::img, Gif_Image::left, Gt_Crop::left_off, Gt_Crop::ready, Gt_Crop::right_off, Gt_Crop::spec_h, Gt_Crop::spec_w, Gt_Crop::spec_x, Gt_Crop::spec_y, Gif_Image::top, Gt_Crop::w, Gt_Crop::whole_stream, Gif_Image::width, Gt_Crop::x, and Gt_Crop::y.

Referenced by merge_frame_interval().

00193 {
00194   int x, y, w, h, j;
00195   byte **img;
00196   
00197   if (!crop->ready) {
00198     crop->x = crop->spec_x + gfi->left;
00199     crop->y = crop->spec_y + gfi->top;
00200     crop->w = crop->spec_w <= 0 ? gfi->width + crop->spec_w : crop->spec_w;
00201     crop->h = crop->spec_h <= 0 ? gfi->height + crop->spec_h : crop->spec_h;
00202     if (crop->x < 0 || crop->y < 0 || crop->w <= 0 || crop->h <= 0
00203         || crop->x + crop->w > gfi->width
00204         || crop->y + crop->h > gfi->height) {
00205       error("cropping dimensions don't fit image");
00206       crop->ready = 2;
00207     } else
00208       crop->ready = 1;
00209   }
00210   if (crop->ready == 2)
00211     return 1;
00212   
00213   x = crop->x - gfi->left;
00214   y = crop->y - gfi->top;
00215   w = crop->w;
00216   h = crop->h;
00217   
00218   /* Check that the rectangle actually intersects with the image. */
00219   if (x < 0) w += x, x = 0;
00220   if (y < 0) h += y, y = 0;
00221   if (x + w > gfi->width) w = gfi->width - x;
00222   if (y + h > gfi->height) h = gfi->height - y;
00223   
00224   if (w > 0 && h > 0) {
00225     img = Gif_NewArray(byte *, h + 1);
00226     for (j = 0; j < h; j++)
00227       img[j] = gfi->img[y + j] + x;
00228     img[h] = 0;
00229     
00230     /* Change position of image appropriately */
00231     if (crop->whole_stream) {
00232       /* If cropping the whole stream, then this is the first frame. Position
00233          it at (0,0). */
00234       crop->left_off = x + gfi->left;
00235       crop->right_off = y + gfi->top;
00236       gfi->left = 0;
00237       gfi->top = 0;
00238       crop->whole_stream = 0;
00239     } else {
00240       gfi->left += x - crop->left_off;
00241       gfi->top += y - crop->right_off;
00242     }
00243     
00244   } else {
00245     /* Empty image */
00246     w = h = 0;
00247     img = 0;
00248   }
00249   
00250   Gif_DeleteArray(gfi->img);
00251   gfi->img = img;
00252   gfi->width = w;
00253   gfi->height = h;
00254   return gfi->img != 0;
00255 }

Gt_ColorTransform* delete_color_transforms Gt_ColorTransform   list,
color_transform_func    func
 

Definition at line 44 of file xform.c.

References color_transform_func, Gt_ColorTransform::func, Gif_Delete, and Gt_ColorTransform::next.

00045 {
00046   Gt_ColorTransform *prev = 0, *trav = list;
00047   while (trav) {
00048     Gt_ColorTransform *next = trav->next;
00049     if (trav->func == func) {
00050       if (prev) prev->next = next;
00051       else list = next;
00052       Gif_Delete(trav);
00053     } else
00054       prev = trav;
00055     trav = next;
00056   }
00057   return list;
00058 }

void flip_image Gif_Image   gfi,
int    screen_width,
int    screen_height,
int    is_vert
 

Definition at line 263 of file xform.c.

References Gif_DeleteArray, Gif_NewArray, Gif_Image::height, Gif_Image::img, Gif_Image::left, Gif_Image::top, and Gif_Image::width.

Referenced by handle_flip_and_screen().

00264 {
00265   int x, y;
00266   int width = gfi->width;
00267   int height = gfi->height;
00268   byte **img = gfi->img;
00269   
00270   /* horizontal flips */
00271   if (!is_vert) {
00272     byte *buffer = Gif_NewArray(byte, width);
00273     byte *trav;
00274     for (y = 0; y < height; y++) {
00275       memcpy(buffer, img[y], width);
00276       trav = img[y] + width - 1;
00277       for (x = 0; x < width; x++)
00278         *trav-- = buffer[x];
00279     }
00280     gfi->left = screen_width - (gfi->left + width);
00281     Gif_DeleteArray(buffer);
00282   }
00283   
00284   /* vertical flips */
00285   if (is_vert) {
00286     byte **buffer = Gif_NewArray(byte *, height);
00287     memcpy(buffer, img, height * sizeof(byte *));
00288     for (y = 0; y < height; y++)
00289       img[y] = buffer[height - y - 1];
00290     gfi->top = screen_height - (gfi->top + height);
00291     Gif_DeleteArray(buffer);
00292   }
00293 }

void pipe_color_transformer Gif_Colormap   gfcm,
void *    thunk
 

Definition at line 127 of file xform.c.

References Gif_Colormap::col, error(), fatal_error(), Gif_DeleteArray, Gif_DeleteColormap(), Gif_NewArray, i, nc, Gif_Colormap::ncol, pclose, popen, read_colormap_file(), strerror(), and warning().

00128 {
00129   int i, status;
00130   FILE *f;
00131   Gif_Color *col = gfcm->col;
00132   Gif_Colormap *new_cm = 0;
00133   char *command = (char *)thunk;
00134   char *tmp_file = tmpnam(0);
00135   char *new_command;
00136   
00137   if (!tmp_file)
00138     fatal_error("can't create temporary file!");
00139   
00140   new_command = Gif_NewArray(char, strlen(command) + strlen(tmp_file) + 4);
00141   sprintf(new_command, "%s  >%s", command, tmp_file);
00142   f = popen(new_command, "w");
00143   if (!f)
00144     fatal_error("can't run color transformation command: %s", strerror(errno));
00145   Gif_DeleteArray(new_command);
00146   
00147   for (i = 0; i < gfcm->ncol; i++)
00148     fprintf(f, "%d %d %d\n", col[i].red, col[i].green, col[i].blue);
00149   
00150   errno = 0;
00151   status = pclose(f);
00152   if (status < 0) {
00153     error("color transformation error: %s", strerror(errno));
00154     goto done;
00155   } else if (status > 0) {
00156     error("color transformation command failed");
00157     goto done;
00158   }
00159   
00160   f = fopen(tmp_file, "r");
00161   if (!f || feof(f)) {
00162     error("color transformation command generated no output", command);
00163     if (f) fclose(f);
00164     goto done;
00165   }
00166   new_cm = read_colormap_file("<color transformation>", f);
00167   fclose(f);
00168   
00169   if (new_cm) {
00170     int nc = new_cm->ncol;
00171     if (nc < gfcm->ncol) {
00172       nc = gfcm->ncol;
00173       warning("too few colors in color transformation results");
00174     } else if (nc > gfcm->ncol)
00175       warning("too many colors in color transformation results");
00176     for (i = 0; i < nc; i++)
00177       col[i] = new_cm->col[i];
00178   }
00179   
00180  done:
00181   remove(tmp_file);
00182   Gif_DeleteColormap(new_cm);
00183 }

void resize_stream Gif_Stream   gfs,
int    new_width,
int    new_height
 

Definition at line 423 of file xform.c.

References Gif_CalculateScreenSize(), i, Gif_Stream::images, Gif_Stream::nimages, scale_image(), Gif_Stream::screen_height, and Gif_Stream::screen_width.

Referenced by merge_and_write_frames().

00424 {
00425   double xfactor, yfactor;
00426   int i;
00427 
00428   if (new_width <= 0)
00429     new_width = (int)(((double)gfs->screen_width / gfs->screen_height) * new_height);
00430   if (new_height <= 0)
00431     new_height = (int)(((double)gfs->screen_height / gfs->screen_width) * new_width);
00432   
00433   Gif_CalculateScreenSize(gfs, 0);
00434   xfactor = (double)new_width / gfs->screen_width;
00435   yfactor = (double)new_height / gfs->screen_height;
00436   for (i = 0; i < gfs->nimages; i++)
00437     scale_image(gfs, gfs->images[i], xfactor, yfactor);
00438   
00439   gfs->screen_width = new_width;
00440   gfs->screen_height = new_height;
00441 }

void rotate_image Gif_Image   gfi,
int    screen_width,
int    screen_height,
int    rotation
 

Definition at line 296 of file xform.c.

References Gif_DeleteArrayFunc, Gif_NewArray, Gif_ReleaseUncompressedImage(), Gif_SetUncompressedImage(), Gif_Image::height, Gif_Image::img, Gif_Image::left, Gif_Image::top, and Gif_Image::width.

Referenced by handle_flip_and_screen().

00297 {
00298   int x, y;
00299   int width = gfi->width;
00300   int height = gfi->height;
00301   byte **img = gfi->img;
00302   byte *new_data = Gif_NewArray(byte, width * height);
00303   byte *trav = new_data;
00304   
00305   /* this function can only rotate by 90 or 270 degrees */
00306   assert(rotation == 1 || rotation == 3);
00307   
00308   if (rotation == 1) {
00309     for (x = 0; x < width; x++)
00310       for (y = height - 1; y >= 0; y--)
00311         *trav++ = img[y][x];
00312     x = gfi->left;
00313     gfi->left = screen_height - (gfi->top + height);
00314     gfi->top = x;
00315     
00316   } else {
00317     for (x = width - 1; x >= 0; x--)
00318       for (y = 0; y < height; y++)
00319         *trav++ = img[y][x];
00320     y = gfi->top;
00321     gfi->top = screen_width - (gfi->left + width);
00322     gfi->left = y;
00323   }
00324   
00325   Gif_ReleaseUncompressedImage(gfi);
00326   gfi->width = height;
00327   gfi->height = width;
00328   Gif_SetUncompressedImage(gfi, new_data, Gif_DeleteArrayFunc, 0);
00329 }

void scale_image Gif_Stream   gfs,
Gif_Image   gfi,
double    xfactor,
double    yfactor
 

Definition at line 341 of file xform.c.

References fatal_error(), Gif_DeleteArrayFunc, Gif_NewArray, Gif_ReleaseCompressedImage(), Gif_ReleaseUncompressedImage(), Gif_SetUncompressedImage(), Gif_Image::height, i, Gif_Image::img, Gif_Image::left, SCALE, SCALE_FACTOR, Gif_Image::top, UNSCALE, and Gif_Image::width.

Referenced by resize_stream().

00342 {
00343   byte *new_data;
00344   int new_left, new_top, new_right, new_bottom, new_width, new_height;
00345   
00346   int i, j, new_x, new_y;
00347   int scaled_xstep, scaled_ystep, scaled_new_x, scaled_new_y;
00348 
00349   /* Fri 9 Jan 1999: Fix problem with resizing animated GIFs: we scaled from
00350      left edge of the *subimage* to right edge of the subimage, causing
00351      consistency problems when several subimages overlap. Solution: always use
00352      scale factors relating to the *whole image* (the screen size). */
00353   
00354   /* use fixed-point arithmetic */
00355   scaled_xstep = (int)(SCALE_FACTOR * xfactor + 0.5);
00356   scaled_ystep = (int)(SCALE_FACTOR * yfactor + 0.5);
00357   
00358   /* calculate new width and height based on the four edges (left, right, top,
00359      bottom). This is better than simply multiplying the width and height by
00360      the scale factors because it avoids roundoff inconsistencies between
00361      frames on animated GIFs. Don't allow 0-width or 0-height images; GIF
00362      doesn't support them well. */
00363   new_left = UNSCALE(scaled_xstep * gfi->left);
00364   new_top = UNSCALE(scaled_ystep * gfi->top);
00365   new_right = UNSCALE(scaled_xstep * (gfi->left + gfi->width));
00366   new_bottom = UNSCALE(scaled_ystep * (gfi->top + gfi->height));
00367   
00368   new_width = new_right - new_left;
00369   new_height = new_bottom - new_top;
00370 
00371   if (new_width <= 0) new_width = 1, new_right = new_left + 1;
00372   if (new_height <= 0) new_height = 1, new_bottom = new_top + 1;
00373   if (new_width > UNSCALE(INT_MAX) || new_height > UNSCALE(INT_MAX))
00374     fatal_error("new image size is too big for me to handle");
00375   
00376   assert(gfi->img);
00377   new_data = Gif_NewArray(byte, new_width * new_height);
00378   
00379   new_y = new_top;
00380   scaled_new_y = scaled_ystep * gfi->top;
00381   
00382   for (j = 0; j < gfi->height; j++) {
00383     byte *in_line = gfi->img[j];
00384     byte *out_data;
00385     int x_delta, y_delta, yinc;
00386     
00387     scaled_new_y += scaled_ystep;
00388     /* account for images which should've had 0 height but don't */
00389     if (j == gfi->height - 1) scaled_new_y = SCALE(new_bottom);
00390     
00391     if (scaled_new_y < SCALE(new_y + 1)) continue;
00392     y_delta = UNSCALE(scaled_new_y - SCALE(new_y));
00393     
00394     new_x = new_left;
00395     scaled_new_x = scaled_xstep * gfi->left;
00396     out_data = &new_data[(new_y - new_top) * new_width + (new_x - new_left)];
00397     
00398     for (i = 0; i < gfi->width; i++) {
00399       scaled_new_x += scaled_xstep;
00400       /* account for images which should've had 0 width but don't */
00401       if (i == gfi->width - 1) scaled_new_x = SCALE(new_right);
00402       
00403       x_delta = UNSCALE(scaled_new_x - SCALE(new_x));
00404       
00405       for (; x_delta > 0; new_x++, x_delta--, out_data++)
00406         for (yinc = 0; yinc < y_delta; yinc++)
00407           out_data[yinc * new_width] = in_line[i];
00408     }
00409     
00410     new_y += y_delta;
00411   }
00412   
00413   Gif_ReleaseUncompressedImage(gfi);
00414   Gif_ReleaseCompressedImage(gfi);
00415   gfi->width = new_width;
00416   gfi->height = new_height;
00417   gfi->left = UNSCALE(scaled_xstep * gfi->left);
00418   gfi->top = UNSCALE(scaled_ystep * gfi->top);
00419   Gif_SetUncompressedImage(gfi, new_data, Gif_DeleteArrayFunc, 0);
00420 }
 

Powered by Plone

This site conforms to the following standards: