From 50e63083886d6b6cd86e893c99211e114b7225f9 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Fri, 1 Feb 2002 23:43:07 +0000 Subject: [PATCH] Merge 16- and 32-bit ico support from the stable branch. (#61179) * io-ico.c: Merge 16- and 32-bit ico support from the stable branch. (#61179) * io-gif.c: Recomposite all images if the animation size changes while loading. (#70055) * gdk-pixbuf.c (gdk-pixbuf-fill): Make it work for subpixbufs. (#70055) --- gdk-pixbuf/ChangeLog | 11 +++++ gdk-pixbuf/gdk-pixbuf.c | 25 +++++----- gdk-pixbuf/io-gif.c | 11 +++++ gdk-pixbuf/io-ico.c | 106 ++++++++++++++++++++++++++++++++++------ 4 files changed, 127 insertions(+), 26 deletions(-) diff --git a/gdk-pixbuf/ChangeLog b/gdk-pixbuf/ChangeLog index 3853731e6b..eb89d95db8 100644 --- a/gdk-pixbuf/ChangeLog +++ b/gdk-pixbuf/ChangeLog @@ -1,3 +1,14 @@ +2002-02-01 Matthias Clasen + + * io-ico.c: Merge 16- and 32-bit ico support from the stable + branch. (#61179) + + * io-gif.c: Recomposite all images if the animation size changes + while loading. (#70055) + + * gdk-pixbuf.c (gdk-pixbuf-fill): Make it work for subpixbufs. + (#70055) + Sat Jan 19 20:49:20 2002 Manish Singh * io-jpeg.c, io-png.c: Made sure all the error cases involving diff --git a/gdk-pixbuf/gdk-pixbuf.c b/gdk-pixbuf/gdk-pixbuf.c index 5928ae0dfb..93c4c6db2c 100644 --- a/gdk-pixbuf/gdk-pixbuf.c +++ b/gdk-pixbuf/gdk-pixbuf.c @@ -428,7 +428,9 @@ gdk_pixbuf_fill (GdkPixbuf *pixbuf, guchar *pixels; gboolean all_the_same = FALSE; guint r, g, b, a; - + guchar *p; + gint n; + g_return_if_fail (GDK_IS_PIXBUF (pixbuf)); if (pixbuf->width == 0 || pixbuf->height == 0) @@ -449,12 +451,13 @@ gdk_pixbuf_fill (GdkPixbuf *pixbuf, } if (all_the_same) { - memset (pixels, r, - pixbuf->rowstride * pixbuf->height); + if (pixbuf->has_alpha) + memset (pixels, r, pixbuf->width * 4); + else + memset (pixels, r, pixbuf->width * 3); + } else { - guchar *p; guchar c[4]; - gint n; c[0] = r; c[1] = g; c[2] = b; c[3] = a; @@ -472,12 +475,12 @@ gdk_pixbuf_fill (GdkPixbuf *pixbuf, } while (--n); } - p = pixels; - n = pixbuf->height - 1; - while (n--) { - p += pixbuf->rowstride; - memcpy (p, pixels, pixbuf->width * pixbuf->n_channels); - } + } + p = pixels; + n = pixbuf->height - 1; + while (n--) { + p += pixbuf->rowstride; + memcpy (p, pixels, pixbuf->width * pixbuf->n_channels); } } diff --git a/gdk-pixbuf/io-gif.c b/gdk-pixbuf/io-gif.c index c6bb34eccf..c01a58ff07 100644 --- a/gdk-pixbuf/io-gif.c +++ b/gdk-pixbuf/io-gif.c @@ -725,6 +725,14 @@ gif_fill_in_lines (GifContext *context, guchar *dest, guchar v) } } +static void +set_need_recomposite (gpointer data, gpointer user_data) +{ + GdkPixbufFrame *frame = (GdkPixbufFrame *)data; + frame->need_recomposite = TRUE; +} + + static int gif_get_lzw (GifContext *context) { @@ -802,6 +810,9 @@ gif_get_lzw (GifContext *context) gdk_pixbuf_get_width (context->frame->pixbuf); h = context->frame->y_offset + gdk_pixbuf_get_height (context->frame->pixbuf); + if (w > context->animation->width || h > context->animation->height) { + g_list_foreach (context->animation->frames, set_need_recomposite, NULL); + } if (w > context->animation->width) context->animation->width = w; if (h > context->animation->height) diff --git a/gdk-pixbuf/io-ico.c b/gdk-pixbuf/io-ico.c index 4e871fb9df..412ea319da 100644 --- a/gdk-pixbuf/io-ico.c +++ b/gdk-pixbuf/io-ico.c @@ -139,8 +139,11 @@ struct ico_progressive_state { gint Lines; /* # of finished lines */ gint Type; /* + 32 = RGBA 24 = RGB + 16 = 555 RGB 8 = 8 bit colormapped + 4 = 4 bpp colormapped 1 = 1 bit bitonal */ @@ -247,9 +250,9 @@ static void DecodeHeader(guchar *Data, gint Bytes, /* Step 1: The ICO header */ IconCount = (Data[5] << 8) + (Data[4]); - + State->HeaderSize = 6 + IconCount*16; - + if (State->HeaderSize>State->BytesInHeaderBuf) { State->HeaderBuf=g_try_realloc(State->HeaderBuf,State->HeaderSize); if (!State->HeaderBuf) { @@ -396,17 +399,26 @@ static void DecodeHeader(guchar *Data, gint Bytes, g_assert (State->Header.width > 0); g_assert (State->Header.height > 0); - if (State->Type == 24) + if (State->Type == 32) + State->LineWidth = State->Header.width * 4; + else if (State->Type == 24) State->LineWidth = State->Header.width * 3; - if (State->Type == 8) + else if (State->Type == 16) + State->LineWidth = State->Header.height * 2; + else if (State->Type == 8) State->LineWidth = State->Header.width * 1; - if (State->Type == 4) { + else if (State->Type == 4) State->LineWidth = (State->Header.width+1)/2; - } - if (State->Type == 1) { + else if (State->Type == 1) { State->LineWidth = State->Header.width / 8; if ((State->Header.width & 7) != 0) State->LineWidth++; + } else { + g_set_error (error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_CORRUPT_IMAGE, + _("Unsupported icon type")); + return; } /* Pad to a 32 bit boundary */ @@ -421,8 +433,8 @@ static void DecodeHeader(guchar *Data, gint Bytes, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, _("Not enough memory to load icon")); + return; } - return; } g_assert(State->LineBuf != NULL); @@ -513,6 +525,29 @@ gboolean gdk_pixbuf__ico_image_stop_load(gpointer data, return TRUE; } +static void +OneLine32 (struct ico_progressive_state *context) +{ + gint X; + guchar *Pixels; + + X = 0; + if (context->Header.Negative == 0) + Pixels = (context->pixbuf->pixels + + context->pixbuf->rowstride * + (context->Header.height - context->Lines - 1)); + else + Pixels = (context->pixbuf->pixels + + context->pixbuf->rowstride * + context->Lines); + while (X < context->Header.width) { + Pixels[X * 4 + 0] = context->LineBuf[X * 4 + 2]; + Pixels[X * 4 + 1] = context->LineBuf[X * 4 + 1]; + Pixels[X * 4 + 2] = context->LineBuf[X * 4 + 0]; + Pixels[X * 4 + 3] = context->LineBuf[X * 4 + 3]; + X++; + } +} static void OneLine24(struct ico_progressive_state *context) { @@ -537,6 +572,44 @@ static void OneLine24(struct ico_progressive_state *context) } +static void +OneLine16 (struct ico_progressive_state *context) +{ + int i; + guchar *pixels; + guchar *src; + + if (context->Header.Negative == 0) + pixels = (context->pixbuf->pixels + + context->pixbuf->rowstride * (context->Header.height - context->Lines - 1)); + else + pixels = (context->pixbuf->pixels + + context->pixbuf->rowstride * context->Lines); + + src = context->LineBuf; + + for (i = 0; i < context->Header.width; i++) { + int v, r, g, b; + + v = (int) src[0] | ((int) src[1] << 8); + src += 2; + + /* Extract 5-bit RGB values */ + + r = (v >> 10) & 0x1f; + g = (v >> 5) & 0x1f; + b = v & 0x1f; + + /* Fill the rightmost bits to form 8-bit values */ + + *pixels++ = (r << 3) | (r >> 2); + *pixels++ = (g << 3) | (g >> 2); + *pixels++ = (b << 3) | (b >> 2); + pixels++; /* skip alpha channel */ + } +} + + static void OneLine8(struct ico_progressive_state *context) { gint X; @@ -674,19 +747,22 @@ static void OneLine(struct ico_progressive_state *context) } if (context->Lines Header.height) { - - if (context->Type == 24) + if (context->Type == 32) + OneLine32 (context); + else if (context->Type == 24) OneLine24(context); - if (context->Type == 8) + else if (context->Type == 16) + OneLine16 (context); + else if (context->Type == 8) OneLine8(context); - if (context->Type == 4) + else if (context->Type == 4) OneLine4(context); - if (context->Type == 1) + else if (context->Type == 1) OneLine1(context); + else + g_assert_not_reached (); } else - { OneLineTransp(context); - } context->Lines++; if (context->Lines>=context->Header.height) {