~ubuntu-branches/ubuntu/quantal/shotwell/quantal

« back to all changes in this revision

Viewing changes to src/util/image.vala

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2011-08-24 11:45:16 UTC
  • mfrom: (1.2.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20110824114516-01cf7d83qvc9nse1
Tags: 0.11.0-0ubuntu1
New upstream version, drop patches which are in the new version

Show diffs side-by-side

added added

removed removed

Lines of Context:
225
225
    return result;
226
226
}
227
227
 
 
228
// Converts XRGB/ARGB (Cairo)-formatted pixels to RGBA (GDK).
 
229
void fix_cairo_pixbuf(Gdk.Pixbuf pixbuf) {
 
230
    uchar *gdk_pixels = pixbuf.pixels;
 
231
    for (int j = 0 ; j < pixbuf.height; ++j) {
 
232
        uchar *p = gdk_pixels;
 
233
        uchar *end = p + 4 * pixbuf.width;
 
234
 
 
235
        while (p < end) {
 
236
            uchar tmp = p[0];
 
237
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
 
238
            p[0] = p[2];
 
239
            p[2] = tmp;
 
240
#else     
 
241
            p[0] = p[1];
 
242
            p[1] = p[2];
 
243
            p[2] = p[3];
 
244
            p[3] = tmp;
 
245
#endif
 
246
            p += 4;
 
247
        }
 
248
 
 
249
      gdk_pixels += pixbuf.rowstride;
 
250
    }
 
251
}
 
252
 
 
253
// Rotates a pixbuf to an arbitrary angle, given in degrees, and returns the rotated 
 
254
// pixbuf. The caller is responsible for destroying the returned pixbuf after use.
 
255
Gdk.Pixbuf rotate_arb(Gdk.Pixbuf source_pixbuf, double angle) {
 
256
    angle = degrees_to_radians(angle);
 
257
    
 
258
    double x_min = 0.0, y_min = 0.0, x_max = 0.0, y_max = 0.0;
 
259
    
 
260
    double x_tmp, y_tmp;
 
261
    
 
262
    // Compute how much the corners of the source image will
 
263
    // move by to determine how big the dest pixbuf should be.
 
264
 
 
265
    // Lower left corner.
 
266
    x_tmp = -(Math.sin(angle) * source_pixbuf.height);
 
267
    y_tmp = (Math.cos(angle) * source_pixbuf.height);
 
268
    
 
269
    if(x_tmp < x_min) x_min = x_tmp;
 
270
    if(x_tmp > x_max) x_max = x_tmp;
 
271
 
 
272
    if(y_tmp < y_min) y_min = y_tmp;
 
273
    if(y_tmp > y_max) y_max = y_tmp;
 
274
    
 
275
    // Lower right corner.
 
276
    x_tmp = (Math.cos(angle) * source_pixbuf.width) - (Math.sin(angle) * source_pixbuf.height);
 
277
    y_tmp = (Math.sin(angle) * source_pixbuf.width) + (Math.cos(angle) * source_pixbuf.height);
 
278
    
 
279
    if(x_tmp < x_min) x_min = x_tmp;
 
280
    if(x_tmp > x_max) x_max = x_tmp;
 
281
 
 
282
    if(y_tmp < y_min) y_min = y_tmp;
 
283
    if(y_tmp > y_max) y_max = y_tmp;
 
284
    
 
285
    // Upper right corner.
 
286
    x_tmp = (Math.cos(angle) * source_pixbuf.width); 
 
287
    y_tmp = (Math.sin(angle) * source_pixbuf.width); 
 
288
    
 
289
    if(x_tmp < x_min) x_min = x_tmp;
 
290
    if(x_tmp > x_max) x_max = x_tmp;
 
291
 
 
292
    if(y_tmp < y_min) y_min = y_tmp;
 
293
    if(y_tmp > y_max) y_max = y_tmp;
 
294
    
 
295
    Gdk.Pixbuf dest_pixbuf = new Gdk.Pixbuf(Gdk.Colorspace.RGB, true, 8, (int) Math.round(x_max - x_min), (int) Math.round(y_max - y_min));
 
296
 
 
297
    Cairo.ImageSurface surface;
 
298
    
 
299
    if(source_pixbuf.has_alpha) {
 
300
         surface = new Cairo.ImageSurface.for_data(
 
301
            (uchar []) dest_pixbuf.pixels, Cairo.Format.ARGB32,
 
302
            dest_pixbuf.width, dest_pixbuf.height, dest_pixbuf.rowstride);
 
303
    } else {
 
304
         surface = new Cairo.ImageSurface.for_data(
 
305
            (uchar []) dest_pixbuf.pixels, Cairo.Format.RGB24,
 
306
            dest_pixbuf.width, dest_pixbuf.height, dest_pixbuf.rowstride);
 
307
    }
 
308
            
 
309
    Cairo.Context context = new Cairo.Context(surface);
 
310
    
 
311
    context.set_source_rgb(0, 0, 0);
 
312
    context.rectangle(0, 0, dest_pixbuf.width, dest_pixbuf.height);
 
313
    context.fill();
 
314
    
 
315
    context.translate(-x_min, -y_min);
 
316
    context.rotate(angle);
 
317
    Gdk.cairo_set_source_pixbuf(context, source_pixbuf, 0, 0);
 
318
    context.get_source().set_filter(Cairo.Filter.BEST);
 
319
    context.paint();
 
320
 
 
321
    fix_cairo_pixbuf(dest_pixbuf);
 
322
 
 
323
    return dest_pixbuf;
 
324
}