2 * QImageIO Routines to read/write XV images.
3 * copyright (c) 1998 Torben Weis <weis@kde.org>
4 * copyright (c) 1999 Oliver Eiden <o.eiden@pop.ruhr.de>
6 * This library is distributed under the conditions of the GNU LGPL.
14 #include <QtGui/QImage>
18 static const int b_255_3
[]= {0,85,170,255}, // index*255/3
19 rg_255_7
[]={0,36,72,109,145,182,218,255}; // index *255/7
22 XVHandler::XVHandler()
26 bool XVHandler::canRead() const
28 if (canRead(device())) {
35 bool XVHandler::read(QImage
*retImage
)
40 QIODevice
*iodev
= device();
44 // magic number must be "P7 332"
45 iodev
->readLine( str
, BUFSIZE
);
46 if (strncmp(str
,"P7 332",6))
49 // next line #XVVERSION
50 iodev
->readLine( str
, BUFSIZE
);
51 if (strncmp(str
, "#XVVERSION", 10))
54 // now it gets interesting, #BUILTIN means we are out.
55 // if IMGINFO comes, we are happy!
56 iodev
->readLine( str
, BUFSIZE
);
57 if (strncmp(str
, "#IMGINFO:", 9))
60 // after this an #END_OF_COMMENTS signals everything to be ok!
61 iodev
->readLine( str
, BUFSIZE
);
62 if (strncmp(str
, "#END_OF", 7))
65 // now a last line with width, height, maxval which is
67 iodev
->readLine( str
, BUFSIZE
);
68 sscanf(str
, "%d %d %d", &x
, &y
, &maxval
);
73 if(x
< 0 || y
< 0 || blocksize
< x
|| blocksize
< y
)
76 // now follows a binary block of x*y bytes.
77 char *block
= (char*) malloc(blocksize
);
81 if (iodev
->read(block
, blocksize
) != blocksize
)
88 QImage
image( x
, y
, QImage::Format_Indexed8
);
90 numColors
= qMin( maxval
+ 1, 0 );
91 numColors
= qMax( 0, maxval
+ 1 );
92 image
.setNumColors( numColors
);
94 // how do the color handling? they are absolute 24bpp
95 // or at least can be calculated as such.
98 for ( int j
= 0; j
< 256; j
++ )
100 r
= rg_255_7
[((j
>> 5) & 0x07)];
101 g
= rg_255_7
[((j
>> 2) & 0x07)];
102 b
= b_255_3
[((j
>> 0) & 0x03)];
103 image
.setColor( j
, qRgb( r
, g
, b
) );
106 for ( int py
= 0; py
< y
; py
++ )
108 uchar
*data
= image
.scanLine( py
);
109 memcpy( data
, block
+ py
* x
, x
);
118 bool XVHandler::write(const QImage
&image
)
120 QIODevice
& f
= *( device() );
122 // Removed "f.open(...)" and "f.close()" (tanghus)
124 int w
= image
.width(), h
= image
.height();
128 // magic number must be "P7 332"
129 f
.write( "P7 332\n", 7 );
131 // next line #XVVERSION
132 f
.write( "#XVVERSION:\n", 12 );
134 // now it gets interesting, #BUILTIN means we are out.
135 // if IMGINFO comes, we are happy!
136 f
.write( "#IMGINFO:\n", 10 );
138 // after this an #END_OF_COMMENTS signals everything to be ok!
139 f
.write( "#END_OF_COMMENTS:\n", 18 );
141 // now a last line with width, height, maxval which is supposed to be 255
142 sprintf( str
, "%i %i 255\n", w
, h
);
143 f
.write( str
, strlen( str
) );
146 QImage
tmpImage( image
);
147 if ( image
.depth() == 1 )
148 tmpImage
= image
.convertToFormat( QImage::Format_Indexed8
, Qt::AutoColor
);
150 uchar
* buffer
= new uchar
[ w
];
152 for ( int py
= 0; py
< h
; py
++ )
154 const uchar
*data
= tmpImage
.scanLine( py
);
155 for ( int px
= 0; px
< w
; px
++ )
158 if ( tmpImage
.depth() == 32 )
160 const QRgb
*data32
= (QRgb
*) data
;
161 r
= qRed( *data32
) >> 5;
162 g
= qGreen( *data32
) >> 5;
163 b
= qBlue( *data32
) >> 6;
164 data
+= sizeof( QRgb
);
168 QRgb color
= tmpImage
.color( *data
);
169 r
= qRed( color
) >> 5;
170 g
= qGreen( color
) >> 5;
171 b
= qBlue( color
) >> 6;
174 buffer
[ px
] = ( r
<< 5 ) | ( g
<< 2 ) | b
;
176 f
.write( (const char*)buffer
, w
);
183 QByteArray
XVHandler::name() const
188 bool XVHandler::canRead(QIODevice
*device
)
191 qWarning("XVHandler::canRead() called with no device");
195 qint64 oldPos
= device
->pos();
198 qint64 readBytes
= device
->read(head
, sizeof(head
));
199 if (readBytes
!= sizeof(head
)) {
200 if (device
->isSequential()) {
201 while (readBytes
> 0)
202 device
->ungetChar(head
[readBytes
-- - 1]);
204 device
->seek(oldPos
);
209 if (device
->isSequential()) {
210 while (readBytes
> 0)
211 device
->ungetChar(head
[readBytes
-- - 1]);
213 device
->seek(oldPos
);
216 return qstrncmp(head
, "P7 332", 6) == 0;
220 class XVPlugin
: public QImageIOPlugin
223 QStringList
keys() const;
224 Capabilities
capabilities(QIODevice
*device
, const QByteArray
&format
) const;
225 QImageIOHandler
*create(QIODevice
*device
, const QByteArray
&format
= QByteArray()) const;
228 QStringList
XVPlugin::keys() const
230 return QStringList() << "xv";
233 QImageIOPlugin::Capabilities
XVPlugin::capabilities(QIODevice
*device
, const QByteArray
&format
) const
236 return Capabilities(CanRead
| CanWrite
);
237 if (!format
.isEmpty())
239 if (!device
->isOpen())
243 if (device
->isReadable() && XVHandler::canRead(device
))
245 if (device
->isWritable())
250 QImageIOHandler
*XVPlugin::create(QIODevice
*device
, const QByteArray
&format
) const
252 QImageIOHandler
*handler
= new XVHandler
;
253 handler
->setDevice(device
);
254 handler
->setFormat(format
);
258 Q_EXPORT_STATIC_PLUGIN(XVPlugin
)
259 Q_EXPORT_PLUGIN2(xv
, XVPlugin
)