00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #undef LOCAL_DEBUG
00022 #undef DO_CLOCKING
00023 #undef DEBUG_TRANSP_GIF
00024
00025 #ifdef _WIN32
00026 # include "win32/config.h"
00027 # include <windows.h>
00028 # include "win32/afterbase.h"
00029 #else
00030 # include "config.h"
00031 # include <string.h>
00032 # include "afterbase.h"
00033 #endif
00034
00035 #include "asimage.h"
00036 #include "imencdec.h"
00037 #include "bmp.h"
00038
00039
00040 void
00041 dib_data_to_scanline( ASScanline *buf,
00042 BITMAPINFOHEADER *bmp_info, CARD8 *gamma_table,
00043 CARD8 *data, CARD8 *cmap, int cmap_entry_size)
00044 {
00045 int x ;
00046 switch( bmp_info->biBitCount )
00047 {
00048 case 1 :
00049 for( x = 0 ; x < bmp_info->biWidth ; x++ )
00050 {
00051 int entry = (data[x>>3]&(1<<(x&0x07)))?cmap_entry_size:0 ;
00052 buf->red[x] = cmap[entry+2];
00053 buf->green[x] = cmap[entry+1];
00054 buf->blue[x] = cmap[entry];
00055 }
00056 break ;
00057 case 4 :
00058 for( x = 0 ; x < (int)bmp_info->biWidth ; x++ )
00059 {
00060 int entry = data[x>>1];
00061 if(x&0x01)
00062 entry = ((entry>>4)&0x0F)*cmap_entry_size ;
00063 else
00064 entry = (entry&0x0F)*cmap_entry_size ;
00065 buf->red[x] = cmap[entry+2];
00066 buf->green[x] = cmap[entry+1];
00067 buf->blue[x] = cmap[entry];
00068 }
00069 break ;
00070 case 8 :
00071 for( x = 0 ; x < (int)bmp_info->biWidth ; x++ )
00072 {
00073 int entry = data[x]*cmap_entry_size ;
00074 buf->red[x] = cmap[entry+2];
00075 buf->green[x] = cmap[entry+1];
00076 buf->blue[x] = cmap[entry];
00077 }
00078 break ;
00079 case 16 :
00080 for( x = 0 ; x < (int)bmp_info->biWidth ; ++x )
00081 {
00082 CARD8 c1 = data[x] ;
00083 CARD8 c2 = data[++x];
00084 buf->blue[x] = c1&0x1F;
00085 buf->green[x] = ((c1>>5)&0x07)|((c2<<3)&0x18);
00086 buf->red[x] = ((c2>>2)&0x1F);
00087 }
00088 break ;
00089 default:
00090 raw2scanline( data, buf, gamma_table, buf->width, False, (bmp_info->biBitCount==32));
00091 }
00092 }
00093
00094 BITMAPINFO *
00095 ASImage2DIB( ASVisual *asv, ASImage *im,
00096 int offset_x, int offset_y,
00097 unsigned int to_width,
00098 unsigned int to_height,
00099 void **pBits, int mask )
00100 {
00101 BITMAPINFO *bmp_info = NULL;
00102 CARD8 *bits = NULL, *curr ;
00103 int line_size, pad ;
00104 ASImageDecoder *imdec ;
00105 int y, max_y = to_height;
00106 int tiling_step = 0 ;
00107 CARD32 *a = 0;
00108 CARD32 *r = 0;
00109 CARD32 *g = 0;
00110 CARD32 *b = 0;
00111 START_TIME(started);
00112
00113 LOCAL_DEBUG_CALLER_OUT( "src = %p, offset_x = %d, offset_y = %d, to_width = %d, to_height = %d", im, offset_x, offset_y, to_width, to_height );
00114 if( im== NULL || (imdec = start_image_decoding(asv, im, mask ? SCL_DO_ALPHA : SCL_DO_ALL, offset_x, offset_y, to_width, 0, NULL)) == NULL )
00115 {
00116 LOCAL_DEBUG_OUT( "failed to start image decoding%s", "");
00117 return NULL;
00118 }
00119
00120 if( to_height > im->height )
00121 {
00122 tiling_step = im->height ;
00123 max_y = im->height ;
00124 }
00125
00126 bmp_info = (BITMAPINFO *)safecalloc( 1, sizeof(BITMAPINFO) );
00127 bmp_info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
00128 bmp_info->bmiHeader.biWidth = to_width ;
00129 bmp_info->bmiHeader.biHeight = to_height ;
00130 bmp_info->bmiHeader.biPlanes = 1 ;
00131 bmp_info->bmiHeader.biBitCount = mask ? 1 : 24 ;
00132 bmp_info->bmiHeader.biCompression = BI_RGB ;
00133 bmp_info->bmiHeader.biSizeImage = 0 ;
00134 bmp_info->bmiHeader.biClrUsed = 0 ;
00135 bmp_info->bmiHeader.biClrImportant = 0 ;
00136
00137 line_size = mask ? to_width : ((to_width*3+3)/4)*4;
00138 pad = line_size-(to_width*(mask ? 1 : 3)) ;
00139 bits = (CARD8 *)safemalloc(line_size * to_height);
00140 curr = bits + line_size * to_height ;
00141
00142 if (mask) {
00143 a = imdec->buffer.alpha ;
00144 } else {
00145 r = imdec->buffer.red ;
00146 g = imdec->buffer.green ;
00147 b = imdec->buffer.blue ;
00148 }
00149
00150 for( y = 0 ; y < max_y ; y++ )
00151 {
00152 register int x = to_width;
00153 imdec->decode_image_scanline( imdec );
00154
00155 curr -= pad ;
00156 while( --x >= 0 )
00157 {
00158 curr -= (mask ? 1 : 3) ;
00159 if (mask) {
00160 curr[0] = a[x]==0 ? 0 : 1 ;
00161 } else {
00162 curr[0] = b[x] ;
00163 curr[1] = g[x] ;
00164 curr[2] = r[x] ;
00165 }
00166 }
00167 if( tiling_step > 0 )
00168 {
00169 CARD8 *tile ;
00170 int offset = tiling_step ;
00171 while( y + offset < (int)to_height )
00172 {
00173 tile = curr - offset*line_size ;
00174 memcpy( tile, curr, line_size );
00175 offset += tiling_step ;
00176 }
00177 }
00178 }
00179
00180 stop_image_decoding( &imdec );
00181
00182 SHOW_TIME("", started);
00183 *pBits = bits ;
00184 return bmp_info;
00185 }
00186
00187
00188 #undef ASImage2DBI
00189 BITMAPINFO *
00190 ASImage2DBI( ASVisual *asv, ASImage *im,
00191 int offset_x, int offset_y,
00192 unsigned int to_width,
00193 unsigned int to_height,
00194 void **pBits, int mask )
00195 {
00196 return ASImage2DIB(asv, im, offset_x, offset_y, to_width, to_height, pBits, mask );
00197 }
00198
00199
00200
00201 ASImage *
00202 DIB2ASImage(BITMAPINFO *bmp_info, int compression)
00203 {
00204 int width = bmp_info->bmiHeader.biWidth;
00205 int height = bmp_info->bmiHeader.biHeight;
00206 ASImage *im = NULL;
00207 ASScanline buf;
00208 int y;
00209 CARD8 *data ;
00210 CARD8 *cmap = NULL ;
00211 int direction = -1 ;
00212 int cmap_entries = 0, cmap_entry_size = 4, row_size ;
00213
00214 if (width <= 0 || height == 0 )
00215 return NULL;
00216
00217 if( height < 0 )
00218 {
00219 direction = 1 ;
00220 height = -height;
00221 }
00222
00223 if( bmp_info->bmiHeader.biBitCount < 16 )
00224 cmap_entries = 0x01<<bmp_info->bmiHeader.biBitCount ;
00225
00226 if( bmp_info->bmiHeader.biSize != 40 )
00227 cmap_entry_size = 3;
00228
00229 if( cmap_entries )
00230 {
00231 cmap = (CARD8*)&(bmp_info->bmiColors[0]);
00232 data = cmap + cmap_entries*cmap_entry_size;
00233 }
00234 else
00235 data = (CARD8*)&(bmp_info->bmiColors[0]);
00236
00237 row_size = (width*bmp_info->bmiHeader.biBitCount)>>3 ;
00238 if( row_size == 0 )
00239 row_size = 1 ;
00240 else
00241 row_size = (row_size+3)/4 ;
00242 row_size *= 4 ;
00243
00244 im = create_asimage(width, height, compression);
00245
00246
00247 prepare_scanline( width, 0, &buf, True );
00248
00249 y =( direction == 1 )?0:height-1 ;
00250 while( y >= 0 && y < (int)height)
00251 {
00252 dib_data_to_scanline(&buf, &(bmp_info->bmiHeader), NULL, data, cmap, cmap_entry_size);
00253 asimage_add_line (im, IC_RED, buf.red , y);
00254 asimage_add_line (im, IC_GREEN, buf.green, y);
00255 asimage_add_line (im, IC_BLUE, buf.blue , y);
00256 y += direction ;
00257 data += row_size;
00258 }
00259
00260 free_scanline( &buf, True );
00261
00262 return im;
00263 }
00264
00265
00266 ASImage *
00267 bitmap2asimage (unsigned char *xim, int width, int height, unsigned int compression,
00268 unsigned char *mask)
00269 {
00270 ASImage *im = NULL;
00271 int i, bpl, x;
00272 ASScanline xim_buf;
00273
00274 if( xim == NULL )
00275 return NULL ;
00276
00277 im = create_asimage( width, height, compression);
00278 prepare_scanline( width, 0, &xim_buf, True );
00279
00280 if( xim )
00281 {
00282 bpl = (width*32)>>3 ;
00283 if( bpl == 0 )
00284 bpl = 1 ;
00285 else
00286 bpl = (bpl+3)/4;
00287 bpl *= 4;
00288 for (i = 0; i < height; i++) {
00289 if (mask) {
00290 for (x = 0; x < width<<2; x += 4) {
00291 xim[3 + x] = mask[x] == 0 ? 0 : 255;
00292 }
00293 }
00294 raw2scanline( xim, &xim_buf, 0, width, False, True);
00295 if (mask) asimage_add_line (im, IC_ALPHA, xim_buf.alpha, i);
00296 asimage_add_line (im, IC_RED, xim_buf.red, i);
00297 asimage_add_line (im, IC_GREEN, xim_buf.green, i);
00298 asimage_add_line (im, IC_BLUE, xim_buf.blue, i);
00299 xim += bpl;
00300 if (mask) mask += bpl;
00301 }
00302 }
00303 free_scanline(&xim_buf, True);
00304
00305 return im;
00306 }
00307