~noskcaj/ubuntu/trusty/tumbler/0.1.30

« back to all changes in this revision

Viewing changes to plugins/pixbuf-thumbnailer/pixbuf-thumbnailer.c

  • Committer: Package Import Robot
  • Author(s): Yves-Alexis Perez, Lionel Le Folgoc, Yves-Alexis Perez
  • Date: 2012-02-05 21:03:17 UTC
  • mfrom: (4.1.2)
  • Revision ID: package-import@ubuntu.com-20120205210317-bnl5qa1pxpro64ih
Tags: 0.1.23-1
[ Lionel Le Folgoc ]
* New upstream release:
  - fix crashes in the pixbuf thumbnailer.                        lp: #804921
* debian/control: build-depends on libgsf-1-dev and libopenrawgnome-dev to
  enable the new thumbnailers.
* debian/copyright: fix EOLs.
* Add a new binary package, tumbler-plugins-extra, to ship plugins using
  libraries not present in the default xfce desktop (openraw, gsf), and let
  tumbler suggest it.
* debian/patches:
  - 02_start-gst-pipeline.patch: dropped, applied upstream.
  - 01_fix-link-lm.patch: refreshed for the new plugins.
* debian/libtumbler-1-dev.install: updated, .a files aren't created anymore.

[ Yves-Alexis Perez ]
* debian/watch updated for new tumbler location.
* debian/control:
  - update debhelper build-dep to 9 now that it's released.

Show diffs side-by-side

added added

removed removed

Lines of Context:
9
9
 *
10
10
 * This library is distributed in the hope that it will be useful,
11
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
13
 * GNU Library General Public License for more details.
14
14
 *
15
 
 * You should have received a copy of the GNU Library General 
16
 
 * Public License along with this library; if not, write to the 
 
15
 * You should have received a copy of the GNU Library General
 
16
 * Public License along with this library; if not, write to the
17
17
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18
18
 * Boston, MA 02110-1301, USA.
19
19
 */
53
53
 
54
54
 
55
55
 
56
 
G_DEFINE_DYNAMIC_TYPE (PixbufThumbnailer, 
 
56
G_DEFINE_DYNAMIC_TYPE (PixbufThumbnailer,
57
57
                       pixbuf_thumbnailer,
58
58
                       TUMBLER_TYPE_ABSTRACT_THUMBNAILER);
59
59
 
92
92
 
93
93
 
94
94
 
95
 
static GdkPixbuf *
96
 
generate_pixbuf (GdkPixbuf              *source,
97
 
                 TumblerThumbnailFlavor *flavor)
 
95
static void
 
96
pixbuf_thumbnailer_size_prepared (GdkPixbufLoader  *loader,
 
97
                                  gint              source_width,
 
98
                                  gint              source_height,
 
99
                                  TumblerThumbnail *thumbnail)
98
100
{
99
 
  gdouble    hratio;
100
 
  gdouble    wratio;
101
 
  gint       dest_width;
102
 
  gint       dest_height;
103
 
  gint       source_width;
104
 
  gint       source_height;
105
 
 
106
 
  /* determine the source pixbuf dimensions */
107
 
  source_width = gdk_pixbuf_get_width (source);
108
 
  source_height = gdk_pixbuf_get_height (source);
109
 
 
110
 
  /* determine the desired size for this flavor */
 
101
  TumblerThumbnailFlavor *flavor;
 
102
  gint                    dest_width;
 
103
  gint                    dest_height;
 
104
  gdouble                 hratio;
 
105
  gdouble                 wratio;
 
106
 
 
107
  g_return_if_fail (GDK_IS_PIXBUF_LOADER (loader));
 
108
  g_return_if_fail (TUMBLER_IS_THUMBNAIL (thumbnail));
 
109
 
 
110
  flavor = tumbler_thumbnail_get_flavor (thumbnail);
111
111
  tumbler_thumbnail_flavor_get_size (flavor, &dest_width, &dest_height);
 
112
  g_object_unref (flavor);
112
113
 
113
 
  /* return the same pixbuf if no scaling is required */
114
114
  if (source_width <= dest_width && source_height <= dest_height)
115
 
    return g_object_ref (source);
116
 
 
117
 
  /* determine which axis needs to be scaled down more */
118
 
  wratio = (gdouble) source_width / (gdouble) dest_width;
119
 
  hratio = (gdouble) source_height / (gdouble) dest_height;
120
 
 
121
 
  /* adjust the other axis */
122
 
  if (hratio > wratio)
123
 
    dest_width = rint (source_width / hratio);
 
115
    {
 
116
      /* do not scale the image */
 
117
      dest_width = source_width;
 
118
      dest_height = source_height;
 
119
    }
124
120
  else
125
 
    dest_height = rint (source_height / wratio);
126
 
  
127
 
  /* scale the pixbuf down to the desired size */
128
 
  return gdk_pixbuf_scale_simple (source, 
129
 
                                  MAX (dest_width, 1), MAX (dest_height, 1), 
130
 
                                  GDK_INTERP_BILINEAR);
 
121
    {
 
122
      /* determine which axis needs to be scaled down more */
 
123
      wratio = (gdouble) source_width / (gdouble) dest_width;
 
124
      hratio = (gdouble) source_height / (gdouble) dest_height;
 
125
 
 
126
      /* adjust the other axis */
 
127
      if (hratio > wratio)
 
128
        dest_width = rint (source_width / hratio);
 
129
     else
 
130
        dest_height = rint (source_height / wratio);
 
131
    }
 
132
 
 
133
  gdk_pixbuf_loader_set_size (loader, MAX (dest_width, 1), MAX (dest_height, 1));
 
134
}
 
135
 
 
136
 
 
137
 
 
138
static GdkPixbuf *
 
139
pixbuf_thumbnailer_new_from_stream (GInputStream      *stream,
 
140
                                    TumblerThumbnail  *thumbnail,
 
141
                                    GCancellable      *cancellable,
 
142
                                    GError           **error)
 
143
{
 
144
  GdkPixbufLoader *loader;
 
145
  gssize           n_read;
 
146
  gboolean         result;
 
147
  GdkPixbuf       *pixbuf = NULL;
 
148
  guchar           buffer[65536];
 
149
 
 
150
  g_return_val_if_fail (G_IS_INPUT_STREAM (stream), NULL);
 
151
 
 
152
  /* prepare the loader */
 
153
  loader = gdk_pixbuf_loader_new ();
 
154
  g_signal_connect (loader, "size-prepared",
 
155
      G_CALLBACK (pixbuf_thumbnailer_size_prepared), thumbnail);
 
156
 
 
157
  result = TRUE;
 
158
  for (;;)
 
159
    {
 
160
      n_read = g_input_stream_read (stream, buffer, sizeof (buffer),
 
161
                                    cancellable, error);
 
162
 
 
163
      if (n_read < 0)
 
164
        {
 
165
          result = FALSE;
 
166
          error = NULL;
 
167
          break;
 
168
        }
 
169
 
 
170
      if (n_read == 0)
 
171
        break;
 
172
 
 
173
      if (!gdk_pixbuf_loader_write (loader, buffer, n_read, error))
 
174
        {
 
175
          result = FALSE;
 
176
          error = NULL;
 
177
          break;
 
178
        }
 
179
    }
 
180
 
 
181
  if (!gdk_pixbuf_loader_close (loader, error))
 
182
    {
 
183
      result = FALSE;
 
184
      error = NULL;
 
185
    }
 
186
 
 
187
  if (result)
 
188
    {
 
189
      pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
 
190
      if (G_LIKELY (pixbuf != NULL))
 
191
        g_object_ref (pixbuf);
 
192
    }
 
193
 
 
194
  g_object_unref (loader);
 
195
 
 
196
  return pixbuf;
131
197
}
132
198
 
133
199
 
137
203
                           GCancellable               *cancellable,
138
204
                           TumblerFileInfo            *info)
139
205
{
140
 
  TumblerThumbnailFlavor *flavor;
141
 
  GFileInputStream       *stream;
142
 
  TumblerImageData        data;
143
 
  TumblerThumbnail       *thumbnail;
144
 
  const gchar            *uri;
145
 
  GdkPixbuf              *source_pixbuf;
146
 
  GdkPixbuf              *pixbuf;
147
 
  GError                 *error = NULL;
148
 
  GFile                  *file;
 
206
 
 
207
  GFileInputStream *stream;
 
208
  TumblerImageData  data;
 
209
  TumblerThumbnail *thumbnail;
 
210
  const gchar      *uri;
 
211
  GdkPixbuf        *pixbuf;
 
212
  GError           *error = NULL;
 
213
  GFile            *file;
149
214
 
150
215
  g_return_if_fail (IS_PIXBUF_THUMBNAILER (thumbnailer));
151
216
  g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
152
217
  g_return_if_fail (TUMBLER_IS_FILE_INFO (info));
153
218
 
154
219
  /* do nothing if cancelled */
155
 
  if (g_cancellable_is_cancelled (cancellable)) 
 
220
  if (g_cancellable_is_cancelled (cancellable))
156
221
    return;
157
222
 
158
223
  uri = tumbler_file_info_get_uri (info);
164
229
 
165
230
  if (stream == NULL)
166
231
    {
167
 
      g_signal_emit_by_name (thumbnailer, "error", uri, error->code, error->message);
168
 
      g_error_free (error);
169
 
      return;
170
 
    }
171
 
 
172
 
  source_pixbuf = gdk_pixbuf_new_from_stream (G_INPUT_STREAM (stream), 
173
 
                                              cancellable, &error);
174
 
  g_object_unref (stream);
175
 
 
176
 
  if (source_pixbuf == NULL)
177
 
    {
178
 
      g_signal_emit_by_name (thumbnailer, "error", uri, error->code, error->message);
179
 
      g_error_free (error);
 
232
      if (error != NULL)
 
233
        {
 
234
          g_signal_emit_by_name (thumbnailer, "error", uri, error->code,
 
235
                                 error->message);
 
236
          g_error_free (error);
 
237
        }
 
238
      else
 
239
        {
 
240
          g_signal_emit_by_name (thumbnailer, "error", uri, TUMBLER_ERROR_NO_CONTENT,
 
241
                                 "Failed to open pixbuf stream");
 
242
        }
 
243
 
180
244
      return;
181
245
    }
182
246
 
183
247
  thumbnail = tumbler_file_info_get_thumbnail (info);
184
 
 
185
248
  g_assert (thumbnail != NULL);
186
249
 
187
 
  /* generate a pixbuf for the thumbnail */
188
 
  flavor = tumbler_thumbnail_get_flavor (thumbnail);
189
 
  pixbuf = generate_pixbuf (source_pixbuf, flavor);
190
 
  g_object_unref (flavor);
 
250
  /* load the scaled pixbuf from the stream. this works like
 
251
   * gdk_pixbuf_new_from_file_at_scale(), but without increasing the
 
252
   * pixbuf size. */
 
253
  pixbuf = pixbuf_thumbnailer_new_from_stream (G_INPUT_STREAM (stream), thumbnail,
 
254
                                               cancellable, &error);
 
255
 
 
256
  g_object_unref (stream);
 
257
 
 
258
  if (pixbuf == NULL)
 
259
    {
 
260
      if (error != NULL)
 
261
        {
 
262
          g_signal_emit_by_name (thumbnailer, "error", uri, error->code,
 
263
                                 error->message);
 
264
          g_error_free (error);
 
265
        }
 
266
      else
 
267
        {
 
268
          g_signal_emit_by_name (thumbnailer, "error", uri, TUMBLER_ERROR_NO_CONTENT,
 
269
                                 "Failed to create pixbuf from stream");
 
270
        }
 
271
 
 
272
      g_object_unref (thumbnail);
 
273
      return;
 
274
    }
191
275
 
192
276
  g_assert (pixbuf != NULL);
193
277
 
199
283
  data.rowstride = gdk_pixbuf_get_rowstride (pixbuf);
200
284
  data.colorspace = (TumblerColorspace) gdk_pixbuf_get_colorspace (pixbuf);
201
285
 
202
 
  tumbler_thumbnail_save_image_data (thumbnail, &data, 
203
 
                                     tumbler_file_info_get_mtime (info), 
 
286
  tumbler_thumbnail_save_image_data (thumbnail, &data,
 
287
                                     tumbler_file_info_get_mtime (info),
204
288
                                     NULL, &error);
205
289
 
206
290
  if (error != NULL)
213
297
      g_signal_emit_by_name (thumbnailer, "ready", uri);
214
298
    }
215
299
 
 
300
  g_object_unref (pixbuf);
216
301
  g_object_unref (thumbnail);
217
 
  g_object_unref (pixbuf);
218
 
  g_object_unref (source_pixbuf);
219
302
}