]> gitweb.factorcode.org Git - factor.git/blob - basis/images/loader/gdiplus/gdiplus.factor
Update some copyright headers to follow the current convention
[factor.git] / basis / images / loader / gdiplus / gdiplus.factor
1 ! Copyright (C) 2010 Joe Groff.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors alien alien.c-types alien.data alien.enums alien.strings
4 assocs byte-arrays classes.struct destructors grouping images images.loader
5 io kernel libc locals math mime.types namespaces sequences specialized-arrays
6 system windows.com windows.gdiplus windows.streams windows.types ;
7 IN: images.loader.gdiplus
8
9 SPECIALIZED-ARRAY: ImageCodecInfo
10
11 SINGLETON: gdi+-image
12
13 os windows? [
14     { "png" "tif" "tiff" "gif" "jpg" "jpeg" "bmp" "ico" }
15     [ gdi+-image register-image-class ] each
16 ] when
17
18 <PRIVATE
19
20 : <GpRect> ( x y w h -- rect )
21     GpRect <struct-boa> ; inline
22
23 : stream>gdi+-bitmap ( stream -- bitmap )
24     stream>IStream &com-release
25     { void* } [ GdipCreateBitmapFromStream check-gdi+-status ]
26     with-out-parameters &GdipFree ;
27
28 : gdi+-bitmap-width ( bitmap -- w )
29     { UINT } [ GdipGetImageWidth check-gdi+-status ]
30     with-out-parameters ;
31
32 : gdi+-bitmap-height ( bitmap -- h )
33     { UINT } [ GdipGetImageHeight check-gdi+-status ]
34     with-out-parameters ;
35
36 :: gdi+-lock-bitmap ( bitmap rect mode format -- data )
37     ! Copy the rect to stack space because the gc might move it
38     ! because calling GdipBitmapLockBits triggers callbacks to Factor.
39     { BitmapData GpRect } [
40         :> ( stack-data stack-rect )
41         stack-rect rect binary-object memcpy
42         bitmap stack-rect mode format stack-data GdipBitmapLockBits
43         check-gdi+-status
44     ] with-out-parameters drop ;
45
46 :: gdi+-bitmap>data ( bitmap -- w h pixels )
47     bitmap [ gdi+-bitmap-width ] [ gdi+-bitmap-height ] bi :> ( w h )
48     bitmap 0 0 w h <GpRect> ImageLockModeRead enum>number
49     PixelFormat32bppARGB gdi+-lock-bitmap :> bitmap-data
50     bitmap-data [ Scan0>> ] [ Stride>> ] [ Height>> * ] tri
51     memory>byte-array :> pixels
52     bitmap bitmap-data GdipBitmapUnlockBits check-gdi+-status
53     w h pixels ;
54
55 :: data>image ( w h pixels -- image )
56     image new
57         { w h } >>dim
58         pixels >>bitmap
59         BGRA >>component-order
60         ubyte-components >>component-type
61         f >>upside-down? ;
62
63 ! Loaded images usually have the format BGRA, text rendered BGRX.
64 ERROR: unsupported-pixel-format component-order ;
65
66 : check-pixel-format ( component-order -- )
67     dup { BGRX BGRA } member? [ drop ] [ unsupported-pixel-format ] if ;
68
69 : image>gdi+-bitmap ( image -- bitmap )
70     dup component-order>> check-pixel-format
71     [ dim>> first2 ] [ rowstride PixelFormat32bppARGB ] [ bitmap>> ] tri
72     { void* } [
73         GdipCreateBitmapFromScan0 check-gdi+-status
74     ] with-out-parameters &GdipFree ;
75
76 : image-encoders-size ( -- num size )
77     { UINT UINT } [
78         GdipGetImageEncodersSize check-gdi+-status
79     ] with-out-parameters ;
80
81 : image-encoders ( -- codec-infos )
82     image-encoders-size dup <byte-array> 3dup
83     GdipGetImageEncoders check-gdi+-status
84     nip swap ImageCodecInfo <c-direct-array> ;
85
86 : extension>mime-type ( extension -- mime-type )
87     ! Crashes if you let this mime through on my machine.
88     dup mime-types at dup "image/bmp" = [ unknown-image-extension ] when nip ;
89
90 : mime-type>clsid ( mime-type -- clsid )
91     image-encoders [ MimeType>> alien>native-string = ] with find nip Clsid>> ;
92
93 : startup-gdi+ ( -- )
94     start-gdi+ &stop-gdi+ drop ;
95
96 : write-image-to-stream ( image stream extension -- )
97     [ image>gdi+-bitmap ]
98     [ stream>IStream &com-release ]
99     [ extension>mime-type mime-type>clsid ] tri*
100     f GdipSaveImageToStream check-gdi+-status ;
101
102 PRIVATE>
103
104 M: gdi+-image stream>image*
105     drop startup-gdi+
106     stream>gdi+-bitmap
107     gdi+-bitmap>data
108     data>image ;
109
110 M: gdi+-image image>stream ( image extension class -- )
111     drop startup-gdi+ output-stream get swap write-image-to-stream ;