File: Pixbuf.chs

package info (click to toggle)
haskell-gtk 0.11.0-5
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 2,920 kB
  • ctags: 82
  • sloc: haskell: 1,929; ansic: 714; sh: 5; makefile: 3
file content (781 lines) | stat: -rw-r--r-- 29,371 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
{-# LANGUAGE CPP #-}
-- -*-haskell-*-
--  GIMP Toolkit (GTK) Pixbuf
--
--  Author : Vincenzo Ciancia, Axel Simon
--
--  Created: 26 March 2002
--
--  Copyright (C) 2002-2005 Axel Simon, Vincenzo Ciancia
--
--  This library is free software; you can redistribute it and/or
--  modify it under the terms of the GNU Lesser General Public
--  License as published by the Free Software Foundation; either
--  version 2.1 of the License, or (at your option) any later version.
--
--  This library is distributed in the hope that it will be useful,
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
--  Lesser General Public License for more details.
--
-- TODO
--
-- if anybody writes an image manipulation program, do the checker board
-- functions: gdk_pixbuf_composite_color_simple and
-- gdk_pixbuf_composite_color. Moreover, do: pixbuf_saturate_and_pixelate
--
--
-- pixbuf loader
--
-- module interface
--
-- rendering function for Bitmaps and Pixmaps when the latter are added
--
-- |
-- Maintainer  : gtk2hs-users@lists.sourceforge.net
-- Stability   : provisional
-- Portability : portable (depends on GHC)
--
-- 'Pixbuf's are bitmap images in memory.
--
-- * A Pixbuf is used to represent images. It contains information
--   about the image's pixel data, its color space, bits per sample, width
--   and height, and the rowstride or number of bytes between rows.
--
-- * This module contains functions to scale and crop
--   'Pixbuf's and to scale and crop a 'Pixbuf' and
--   compose the result with an existing image.
--
-- * 'Pixbuf's can be displayed on screen by either creating an 'Image' that
--   from the 'Pixbuf' or by rendering (part of) the 'Pixbuf' into a
--   vanilla widget like 'DrawWindow' using
--  'Graphics.UI.Gtk.Gdk.Drawable.drawPixbuf'.
--
module Graphics.UI.Gtk.Gdk.Pixbuf (
-- * Class Hierarchy
-- |
-- @
-- |  'GObject'
-- |   +----Pixbuf
-- @

-- * Types
  Pixbuf,
  PixbufClass,
  castToPixbuf, gTypePixbuf,
  toPixbuf,
  PixbufError(..),
  Colorspace(..),

-- * Constructors
  pixbufNew,
  pixbufNewFromFile,
#if GTK_CHECK_VERSION(2,4,0)
  pixbufNewFromFileAtSize,
#endif
#if GTK_CHECK_VERSION(2,6,0)
  pixbufNewFromFileAtScale,
#endif
  pixbufNewFromInline,
  InlineImage,
  pixbufNewSubpixbuf,
  pixbufNewFromXPMData,

-- * Methods
  pixbufGetColorSpace,
  pixbufGetNChannels,
  pixbufGetHasAlpha,
  pixbufGetBitsPerSample,
  PixbufData,
  pixbufGetPixels,
  pixbufGetWidth,
  pixbufGetHeight,
  pixbufGetRowstride,
  pixbufGetOption,
  ImageFormat,
  pixbufGetFormats,
  pixbufSave,
  pixbufCopy,
  InterpType(..),
  pixbufScaleSimple,
  pixbufScale,
  pixbufComposite,
#if GTK_CHECK_VERSION(2,6,0)
  pixbufFlipHorizontally,
  pixbufFlipHorazontally,
  pixbufFlipVertically,
  pixbufRotateSimple,
  PixbufRotation(..),
#endif
  pixbufAddAlpha,
  pixbufCopyArea,
  pixbufFill,
  pixbufGetFromDrawable,

  pixbufRenderThresholdAlpha,
  pixbufRenderPixmapAndMaskForColormap
  ) where

import Control.Monad (liftM)
import Data.Ix
import System.Glib.FFI
import System.Glib.UTFString
import System.Glib.GDateTime
import System.Glib.GObject
{#import Graphics.UI.Gtk.Types#}
import Graphics.UI.Gtk.General.Structs		(Rectangle(..))
import System.Glib.GError	(GError(..), GErrorClass(..), GErrorDomain,
				propagateGError)
import Graphics.UI.Gtk.Gdk.PixbufData ( PixbufData, mkPixbufData )
import Graphics.UI.Gtk.Gdk.Pixmap (Bitmap, Pixmap)

{# context prefix="gdk" #}

-- | Error codes for loading image files.
--
{#enum PixbufError {underscoreToCase} #}

-- | Enumerate all supported color spaces.
--
-- * Only RGB is supported right now.
--
{#enum Colorspace {underscoreToCase} #}

-- | Queries the color space of a pixbuf.
--
pixbufGetColorSpace :: Pixbuf -> IO Colorspace
pixbufGetColorSpace pb = liftM (toEnum . fromIntegral) $
  {#call unsafe pixbuf_get_colorspace#} pb

-- | Queries the number of colors for each pixel.
--
-- * This function returns 3 for an RGB image without alpha (transparency)
--   channel, 4 for an RGB image with alpha channel.
--
pixbufGetNChannels :: Pixbuf -> IO Int
pixbufGetNChannels pb = liftM fromIntegral $
  {#call unsafe pixbuf_get_n_channels#} pb

-- | Query if the image has an alpha channel.
--
-- * The alpha channel determines the opaqueness of the pixel.
--
pixbufGetHasAlpha :: Pixbuf -> IO Bool
pixbufGetHasAlpha pb =
  liftM toBool $ {#call unsafe pixbuf_get_has_alpha#} pb

-- | Queries the number of bits for each color.
--
-- * Each pixel is has a number of cannels for each pixel, each channel
--   has this many bits.
--
pixbufGetBitsPerSample :: Pixbuf -> IO Int
pixbufGetBitsPerSample pb = liftM fromIntegral $
  {#call unsafe pixbuf_get_bits_per_sample#} pb

-- | Retrieve the internal array of raw image data.
--
-- * Image data in a pixbuf is stored in memory in uncompressed,
--   packed format. Rows in the image are stored top to bottom, and in each
--   row pixels are stored from left to right. There may be padding at the
--   end of a row. The "rowstride" value of a pixbuf, as returned by
--   'pixbufGetRowstride', indicates the number of bytes between rows.
--
-- * The returned array is a flat representation of a three dimensional
--   array: x-coordiante, y-coordinate and several channels for each color.
--   The number of channels is usually 3 for plain RGB data or 4 for
--   RGB data with an alpha channel. To read or write a specific pixel
--   use the formula: @p = y * rowstride + x * nChannels@ for the pixel.
--   If the array contains bytes (or 'Word8's), @p+0@ is the red value,
--   @p+1@ green, @p+2@ blue and @p+3@ the alpha (transparency) channel
--   if present. If the alpha channel is present, the array can accessed
--   as an array over 'Word32' to modify a whole pixel at a time. See also
--   'pixbufGetBitsPerSample' and 'pixbufGetNChannels'.
--
-- * Calling this function without explicitly giving it a type will often
--   lead to a compiler error since the type parameter @e@ is underspecified.
--   If this happens the function can be explicitly typed:
--   @pbData <- (pixbufGetPixels pb :: IO (PixbufData Int Word8))@
--
-- * If modifying an image through Haskell\'s array interface is not
--   fast enough, it is possible to use 'unsafeRead' and
--   'unsafeWrite' which have the same type signatures
--   as 'readArray' and 'writeArray'.
--   Note that these are internal
--   functions that might change with GHC.
--
pixbufGetPixels :: Storable e => Pixbuf -> IO (PixbufData Int e)
pixbufGetPixels pb = do
  pixPtr_ <- {#call unsafe pixbuf_get_pixels#} pb
  chan <- pixbufGetNChannels pb
  bits <- pixbufGetBitsPerSample pb
  w <- pixbufGetWidth pb
  h <- pixbufGetHeight pb
  r <- pixbufGetRowstride pb
  let pixPtr = castPtr pixPtr_
  let bytes = (h-1)*r+w*((chan*bits+7) `div` 8)
  return (mkPixbufData pb pixPtr bytes)

-- | Queries the width of this image.
--
pixbufGetWidth :: Pixbuf -> IO Int
pixbufGetWidth pb = liftM fromIntegral $
  {#call unsafe pixbuf_get_width#} pb

-- | Queries the height of this image.
--
pixbufGetHeight :: Pixbuf -> IO Int
pixbufGetHeight pb = liftM fromIntegral $
  {#call unsafe pixbuf_get_height#} pb

-- | Queries the rowstride of this image.
--
-- * Queries the rowstride of a pixbuf, which is the number of bytes between
--   rows. Use this value to caculate the offset to a certain row.
--
pixbufGetRowstride :: Pixbuf -> IO Int
pixbufGetRowstride pb = liftM fromIntegral $
  {#call unsafe pixbuf_get_rowstride#} pb

-- | Returns an attribut of an image.
--
-- * Looks up if some information was stored under the @key@ when
--   this image was saved.
--
pixbufGetOption :: Pixbuf -> String -> IO (Maybe String)
pixbufGetOption pb key = withUTFString key $ \strPtr -> do
  resPtr <- {#call unsafe pixbuf_get_option#} pb strPtr
  if (resPtr==nullPtr) then return Nothing else
    liftM Just $ peekUTFString resPtr

-- helper functions
pixbufErrorDomain :: GErrorDomain
pixbufErrorDomain = {#call pure unsafe pixbuf_error_quark#}

instance GErrorClass PixbufError where
  gerrorDomain _ = pixbufErrorDomain


-- | Load an image synchonously.
--
-- * Use this function to load only small images as this call will block.
--
-- * If an error occurs, the function will throw an exception that can
--   be caught using e.g. 'System.Glib.GError.catchGErrorJust' and one of the
--   error codes in 'PixbufError'.
--
pixbufNewFromFile :: FilePath -> IO Pixbuf
pixbufNewFromFile fname =
  constructNewGObject mkPixbuf $
  propagateGError $ \errPtrPtr ->
     withUTFString fname $ \strPtr ->
#if defined (WIN32) && GTK_CHECK_VERSION(2,6,0)
     {#call unsafe pixbuf_new_from_file_utf8#}
#else
     {#call unsafe pixbuf_new_from_file#}
#endif
    strPtr errPtrPtr

#if GTK_CHECK_VERSION(2,4,0)
-- | Creates a new pixbuf by loading an image from a file. The file format is
-- detected automatically. The image will be scaled to fit in the requested
-- size, preserving the image's aspect ratio.
--
-- * If an error occurs, the function will throw an exception that can
--   be caught using e.g. 'System.Glib.GError.catchGErrorJust' and one of the
--   error codes in 'PixbufError'.
--
-- * Available since Gtk+ version 2.4
--
pixbufNewFromFileAtSize :: String -> Int -> Int -> IO Pixbuf
pixbufNewFromFileAtSize filename width height =
  constructNewGObject mkPixbuf $
  propagateGError $ \errPtrPtr ->
    withUTFString filename $ \filenamePtr ->
#if defined (WIN32) && GTK_CHECK_VERSION(2,6,0)
    {# call gdk_pixbuf_new_from_file_at_size_utf8 #}
#else
    {# call gdk_pixbuf_new_from_file_at_size #}
#endif
    filenamePtr
    (fromIntegral width)
    (fromIntegral height)
    errPtrPtr
#endif

#if GTK_CHECK_VERSION(2,6,0)
-- | Creates a new pixbuf by loading an image from a file. The file format is
-- detected automatically. The image will be scaled to fit in the requested
-- size, optionally preserving the image's aspect ratio.
--
-- When preserving the aspect ratio, a width of -1 will cause the image to be
-- scaled to the exact given height, and a height of -1 will cause the image to
-- be scaled to the exact given width. When not preserving aspect ratio, a width
-- or height of -1 means to not scale the image at all in that dimension.
-- Negative values for width and height are allowed since Gtk+ 2.8.
--
-- * If an error occurs, the function will throw an exception that can
--   be caught using e.g. 'System.Glib.GError.catchGErrorJust' and one of the
--   error codes in 'PixbufError'.
--
-- * Available since Gtk+ version 2.6
--
pixbufNewFromFileAtScale ::
     String -- ^ the name of the file
  -> Int -- ^ target width
  -> Int -- ^ target height
  -> Bool -- ^ whether to preserve the aspect ratio
  -> IO Pixbuf
pixbufNewFromFileAtScale filename width height preserveAspectRatio =
  constructNewGObject mkPixbuf $
  propagateGError $ \errPtrPtr ->
    withUTFString filename $ \filenamePtr ->
#if defined (WIN32) && GTK_CHECK_VERSION(2,6,0)
    {# call gdk_pixbuf_new_from_file_at_scale_utf8 #}
#else
    {# call gdk_pixbuf_new_from_file_at_scale #}
#endif
    filenamePtr
    (fromIntegral width)
    (fromIntegral height)
    (fromBool preserveAspectRatio)
    errPtrPtr
#endif

-- | A string representing an image file format.
--
type ImageFormat = String

-- constant pixbufGetFormats A list of valid image file formats.
--
pixbufGetFormats :: [ImageFormat]

pixbufGetFormats = ["png","bmp","wbmp", "gif","ico","ani","jpeg","pnm",
		    "ras","tiff","xpm","xbm","tga"]

-- | Save an image to disk.
--
-- * The function takes a list of key - value pairs to specify
--   either how an image is saved or to actually save this additional
--   data with the image. JPEG images can be saved with a \"quality\"
--   parameter; its value should be in the range [0,100]. Text chunks
--   can be attached to PNG images by specifying parameters of the form
--   \"tEXt::key\", where key is an ASCII string of length 1-79.
--   The values are Unicode strings.
--
-- * If an error occurs, the function will throw an exception that can
--   be caught using e.g. 'System.Glib.GError.catchGErrorJust' and one of the
--   error codes in 'PixbufError'.
--
pixbufSave :: Pixbuf -> FilePath -> ImageFormat -> [(String, String)] ->
	      IO ()
pixbufSave pb fname iType options =
  let (keys, values) = unzip options in
  let optLen = length keys in
  propagateGError $ \errPtrPtr ->
    withUTFString fname $ \fnPtr ->
    withUTFString iType $ \tyPtr ->
    withUTFStringArray0 keys $ \keysPtr ->
    withUTFStringArray values $ \valuesPtr -> do
#if defined (WIN32) && GTK_CHECK_VERSION(2,6,5)
      {# call unsafe pixbuf_savev_utf8 #}
#else
      {# call unsafe pixbuf_savev #}
#endif
        pb fnPtr tyPtr keysPtr valuesPtr errPtrPtr
      return ()

-- | Create a new image in memory.
--
-- * Creates a new pixbuf structure and allocates a buffer for
--   it. Note that the buffer is not cleared initially.
--
-- * The boolean flag is true if the pixbuf should have an alpha
--   (transparency) channel. The next integer denotes the bits per
--   color sample, e.g. 8 bits per color for 2^24 colors. The last
--   two integers denote the width and height, respectively.
--
pixbufNew :: Colorspace -> Bool -> Int -> Int -> Int -> IO Pixbuf
pixbufNew colorspace hasAlpha bitsPerSample width height =
  constructNewGObject mkPixbuf $
    {#call pixbuf_new#} ((fromIntegral . fromEnum) colorspace)
      (fromBool hasAlpha) (fromIntegral bitsPerSample) (fromIntegral width)
      (fromIntegral height)

-- | Create a new image from a String.
--
-- * Creates a new pixbuf from a string description.
--
pixbufNewFromXPMData :: [String] -> IO Pixbuf
pixbufNewFromXPMData s =
  withUTFStringArray0 s $ \strsPtr ->
    constructNewGObject mkPixbuf $ {#call pixbuf_new_from_xpm_data#} strsPtr

-- | A dymmy type for inline picture data.
--
-- * This dummy type is used to declare pointers to image data
--   that is embedded in the executable. See
--   'pixbufNewFromInline' for an example.
--
data InlineImage = InlineImage

-- | Create a new image from a static pointer.
--
-- * Like 'pixbufNewFromXPMData', this function allows to
--   include images in the final binary program. The method used by this
--   function uses a binary representation and therefore needs less space
--   in the final executable. Save the image you want to include as
--   @png@ and run:
--
-- > @echo #include "my_image.h" > my_image.c
-- > gdk-pixbuf-csource --raw --extern --name=my_image myimage.png >> my_image.c
--
--   on it. Write a header file @my_image.h@ containing:
--
-- > #include <gdk/gdk.h>
-- > extern guint8 my_image[];
--
--   and save it in the current directory.
--   The created file can be compiled with: 
--
-- > cc -c my_image.c `pkg-config --cflags gdk-2.0`
--
--    into an object file which must be linked into your Haskell program by
--   specifying @my_image.o@ and @\"-#include my_image.h\"@ on
--   the command line of GHC.
--   Within you application you delcare a pointer to this image:
--
-- > foreign label "my_image" myImage :: Ptr InlineImage
--
--   Calling 'pixbufNewFromInline' with this pointer will
--   return the image in the object file. Creating the C file with
--   the @--raw@ flag will result in a non-compressed image in the
--   object file. The advantage is that the picture will not be
--   copied when this function is called.
--
--
pixbufNewFromInline :: Ptr InlineImage -> IO Pixbuf
pixbufNewFromInline iPtr = alloca $ \errPtrPtr -> do
  pbPtr <- {#call unsafe pixbuf_new_from_inline#} (-1) (castPtr iPtr)
    (fromBool False) (castPtr errPtrPtr)
  if pbPtr/=nullPtr then constructNewGObject mkPixbuf (return pbPtr)
    else do
      errPtr <- peek errPtrPtr
      (GError dom code msg) <- peek errPtr
      error msg

-- | Create a restricted view of an image.
--
-- * This function returns a 'Pixbuf' object which shares
--   the image of the original one but only shows a part of it.
--   Modifying either buffer will affect the other.
--
-- * This function throw an exception if the requested bounds are invalid.
--
pixbufNewSubpixbuf :: Pixbuf -> Int -> Int -> Int -> Int -> IO Pixbuf
pixbufNewSubpixbuf pb srcX srcY height width =
  constructNewGObject mkPixbuf $ do
    pbPtr <- {#call unsafe pixbuf_new_subpixbuf#} pb
      (fromIntegral srcX) (fromIntegral srcY)
      (fromIntegral height) (fromIntegral width)
    if pbPtr==nullPtr then error "pixbufNewSubpixbuf: invalid bounds"
      else return pbPtr

-- | Create a deep copy of an image.
--
pixbufCopy :: Pixbuf -> IO Pixbuf
pixbufCopy pb = constructNewGObject mkPixbuf $ {#call unsafe pixbuf_copy#} pb


-- | How an image is scaled.
--
-- [@InterpNearest@] Nearest neighbor sampling; this is the
--   fastest and lowest quality mode. Quality is normally unacceptable when
--   scaling down, but may be OK when scaling up.
--
-- [@InterpTiles@] This is an accurate simulation of the
--   PostScript image operator without any interpolation enabled. Each
--   pixel is rendered as a tiny parallelogram of solid color, the edges of
--   which are implemented with antialiasing. It resembles nearest neighbor
--   for enlargement, and bilinear for reduction.
--
-- [@InterpBilinear@] Best quality\/speed balance; use this
--   mode by default. Bilinear interpolation. For enlargement, it is
--   equivalent to point-sampling the ideal bilinear-interpolated
--   image. For reduction, it is equivalent to laying down small tiles and
--   integrating over the coverage area.
--
-- [@InterpHyper@] This is the slowest and highest quality
--   reconstruction function. It is derived from the hyperbolic filters in
--   Wolberg's \"Digital Image Warping\", and is formally defined as the
--   hyperbolic-filter sampling the ideal hyperbolic-filter interpolated
--   image (the filter is designed to be idempotent for 1:1 pixel mapping).
--
{#enum InterpType {underscoreToCase} #}

-- | Scale an image.
--
-- * Creates a new 'Pixbuf' containing a copy of 
--   @src@ scaled to the given measures. Leaves @src@
--   unaffected. 
--
-- * @interp@ affects the quality and speed of the scaling function.
--   'InterpNearest' is the fastest option but yields very poor quality
--   when scaling down. 'InterpBilinear' is a good trade-off between
--   speed and quality and should thus be used as a default.
--
pixbufScaleSimple :: 
  Pixbuf -- ^ @src@ - the source image
  -> Int -- ^ @width@ - the target width
  -> Int -- ^ @height@ the target height
  -> InterpType -- ^ interpolation type
  -> IO Pixbuf
pixbufScaleSimple pb width height interp =
    constructNewGObject mkPixbuf $ liftM castPtr $
	{#call pixbuf_scale_simple#} (toPixbuf pb)
	(fromIntegral width) (fromIntegral height)
	(fromIntegral $ fromEnum interp)

-- | Copy a scaled image part to another image.
--
-- * This function is the generic version of 'pixbufScaleSimple'. It scales
-- @src@ by @scaleX@ and @scaleY@ and translate the image by @offsetX@ and
-- @offsetY@. Whatever is in the intersection with the rectangle @destX@,
-- @destY@, @destWidth@, @destHeight@ will be rendered into @dest@.
--
-- * The rectangle in the destination is simply overwritten. Use
-- 'pixbufComposite' if you need to blend the source image onto the
-- destination.
--
pixbufScale :: 
    Pixbuf     -- ^ @src@ - the source pixbuf
 -> Pixbuf     -- ^ @dest@ - the pixbuf into which to render the results
 -> Int        -- ^ @destX@ - the left coordinate for region to render
 -> Int        -- ^ @destY@ - the top coordinate for region to render 
 -> Int        -- ^ @destWidth@ - the width of the region to render
 -> Int        -- ^ @destHeight@ - the height of the region to render
 -> Double     -- ^ @offsetX@ - the offset in the X direction (currently
               -- rounded to an integer)
 -> Double     -- ^ @offsetY@ - the offset in the Y direction 
               -- (currently rounded to an integer)
 -> Double     -- ^ @scaleX@ - the scale factor in the X direction
 -> Double     -- ^ @scaleY@ - the scale factor in the Y direction
 -> InterpType -- ^ the interpolation type for the transformation.
 -> IO ()
pixbufScale src dest destX destY destWidth destHeight offsetX offsetY
  scaleX scaleY interp =
  {#call unsafe pixbuf_scale#} src dest
    (fromIntegral destX) (fromIntegral destY)
    (fromIntegral destWidth) (fromIntegral destHeight)
    (realToFrac offsetX) (realToFrac offsetY)
    (realToFrac scaleX) (realToFrac scaleY)
    ((fromIntegral . fromEnum) interp)

-- | Blend a scaled image part onto another image.
--
-- * This function is similar to 'pixbufScale' but allows the
--   original image to \"shine through\". The @alpha@ value determines
--   how opaque the source image is. Passing @0@ is
--   equivalent to not calling this function at all, passing
--   @255@ has the
--   same effect as calling 'pixbufScale'.
--
pixbufComposite ::
     Pixbuf     -- ^ @src@ - the source pixbuf
  -> Pixbuf     -- ^ @dest@ - the pixbuf into which to render the results
  -> Int        -- ^ @destX@ - the left coordinate for region to render
  -> Int        -- ^ @destY@ - the top coordinate for region to render 
  -> Int        -- ^ @destWidth@ - the width of the region to render
  -> Int        -- ^ @destHeight@ - the height of the region to render
  -> Double     -- ^ @offsetX@ - the offset in the X direction (currently
                -- rounded to an integer)
  -> Double     -- ^ @offsetY@ - the offset in the Y direction 
                -- (currently rounded to an integer)
  -> Double     -- ^ @scaleX@ - the scale factor in the X direction
  -> Double     -- ^ @scaleY@ - the scale factor in the Y direction
  -> InterpType -- ^ the interpolation type for the transformation.
  -> Word8 	-- ^ @alpha@ - the transparency
  -> IO ()
pixbufComposite src dest destX destY destWidth destHeight
  offsetX offsetY scaleX scaleY interp alpha =
  {#call unsafe pixbuf_composite#} src dest
  (fromIntegral destX) (fromIntegral destY) (fromIntegral destWidth)
  (fromIntegral destHeight) (realToFrac offsetX) (realToFrac offsetY)
  (realToFrac scaleX) (realToFrac scaleY)
  ((fromIntegral . fromEnum) interp) (fromIntegral alpha)

#if GTK_CHECK_VERSION(2,6,0)
-- | Flips a pixbuf horizontally and returns the result in a new pixbuf.
--
pixbufFlipHorizontally :: Pixbuf -> IO Pixbuf
pixbufFlipHorizontally self =
  constructNewGObject mkPixbuf $
  {# call pixbuf_flip #}
    self
    (fromBool True)
pixbufFlipHorazontally = pixbufFlipHorizontally

-- | Flips a pixbuf vertically and returns the result in a new pixbuf.
--
pixbufFlipVertically :: Pixbuf -> IO Pixbuf
pixbufFlipVertically self =
  constructNewGObject mkPixbuf $
  {# call pixbuf_flip #}
    self
    (fromBool False)

-- | Rotates a pixbuf by a multiple of 90 degrees, and returns the result in a
-- new pixbuf.
--
pixbufRotateSimple :: Pixbuf -> PixbufRotation -> IO Pixbuf
pixbufRotateSimple self angle =
  constructNewGObject mkPixbuf $
  {# call pixbuf_rotate_simple #}
    self
    ((fromIntegral . fromEnum) angle)

-- | The possible rotations which can be passed to 'pixbufRotateSimple'.
--
-- To make them easier to use, their numerical values are the actual degrees.
--
{#enum PixbufRotation {underscoreToCase} #}
#endif

-- | Add an opacity layer to the 'Pixbuf'.
--
-- * This function returns a copy of the given @src@
--   'Pixbuf', leaving @src@ unmodified.
--   The new 'Pixbuf' has an alpha (opacity)
--   channel which defaults to @255@ (fully opaque pixels)
--   unless @src@ already had an alpha channel in which case
--   the original values are kept.
--   Passing in a color triple @(r,g,b)@ makes all
--   pixels that have this color fully transparent
--   (opacity of @0@). The pixel color itself remains unchanged
--   during this substitution.
--
pixbufAddAlpha :: Pixbuf -> Maybe (Word8, Word8, Word8) -> IO Pixbuf
pixbufAddAlpha pb Nothing = constructNewGObject mkPixbuf $
  {#call unsafe pixbuf_add_alpha#} pb (fromBool False) 0 0 0
pixbufAddAlpha pb (Just (r,g,b)) = constructNewGObject mkPixbuf $
  {#call unsafe pixbuf_add_alpha#} pb (fromBool True)
    (fromIntegral r) (fromIntegral g) (fromIntegral b)

-- | Copy a rectangular portion into another 'Pixbuf'.
--
-- The source 'Pixbuf' remains unchanged. Converion between
-- different formats is done automatically.
--
pixbufCopyArea ::
    Pixbuf -- ^ Source pixbuf
 -> Int    -- ^ Source X coordinate within the source pixbuf
 -> Int    -- ^ Source Y coordinate within the source pixbuf
 -> Int    -- ^ Width of the area to copy
 -> Int    -- ^ Height of the area to copy
 -> Pixbuf -- ^ Destination pixbuf
 -> Int    -- ^ X coordinate within the destination pixbuf
 -> Int    -- ^ Y coordinate within the destination pixbuf
 -> IO ()
pixbufCopyArea src srcX srcY srcWidth srcHeight dest destX destY =
  {#call unsafe pixbuf_copy_area#} src
    (fromIntegral srcX) (fromIntegral srcY)
    (fromIntegral srcWidth) (fromIntegral srcHeight)
    dest (fromIntegral destX) (fromIntegral destY)

-- | Fills a 'Pixbuf' with a color.
--
-- * The passed-in color is a quadruple consisting of the red, green, blue
--   and alpha component of the pixel. If the 'Pixbuf' does not
--   have an alpha channel, the alpha value is ignored.
--
pixbufFill :: Pixbuf -> Word8 -> Word8 -> Word8 -> Word8 -> IO ()
pixbufFill pb red green blue alpha = {#call unsafe pixbuf_fill#} pb
  ((fromIntegral red)   `shiftL` 24 .|.
   (fromIntegral green) `shiftL` 16 .|.
   (fromIntegral blue)  `shiftL`  8 .|.
   (fromIntegral alpha))

-- | Take a screenshot of a 'Drawable'.
--
-- * This function creates a 'Pixbuf' and fills it with the image
--   currently in the 'Drawable' (which might be invalid if the
--   window is obscured or minimized). Note that this transfers data from
--   the server to the client on X Windows.
--
-- * This function will return a 'Pixbuf' with no alpha channel
--   containing the part of the 'Drawable' specified by the
--   rectangle. The function will return @Nothing@ if the window
--   is not currently visible.
--
pixbufGetFromDrawable :: DrawableClass d => d -> Rectangle -> IO (Maybe Pixbuf)
pixbufGetFromDrawable d (Rectangle x y width height) =
  maybeNull (constructNewGObject mkPixbuf) $
  {#call unsafe pixbuf_get_from_drawable#}
    (Pixbuf nullForeignPtr) (toDrawable d) (Colormap nullForeignPtr)
    (fromIntegral x) (fromIntegral y) 0 0
    (fromIntegral width) (fromIntegral height)



-- | Takes the opacity values in a rectangular portion of a pixbuf and
-- thresholds them to produce a bi-level alpha mask that can be used
-- as a clipping mask for a drawable.
pixbufRenderThresholdAlpha ::
    Pixbuf -- ^ A pixbuf.
 -> Bitmap -- ^ Bitmap where the bilevel mask will be painted to.
 -> Int  -- ^ Source X coordinate.
 -> Int  -- ^ source Y coordinate.
 -> Int -- ^ Destination X coordinate.
 -> Int -- ^ Destination Y coordinate.
 -> Int -- ^ Width of region to threshold, or -1 to use pixbuf width
 -> Int -- ^ Height of region to threshold, or -1 to use pixbuf height
 -> Int -- ^ Opacity values below this will be painted as zero; all other values will be painted as one.
 -> IO ()
pixbufRenderThresholdAlpha src dest srcX srcY destX destY w h at =
  withForeignPtr (unPixmap dest) $ \destPtr ->
  {#call unsafe pixbuf_render_threshold_alpha#} src
                                                (castPtr destPtr)
                                                (fromIntegral srcX)
                                                (fromIntegral srcY)
                                                (fromIntegral destX)
                                                (fromIntegral destY)
                                                (fromIntegral w)
                                                (fromIntegral h)
                                                (fromIntegral at)





-- | Creates a pixmap and a mask bitmap which are returned and renders
-- a pixbuf and its corresponding thresholded alpha mask to them. This
-- is merely a convenience function; applications that need to render
-- pixbufs with dither offsets or to given drawables should use
-- 'Graphics.UI.Gtk.Gdk.Drawable.drawPixbuf', and
-- 'pixbufRenderThresholdAlpha'.
--
-- The pixmap that is created uses the 'Colormap' specified by
-- colormap. This colormap must match the colormap of the window where
-- the pixmap will eventually be used or an error will result.
--
-- If the pixbuf does not have an alpha channel, then the returned
-- mask will be @Nothing@.
--
pixbufRenderPixmapAndMaskForColormap ::
    Pixbuf                    -- ^ A pixbuf.
 -> Colormap                  -- ^ A Colormap
 -> Int                       -- ^ Threshold value for opacity values
 -> IO (Pixmap, Maybe Bitmap) -- ^ (Created pixmap, created mask)
pixbufRenderPixmapAndMaskForColormap pixbuf colormap threshold =
  alloca $ \pmRetPtr ->
    alloca $ \bmRetPtr -> do
      {#call unsafe pixbuf_render_pixmap_and_mask_for_colormap#} pixbuf
                                                                 colormap
                                                                 (castPtr pmRetPtr) -- seems to reject Pixmap**, so cast
                                                                 (castPtr bmRetPtr)
                                                                 (fromIntegral threshold)
      pm <- constructNewGObject mkPixmap (peek pmRetPtr :: IO (Ptr Pixmap))
      bm <- maybeNull (constructNewGObject mkPixmap) (peek bmRetPtr :: IO (Ptr Bitmap))
      return (pm, bm)