diff options
| author | Kim F. Storm | 2006-04-21 14:07:05 +0000 |
|---|---|---|
| committer | Kim F. Storm | 2006-04-21 14:07:05 +0000 |
| commit | 6ac3c7bb025ec4b37ca61c632c05d479cbfb6eb2 (patch) | |
| tree | fd108f706bda4ac088465a4de7f1b32da19a236b | |
| parent | 7b48cc1354a2efff9fb528c1b3c78f47d001178e (diff) | |
| download | emacs-6ac3c7bb025ec4b37ca61c632c05d479cbfb6eb2.tar.gz emacs-6ac3c7bb025ec4b37ca61c632c05d479cbfb6eb2.zip | |
(four_corners_best): New arg CORNERS specifies what pixels
to look at in case image has margin.
(x_create_bitmap_mask): Pass NULL for CORNERS to four_corners_best.
(image_background, image_background_transparent)
(x_build_heuristic_mask): Pass img->corners to four_corners_best.
(gif_load): Set img->corners according to image's margin spec.
Use img->corners values directly where applicable.
Save image extension data in img->data.lisp_val.
(gif_clear_image): New function to free img->data.lisp_val.
(gif_type): Use it instead of generic x_clear_image.
(Fimage_extension_data): New defun.
(syms_of_image): Defsubr it.
| -rw-r--r-- | src/image.c | 132 |
1 files changed, 101 insertions, 31 deletions
diff --git a/src/image.c b/src/image.c index e1962d87b0f..688ff200055 100644 --- a/src/image.c +++ b/src/image.c | |||
| @@ -603,7 +603,9 @@ x_destroy_all_bitmaps (dpyinfo) | |||
| 603 | /* Useful functions defined in the section | 603 | /* Useful functions defined in the section |
| 604 | `Image type independent image structures' below. */ | 604 | `Image type independent image structures' below. */ |
| 605 | 605 | ||
| 606 | static unsigned long four_corners_best P_ ((XImagePtr ximg, unsigned long width, | 606 | static unsigned long four_corners_best P_ ((XImagePtr ximg, |
| 607 | int *corners, | ||
| 608 | unsigned long width, | ||
| 607 | unsigned long height)); | 609 | unsigned long height)); |
| 608 | 610 | ||
| 609 | static int x_create_x_image_and_pixmap P_ ((struct frame *f, int width, int height, | 611 | static int x_create_x_image_and_pixmap P_ ((struct frame *f, int width, int height, |
| @@ -657,7 +659,7 @@ x_create_bitmap_mask (f, id) | |||
| 657 | return -1; | 659 | return -1; |
| 658 | } | 660 | } |
| 659 | 661 | ||
| 660 | bg = four_corners_best (ximg, width, height); | 662 | bg = four_corners_best (ximg, NULL, width, height); |
| 661 | 663 | ||
| 662 | for (y = 0; y < ximg->height; ++y) | 664 | for (y = 0; y < ximg->height; ++y) |
| 663 | { | 665 | { |
| @@ -732,7 +734,7 @@ Lisp_Object Qxbm; | |||
| 732 | /* Keywords. */ | 734 | /* Keywords. */ |
| 733 | 735 | ||
| 734 | extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile; | 736 | extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile; |
| 735 | extern Lisp_Object QCdata, QCtype; | 737 | extern Lisp_Object QCdata, QCtype, Qcount; |
| 736 | extern Lisp_Object Qcenter; | 738 | extern Lisp_Object Qcenter; |
| 737 | Lisp_Object QCascent, QCmargin, QCrelief; | 739 | Lisp_Object QCascent, QCmargin, QCrelief; |
| 738 | Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask; | 740 | Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask; |
| @@ -1141,6 +1143,27 @@ or omitted means use the selected frame. */) | |||
| 1141 | return mask; | 1143 | return mask; |
| 1142 | } | 1144 | } |
| 1143 | 1145 | ||
| 1146 | DEFUN ("image-extension-data", Fimage_extension_data, Simage_extension_data, 1, 2, 0, | ||
| 1147 | doc: /* Return extension data for image SPEC. | ||
| 1148 | FRAME is the frame on which the image will be displayed. FRAME nil | ||
| 1149 | or omitted means use the selected frame. */) | ||
| 1150 | (spec, frame) | ||
| 1151 | Lisp_Object spec, frame; | ||
| 1152 | { | ||
| 1153 | Lisp_Object ext; | ||
| 1154 | |||
| 1155 | ext = Qnil; | ||
| 1156 | if (valid_image_p (spec)) | ||
| 1157 | { | ||
| 1158 | struct frame *f = check_x_frame (frame); | ||
| 1159 | int id = lookup_image (f, spec); | ||
| 1160 | struct image *img = IMAGE_FROM_ID (f, id); | ||
| 1161 | ext = img->data.lisp_val; | ||
| 1162 | } | ||
| 1163 | |||
| 1164 | return ext; | ||
| 1165 | } | ||
| 1166 | |||
| 1144 | 1167 | ||
| 1145 | /*********************************************************************** | 1168 | /*********************************************************************** |
| 1146 | Image type independent image structures | 1169 | Image type independent image structures |
| @@ -1171,6 +1194,7 @@ make_image (spec, hash) | |||
| 1171 | img->data.lisp_val = Qnil; | 1194 | img->data.lisp_val = Qnil; |
| 1172 | img->ascent = DEFAULT_IMAGE_ASCENT; | 1195 | img->ascent = DEFAULT_IMAGE_ASCENT; |
| 1173 | img->hash = hash; | 1196 | img->hash = hash; |
| 1197 | img->corners[BOT_CORNER] = -1; /* Full image */ | ||
| 1174 | return img; | 1198 | return img; |
| 1175 | } | 1199 | } |
| 1176 | 1200 | ||
| @@ -1322,30 +1346,41 @@ image_ascent (img, face, slice) | |||
| 1322 | On W32, XIMG is assumed to a device context with the bitmap selected. */ | 1346 | On W32, XIMG is assumed to a device context with the bitmap selected. */ |
| 1323 | 1347 | ||
| 1324 | static RGB_PIXEL_COLOR | 1348 | static RGB_PIXEL_COLOR |
| 1325 | four_corners_best (ximg, width, height) | 1349 | four_corners_best (ximg, corners, width, height) |
| 1326 | XImagePtr_or_DC ximg; | 1350 | XImagePtr_or_DC ximg; |
| 1351 | int *corners; | ||
| 1327 | unsigned long width, height; | 1352 | unsigned long width, height; |
| 1328 | { | 1353 | { |
| 1329 | RGB_PIXEL_COLOR corners[4], best; | 1354 | RGB_PIXEL_COLOR corner_pixels[4], best; |
| 1330 | int i, best_count; | 1355 | int i, best_count; |
| 1331 | 1356 | ||
| 1332 | /* Get the colors at the corners of ximg. */ | 1357 | if (corners && corners[BOT_CORNER] >= 0) |
| 1333 | corners[0] = GET_PIXEL (ximg, 0, 0); | 1358 | { |
| 1334 | corners[1] = GET_PIXEL (ximg, width - 1, 0); | 1359 | /* Get the colors at the corner_pixels of ximg. */ |
| 1335 | corners[2] = GET_PIXEL (ximg, width - 1, height - 1); | 1360 | corner_pixels[0] = GET_PIXEL (ximg, corners[LEFT_CORNER], corners[TOP_CORNER]); |
| 1336 | corners[3] = GET_PIXEL (ximg, 0, height - 1); | 1361 | corner_pixels[1] = GET_PIXEL (ximg, corners[RIGHT_CORNER] - 1, corners[TOP_CORNER]); |
| 1337 | 1362 | corner_pixels[2] = GET_PIXEL (ximg, corners[RIGHT_CORNER] - 1, corners[BOT_CORNER] - 1); | |
| 1363 | corner_pixels[3] = GET_PIXEL (ximg, corners[LEFT_CORNER], corners[BOT_CORNER] - 1); | ||
| 1364 | } | ||
| 1365 | else | ||
| 1366 | { | ||
| 1367 | /* Get the colors at the corner_pixels of ximg. */ | ||
| 1368 | corner_pixels[0] = GET_PIXEL (ximg, 0, 0); | ||
| 1369 | corner_pixels[1] = GET_PIXEL (ximg, width - 1, 0); | ||
| 1370 | corner_pixels[2] = GET_PIXEL (ximg, width - 1, height - 1); | ||
| 1371 | corner_pixels[3] = GET_PIXEL (ximg, 0, height - 1); | ||
| 1372 | } | ||
| 1338 | /* Choose the most frequently found color as background. */ | 1373 | /* Choose the most frequently found color as background. */ |
| 1339 | for (i = best_count = 0; i < 4; ++i) | 1374 | for (i = best_count = 0; i < 4; ++i) |
| 1340 | { | 1375 | { |
| 1341 | int j, n; | 1376 | int j, n; |
| 1342 | 1377 | ||
| 1343 | for (j = n = 0; j < 4; ++j) | 1378 | for (j = n = 0; j < 4; ++j) |
| 1344 | if (corners[i] == corners[j]) | 1379 | if (corner_pixels[i] == corner_pixels[j]) |
| 1345 | ++n; | 1380 | ++n; |
| 1346 | 1381 | ||
| 1347 | if (n > best_count) | 1382 | if (n > best_count) |
| 1348 | best = corners[i], best_count = n; | 1383 | best = corner_pixels[i], best_count = n; |
| 1349 | } | 1384 | } |
| 1350 | 1385 | ||
| 1351 | return best; | 1386 | return best; |
| @@ -1404,7 +1439,7 @@ image_background (img, f, ximg) | |||
| 1404 | #endif /* !HAVE_NTGUI */ | 1439 | #endif /* !HAVE_NTGUI */ |
| 1405 | } | 1440 | } |
| 1406 | 1441 | ||
| 1407 | img->background = four_corners_best (ximg, img->width, img->height); | 1442 | img->background = four_corners_best (ximg, img->corners, img->width, img->height); |
| 1408 | 1443 | ||
| 1409 | if (free_ximg) | 1444 | if (free_ximg) |
| 1410 | Destroy_Image (ximg, prev); | 1445 | Destroy_Image (ximg, prev); |
| @@ -1449,7 +1484,7 @@ image_background_transparent (img, f, mask) | |||
| 1449 | } | 1484 | } |
| 1450 | 1485 | ||
| 1451 | img->background_transparent | 1486 | img->background_transparent |
| 1452 | = (four_corners_best (mask, img->width, img->height) == PIX_MASK_RETAIN); | 1487 | = (four_corners_best (mask, img->corners, img->width, img->height) == PIX_MASK_RETAIN); |
| 1453 | 1488 | ||
| 1454 | if (free_mask) | 1489 | if (free_mask) |
| 1455 | Destroy_Image (mask, prev); | 1490 | Destroy_Image (mask, prev); |
| @@ -5358,7 +5393,7 @@ x_build_heuristic_mask (f, img, how) | |||
| 5358 | } | 5393 | } |
| 5359 | 5394 | ||
| 5360 | if (use_img_background) | 5395 | if (use_img_background) |
| 5361 | bg = four_corners_best (ximg, img->width, img->height); | 5396 | bg = four_corners_best (ximg, img->corners, img->width, img->height); |
| 5362 | 5397 | ||
| 5363 | /* Set all bits in mask_img to 1 whose color in ximg is different | 5398 | /* Set all bits in mask_img to 1 whose color in ximg is different |
| 5364 | from the background color bg. */ | 5399 | from the background color bg. */ |
| @@ -7451,6 +7486,7 @@ tiff_load (f, img) | |||
| 7451 | 7486 | ||
| 7452 | static int gif_image_p P_ ((Lisp_Object object)); | 7487 | static int gif_image_p P_ ((Lisp_Object object)); |
| 7453 | static int gif_load P_ ((struct frame *f, struct image *img)); | 7488 | static int gif_load P_ ((struct frame *f, struct image *img)); |
| 7489 | static void gif_clear_image P_ ((struct frame *f, struct image *img)); | ||
| 7454 | 7490 | ||
| 7455 | /* The symbol `gif' identifying images of this type. */ | 7491 | /* The symbol `gif' identifying images of this type. */ |
| 7456 | 7492 | ||
| @@ -7499,10 +7535,22 @@ static struct image_type gif_type = | |||
| 7499 | &Qgif, | 7535 | &Qgif, |
| 7500 | gif_image_p, | 7536 | gif_image_p, |
| 7501 | gif_load, | 7537 | gif_load, |
| 7502 | x_clear_image, | 7538 | gif_clear_image, |
| 7503 | NULL | 7539 | NULL |
| 7504 | }; | 7540 | }; |
| 7505 | 7541 | ||
| 7542 | /* Free X resources of GIF image IMG which is used on frame F. */ | ||
| 7543 | |||
| 7544 | static void | ||
| 7545 | gif_clear_image (f, img) | ||
| 7546 | struct frame *f; | ||
| 7547 | struct image *img; | ||
| 7548 | { | ||
| 7549 | /* IMG->data.ptr_val may contain extension data. */ | ||
| 7550 | img->data.lisp_val = Qnil; | ||
| 7551 | x_clear_image (f, img); | ||
| 7552 | } | ||
| 7553 | |||
| 7506 | /* Return non-zero if OBJECT is a valid GIF image specification. */ | 7554 | /* Return non-zero if OBJECT is a valid GIF image specification. */ |
| 7507 | 7555 | ||
| 7508 | static int | 7556 | static int |
| @@ -7623,7 +7671,7 @@ gif_load (f, img) | |||
| 7623 | GifFileType *gif; | 7671 | GifFileType *gif; |
| 7624 | struct gcpro gcpro1; | 7672 | struct gcpro gcpro1; |
| 7625 | Lisp_Object image; | 7673 | Lisp_Object image; |
| 7626 | int ino, image_left, image_top, image_width, image_height; | 7674 | int ino, image_height, image_width; |
| 7627 | gif_memory_source memsrc; | 7675 | gif_memory_source memsrc; |
| 7628 | unsigned char *raster; | 7676 | unsigned char *raster; |
| 7629 | 7677 | ||
| @@ -7700,17 +7748,19 @@ gif_load (f, img) | |||
| 7700 | return 0; | 7748 | return 0; |
| 7701 | } | 7749 | } |
| 7702 | 7750 | ||
| 7703 | image_top = gif->SavedImages[ino].ImageDesc.Top; | 7751 | img->corners[TOP_CORNER] = gif->SavedImages[ino].ImageDesc.Top; |
| 7704 | image_left = gif->SavedImages[ino].ImageDesc.Left; | 7752 | img->corners[LEFT_CORNER] = gif->SavedImages[ino].ImageDesc.Left; |
| 7705 | image_width = gif->SavedImages[ino].ImageDesc.Width; | ||
| 7706 | image_height = gif->SavedImages[ino].ImageDesc.Height; | 7753 | image_height = gif->SavedImages[ino].ImageDesc.Height; |
| 7754 | img->corners[BOT_CORNER] = img->corners[TOP_CORNER] + image_height; | ||
| 7755 | image_width = gif->SavedImages[ino].ImageDesc.Width; | ||
| 7756 | img->corners[RIGHT_CORNER] = img->corners[LEFT_CORNER] + image_width; | ||
| 7707 | 7757 | ||
| 7708 | width = img->width = max (gif->SWidth, | 7758 | width = img->width = max (gif->SWidth, |
| 7709 | max (gif->Image.Left + gif->Image.Width, | 7759 | max (gif->Image.Left + gif->Image.Width, |
| 7710 | image_left + image_width)); | 7760 | img->corners[RIGHT_CORNER])); |
| 7711 | height = img->height = max (gif->SHeight, | 7761 | height = img->height = max (gif->SHeight, |
| 7712 | max (gif->Image.Top + gif->Image.Height, | 7762 | max (gif->Image.Top + gif->Image.Height, |
| 7713 | image_top + image_height)); | 7763 | img->corners[BOT_CORNER])); |
| 7714 | 7764 | ||
| 7715 | if (!check_image_size (f, width, height)) | 7765 | if (!check_image_size (f, width, height)) |
| 7716 | { | 7766 | { |
| @@ -7753,19 +7803,19 @@ gif_load (f, img) | |||
| 7753 | requires more than can be done here (see the gif89 spec, | 7803 | requires more than can be done here (see the gif89 spec, |
| 7754 | disposal methods). Let's simply assume that the part | 7804 | disposal methods). Let's simply assume that the part |
| 7755 | not covered by a sub-image is in the frame's background color. */ | 7805 | not covered by a sub-image is in the frame's background color. */ |
| 7756 | for (y = 0; y < image_top; ++y) | 7806 | for (y = 0; y < img->corners[TOP_CORNER]; ++y) |
| 7757 | for (x = 0; x < width; ++x) | 7807 | for (x = 0; x < width; ++x) |
| 7758 | XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f)); | 7808 | XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f)); |
| 7759 | 7809 | ||
| 7760 | for (y = image_top + image_height; y < height; ++y) | 7810 | for (y = img->corners[BOT_CORNER]; y < height; ++y) |
| 7761 | for (x = 0; x < width; ++x) | 7811 | for (x = 0; x < width; ++x) |
| 7762 | XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f)); | 7812 | XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f)); |
| 7763 | 7813 | ||
| 7764 | for (y = image_top; y < image_top + image_height; ++y) | 7814 | for (y = img->corners[TOP_CORNER]; y < img->corners[BOT_CORNER]; ++y) |
| 7765 | { | 7815 | { |
| 7766 | for (x = 0; x < image_left; ++x) | 7816 | for (x = 0; x < img->corners[LEFT_CORNER]; ++x) |
| 7767 | XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f)); | 7817 | XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f)); |
| 7768 | for (x = image_left + image_width; x < width; ++x) | 7818 | for (x = img->corners[RIGHT_CORNER]; x < width; ++x) |
| 7769 | XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f)); | 7819 | XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f)); |
| 7770 | } | 7820 | } |
| 7771 | 7821 | ||
| @@ -7795,8 +7845,8 @@ gif_load (f, img) | |||
| 7795 | for (x = 0; x < image_width; x++) | 7845 | for (x = 0; x < image_width; x++) |
| 7796 | { | 7846 | { |
| 7797 | int i = raster[(y * image_width) + x]; | 7847 | int i = raster[(y * image_width) + x]; |
| 7798 | XPutPixel (ximg, x + image_left, row + image_top, | 7848 | XPutPixel (ximg, x + img->corners[LEFT_CORNER], |
| 7799 | pixel_colors[i]); | 7849 | row + img->corners[TOP_CORNER], pixel_colors[i]); |
| 7800 | } | 7850 | } |
| 7801 | 7851 | ||
| 7802 | row += interlace_increment[pass]; | 7852 | row += interlace_increment[pass]; |
| @@ -7808,10 +7858,29 @@ gif_load (f, img) | |||
| 7808 | for (x = 0; x < image_width; ++x) | 7858 | for (x = 0; x < image_width; ++x) |
| 7809 | { | 7859 | { |
| 7810 | int i = raster[y * image_width + x]; | 7860 | int i = raster[y * image_width + x]; |
| 7811 | XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]); | 7861 | XPutPixel (ximg, x + img->corners[LEFT_CORNER], |
| 7862 | y + img->corners[TOP_CORNER], pixel_colors[i]); | ||
| 7812 | } | 7863 | } |
| 7813 | } | 7864 | } |
| 7814 | 7865 | ||
| 7866 | /* Save GIF image extension data for `image-extension-data'. | ||
| 7867 | Format is (count IMAGES FUNCTION "BYTES" ...). */ | ||
| 7868 | img->data.lisp_val = Qnil; | ||
| 7869 | if (gif->SavedImages[ino].ExtensionBlockCount > 0) | ||
| 7870 | { | ||
| 7871 | ExtensionBlock *ext = gif->SavedImages[ino].ExtensionBlocks; | ||
| 7872 | for (i = 0; i < gif->SavedImages[ino].ExtensionBlockCount; i++, ext++) | ||
| 7873 | /* Append (... FUNCTION "BYTES") */ | ||
| 7874 | img->data.lisp_val = Fcons (make_unibyte_string (ext->Bytes, ext->ByteCount), | ||
| 7875 | Fcons (make_number (ext->Function), | ||
| 7876 | img->data.lisp_val)); | ||
| 7877 | img->data.lisp_val = Fnreverse (img->data.lisp_val); | ||
| 7878 | } | ||
| 7879 | if (gif->ImageCount > 1) | ||
| 7880 | img->data.lisp_val = Fcons (Qcount, | ||
| 7881 | Fcons (make_number (gif->ImageCount), | ||
| 7882 | img->data.lisp_val)); | ||
| 7883 | |||
| 7815 | fn_DGifCloseFile (gif); | 7884 | fn_DGifCloseFile (gif); |
| 7816 | 7885 | ||
| 7817 | /* Maybe fill in the background field while we have ximg handy. */ | 7886 | /* Maybe fill in the background field while we have ximg handy. */ |
| @@ -8557,6 +8626,7 @@ non-numeric, there is no explicit limit on the size of images. */); | |||
| 8557 | defsubr (&Sclear_image_cache); | 8626 | defsubr (&Sclear_image_cache); |
| 8558 | defsubr (&Simage_size); | 8627 | defsubr (&Simage_size); |
| 8559 | defsubr (&Simage_mask_p); | 8628 | defsubr (&Simage_mask_p); |
| 8629 | defsubr (&Simage_extension_data); | ||
| 8560 | 8630 | ||
| 8561 | #if GLYPH_DEBUG | 8631 | #if GLYPH_DEBUG |
| 8562 | defsubr (&Simagep); | 8632 | defsubr (&Simagep); |