1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // INTEL CORPORATION PROPRIETARY INFORMATION
4 // This software is supplied under the terms of a license agreement or
5 // nondisclosure agreement with Intel Corporation and may not be copied
6 // or disclosed except in accordance with the terms of that agreement.
7 // Copyright (c) 1999 Intel Corporation. All Rights Reserved.
10 // Source: rd_rle.cpp$
14 // Authors: Vadim Pisarevsky
22 /************************ Common functions *****************************/
24 static byte* fill_uni( byte* data, byte* line_end, int width3, int delta,
25 int x_shift3, int y_shift, palette_entry clr, int color )
27 int new_x3 = (data - (line_end - width3)) + x_shift3;
31 cvt_bgr_to_gray( (byte*)&clr, &gr_val, 1 );
38 for( byte* end = y_shift == 0 ? (line_end - width3) + new_x3 : line_end;
39 data < end; data += 3 )
41 WRITE_PIX( data, clr );
46 for( byte* end = y_shift == 0 ? (line_end - width3) + new_x3 : line_end;
52 if( y_shift == 0 ) break;
53 data = line_end + delta;
54 line_end = data + width3;
60 static byte* fill_row32( byte* data, byte* src, int len )
62 for( byte* end = data + len*3; (data += 3) < end; src += 4 )
64 *((palette_entry*)(data-3)) = *((palette_entry*)src);
66 palette_entry clr = *((palette_entry*)src);
67 WRITE_PIX( data - 3, clr );
72 static byte* fill_color_row8( byte* data, byte* indices, int len, palette_entry* palette )
74 byte* end = data + len*3;
75 while( (data += 3) < end )
77 *((palette_entry*)(data-3)) = palette[*indices++];
79 palette_entry clr = palette[indices[0]];
80 WRITE_PIX( data - 3, clr );
85 static byte* fill_gray_row8( byte* data, byte* indices, int len, byte* palette )
88 for( i = 0; i < len; i++ )
90 data[i] = palette[indices[i]];
96 static byte* fill_color_row4( byte* data, byte* indices, int len, palette_entry* palette )
98 byte* end = data + len*3;
100 while( (data += 6) < end )
102 int idx = *indices++;
103 *((palette_entry*)(data-6)) = palette[idx >> 4];
104 *((palette_entry*)(data-3)) = palette[idx & 15];
107 int idx = indices[0];
108 palette_entry clr = palette[idx >> 4];
109 WRITE_PIX( data - 6, clr );
113 clr = palette[idx & 15];
114 WRITE_PIX( data - 3, clr );
120 static byte* fill_gray_row4( byte* data, byte* indices, int len, byte* palette )
122 byte* end = data + len;
123 while( (data += 2) < end )
125 int idx = *indices++;
126 data[-2] = palette[idx >> 4];
127 data[-1] = palette[idx & 15];
130 int idx = indices[0];
131 byte clr = palette[idx >> 4];
136 clr = palette[idx & 15];
143 static byte* fill_row1( byte* data, byte* indices, int len, palette_entry* palette )
145 byte* end = data + len*3;
146 long clr0 = ((long*)palette)[0];
147 long clr1 = ((long*)palette)[1] ^ clr0;
149 while( (data += 24) < end )
151 int idx = *indices++;
152 *((long*)(data -24)) = (clr1 & (idx & 128 ? -1 : 0)) ^ clr0;
153 *((long*)(data -21)) = (clr1 & (idx & 64 ? -1 : 0)) ^ clr0;
154 *((long*)(data -18)) = (clr1 & (idx & 32 ? -1 : 0)) ^ clr0;
155 *((long*)(data -15)) = (clr1 & (idx & 16 ? -1 : 0)) ^ clr0;
156 *((long*)(data -12)) = (clr1 & (idx & 8 ? -1 : 0)) ^ clr0;
157 *((long*)(data - 9)) = (clr1 & (idx & 4 ? -1 : 0)) ^ clr0;
158 *((long*)(data - 6)) = (clr1 & (idx & 2 ? -1 : 0)) ^ clr0;
159 *((long*)(data - 3)) = (clr1 & (idx & 1 ? -1 : 0)) ^ clr0;
162 int idx = indices[0] << 24;
163 for( data -= 24; data < end; data += 3, idx += idx )
165 palette_entry clr = palette[idx < 0];
166 WRITE_PIX( data, clr );
173 /************************ BMP reader *****************************/
175 grfmt_bmp_reader::grfmt_bmp_reader()
179 m_description = "Windows bitmap (*.bmp;*.dib)";
181 m_width = m_height = -1;
186 int grfmt_bmp_reader::get_color()
188 return m_bpp > 8 ? 1 : -1;
192 void grfmt_bmp_reader::close()
198 bool grfmt_bmp_reader::read_header()
202 assert( strlen(m_filename) != 0 );
203 if( !m_strm.open( m_filename )) return false;
208 m_offset = m_strm.get_dword();
210 int size = m_strm.get_dword();
214 m_width = m_strm.get_dword();
215 m_height = m_strm.get_dword();
216 m_bpp = m_strm.get_dword() >> 16;
217 m_rle_code = m_strm.get_dword();
219 int clrused = m_strm.get_dword();
220 m_strm.skeep( size - 36 );
222 if( m_width > 0 && m_height > 0 &&
223 (((m_bpp == 1 || m_bpp == 4 || m_bpp == 8 ||
224 m_bpp == 24 || m_bpp == 32 ) && m_rle_code == 0) ||
225 (m_bpp == 4 && m_rle_code == 2) || (m_bpp == 8 && m_rle_code == 1)))
229 memset( m_palette, 0, sizeof(m_palette));
230 m_strm.get_bytes( m_palette, (clrused == 0? 1<<m_bpp : clrused)*4 );
235 else if( size == 12 )
237 m_width = m_strm.get_word();
238 m_height = m_strm.get_word();
239 m_bpp = m_strm.get_dword() >> 16;
242 if( m_width > 0 && m_height > 0 &&
243 (m_bpp == 1 || m_bpp == 4 || m_bpp == 8 ||
244 m_bpp == 24 || m_bpp == 32 ))
249 int j, clrused = 1 << m_bpp;
250 m_strm.get_bytes( buffer, clrused*3 );
251 for( j = 0; j < clrused; j++ )
253 m_palette[j].b = buffer[3*j+0];
254 m_palette[j].g = buffer[3*j+1];
255 m_palette[j].r = buffer[3*j+2];
269 m_width = m_height = -1;
275 bool grfmt_bmp_reader::read_data( byte* data, int pitch, int color )
277 const int buffer_size = 1 << 12;
278 byte buffer[buffer_size];
279 byte bgr_buffer[buffer_size];
280 byte gray_palette[256];
283 byte* bgr = bgr_buffer;
284 int src_pitch = ((m_width*m_bpp + 7)/8 + 3) & -4;
285 int nch = color ? 3 : 1;
286 int width3 = m_width*nch;
287 int delta = -(width3 + pitch);
290 if( m_offset < 0 || !m_strm.is_opened())
293 data += (m_height - 1)*pitch;
297 if( src_pitch+32 > buffer_size ) src = new byte[src_pitch+32];
304 cvt_palette_to_gray( m_palette, gray_palette, 1 << m_bpp );
306 if( m_width*3 + 32 > buffer_size ) bgr = new byte[m_width*3 + 32];
311 m_strm.set_pos( m_offset );
315 /************************* 1 BPP ************************/
317 for( y = 0; y < m_height; y++, data -= pitch )
319 m_strm.get_bytes( src, src_pitch );
320 fill_row1( color ? data : bgr, src, m_width, m_palette );
321 if( !color ) cvt_bgr_to_gray( bgr, data, m_width );
326 /************************* 4 BPP ************************/
328 if( m_rle_code == 0 )
330 for( y = 0; y < m_height; y++, data -= pitch )
332 m_strm.get_bytes( src, src_pitch );
334 fill_color_row4( data, src, m_width, m_palette );
336 fill_gray_row4( data, src, m_width, gray_palette );
340 else if( m_rle_code == 2 ) // rle4 compression
342 byte* line_end = data + width3;
347 int code = m_strm.get_word();
348 int len = code & 255;
350 if( len != 0 ) // encoded mode
352 palette_entry clr[2];
354 clr[0] = m_palette[code >> 4];
355 clr[1] = m_palette[code & 15];
356 byte* end = data + len*nch;
357 if( end > line_end ) goto decode_rle4_bad;
362 WRITE_PIX( data, clr[t] );
366 WRITE_PIX( bgr, clr[t] );
367 cvt_bgr_to_gray( bgr, data, 1 );
371 while( (data += nch) < end );
373 else if( code > 2 ) // absolute mode
375 if( data + code*nch > line_end ) goto decode_rle4_bad;
376 m_strm.get_bytes( src, (((code + 1)>>1) + 1) & -2 );
378 data = fill_color_row4( data, src, code, m_palette );
380 data = fill_gray_row4( data, src, code, gray_palette );
384 if( code == 0 ) // line end
386 if( data < line_end )
388 fill_uni( data, line_end, width3, delta,
389 line_end - data, 0, m_palette[0], color );
391 data = line_end + delta;
392 line_end = data + width3;
393 if( ++y == m_height ) goto decode_rle4_good;
395 else if( code == 1 ) // image end
396 goto decode_rle4_good;
399 int x_shift3 = m_strm.get_byte()*nch;
400 int y_shift = m_strm.get_byte();
402 if( (y += y_shift) >= m_height ||
403 data + x_shift3 > line_end ) goto decode_rle4_bad;
405 data = fill_uni( data, line_end, width3, delta,
406 x_shift3, y_shift, m_palette[0], color );
407 line_end -= pitch*y_shift;
417 /************************* 8 BPP ************************/
419 if( m_rle_code == 0 )
421 for( y = 0; y < m_height; y++, data -= pitch )
423 m_strm.get_bytes( src, src_pitch );
425 fill_color_row8( data, src, m_width, m_palette );
427 fill_gray_row8( data, src, m_width, gray_palette );
431 else if( m_rle_code == 1 ) // rle8 compression
433 byte* line_end = data + width3;
438 int code = m_strm.get_word();
439 int len = code & 255;
441 if( len != 0 ) // encoded mode
444 if( data + len > line_end ) goto decode_rle8_bad;
445 data = fill_uni( data, line_end, width3, delta,
446 len, 0, m_palette[code], color );
448 else if( code > 2 ) // absolute mode
450 int code3 = code*nch;
451 if( data + code3 > line_end ) goto decode_rle8_bad;
452 m_strm.get_bytes( src, (code + 1) & -2 );
454 data = fill_color_row8( data, src, code, m_palette );
456 data = fill_gray_row8( data, src, code, gray_palette );
460 if( code == 0 ) // line end
462 if( data < line_end )
464 fill_uni( data, line_end, width3, delta,
465 line_end - data, 0, m_palette[0], color );
467 data = line_end + delta;
468 line_end = data + width3;
469 if( ++y == m_height ) goto decode_rle8_good;
471 else if( code == 1 ) // image end
472 goto decode_rle8_good;
475 int x_shift3 = m_strm.get_byte()*nch;
476 int y_shift = m_strm.get_byte();
478 if( (y += y_shift) >= m_height ||
479 data + x_shift3 > line_end ) goto decode_rle8_bad;
481 data = fill_uni( data, line_end, width3, delta,
482 x_shift3, y_shift, m_palette[0], color );
483 line_end -= pitch*y_shift;
492 /************************* 24 BPP ************************/
494 for( y = 0; y < m_height; y++, data -= pitch )
496 m_strm.get_bytes( color ? data : bgr, src_pitch );
497 if( !color ) cvt_bgr_to_gray( bgr, data, m_width );
501 /************************* 32 BPP ************************/
503 for( y = 0; y < m_height; y++, data -= pitch )
505 m_strm.get_bytes( src, src_pitch );
506 fill_row32( color ? data : bgr, src, m_width );
507 if( !color ) cvt_bgr_to_gray( bgr, data, m_width );
517 if( src != buffer ) delete src;
518 if( bgr != bgr_buffer ) delete bgr;
522 /************************ Sun raster reader (very simple) *****************************/
524 grfmt_sun_raster_reader::grfmt_sun_raster_reader()
527 m_signature ="\x59\xA6\x6A\x95";
528 m_description = "Sun raster files (*.sr)";
530 m_width = m_height = -1;
534 void grfmt_sun_raster_reader::close()
540 bool grfmt_sun_raster_reader::read_header()
544 assert( strlen(m_filename) != 0 );
545 if( !m_strm.open( m_filename )) return false;
550 m_width = m_strm.get_dword();
551 m_height = m_strm.get_dword();
552 m_bpp = m_strm.get_dword();
554 int type = m_strm.get_dword();
557 if( m_width > 0 && m_height > 0 && m_bpp == 24 && (type == 1 || type == 0))
570 m_width = m_height = -1;
577 int grfmt_sun_raster_reader::get_color()
579 return m_bpp > 8 ? 1 : 0;
583 bool grfmt_sun_raster_reader::read_data( byte* data, int pitch, int color )
585 const int buffer_size = 1 << 12;
586 byte bgr_buffer[buffer_size];
587 byte* bgr = bgr_buffer;
589 int src_pitch = ((m_width*m_bpp + 7)/8 + 1) & -2;
592 if( m_offset < 0 || !m_strm.is_opened() )
597 if( m_width*3 + 32 > buffer_size ) bgr = new byte[m_width*3 + 32];
602 m_strm.set_pos( m_offset );
606 /************************* 24 BPP ************************/
608 for( y = 0; y < m_height; y++, data += pitch )
610 m_strm.get_bytes( color ? data : bgr, src_pitch );
611 if( !color ) cvt_bgr_to_gray( bgr, data, m_width );
621 if( bgr != bgr_buffer ) delete bgr;