1 // GnashImageGif.cpp: gif_lib wrapper for Gnash.
3 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 3 of the License, or
9 // (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 #include "GnashImageGif.h"
25 #include <boost/scoped_array.hpp>
33 #include "GnashException.h"
34 #include "IOChannel.h"
43 readData(GifFileType
* ft
, GifByteType
* data
, int length
)
45 // Do not read until opened.
47 IOChannel
* in
= reinterpret_cast<IOChannel
*>(ft
->UserData
);
48 return in
->read(reinterpret_cast<char*>(data
), length
);
53 GifInput::GifInput(boost::shared_ptr
<IOChannel
> in
)
63 // Clean up allocated data.
68 GifInput::getHeight() const
75 GifInput::getWidth() const
82 GifInput::readScanline(unsigned char* rgbData
)
85 const ColorMapObject
* const colormap
= (_gif
->Image
.ColorMap
) ?
86 _gif
->Image
.ColorMap
: _gif
->SColorMap
;
90 unsigned char* ptr
= rgbData
;
92 for (size_t i
= 0, e
= getWidth(); i
< e
; ++i
) {
94 const GifColorType
* const mapentry
=
95 &colormap
->Colors
[_gifData
[_currentRow
][i
]];
97 *ptr
++ = mapentry
->Red
;
98 *ptr
++ = mapentry
->Green
;
99 *ptr
++ = mapentry
->Blue
;
109 _gif
= DGifOpen(_inStream
.get(), &readData
);
111 GifRecordType record
;
113 // Parse the (first?) image into memory.
114 // Is there a multi-dimensional smart array? It's silly to
115 // have to allocate each row separately and can mean a lot
119 if (DGifGetRecordType(_gif
, &record
) != GIF_OK
) {
120 throw ParserException(_("GIF: Error retrieving record type"));
125 case IMAGE_DESC_RECORD_TYPE
:
127 // Fill the _gif->Image fields
128 if (DGifGetImageDesc(_gif
) != GIF_OK
) {
129 throw ParserException(_("GIF: Error retrieving image "
132 const int backgroundColor
= _gif
->SBackGroundColor
;
134 // Set the height dimension of the array
135 _gifData
.reset(new PixelRow
[getHeight()]);
137 // The GIF 'screen' width and height
138 const size_t screenWidth
= getWidth();
139 const size_t screenHeight
= getHeight();
141 // Set all the pixels to the background colour.
142 for (size_t i
= 0; i
< screenHeight
; ++i
) {
143 // Set the width dimension of the array
144 _gifData
[i
].reset(new GifPixelType
[screenWidth
]);
145 // Fill all the pixels with the background color.
146 std::fill_n(_gifData
[i
].get(), screenWidth
,
150 // The position of the image on the GIF 'screen'
151 const size_t imageHeight
= _gif
->Image
.Height
;
152 const size_t imageWidth
= _gif
->Image
.Width
;
153 const size_t imageTop
= _gif
->Image
.Top
;
154 const size_t imageLeft
= _gif
->Image
.Left
;
156 if (imageHeight
+ imageTop
> screenHeight
||
157 imageWidth
+ imageLeft
> screenWidth
) {
158 throw ParserException(_("GIF: invalid image data "
159 "(bounds outside GIF screen)"));
162 // Handle interlaced data in four passes.
163 if (_gif
->Image
.Interlace
) {
164 log_debug(_("Found interlaced GIF (%d x %d)"),
165 screenWidth
, screenHeight
);
167 // The order of interlaced GIFs.
168 const int interlacedOffsets
[] = { 0, 4, 2, 1 };
169 const int interlacedJumps
[] = { 8, 8, 4, 2 };
171 for (size_t i
= 0; i
< 4; ++i
) {
173 for (size_t j
= imageTop
+ interlacedOffsets
[i
];
174 j
< imageTop
+ imageHeight
;
175 j
+= interlacedJumps
[i
]) {
177 if (DGifGetLine(_gif
, &_gifData
[j
][imageLeft
],
178 imageWidth
) != GIF_OK
) {
180 throw ParserException(_("GIF: failed reading "
189 // Non-interlaced data.
190 log_debug(_("Found non-interlaced GIF (%d x %d)"),
191 screenWidth
, screenHeight
);
193 for (size_t i
= imageTop
; i
< imageHeight
; ++i
) {
194 // Read the gif data into the gif array.
195 if (DGifGetLine(_gif
, &_gifData
[i
][imageLeft
], imageWidth
)
197 throw ParserException(_("GIF: failed reading "
203 case EXTENSION_RECORD_TYPE
:
204 // Skip all extension records.
205 GifByteType
* extension
;
207 DGifGetExtension(_gif
, &extCode
, &extension
);
209 if (DGifGetExtensionNext(_gif
, &extension
) == GIF_ERROR
) {
217 } while (record
!= TERMINATE_RECORD_TYPE
);
219 // Set the type to RGB
220 // TODO: implement RGBA!
232 // indent-tabs-mode: t