Bug 233935 - gt2k does not handle tiff G4 well: nautilus takes a few minutes for a 2K bytes file.
gt2k does not handle tiff G4 well: nautilus takes a few minutes for a 2K byte...
Product: Fedora
Classification: Fedora
Component: gtk2 (Show other bugs)
All Linux
medium Severity medium
: ---
: ---
Assigned To: Matthias Clasen
Depends On:
  Show dependency treegraph
Reported: 2007-03-25 22:47 EDT by Tim Taiwanese Liim
Modified: 2007-11-30 17:12 EST (History)
0 users

See Also:
Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Last Closed: 2007-03-26 17:35:09 EDT
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---

Attachments (Terms of Use)
sample file that caused gtk2 slowness. (1.64 KB, image/tiff)
2007-03-25 22:47 EDT, Tim Taiwanese Liim
no flags Details

  None (edit)
Description Tim Taiwanese Liim 2007-03-25 22:47:30 EDT
Description of problem:
    Using nautilus, in "View as List," when previewing a 2K-byte tiff
    file with "G4 Fax" compression, /usr/lib/libgdk_pixbuf-2.0.so.0
    in gtk2 takes a minutes before responding.

    The method in question is correct_total() in

Version-Release number of selected component (if applicable):
    gtk2-2.10.8-1 in FC6.

How reproducible:

Steps to Reproduce:
1. mkdir ~/t1
   cd ~/t1
   wget http://formosa.homelinux.com/pub/t11.tif
2. nautilus ~/t1
3. change display mode from "View as Icons" to "View as List".
Actual results:
- preview icon was shown after a few MINUTES.

Expected results:
- preview icon be shown in one second.

Additional info:
1. info about image:
    B/W document (ie. color depth=1)
    saved in TIFF with "G4 fax" compression.
        (Other choices for compression are "G3 fax", "packedbits", 
        "uncompressed".  When the same image is saved in non-G4
        compression, nautilus is ok to display (ie. no lengthy 

2. If nautlius is allowed to complete the "View as List", it seems
   that nautilus caches the result and no longer exhibits the delay.
   To reproduce problem: 
   method1: use ~/t2, ~/t3, ... (use new dir each time)
   method2: rm -rf ~/.nautilus; pkill nautilus
Comment 1 Tim Taiwanese Liim 2007-03-25 22:47:30 EDT
Created attachment 150866 [details]
sample file that caused gtk2 slowness.
Comment 2 Tim Taiwanese Liim 2007-03-25 22:50:29 EDT
3. use dbx to determine where the busy loop is:
   - attach to nautilus when it's in busy loop, and hit control-C:
        #0  0x4a9fa948 in gdk_pixbuf_alpha_mode_get_type ()
           from /usr/lib/libgdk_pixbuf-2.0.so.0
     which comes from gtk2-2.10.8-1.fc6.

   Here is the busy loop, between +6096~+6190.
        0x4a9fa940 <gdk_pixbuf_alpha_mode_get_type+6096>:       mov   
        0x4a9fa946 <gdk_pixbuf_alpha_mode_get_type+6102>:       mov    (%edx),%ecx
        0x4a9fa948 <gdk_pixbuf_alpha_mode_get_type+6104>:       add    %eax,%ecx
        0x4a9fa94a <gdk_pixbuf_alpha_mode_get_type+6106>:       mov   
        0x4a9fa950 <gdk_pixbuf_alpha_mode_get_type+6112>:       js    
0x4a9fa97a <gdk_pixbuf_alpha_mode_get_type+6154>
        0x4a9fa952 <gdk_pixbuf_alpha_mode_get_type+6114>:       sub   
        0x4a9fa958 <gdk_pixbuf_alpha_mode_get_type+6120>:       mov    %ecx,(%edx)
        0x4a9fa95a <gdk_pixbuf_alpha_mode_get_type+6122>:       mov   
        0x4a9fa960 <gdk_pixbuf_alpha_mode_get_type+6128>:       test   %ecx,%ecx
        0x4a9fa962 <gdk_pixbuf_alpha_mode_get_type+6130>:       jle   
0x4a9fafa7 <gdk_pixbuf_alpha_mode_get_type+7735>
        0x4a9fa968 <gdk_pixbuf_alpha_mode_get_type+6136>:       cmp   
        0x4a9fa96e <gdk_pixbuf_alpha_mode_get_type+6142>:       jge   
0x4a9fafa7 <gdk_pixbuf_alpha_mode_get_type+7735>
        0x4a9fa974 <gdk_pixbuf_alpha_mode_get_type+6148>:       mov   
        0x4a9fa97a <gdk_pixbuf_alpha_mode_get_type+6154>:       subl  
        0x4a9fa981 <gdk_pixbuf_alpha_mode_get_type+6161>:       js    
0x4a9faf80 <gdk_pixbuf_alpha_mode_get_type+7696>
        0x4a9fa987 <gdk_pixbuf_alpha_mode_get_type+6167>:       test   %eax,%eax
        0x4a9fa989 <gdk_pixbuf_alpha_mode_get_type+6169>:       je    
0x4a9faf80 <gdk_pixbuf_alpha_mode_get_type+7696>
        0x4a9fa98f <gdk_pixbuf_alpha_mode_get_type+6175>:       mov   
        0x4a9fa995 <gdk_pixbuf_alpha_mode_get_type+6181>:       subl  
        0x4a9fa99c <gdk_pixbuf_alpha_mode_get_type+6188>:       test   %ecx,%ecx
        0x4a9fa99e <gdk_pixbuf_alpha_mode_get_type+6190>:       jne   
0x4a9fa940 <gdk_pixbuf_alpha_mode_get_type+6096>
   but look at gdk-pixbuf/gdk-pixbuf-enum-types.c, line 9-line 21
        gdk_pixbuf_alpha_mode_get_type (void)
          static GType etype = 0;
          if (etype == 0) {
            static const GEnumValue values[] = {
              { GDK_PIXBUF_ALPHA_FULL, "GDK_PIXBUF_ALPHA_FULL", "full" },
              { 0, NULL, NULL }
            etype = g_enum_register_static (g_intern_static_string
("GdkPixbufAlphaMode"), values);
          return etype;
   It's quite possible that gdb is reporting wrong symbols (ie. the method
   name gdk_pixbuf_alpha_mode_get_type is scapegoat).

4. try to build libgdk_pixbuf-2.0.so.0 from source tree.
   4.1 download and install gtk2-2.10.8-1.fc6.src.rpm in /usr/src/redhat
   4.2 rpmbuild -bc --target i686      SPECS/gtk2.spec
   4.3 export LD_LIBRARY_PATH=/usr/src/redhat/BUILD/gtk+-2.10.8/gdk-pixbuf/.libs
       gdb nautilus
   - this time the infinite loop is at
            0x00aff630 <pixops_process+608>:        mov    0xffffff70(%ebp),%edx
            0x00aff636 <pixops_process+614>:        mov    (%edx),%ecx
            0x00aff638 <pixops_process+616>:        add    %eax,%ecx
            0x00aff63a <pixops_process+618>:        mov    %ecx,0xfffffe9c(%ebp)

            0x00aff640 <pixops_process+624>:        js     0xaff66a
            0x00aff642 <pixops_process+626>:        sub    %eax,0xfffffe94(%ebp)
            0x00aff648 <pixops_process+632>:        mov    %ecx,(%edx)
            0x00aff64a <pixops_process+634>:        mov    0xfffffe94(%ebp),%ecx
            0x00aff650 <pixops_process+640>:        test   %ecx,%ecx
        if (c<=0) go 1492
            0x00aff652 <pixops_process+642>:        jle    0xaff9a4
            0x00aff658 <pixops_process+648>:        cmp    %eax,0xfffffe94(%ebp)
        if (eax >= c) go 1492
            0x00aff65e <pixops_process+654>:        jge    0xaff9a4
            0x00aff664 <pixops_process+660>:        mov    0xfffffe94(%ebp),%eax
                                                                ^ c
            0x00aff66a <pixops_process+666>:        subl   $0x1,0xffffff3c(%ebp)
                                                                 ^ copy of i
        ?if (i<0) go 1453
            0x00aff671 <pixops_process+673>:        js     0xaff97d
            0x00aff677 <pixops_process+679>:        test   %eax,%eax
        if c==0 goto 1453
            0x00aff679 <pixops_process+681>:        je     0xaff97d
            0x00c5c67f <pixops_process+687>:        mov    0xfffffe94(%ebp),%ecx
            0x00c5c685 <pixops_process+693>:        subl   $0x4,0xffffff70(%ebp)
            0x00c5c68c <pixops_process+700>:        test   %ecx,%ecx
        if c!=0 go 608
            0x00c5c68e <pixops_process+702>:        jne    0xc5c630

    4.4 compare this code with <gdk_pixbuf_alpha_mode_get_type+6096> listed
        in #3: they are identical.  Very likely gdb identified correct_total()
        as <gdk_pixbuf_alpha_mode_get_type+6096>.

    4.5 This slow loop is the optimized code for
        correct_total (int    *weights, 
                       int    n_x, 
                       int    n_y,
                       int    total, 
                       double overall_alpha)
          int correction = (int)(0.5 + 65536 * overall_alpha) - total;
          int remaining, c, d, i;

          if (correction != 0)
              remaining = correction;
              for (d = 1, c = correction; c != 0 && remaining != 0; d++, c =
correction / d) 
                for (i = n_x * n_y - 1; i >= 0 && c != 0 && remaining != 0; i--) 
                  if (*(weights + i) + c >= 0) 
                      *(weights + i) += c;
                      remaining -= c;
                      if ((0 < remaining && remaining < c) ||
                          (0 > remaining && remaining > c))
                        c = remaining;

Comment 3 Matthias Clasen 2007-03-26 17:35:09 EDT
This is the well-known problem of gdk-pixbuf being not very clever when scaling
down images a lot. This is tracked upstream at

Note You need to log in before you can comment on or make changes to this bug.