aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Rumney2003-01-25 15:14:16 +0000
committerJason Rumney2003-01-25 15:14:16 +0000
commit54eefef1cfc4083f5407860af480ca7727f3b737 (patch)
treea1a0ae0592d781eb9ebcf3ec286bbdca123a57ac
parentd6f9ff152a19d0359a108088200fcbdaa0da5b3b (diff)
downloademacs-54eefef1cfc4083f5407860af480ca7727f3b737.tar.gz
emacs-54eefef1cfc4083f5407860af480ca7727f3b737.zip
(XPutPixel): Handle monochrome images; used for masks.
[HAVE_PNG]: Sync with xfns.c version. (png_load): Adjust colors for Windows. Use Windows bitmaps. Disable color table lookups.
-rw-r--r--src/ChangeLog7
-rw-r--r--src/w32fns.c178
2 files changed, 109 insertions, 76 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index b7c833928ba..bc02917930c 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,10 @@
12003-01-25 Jason Rumney <jasonr@gnu.org>
2
3 * w32fns.c (XPutPixel): Handle monochrome images; used for masks.
4 [HAVE_PNG]: Sync with xfns.c version.
5 (png_load): Adjust colors for Windows. Use Windows
6 bitmaps. Disable color table lookups.
7
12003-01-24 Andreas Schwab <schwab@suse.de> 82003-01-24 Andreas Schwab <schwab@suse.de>
2 9
3 * minibuf.c (Fminibuffer_message): Verify type of parameter. 10 * minibuf.c (Fminibuffer_message): Verify type of parameter.
diff --git a/src/w32fns.c b/src/w32fns.c
index a1fa27cf742..1e54a07be72 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -10812,24 +10812,40 @@ static void XPutPixel (ximg, x, y, color)
10812{ 10812{
10813 int width = ximg->info.bmiHeader.biWidth; 10813 int width = ximg->info.bmiHeader.biWidth;
10814 int height = ximg->info.bmiHeader.biHeight; 10814 int height = ximg->info.bmiHeader.biHeight;
10815 int rowbytes = width * 3;
10816 unsigned char * pixel; 10815 unsigned char * pixel;
10817 10816
10818 /* Don't support putting pixels in images with palettes. */ 10817 /* True color images. */
10819 xassert (ximg->info.bmiHeader.biBitCount == 24); 10818 if (ximg->info.bmiHeader.biBitCount == 24)
10820 10819 {
10821 /* Ensure scanlines are aligned on 4 byte boundaries. */ 10820 int rowbytes = width * 3;
10822 if (rowbytes % 4) 10821 /* Ensure scanlines are aligned on 4 byte boundaries. */
10823 rowbytes += 4 - (rowbytes % 4); 10822 if (rowbytes % 4)
10824 10823 rowbytes += 4 - (rowbytes % 4);
10825 pixel = ximg->data + y * rowbytes + x * 3; 10824
10826 /* Windows bitmaps are in BGR order. */ 10825 pixel = ximg->data + y * rowbytes + x * 3;
10827 *pixel = GetBValue (color); 10826 /* Windows bitmaps are in BGR order. */
10828 *(pixel + 1) = GetGValue (color); 10827 *pixel = GetBValue (color);
10829 *(pixel + 2) = GetRValue (color); 10828 *(pixel + 1) = GetGValue (color);
10829 *(pixel + 2) = GetRValue (color);
10830 }
10831 /* Monochrome images. */
10832 else if (ximg->info.bmiHeader.biBitCount == 1)
10833 {
10834 int rowbytes = width / 8;
10835 /* Ensure scanlines are aligned on 4 byte boundaries. */
10836 if (rowbytes % 4)
10837 rowbytes += 4 - (rowbytes % 4);
10838 pixel = ximg->data + y * rowbytes + x / 8;
10839 /* Filter out palette info. */
10840 if (color & 0x00ffffff)
10841 *pixel = *pixel | (1 << x % 8);
10842 else
10843 *pixel = *pixel & ~(1 << x % 8);
10844 }
10845 else
10846 image_error ("XPutPixel: palette image not supported.", NULL, Qnil);
10830} 10847}
10831 10848
10832
10833/* Create IMG->pixmap from an array COLORS of XColor structures, whose 10849/* Create IMG->pixmap from an array COLORS of XColor structures, whose
10834 RGB members are set. F is the frame on which this all happens. 10850 RGB members are set. F is the frame on which this all happens.
10835 COLORS will be freed; an existing IMG->pixmap will be freed, too. */ 10851 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
@@ -11165,7 +11181,7 @@ x_build_heuristic_mask (f, img, how)
11165 image_background_transparent (img, f, img_dc); 11181 image_background_transparent (img, f, img_dc);
11166 11182
11167 /* Put mask_img into img->mask. */ 11183 /* Put mask_img into img->mask. */
11168 x_destroy_x_image (mask_img); 11184 x_destroy_x_image ((XImage *)mask_img);
11169 SelectObject (img_dc, prev); 11185 SelectObject (img_dc, prev);
11170 DeleteDC (img_dc); 11186 DeleteDC (img_dc);
11171 11187
@@ -11618,7 +11634,7 @@ png_image_p (object)
11618{ 11634{
11619 struct image_keyword fmt[PNG_LAST]; 11635 struct image_keyword fmt[PNG_LAST];
11620 bcopy (png_format, fmt, sizeof fmt); 11636 bcopy (png_format, fmt, sizeof fmt);
11621 11637
11622 if (!parse_image_spec (object, fmt, PNG_LAST, Qpng)) 11638 if (!parse_image_spec (object, fmt, PNG_LAST, Qpng))
11623 return 0; 11639 return 0;
11624 11640
@@ -11675,7 +11691,7 @@ png_read_from_memory (png_ptr, data, length)
11675 11691
11676 if (length > tbr->len - tbr->index) 11692 if (length > tbr->len - tbr->index)
11677 png_error (png_ptr, "Read error"); 11693 png_error (png_ptr, "Read error");
11678 11694
11679 bcopy (tbr->bytes + tbr->index, data, length); 11695 bcopy (tbr->bytes + tbr->index, data, length);
11680 tbr->index = tbr->index + length; 11696 tbr->index = tbr->index + length;
11681} 11697}
@@ -11697,14 +11713,13 @@ png_load (f, img)
11697 png_info *info_ptr = NULL, *end_info = NULL; 11713 png_info *info_ptr = NULL, *end_info = NULL;
11698 FILE *volatile fp = NULL; 11714 FILE *volatile fp = NULL;
11699 png_byte sig[8]; 11715 png_byte sig[8];
11700 png_byte *volatile pixels = NULL; 11716 png_byte * volatile pixels = NULL;
11701 png_byte **volatile rows = NULL; 11717 png_byte ** volatile rows = NULL;
11702 png_uint_32 width, height; 11718 png_uint_32 width, height;
11703 int bit_depth, color_type, interlace_type; 11719 int bit_depth, color_type, interlace_type;
11704 png_byte channels; 11720 png_byte channels;
11705 png_uint_32 row_bytes; 11721 png_uint_32 row_bytes;
11706 int transparent_p; 11722 int transparent_p;
11707 char *gamma_str;
11708 double screen_gamma, image_gamma; 11723 double screen_gamma, image_gamma;
11709 int intent; 11724 int intent;
11710 struct png_memory_storage tbr; /* Data to be read */ 11725 struct png_memory_storage tbr; /* Data to be read */
@@ -11719,31 +11734,31 @@ png_load (f, img)
11719 { 11734 {
11720 file = x_find_image_file (specified_file); 11735 file = x_find_image_file (specified_file);
11721 if (!STRINGP (file)) 11736 if (!STRINGP (file))
11722 { 11737 {
11723 image_error ("Cannot find image file `%s'", specified_file, Qnil); 11738 image_error ("Cannot find image file `%s'", specified_file, Qnil);
11724 UNGCPRO; 11739 UNGCPRO;
11725 return 0; 11740 return 0;
11726 } 11741 }
11727 11742
11728 /* Open the image file. */ 11743 /* Open the image file. */
11729 fp = fopen (SDATA (file), "rb"); 11744 fp = fopen (SDATA (file), "rb");
11730 if (!fp) 11745 if (!fp)
11731 { 11746 {
11732 image_error ("Cannot open image file `%s'", file, Qnil); 11747 image_error ("Cannot open image file `%s'", file, Qnil);
11733 UNGCPRO; 11748 UNGCPRO;
11734 fclose (fp); 11749 fclose (fp);
11735 return 0; 11750 return 0;
11736 } 11751 }
11737 11752
11738 /* Check PNG signature. */ 11753 /* Check PNG signature. */
11739 if (fread (sig, 1, sizeof sig, fp) != sizeof sig 11754 if (fread (sig, 1, sizeof sig, fp) != sizeof sig
11740 || !png_check_sig (sig, sizeof sig)) 11755 || !png_check_sig (sig, sizeof sig))
11741 { 11756 {
11742 image_error ("Not a PNG file:` %s'", file, Qnil); 11757 image_error ("Not a PNG file: `%s'", file, Qnil);
11743 UNGCPRO; 11758 UNGCPRO;
11744 fclose (fp); 11759 fclose (fp);
11745 return 0; 11760 return 0;
11746 } 11761 }
11747 } 11762 }
11748 else 11763 else
11749 { 11764 {
@@ -11818,14 +11833,14 @@ png_load (f, img)
11818 png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 11833 png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
11819 &interlace_type, NULL, NULL); 11834 &interlace_type, NULL, NULL);
11820 11835
11821 /* If image contains simply transparency data, we prefer to 11836 /* If image contains simply transparency data, we prefer to
11822 construct a clipping mask. */ 11837 construct a clipping mask. */
11823 if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) 11838 if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
11824 transparent_p = 1; 11839 transparent_p = 1;
11825 else 11840 else
11826 transparent_p = 0; 11841 transparent_p = 0;
11827 11842
11828 /* This function is easier to write if we only have to handle 11843 /* This function is easier to write if we only have to handle
11829 one data format: RGB or RGBA with 8 bits per channel. Let's 11844 one data format: RGB or RGBA with 8 bits per channel. Let's
11830 transform other formats into that format. */ 11845 transform other formats into that format. */
11831 11846
@@ -11838,39 +11853,37 @@ png_load (f, img)
11838 png_set_expand (png_ptr); 11853 png_set_expand (png_ptr);
11839 11854
11840 /* Convert grayscale images to RGB. */ 11855 /* Convert grayscale images to RGB. */
11841 if (color_type == PNG_COLOR_TYPE_GRAY 11856 if (color_type == PNG_COLOR_TYPE_GRAY
11842 || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) 11857 || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
11843 png_set_gray_to_rgb (png_ptr); 11858 png_set_gray_to_rgb (png_ptr);
11844 11859
11845 /* The value 2.2 is a guess for PC monitors from PNG example.c. */ 11860 screen_gamma = (f->gamma ? 1 / f->gamma / 0.45455 : 2.2);
11846 gamma_str = getenv ("SCREEN_GAMMA");
11847 screen_gamma = gamma_str ? atof (gamma_str) : 2.2;
11848 11861
11862#if 0 /* Avoid double gamma correction for PNG images. */
11849 /* Tell the PNG lib to handle gamma correction for us. */ 11863 /* Tell the PNG lib to handle gamma correction for us. */
11850
11851#if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED) 11864#if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
11852 if (png_get_sRGB (png_ptr, info_ptr, &intent)) 11865 if (png_get_sRGB (png_ptr, info_ptr, &intent))
11853 /* There is a special chunk in the image specifying the gamma. */ 11866 /* The libpng documentation says this is right in this case. */
11854 png_set_sRGB (png_ptr, info_ptr, intent); 11867 png_set_gamma (png_ptr, screen_gamma, 0.45455);
11855 else 11868 else
11856#endif 11869#endif
11857 if (png_get_gAMA (png_ptr, info_ptr, &image_gamma)) 11870 if (png_get_gAMA (png_ptr, info_ptr, &image_gamma))
11858 /* Image contains gamma information. */ 11871 /* Image contains gamma information. */
11859 png_set_gamma (png_ptr, screen_gamma, image_gamma); 11872 png_set_gamma (png_ptr, screen_gamma, image_gamma);
11860 else 11873 else
11861 /* Use a default of 0.5 for the image gamma. */ 11874 /* Use the standard default for the image gamma. */
11862 png_set_gamma (png_ptr, screen_gamma, 0.5); 11875 png_set_gamma (png_ptr, screen_gamma, 0.45455);
11876#endif /* if 0 */
11863 11877
11864 /* Handle alpha channel by combining the image with a background 11878 /* Handle alpha channel by combining the image with a background
11865 color. Do this only if a real alpha channel is supplied. For 11879 color. Do this only if a real alpha channel is supplied. For
11866 simple transparency, we prefer a clipping mask. */ 11880 simple transparency, we prefer a clipping mask. */
11867 if (!transparent_p) 11881 if (!transparent_p)
11868 { 11882 {
11869 png_color_16 *image_background; 11883 png_color_16 *image_bg;
11870 Lisp_Object specified_bg 11884 Lisp_Object specified_bg
11871 = image_spec_value (img->spec, QCbackground, NULL); 11885 = image_spec_value (img->spec, QCbackground, NULL);
11872 11886
11873
11874 if (STRINGP (specified_bg)) 11887 if (STRINGP (specified_bg))
11875 /* The user specified `:background', use that. */ 11888 /* The user specified `:background', use that. */
11876 { 11889 {
@@ -11880,36 +11893,38 @@ png_load (f, img)
11880 png_color_16 user_bg; 11893 png_color_16 user_bg;
11881 11894
11882 bzero (&user_bg, sizeof user_bg); 11895 bzero (&user_bg, sizeof user_bg);
11883 user_bg.red = color.red; 11896 user_bg.red = 256 * GetRValue (color);
11884 user_bg.green = color.green; 11897 user_bg.green = 256 * GetGValue (color);
11885 user_bg.blue = color.blue; 11898 user_bg.blue = 256 * GetBValue (color);
11886 11899
11887 png_set_background (png_ptr, &user_bg, 11900 png_set_background (png_ptr, &user_bg,
11888 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); 11901 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
11889 } 11902 }
11890 } 11903 }
11891 else if (png_get_bKGD (png_ptr, info_ptr, &image_background)) 11904 else if (png_get_bKGD (png_ptr, info_ptr, &image_bg))
11892 /* Image contains a background color with which to 11905 /* Image contains a background color with which to
11893 combine the image. */ 11906 combine the image. */
11894 png_set_background (png_ptr, image_background, 11907 png_set_background (png_ptr, image_bg,
11895 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); 11908 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
11896 else 11909 else
11897 { 11910 {
11898 /* Image does not contain a background color with which 11911 /* Image does not contain a background color with which
11899 to combine the image data via an alpha channel. Use 11912 to combine the image data via an alpha channel. Use
11900 the frame's background instead. */ 11913 the frame's background instead. */
11901 XColor color; 11914 COLORREF color;
11902 Colormap cmap;
11903 png_color_16 frame_background; 11915 png_color_16 frame_background;
11916 color = FRAME_BACKGROUND_PIXEL (f);
11917#if 0 /* TODO : Colormap support. */
11918 Colormap cmap;
11904 11919
11905 cmap = FRAME_X_COLORMAP (f); 11920 cmap = FRAME_X_COLORMAP (f);
11906 color.pixel = FRAME_BACKGROUND_PIXEL (f);
11907 x_query_color (f, &color); 11921 x_query_color (f, &color);
11922#endif
11908 11923
11909 bzero (&frame_background, sizeof frame_background); 11924 bzero (&frame_background, sizeof frame_background);
11910 frame_background.red = color.red; 11925 frame_background.red = 256 * GetRValue (color);
11911 frame_background.green = color.green; 11926 frame_background.green = 256 * GetGValue (color);
11912 frame_background.blue = color.blue; 11927 frame_background.blue = 256 * GetBValue (color);
11913 11928
11914 png_set_background (png_ptr, &frame_background, 11929 png_set_background (png_ptr, &frame_background,
11915 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); 11930 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
@@ -11944,12 +11959,12 @@ png_load (f, img)
11944 fclose (fp); 11959 fclose (fp);
11945 fp = NULL; 11960 fp = NULL;
11946 } 11961 }
11947 11962
11948 /* Create the X image and pixmap. */ 11963 /* Create the X image and pixmap. */
11949 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, 11964 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
11950 &img->pixmap)) 11965 &img->pixmap))
11951 goto error; 11966 goto error;
11952 11967
11953 /* Create an image and pixmap serving as mask if the PNG image 11968 /* Create an image and pixmap serving as mask if the PNG image
11954 contains an alpha channel. */ 11969 contains an alpha channel. */
11955 if (channels == 4 11970 if (channels == 4
@@ -11958,13 +11973,14 @@ png_load (f, img)
11958 &mask_img, &img->mask)) 11973 &mask_img, &img->mask))
11959 { 11974 {
11960 x_destroy_x_image (ximg); 11975 x_destroy_x_image (ximg);
11961 XFreePixmap (FRAME_W32_DISPLAY (f), img->pixmap); 11976 DeleteObject (img->pixmap);
11962 img->pixmap = 0; 11977 img->pixmap = 0;
11963 goto error; 11978 goto error;
11964 } 11979 }
11965
11966 /* Fill the X image and mask from PNG data. */ 11980 /* Fill the X image and mask from PNG data. */
11981#if 0 /* TODO: Color tables. */
11967 init_color_table (); 11982 init_color_table ();
11983#endif
11968 11984
11969 for (y = 0; y < height; ++y) 11985 for (y = 0; y < height; ++y)
11970 { 11986 {
@@ -11974,22 +11990,25 @@ png_load (f, img)
11974 { 11990 {
11975 unsigned r, g, b; 11991 unsigned r, g, b;
11976 11992
11977 r = *p++ << 8; 11993 r = *p++;
11978 g = *p++ << 8; 11994 g = *p++;
11979 b = *p++ << 8; 11995 b = *p++;
11996#if 0 /* TODO: Color tables. */
11980 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b)); 11997 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
11981 11998#else
11999 XPutPixel (ximg, x, y, PALETTERGB (r, g, b));
12000#endif
11982 /* An alpha channel, aka mask channel, associates variable 12001 /* An alpha channel, aka mask channel, associates variable
11983 transparency with an image. Where other image formats 12002 transparency with an image. Where other image formats
11984 support binary transparency---fully transparent or fully 12003 support binary transparency---fully transparent or fully
11985 opaque---PNG allows up to 254 levels of partial transparency. 12004 opaque---PNG allows up to 254 levels of partial transparency.
11986 The PNG library implements partial transparency by combining 12005 The PNG library implements partial transparency by combining
11987 the image with a specified background color. 12006 the image with a specified background color.
11988 12007
11989 I'm not sure how to handle this here nicely: because the 12008 I'm not sure how to handle this here nicely: because the
11990 background on which the image is displayed may change, for 12009 background on which the image is displayed may change, for
11991 real alpha channel support, it would be necessary to create 12010 real alpha channel support, it would be necessary to create
11992 a new image for each possible background. 12011 a new image for each possible background.
11993 12012
11994 What I'm doing now is that a mask is created if we have 12013 What I'm doing now is that a mask is created if we have
11995 boolean transparency information. Otherwise I'm using 12014 boolean transparency information. Otherwise I'm using
@@ -12011,14 +12030,21 @@ png_load (f, img)
12011 png_color_16 *bg; 12030 png_color_16 *bg;
12012 if (png_get_bKGD (png_ptr, info_ptr, &bg)) 12031 if (png_get_bKGD (png_ptr, info_ptr, &bg))
12013 { 12032 {
12033#if 0 /* TODO: Color tables. */
12014 img->background = lookup_rgb_color (f, bg->red, bg->green, bg->blue); 12034 img->background = lookup_rgb_color (f, bg->red, bg->green, bg->blue);
12035#else
12036 img->background = PALETTERGB (bg->red / 256, bg->green / 256,
12037 bg->blue / 256);
12038#endif
12015 img->background_valid = 1; 12039 img->background_valid = 1;
12016 } 12040 }
12017 } 12041 }
12018 12042
12043#if 0 /* TODO: Color tables. */
12019 /* Remember colors allocated for this image. */ 12044 /* Remember colors allocated for this image. */
12020 img->colors = colors_in_color_table (&img->ncolors); 12045 img->colors = colors_in_color_table (&img->ncolors);
12021 free_color_table (); 12046 free_color_table ();
12047#endif
12022 12048
12023 /* Clean up. */ 12049 /* Clean up. */
12024 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info); 12050 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);