diff options
Diffstat (limited to 'src/image.c')
| -rw-r--r-- | src/image.c | 535 |
1 files changed, 534 insertions, 1 deletions
diff --git a/src/image.c b/src/image.c index 34d89d2e195..ae4bf2fd937 100644 --- a/src/image.c +++ b/src/image.c | |||
| @@ -583,7 +583,7 @@ Lisp_Object Qxbm; | |||
| 583 | 583 | ||
| 584 | Lisp_Object QCascent, QCmargin, QCrelief, Qcount, Qextension_data; | 584 | Lisp_Object QCascent, QCmargin, QCrelief, Qcount, Qextension_data; |
| 585 | Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask; | 585 | Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask; |
| 586 | Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask; | 586 | Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask, QCgeometry, QCcrop, QCrotation; |
| 587 | 587 | ||
| 588 | /* Other symbols. */ | 588 | /* Other symbols. */ |
| 589 | 589 | ||
| @@ -7342,6 +7342,510 @@ gif_load (struct frame *f, struct image *img) | |||
| 7342 | #endif /* HAVE_GIF */ | 7342 | #endif /* HAVE_GIF */ |
| 7343 | 7343 | ||
| 7344 | 7344 | ||
| 7345 | /*********************************************************************** | ||
| 7346 | imagemagick | ||
| 7347 | ***********************************************************************/ | ||
| 7348 | #if defined (HAVE_IMAGEMAGICK) | ||
| 7349 | Lisp_Object Vimagemagick_render_type; | ||
| 7350 | |||
| 7351 | /* The symbol `imagemagick' identifying images of this type. */ | ||
| 7352 | |||
| 7353 | Lisp_Object Qimagemagick; | ||
| 7354 | Lisp_Object Vimagemagick_render_type; | ||
| 7355 | |||
| 7356 | /* Indices of image specification fields in imagemagick_format, below. */ | ||
| 7357 | |||
| 7358 | enum imagemagick_keyword_index | ||
| 7359 | { | ||
| 7360 | IMAGEMAGICK_TYPE, | ||
| 7361 | IMAGEMAGICK_DATA, | ||
| 7362 | IMAGEMAGICK_FILE, | ||
| 7363 | IMAGEMAGICK_ASCENT, | ||
| 7364 | IMAGEMAGICK_MARGIN, | ||
| 7365 | IMAGEMAGICK_RELIEF, | ||
| 7366 | IMAGEMAGICK_ALGORITHM, | ||
| 7367 | IMAGEMAGICK_HEURISTIC_MASK, | ||
| 7368 | IMAGEMAGICK_MASK, | ||
| 7369 | IMAGEMAGICK_BACKGROUND, | ||
| 7370 | IMAGEMAGICK_HEIGHT, | ||
| 7371 | IMAGEMAGICK_WIDTH, | ||
| 7372 | IMAGEMAGICK_ROTATION, | ||
| 7373 | IMAGEMAGICK_CROP, | ||
| 7374 | IMAGEMAGICK_LAST | ||
| 7375 | }; | ||
| 7376 | |||
| 7377 | /* Vector of image_keyword structures describing the format | ||
| 7378 | of valid user-defined image specifications. */ | ||
| 7379 | |||
| 7380 | static struct image_keyword imagemagick_format[IMAGEMAGICK_LAST] = | ||
| 7381 | { | ||
| 7382 | {":type", IMAGE_SYMBOL_VALUE, 1}, | ||
| 7383 | {":data", IMAGE_STRING_VALUE, 0}, | ||
| 7384 | {":file", IMAGE_STRING_VALUE, 0}, | ||
| 7385 | {":ascent", IMAGE_ASCENT_VALUE, 0}, | ||
| 7386 | {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0}, | ||
| 7387 | {":relief", IMAGE_INTEGER_VALUE, 0}, | ||
| 7388 | {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | ||
| 7389 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | ||
| 7390 | {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | ||
| 7391 | {":background", IMAGE_STRING_OR_NIL_VALUE, 0}, | ||
| 7392 | {":height", IMAGE_INTEGER_VALUE, 0}, | ||
| 7393 | {":width", IMAGE_INTEGER_VALUE, 0}, | ||
| 7394 | {":rotation", IMAGE_NUMBER_VALUE, 0}, | ||
| 7395 | {":crop", IMAGE_DONT_CHECK_VALUE_TYPE, 0} | ||
| 7396 | }; | ||
| 7397 | /* Free X resources of imagemagick image IMG which is used on frame F. */ | ||
| 7398 | |||
| 7399 | static void | ||
| 7400 | imagemagick_clear_image (struct frame *f, | ||
| 7401 | struct image *img) | ||
| 7402 | { | ||
| 7403 | x_clear_image (f, img); | ||
| 7404 | } | ||
| 7405 | |||
| 7406 | |||
| 7407 | |||
| 7408 | /* Return non-zero if OBJECT is a valid IMAGEMAGICK image specification. Do | ||
| 7409 | this by calling parse_image_spec and supplying the keywords that | ||
| 7410 | identify the IMAGEMAGICK format. */ | ||
| 7411 | |||
| 7412 | static int | ||
| 7413 | imagemagick_image_p (Lisp_Object object) | ||
| 7414 | { | ||
| 7415 | struct image_keyword fmt[IMAGEMAGICK_LAST]; | ||
| 7416 | bcopy (imagemagick_format, fmt, sizeof fmt); | ||
| 7417 | |||
| 7418 | if (!parse_image_spec (object, fmt, IMAGEMAGICK_LAST, Qimagemagick)) | ||
| 7419 | return 0; | ||
| 7420 | |||
| 7421 | /* Must specify either the :data or :file keyword. */ | ||
| 7422 | return fmt[IMAGEMAGICK_FILE].count + fmt[IMAGEMAGICK_DATA].count == 1; | ||
| 7423 | } | ||
| 7424 | |||
| 7425 | /* The GIF library also defines DrawRectangle, but its never used in Emacs. | ||
| 7426 | Therefore rename the function so it doesnt collide with ImageMagick. */ | ||
| 7427 | #define DrawRectangle DrawRectangleGif | ||
| 7428 | #include <wand/MagickWand.h> | ||
| 7429 | |||
| 7430 | /* imagemagick_load_image is a helper function for imagemagick_load, | ||
| 7431 | which does the actual loading given contents and size, apart from | ||
| 7432 | frame and image structures, passed from imagemagick_load. | ||
| 7433 | |||
| 7434 | Uses librimagemagick to do most of the image processing. | ||
| 7435 | |||
| 7436 | non-zero when successful. | ||
| 7437 | */ | ||
| 7438 | |||
| 7439 | static int | ||
| 7440 | imagemagick_load_image (/* Pointer to emacs frame structure. */ | ||
| 7441 | struct frame *f, | ||
| 7442 | /* Pointer to emacs image structure. */ | ||
| 7443 | struct image *img, | ||
| 7444 | /* String containing the IMAGEMAGICK data to | ||
| 7445 | be parsed. */ | ||
| 7446 | unsigned char *contents, | ||
| 7447 | /* Size of data in bytes. */ | ||
| 7448 | unsigned int size, | ||
| 7449 | /* Filename, either pass filename or | ||
| 7450 | contents/size. */ | ||
| 7451 | unsigned char *filename) | ||
| 7452 | { | ||
| 7453 | size_t width; | ||
| 7454 | size_t height; | ||
| 7455 | |||
| 7456 | MagickBooleanType | ||
| 7457 | status; | ||
| 7458 | |||
| 7459 | XImagePtr ximg; | ||
| 7460 | Lisp_Object specified_bg; | ||
| 7461 | XColor background; | ||
| 7462 | int x; | ||
| 7463 | int y; | ||
| 7464 | |||
| 7465 | MagickWand *image_wand; | ||
| 7466 | MagickWand *ping_wand; | ||
| 7467 | PixelIterator *iterator; | ||
| 7468 | PixelWand **pixels; | ||
| 7469 | MagickPixelPacket pixel; | ||
| 7470 | Lisp_Object image; | ||
| 7471 | Lisp_Object value; | ||
| 7472 | Lisp_Object crop, geometry; | ||
| 7473 | long ino; | ||
| 7474 | int desired_width, desired_height; | ||
| 7475 | double rotation; | ||
| 7476 | int imagemagick_rendermethod; | ||
| 7477 | int pixelwidth; | ||
| 7478 | ImageInfo *image_info; | ||
| 7479 | ExceptionInfo *exception; | ||
| 7480 | Image * im_image; | ||
| 7481 | |||
| 7482 | |||
| 7483 | /* Handle image index for image types who can contain more than one | ||
| 7484 | image. Interface :index is same as for GIF. First we "ping" the | ||
| 7485 | image to see how many sub-images it contains. Pinging is faster | ||
| 7486 | than loading the image to find out things about it. */ | ||
| 7487 | image = image_spec_value (img->spec, QCindex, NULL); | ||
| 7488 | ino = INTEGERP (image) ? XFASTINT (image) : 0; | ||
| 7489 | ping_wand=NewMagickWand(); | ||
| 7490 | MagickSetResolution(ping_wand, 2, 2); | ||
| 7491 | if (filename != NULL) | ||
| 7492 | { | ||
| 7493 | status = MagickPingImage(ping_wand, filename); | ||
| 7494 | } | ||
| 7495 | else | ||
| 7496 | { | ||
| 7497 | status = MagickPingImageBlob(ping_wand, contents, size); | ||
| 7498 | } | ||
| 7499 | |||
| 7500 | if (ino >= MagickGetNumberImages(ping_wand)) | ||
| 7501 | { | ||
| 7502 | image_error ("Invalid image number `%s' in image `%s'", | ||
| 7503 | image, img->spec); | ||
| 7504 | UNGCPRO; | ||
| 7505 | return 0; | ||
| 7506 | } | ||
| 7507 | |||
| 7508 | if (MagickGetNumberImages(ping_wand) > 1) | ||
| 7509 | img->data.lisp_val = | ||
| 7510 | Fcons (Qcount, | ||
| 7511 | Fcons (make_number (MagickGetNumberImages(ping_wand)), | ||
| 7512 | img->data.lisp_val)); | ||
| 7513 | |||
| 7514 | DestroyMagickWand (ping_wand); | ||
| 7515 | /* Now, after pinging, we know how many images are inside the | ||
| 7516 | file. If its not a bundle, just one. */ | ||
| 7517 | |||
| 7518 | if (filename != NULL) | ||
| 7519 | { | ||
| 7520 | image_info=CloneImageInfo((ImageInfo *) NULL); | ||
| 7521 | (void) strcpy(image_info->filename, filename); | ||
| 7522 | image_info -> number_scenes = 1; | ||
| 7523 | image_info -> scene = ino; | ||
| 7524 | exception=AcquireExceptionInfo(); | ||
| 7525 | |||
| 7526 | im_image = ReadImage (image_info, exception); | ||
| 7527 | CatchException(exception); | ||
| 7528 | |||
| 7529 | image_wand = NewMagickWandFromImage(im_image); | ||
| 7530 | } | ||
| 7531 | else | ||
| 7532 | { | ||
| 7533 | image_wand = NewMagickWand(); | ||
| 7534 | status = MagickReadImageBlob(image_wand, contents, size); | ||
| 7535 | } | ||
| 7536 | image_error ("im read failed", Qnil, Qnil); | ||
| 7537 | if (status == MagickFalse) goto imagemagick_error; | ||
| 7538 | |||
| 7539 | /* If width and/or height is set in the display spec assume we want | ||
| 7540 | to scale to those values. if either h or w is unspecified, the | ||
| 7541 | unspecified should be calculated from the specified to preserve | ||
| 7542 | aspect ratio. */ | ||
| 7543 | |||
| 7544 | value = image_spec_value (img->spec, QCwidth, NULL); | ||
| 7545 | desired_width = (INTEGERP (value) ? XFASTINT (value) : -1); | ||
| 7546 | value = image_spec_value (img->spec, QCheight, NULL); | ||
| 7547 | desired_height = (INTEGERP (value) ? XFASTINT (value) : -1); | ||
| 7548 | |||
| 7549 | height = MagickGetImageHeight (image_wand); | ||
| 7550 | width = MagickGetImageWidth (image_wand); | ||
| 7551 | |||
| 7552 | if(desired_width != -1 && desired_height == -1) | ||
| 7553 | { | ||
| 7554 | /* w known, calculate h. */ | ||
| 7555 | desired_height = ( (double)desired_width / width ) * height; | ||
| 7556 | } | ||
| 7557 | if(desired_width == -1 && desired_height != -1) | ||
| 7558 | { | ||
| 7559 | /* h known, calculate w. */ | ||
| 7560 | desired_width = ( (double)desired_height / height ) * width; | ||
| 7561 | } | ||
| 7562 | if(desired_width != -1 && desired_height != -1) | ||
| 7563 | { | ||
| 7564 | status = MagickScaleImage(image_wand, desired_width, desired_height); | ||
| 7565 | if (status == MagickFalse) { | ||
| 7566 | image_error ("Imagemagick scale failed", Qnil, Qnil); | ||
| 7567 | goto imagemagick_error; | ||
| 7568 | } | ||
| 7569 | } | ||
| 7570 | |||
| 7571 | |||
| 7572 | /* crop behaves similar to image slicing in Emacs but is more memory | ||
| 7573 | efficient */ | ||
| 7574 | crop = image_spec_value (img->spec, QCcrop, NULL); | ||
| 7575 | |||
| 7576 | if(CONSP (crop)) | ||
| 7577 | { | ||
| 7578 | /* | ||
| 7579 | after some testing, it seems MagickCropImage is the fastest | ||
| 7580 | crop function in ImageMagick. This crop function seems to do | ||
| 7581 | less copying than the alternatives, but it still reads the | ||
| 7582 | entire image into memory before croping, which is aparently | ||
| 7583 | difficult to avoid when using imagemagick. */ | ||
| 7584 | |||
| 7585 | int w,h,x,y; | ||
| 7586 | w=XFASTINT(XCAR(crop)); | ||
| 7587 | h=XFASTINT(XCAR(XCDR(crop))); | ||
| 7588 | x=XFASTINT(XCAR(XCDR(XCDR(crop)))); | ||
| 7589 | y=XFASTINT(XCAR(XCDR(XCDR(XCDR(crop))))); | ||
| 7590 | MagickCropImage(image_wand, w,h, x,y); | ||
| 7591 | } | ||
| 7592 | |||
| 7593 | /* Furthermore :rotation. we need background color and angle for | ||
| 7594 | rotation. */ | ||
| 7595 | /* | ||
| 7596 | TODO background handling for rotation specified_bg = | ||
| 7597 | image_spec_value (img->spec, QCbackground, NULL); if (!STRINGP | ||
| 7598 | (specified_bg). */ | ||
| 7599 | value = image_spec_value (img->spec, QCrotation, NULL); | ||
| 7600 | if (FLOATP (value)) | ||
| 7601 | { | ||
| 7602 | PixelWand* background = NewPixelWand(); | ||
| 7603 | PixelSetColor (background, "#ffffff");/*TODO remove hardcode*/ | ||
| 7604 | |||
| 7605 | rotation = extract_float (value); | ||
| 7606 | |||
| 7607 | status = MagickRotateImage (image_wand, background, rotation); | ||
| 7608 | DestroyPixelWand (background); | ||
| 7609 | if (status == MagickFalse) | ||
| 7610 | { | ||
| 7611 | image_error ("Imagemagick image rotate failed", Qnil, Qnil); | ||
| 7612 | goto imagemagick_error; | ||
| 7613 | } | ||
| 7614 | } | ||
| 7615 | |||
| 7616 | /* Finaly we are done manipulating the image, figure out resulting | ||
| 7617 | width, height, and then transfer ownerwship to Emacs. */ | ||
| 7618 | height = MagickGetImageHeight (image_wand); | ||
| 7619 | width = MagickGetImageWidth (image_wand); | ||
| 7620 | if (status == MagickFalse) | ||
| 7621 | { | ||
| 7622 | image_error ("Imagemagick image get size failed", Qnil, Qnil); | ||
| 7623 | goto imagemagick_error; | ||
| 7624 | } | ||
| 7625 | |||
| 7626 | if (! check_image_size (f, width, height)) | ||
| 7627 | { | ||
| 7628 | image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil); | ||
| 7629 | goto imagemagick_error; | ||
| 7630 | } | ||
| 7631 | |||
| 7632 | /* We can now get a valid pixel buffer from the imagemagick file, if all | ||
| 7633 | went ok. */ | ||
| 7634 | |||
| 7635 | init_color_table (); | ||
| 7636 | imagemagick_rendermethod = (INTEGERP (Vimagemagick_render_type) | ||
| 7637 | ? XFASTINT (Vimagemagick_render_type) : 0); | ||
| 7638 | if (imagemagick_rendermethod == 0) | ||
| 7639 | { | ||
| 7640 | /* Try to create a x pixmap to hold the imagemagick pixmap. */ | ||
| 7641 | if (!x_create_x_image_and_pixmap (f, width, height, 0, | ||
| 7642 | &ximg, &img->pixmap)) | ||
| 7643 | { | ||
| 7644 | image_error("Imagemagick X bitmap allocation failure", Qnil, Qnil); | ||
| 7645 | goto imagemagick_error; | ||
| 7646 | } | ||
| 7647 | |||
| 7648 | /* Copy imagegmagick image to x with primitive yet robust pixel | ||
| 7649 | pusher loop. This has been tested a lot with many different | ||
| 7650 | images. */ | ||
| 7651 | |||
| 7652 | /* Copy pixels from the imagemagick image structure to the x image map. */ | ||
| 7653 | iterator = NewPixelIterator (image_wand); | ||
| 7654 | if ((iterator == (PixelIterator *) NULL)) | ||
| 7655 | { | ||
| 7656 | image_error ("Imagemagick pixel iterator creation failed", | ||
| 7657 | Qnil, Qnil); | ||
| 7658 | goto imagemagick_error; | ||
| 7659 | } | ||
| 7660 | |||
| 7661 | for (y = 0; y < (long) MagickGetImageHeight(image_wand); y++) | ||
| 7662 | { | ||
| 7663 | pixels = PixelGetNextIteratorRow (iterator, &width); | ||
| 7664 | if ((pixels == (PixelWand **) NULL)) | ||
| 7665 | break; | ||
| 7666 | for (x = 0; x < (long) width; x++) | ||
| 7667 | { | ||
| 7668 | PixelGetMagickColor (pixels[x], &pixel); | ||
| 7669 | XPutPixel (ximg, x, y, | ||
| 7670 | lookup_rgb_color (f, | ||
| 7671 | pixel.red, | ||
| 7672 | pixel.green, | ||
| 7673 | pixel.blue)); | ||
| 7674 | } | ||
| 7675 | } | ||
| 7676 | DestroyPixelIterator (iterator); | ||
| 7677 | } | ||
| 7678 | |||
| 7679 | if (imagemagick_rendermethod == 1) | ||
| 7680 | { | ||
| 7681 | /* Magicexportimage is normaly faster than pixelpushing. This | ||
| 7682 | method is also well tested. Some aspects of this method are | ||
| 7683 | ad-hoc and needs to be more researched. */ | ||
| 7684 | int imagedepth = 24;/*MagickGetImageDepth(image_wand);*/ | ||
| 7685 | char* exportdepth = imagedepth <= 8 ? "I" : "BGRP";/*"RGBP";*/ | ||
| 7686 | /* Try to create a x pixmap to hold the imagemagick pixmap. */ | ||
| 7687 | if (!x_create_x_image_and_pixmap (f, width, height, imagedepth, | ||
| 7688 | &ximg, &img->pixmap)){ | ||
| 7689 | image_error("Imagemagick X bitmap allocation failure", Qnil, Qnil); | ||
| 7690 | goto imagemagick_error; | ||
| 7691 | } | ||
| 7692 | |||
| 7693 | |||
| 7694 | /* Oddly, the below code doesnt seem to work:*/ | ||
| 7695 | /* switch(ximg->bitmap_unit){ */ | ||
| 7696 | /* case 8: */ | ||
| 7697 | /* pixelwidth=CharPixel; */ | ||
| 7698 | /* break; */ | ||
| 7699 | /* case 16: */ | ||
| 7700 | /* pixelwidth=ShortPixel; */ | ||
| 7701 | /* break; */ | ||
| 7702 | /* case 32: */ | ||
| 7703 | /* pixelwidth=LongPixel; */ | ||
| 7704 | /* break; */ | ||
| 7705 | /* } */ | ||
| 7706 | /* | ||
| 7707 | Here im just guessing the format of the bitmap. | ||
| 7708 | happens to work fine for: | ||
| 7709 | - bw djvu images | ||
| 7710 | on rgb display. | ||
| 7711 | seems about 3 times as fast as pixel pushing(not carefully measured) | ||
| 7712 | */ | ||
| 7713 | pixelwidth = CharPixel;/*??? TODO figure out*/ | ||
| 7714 | #ifdef HAVE_MAGICKEXPORTIMAGEPIXELS | ||
| 7715 | MagickExportImagePixels(image_wand, | ||
| 7716 | 0, 0, | ||
| 7717 | width, height, | ||
| 7718 | exportdepth, | ||
| 7719 | pixelwidth, | ||
| 7720 | /*&(img->pixmap));*/ | ||
| 7721 | ximg->data); | ||
| 7722 | #else | ||
| 7723 | image_error("You dont have MagickExportImagePixels, upgrade ImageMagick!", | ||
| 7724 | Qnil, Qnil); | ||
| 7725 | #endif | ||
| 7726 | } | ||
| 7727 | |||
| 7728 | |||
| 7729 | #ifdef COLOR_TABLE_SUPPORT | ||
| 7730 | /* Remember colors allocated for this image. */ | ||
| 7731 | img->colors = colors_in_color_table (&img->ncolors); | ||
| 7732 | free_color_table (); | ||
| 7733 | #endif /* COLOR_TABLE_SUPPORT */ | ||
| 7734 | |||
| 7735 | |||
| 7736 | img->width = width; | ||
| 7737 | img->height = height; | ||
| 7738 | |||
| 7739 | /* Put the image into the pixmap, then free the X image and its | ||
| 7740 | buffer. */ | ||
| 7741 | x_put_x_image (f, ximg, img->pixmap, width, height); | ||
| 7742 | x_destroy_x_image (ximg); | ||
| 7743 | |||
| 7744 | |||
| 7745 | /* Final cleanup. image_wand should be the only resource left. */ | ||
| 7746 | DestroyMagickWand (image_wand); | ||
| 7747 | |||
| 7748 | return 1; | ||
| 7749 | |||
| 7750 | imagemagick_error: | ||
| 7751 | /* TODO more cleanup. */ | ||
| 7752 | image_error ("Error parsing IMAGEMAGICK image `%s'", img->spec, Qnil); | ||
| 7753 | return 0; | ||
| 7754 | } | ||
| 7755 | |||
| 7756 | |||
| 7757 | /* Load IMAGEMAGICK image IMG for use on frame F. Value is non-zero if | ||
| 7758 | successful. this function will go into the imagemagick_type structure, and | ||
| 7759 | the prototype thus needs to be compatible with that structure. */ | ||
| 7760 | |||
| 7761 | static int | ||
| 7762 | imagemagick_load (struct frame *f, | ||
| 7763 | struct image *img) | ||
| 7764 | { | ||
| 7765 | int success_p = 0; | ||
| 7766 | Lisp_Object file_name; | ||
| 7767 | |||
| 7768 | /* If IMG->spec specifies a file name, create a non-file spec from it. */ | ||
| 7769 | file_name = image_spec_value (img->spec, QCfile, NULL); | ||
| 7770 | if (STRINGP (file_name)) | ||
| 7771 | { | ||
| 7772 | Lisp_Object file; | ||
| 7773 | unsigned char *contents; | ||
| 7774 | int size; | ||
| 7775 | struct gcpro gcpro1; | ||
| 7776 | |||
| 7777 | file = x_find_image_file (file_name); | ||
| 7778 | GCPRO1 (file); | ||
| 7779 | if (!STRINGP (file)) | ||
| 7780 | { | ||
| 7781 | image_error ("Cannot find image file `%s'", file_name, Qnil); | ||
| 7782 | UNGCPRO; | ||
| 7783 | return 0; | ||
| 7784 | } | ||
| 7785 | success_p = imagemagick_load_image (f, img, 0, 0, SDATA(file_name)); | ||
| 7786 | UNGCPRO; | ||
| 7787 | } | ||
| 7788 | /* Else its not a file, its a lisp object. Load the image from a | ||
| 7789 | lisp object rather than a file. */ | ||
| 7790 | else | ||
| 7791 | { | ||
| 7792 | Lisp_Object data; | ||
| 7793 | |||
| 7794 | data = image_spec_value (img->spec, QCdata, NULL); | ||
| 7795 | success_p = imagemagick_load_image (f, img, SDATA (data), | ||
| 7796 | SBYTES (data), NULL); | ||
| 7797 | } | ||
| 7798 | |||
| 7799 | return success_p; | ||
| 7800 | } | ||
| 7801 | |||
| 7802 | /* Structure describing the image type `imagemagick'. Its the same | ||
| 7803 | type of structure defined for all image formats, handled by Emacs | ||
| 7804 | image functions. See struct image_type in dispextern.h. */ | ||
| 7805 | |||
| 7806 | static struct image_type imagemagick_type = | ||
| 7807 | { | ||
| 7808 | /* An identifier showing that this is an image structure for the | ||
| 7809 | IMAGEMAGICK format. */ | ||
| 7810 | &Qimagemagick, | ||
| 7811 | /* Handle to a function that can be used to identify a IMAGEMAGICK | ||
| 7812 | file. */ | ||
| 7813 | imagemagick_image_p, | ||
| 7814 | /* Handle to function used to load a IMAGEMAGICK file. */ | ||
| 7815 | imagemagick_load, | ||
| 7816 | /* Handle to function to free resources for IMAGEMAGICK. */ | ||
| 7817 | imagemagick_clear_image, | ||
| 7818 | /* An internal field to link to the next image type in a list of | ||
| 7819 | image types, will be filled in when registering the format. */ | ||
| 7820 | NULL | ||
| 7821 | }; | ||
| 7822 | |||
| 7823 | |||
| 7824 | |||
| 7825 | |||
| 7826 | DEFUN ("imagemagick-types", Fimagemagick_types, Simagemagick_types, 0, 0, 0, | ||
| 7827 | doc: /* Return image file types supported by ImageMagick. | ||
| 7828 | Since ImageMagick recognizes a lot of file-types that clash with Emacs, | ||
| 7829 | such as .c, we want to be able to alter the list at the lisp level. */) | ||
| 7830 | (void) | ||
| 7831 | { | ||
| 7832 | Lisp_Object typelist = Qnil; | ||
| 7833 | size_t numf; | ||
| 7834 | ExceptionInfo ex; | ||
| 7835 | char** imtypes = GetMagickList ("*", &numf, &ex); | ||
| 7836 | int i; | ||
| 7837 | Lisp_Object Qimagemagicktype; | ||
| 7838 | for (i = 0; i < numf; i++) | ||
| 7839 | { | ||
| 7840 | Qimagemagicktype = intern (imtypes[i]); | ||
| 7841 | typelist = Fcons (Qimagemagicktype, typelist); | ||
| 7842 | } | ||
| 7843 | return typelist; | ||
| 7844 | } | ||
| 7845 | |||
| 7846 | #endif /* defined (HAVE_IMAGEMAGICK) */ | ||
| 7847 | |||
| 7848 | |||
| 7345 | 7849 | ||
| 7346 | /*********************************************************************** | 7850 | /*********************************************************************** |
| 7347 | SVG | 7851 | SVG |
| @@ -8117,6 +8621,15 @@ of `image-library-alist', which see). */) | |||
| 8117 | return CHECK_LIB_AVAILABLE (&svg_type, init_svg_functions, libraries); | 8621 | return CHECK_LIB_AVAILABLE (&svg_type, init_svg_functions, libraries); |
| 8118 | #endif | 8622 | #endif |
| 8119 | 8623 | ||
| 8624 | #if defined (HAVE_IMAGEMAGICK) | ||
| 8625 | if (EQ (type, Qimagemagick)){ | ||
| 8626 | /* MagickWandGenesis() initalizes the imagemagick library. */ | ||
| 8627 | MagickWandGenesis(); | ||
| 8628 | return CHECK_LIB_AVAILABLE (&imagemagick_type, init_imagemagick_functions, | ||
| 8629 | libraries); | ||
| 8630 | } | ||
| 8631 | #endif | ||
| 8632 | |||
| 8120 | #ifdef HAVE_GHOSTSCRIPT | 8633 | #ifdef HAVE_GHOSTSCRIPT |
| 8121 | if (EQ (type, Qpostscript)) | 8634 | if (EQ (type, Qpostscript)) |
| 8122 | return CHECK_LIB_AVAILABLE (&gs_type, init_gs_functions, libraries); | 8635 | return CHECK_LIB_AVAILABLE (&gs_type, init_gs_functions, libraries); |
| @@ -8202,6 +8715,12 @@ non-numeric, there is no explicit limit on the size of images. */); | |||
| 8202 | staticpro (&QCheuristic_mask); | 8715 | staticpro (&QCheuristic_mask); |
| 8203 | QCindex = intern_c_string (":index"); | 8716 | QCindex = intern_c_string (":index"); |
| 8204 | staticpro (&QCindex); | 8717 | staticpro (&QCindex); |
| 8718 | QCgeometry = intern (":geometry"); | ||
| 8719 | staticpro (&QCgeometry); | ||
| 8720 | QCcrop = intern (":crop"); | ||
| 8721 | staticpro (&QCcrop); | ||
| 8722 | QCrotation = intern (":rotation"); | ||
| 8723 | staticpro (&QCrotation); | ||
| 8205 | QCmatrix = intern_c_string (":matrix"); | 8724 | QCmatrix = intern_c_string (":matrix"); |
| 8206 | staticpro (&QCmatrix); | 8725 | staticpro (&QCmatrix); |
| 8207 | QCcolor_adjustment = intern_c_string (":color-adjustment"); | 8726 | QCcolor_adjustment = intern_c_string (":color-adjustment"); |
| @@ -8262,6 +8781,12 @@ non-numeric, there is no explicit limit on the size of images. */); | |||
| 8262 | ADD_IMAGE_TYPE (Qpng); | 8781 | ADD_IMAGE_TYPE (Qpng); |
| 8263 | #endif | 8782 | #endif |
| 8264 | 8783 | ||
| 8784 | #if defined (HAVE_IMAGEMAGICK) | ||
| 8785 | Qimagemagick = intern ("imagemagick"); | ||
| 8786 | staticpro (&Qimagemagick); | ||
| 8787 | ADD_IMAGE_TYPE (Qimagemagick); | ||
| 8788 | #endif | ||
| 8789 | |||
| 8265 | #if defined (HAVE_RSVG) | 8790 | #if defined (HAVE_RSVG) |
| 8266 | Qsvg = intern_c_string ("svg"); | 8791 | Qsvg = intern_c_string ("svg"); |
| 8267 | staticpro (&Qsvg); | 8792 | staticpro (&Qsvg); |
| @@ -8278,6 +8803,9 @@ non-numeric, there is no explicit limit on the size of images. */); | |||
| 8278 | #endif /* HAVE_RSVG */ | 8803 | #endif /* HAVE_RSVG */ |
| 8279 | 8804 | ||
| 8280 | defsubr (&Sinit_image_library); | 8805 | defsubr (&Sinit_image_library); |
| 8806 | #ifdef HAVE_IMAGEMAGICK | ||
| 8807 | defsubr (&Simagemagick_types); | ||
| 8808 | #endif | ||
| 8281 | defsubr (&Sclear_image_cache); | 8809 | defsubr (&Sclear_image_cache); |
| 8282 | defsubr (&Simage_flush); | 8810 | defsubr (&Simage_flush); |
| 8283 | defsubr (&Simage_size); | 8811 | defsubr (&Simage_size); |
| @@ -8308,6 +8836,11 @@ The value can also be nil, meaning the cache is never cleared. | |||
| 8308 | 8836 | ||
| 8309 | The function `clear-image-cache' disregards this variable. */); | 8837 | The function `clear-image-cache' disregards this variable. */); |
| 8310 | Vimage_cache_eviction_delay = make_number (300); | 8838 | Vimage_cache_eviction_delay = make_number (300); |
| 8839 | #ifdef HAVE_IMAGEMAGICK | ||
| 8840 | DEFVAR_LISP ("imagemagick-render-type", &Vimagemagick_render_type, | ||
| 8841 | doc: /* Choose between ImageMagick render methods. */); | ||
| 8842 | #endif | ||
| 8843 | |||
| 8311 | } | 8844 | } |
| 8312 | 8845 | ||
| 8313 | void | 8846 | void |