Doxygen Source Code Documentation
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.
Define Documentation
|
|
|
Definition at line 338 of file xform.c. Referenced by scale_image(). |
|
Definition at line 337 of file xform.c. Referenced by scale_image(). |
Typedef Documentation
|
|
Function Documentation
|
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 } |
|
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 } |
|
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 } |
|
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 } |
|
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 } |
|
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 } |
|
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 } |
|
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 } |
|
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 } |
|
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 } |
|
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 } |