2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
5 Desc: Graphics function BitMapScale()
9 #include <aros/debug.h>
10 #include <graphics/scale.h>
11 #include <proto/exec.h>
12 #include <proto/oop.h>
14 #include "graphics_intern.h"
15 #include "gfxfuncsupport.h"
18 /*****************************************************************************
21 #include <proto/graphics.h>
23 AROS_LH1(void, BitMapScale
,
26 AROS_LHA(struct BitScaleArgs
*, bitScaleArgs
, A0
),
29 struct GfxBase
*, GfxBase
, 113, Graphics
)
32 Scale a source bit map to a destination bit map other than
36 Pass a BitScaleArgs structure filled with the following arguments
38 bsa_SrcX, bsa_SrcY - upper left coordinate in source bitmap
39 bsa_SrcWidth, bsa_SrcHeight - Width and Height or source bitmap
40 bsa_DestX, bsa_DestY - upper left coordinate in destination
42 bsa_DestWidth, bsa_DestHeight - this function will set these
43 values. Use the bsa_???Factor for scaling
44 bsa_XSrcFactor:bsa_XDestFactor - Set these to get approximately
45 the same ratio as bsa_SrcWidth:bsa_DestWidth, but
46 usually not exactly the same number.
47 bsa_YSrcFactor:bsa_YDestFactor - Set these to get approximately
48 the same ratio as bsa_SrcHeight:DestHeight, but
49 usually not exactly the same number.
50 bsa_SrcBitMap - pointer to source bitmap to be scaled
51 bsa_DestBitMap - pointer to destination bitmap which will
52 will hold the scaled bitmap. Make sure it's
54 bsa_Flags - reserved for future use. Set it to zero!
55 bsa_XDDA, bsa_YDDA - for future use.
56 bsa_Reserved1, bsa_Reserved2 - for future use.
59 bsa_DestWidth and bsa_DestHeight will be set by this function
62 - Overlapping source and destination bitmaps are not supported
63 - Make sure that you provide enough memory for the destination
64 bitmap to hold the result
65 - In the destination bitmap only the area where the scaled
66 source bitmap is put into is changed. A frame of the old
74 ScalerDiv(), graphics/scale.h
80 *****************************************************************************/
84 if (bitScaleArgs
->bsa_SrcBitMap
->pad
!= 0 ||
85 bitScaleArgs
->bsa_DestBitMap
->pad
!= 0 ||
86 bitScaleArgs
->bsa_SrcBitMap
->Flags
& BMF_SPECIALFMT
||
87 bitScaleArgs
->bsa_DestBitMap
->Flags
& BMF_SPECIALFMT
)
92 BOOL src_colmap_set
= FALSE
;
93 BOOL dst_colmap_set
= FALSE
;
95 BOOL colmaps_ok
= TRUE
;
97 OOP_Object
*srcbm_obj
;
98 OOP_Object
*dstbm_obj
;
101 srcbm_obj
= OBTAIN_HIDD_BM(bitScaleArgs
->bsa_SrcBitMap
);
102 dstbm_obj
= OBTAIN_HIDD_BM(bitScaleArgs
->bsa_DestBitMap
);
103 tmp_gc
= obtain_cache_object(CDD(GfxBase
)->gc_cache
, GfxBase
);
105 /* We must lock any HIDD_BM_SetColorMap calls */
107 if (srcbm_obj
&& dstbm_obj
&& tmp_gc
)
109 /* Try to get a CLUT for the bitmaps */
110 if (IS_HIDD_BM(bitScaleArgs
->bsa_SrcBitMap
)) {
111 if (NULL
!= HIDD_BM_COLMAP(bitScaleArgs
->bsa_SrcBitMap
))
112 srcflags
|= FLG_HASCOLMAP
;
113 srcflags
|= GET_COLMOD_FLAGS(bitScaleArgs
->bsa_SrcBitMap
);
116 srcflags
|= FLG_PALETTE
;
119 if (IS_HIDD_BM(bitScaleArgs
->bsa_DestBitMap
)) {
120 if (NULL
!= HIDD_BM_COLMAP(bitScaleArgs
->bsa_DestBitMap
))
121 dstflags
|= FLG_HASCOLMAP
;
122 dstflags
|= GET_COLMOD_FLAGS(bitScaleArgs
->bsa_DestBitMap
);
125 dstflags
|= FLG_PALETTE
;
129 if ( (srcflags
== FLG_PALETTE
|| srcflags
== FLG_STATICPALETTE
)) {
130 /* palettized with no colmap. Neew to get a colmap from dest*/
131 if (dstflags
== FLG_TRUECOLOR
) {
133 D(bug("!!! NO WAY GETTING PALETTE FOR src IN BltBitMap\n"));
137 } else if (dstflags
== (FLG_TRUECOLOR
| FLG_HASCOLMAP
)) {
139 /* Use the dest colmap for src */
140 HIDD_BM_SetColorMap(srcbm_obj
, HIDD_BM_COLMAP(bitScaleArgs
->bsa_DestBitMap
));
145 if ( (dstflags
== FLG_PALETTE
|| dstflags
== FLG_STATICPALETTE
)) {
146 /* palettized with no pixtab. Nees to get a pixtab from dest*/
147 if (srcflags
== FLG_TRUECOLOR
) {
148 D(bug("!!! NO WAY GETTING PALETTE FOR dst IN BltBitMap\n"));
152 } else if (srcflags
== (FLG_TRUECOLOR
| FLG_HASCOLMAP
)) {
154 /* Use the src colmap for dst */
155 HIDD_BM_SetColorMap(dstbm_obj
, HIDD_BM_COLMAP(bitScaleArgs
->bsa_SrcBitMap
));
157 dst_colmap_set
= TRUE
;
161 if (success
&& colmaps_ok
)
163 struct monitor_driverdata
*driver
, *dst_driver
;
165 HIDDT_DrawMode old_drmd
;
166 struct TagItem cbtags
[] = {
167 { aHidd_GC_DrawMode
, vHidd_GC_DrawMode_Copy
},
171 OOP_GetAttr(tmp_gc
, aHidd_GC_DrawMode
, &old_drmd
);
172 OOP_SetAttrs(tmp_gc
, cbtags
);
174 bitScaleArgs
->bsa_DestWidth
= ScalerDiv(bitScaleArgs
->bsa_SrcWidth
,
175 bitScaleArgs
->bsa_XDestFactor
,
176 bitScaleArgs
->bsa_XSrcFactor
);
178 bitScaleArgs
->bsa_DestHeight
= ScalerDiv(bitScaleArgs
->bsa_SrcHeight
,
179 bitScaleArgs
->bsa_YDestFactor
,
180 bitScaleArgs
->bsa_YSrcFactor
);
183 * Select a driver to call. The same as in BltBitMap(), but select
184 * bitmap object instead of driver object.
186 driver
= GET_BM_DRIVERDATA(bitScaleArgs
->bsa_SrcBitMap
);
187 dst_driver
= GET_BM_DRIVERDATA(bitScaleArgs
->bsa_DestBitMap
);
189 if (driver
== (struct monitor_driverdata
*)CDD(GfxBase
))
191 else if (dst_driver
->flags
& DF_UseFakeGfx
)
196 HIDD_BM_BitMapScale(bm_obj
202 update_bitmap(bitScaleArgs
->bsa_DestBitMap
, dstbm_obj
,
203 bitScaleArgs
->bsa_DestX
, bitScaleArgs
->bsa_DestY
,
204 bitScaleArgs
->bsa_DestWidth
, bitScaleArgs
->bsa_DestHeight
,
207 cbtags
[0].ti_Data
= old_drmd
;
208 OOP_SetAttrs(tmp_gc
, cbtags
);
212 HIDD_BM_SetColorMap(srcbm_obj
, NULL
);
214 HIDD_BM_SetColorMap(dstbm_obj
, NULL
);
218 RELEASE_HIDD_BM(dstbm_obj
, bitScaleArgs
->bsa_DestBitMap
);
221 RELEASE_HIDD_BM(srcbm_obj
, bitScaleArgs
->bsa_SrcBitMap
);
224 release_cache_object(CDD(GfxBase
)->gc_cache
, tmp_gc
, GfxBase
);
232 * Algorithm for plain Amiga bitmaps.
235 * Unfortunately it's not possible to use 16/32 bit copying on bitmaps with this
236 * algorithm as there might be an odd number of bits per line in a bitmap and
237 * this creates problems when accessing the 2nd, 4th and so on line.
241 #define DEF_USIZE ULONG
242 #define DEF_SIZE LONG
243 #define DEF_NUMBITSMINUS1 31
245 #define DEF_READMASK 0x80000000
250 /* The following lines are necessary for BYTE copying and have to be used right
254 #define DEF_USIZE UBYTE
255 #define DEF_SIZE BYTE
256 #define DEF_NUMBITSMINUS1 7
257 #define DEF_ANDMASK 7
258 #define DEF_READMASK 0x80
263 bitScaleArgs
-> bsa_DestWidth
= ScalerDiv(bitScaleArgs
-> bsa_SrcWidth
,
264 bitScaleArgs
-> bsa_XDestFactor
,
265 bitScaleArgs
-> bsa_XSrcFactor
);
267 bitScaleArgs
-> bsa_DestHeight
= ScalerDiv(bitScaleArgs
-> bsa_SrcHeight
,
268 bitScaleArgs
-> bsa_YDestFactor
,
269 bitScaleArgs
-> bsa_YSrcFactor
);
271 /* first of all lets allocate DestHeight words of memory so we can
272 precalculate which original line goes to which destination lines */
274 if (NULL
==(LinePattern
= (UWORD
*) AllocMem(sizeof(UWORD
)*bitScaleArgs
->bsa_DestHeight
, 0)))
278 UWORD DestHeight
= bitScaleArgs
-> bsa_DestHeight
;
279 UWORD ys
= bitScaleArgs
-> bsa_SrcY
;
281 ULONG dyd
= bitScaleArgs
-> bsa_DestHeight
;
282 ULONG dys
= bitScaleArgs
-> bsa_SrcHeight
;
284 LONG accuyd
= - (dys
>> 1);
285 while (count
< DestHeight
)
288 while (accuyd
> accuys
)
293 LinePattern
[count
] = ys
;
300 /* now let's go for the real thing: scaling */
302 UWORD DestWidth
= bitScaleArgs
-> bsa_DestWidth
+ bitScaleArgs
-> bsa_DestX
;
303 ULONG xs
= bitScaleArgs
-> bsa_SrcX
;
304 ULONG count
= bitScaleArgs
-> bsa_DestX
;
305 ULONG dxd
= bitScaleArgs
-> bsa_DestWidth
;
306 ULONG dxs
= bitScaleArgs
-> bsa_SrcWidth
;
308 LONG accuxd
= - (dxs
>> 1);
310 ULONG possible_columns
, columncounter
;
313 while (count
< DestWidth
)
316 while (accuxd
> accuxs
)
322 /* instead of copying column by column we can *maybe* even
323 copy more than one column at a time - we'll have to see */
325 if ((count
& DEF_ANDMASK
) > (xs
& DEF_ANDMASK
))
326 possible_columns
= DEF_NUMBITSMINUS1
- (count
& DEF_ANDMASK
);
328 possible_columns
= DEF_NUMBITSMINUS1
- (xs
& DEF_ANDMASK
);
330 columncounter
= 1; /* one row, that's for sure!*/
331 this_x
= xs
; /* in counter we find the x-coord of the current source pixels */
333 LONG accuxd_tmp
= accuxd
;
334 LONG accuxs_tmp
= accuxs
;
336 ULONG count2
= count
+ 1;
338 while (possible_columns
> 0 && count2
< DestWidth
)
340 /* where's the next x-source-coordinate going to be? */
342 while (accuxd_tmp
> accuxs_tmp
)
348 if (this_x
+ 1 == next_x
)
350 /* it's the immediately following coordinate */
357 /* we're copying more than on column then we have to change
360 if (columncounter
!= 1)
365 break; /* the next column is not the neighbouring one */
368 /* determine how many more columns we can copy */
374 /* let's generate a mask that's columncounter bits wide */
375 ReadMask
= DEF_READMASK
;
376 ReadMask
= (DEF_SIZE
)ReadMask
>> (columncounter
- 1);
377 /* let's adjust this mask to the correct position */
378 ReadMask
= ReadMask
>> (xs
& DEF_ANDMASK
);
379 /* The leftmost set bit is xs & DEF_MASK away from the highest bit */
381 /* now that we have generated the read-mask we can copy all the columns
382 * that need copying in all bitmaps.
388 LONG preshift
= (xs
& DEF_ANDMASK
) - (count
& DEF_ANDMASK
);
391 struct BitMap
* SrcBitMap
= bitScaleArgs
-> bsa_SrcBitMap
;
392 struct BitMap
* DestBitMap
= bitScaleArgs
-> bsa_DestBitMap
;
397 AndMask
= (ReadMask
<< shift
) ^ (DEF_SIZE
)(-1);
402 AndMask
= (ReadMask
>> shift
) ^ (DEF_SIZE
)(-1);
405 /* treat all the Bitmaps after another */
406 for (i
= 0; (i
< DestBitMap
-> Depth
) && (i
< SrcBitMap
-> Depth
); i
++)
408 for (y
= 0; y
< bitScaleArgs
-> bsa_DestHeight
; y
++)
411 ind
= LinePattern
[y
] * (SrcBitMap
-> BytesPerRow
>> DEF_SHIFTY
) + /* y-Coord */
412 (xs
>> DEF_SHIFTX
); /* x-Coord */
413 CopyData
= ((DEF_USIZE
*)SrcBitMap
-> Planes
[i
])[ind
];
414 CopyData
= CopyData
& ReadMask
;
417 CopyData
= CopyData
<< shift
;
419 CopyData
= CopyData
>> shift
;
421 /* ind correctly calculates the destination Address for the CopyData */
422 ind
= y
* ((bitScaleArgs
-> bsa_DestY
+ DestBitMap
-> BytesPerRow
) >> DEF_SHIFTY
) + /* y-Coord */
423 (count
>> DEF_SHIFTX
); /* x-Coord */
424 /* Leave a previous picture in the bitmap untouched except for in the
425 * area where the scaled picture goes into
427 ((DEF_USIZE
*)DestBitMap
->Planes
[i
])[ind
] =
428 (((DEF_USIZE
*)DestBitMap
->Planes
[i
])[ind
] & AndMask
) | CopyData
;
430 kprintf("Dest: %x\n\n",(LONG)((DEF_USIZE *)DestBitMap ->Planes[i])[ind]);
437 /* go to next x-coordinate */
438 count
+= columncounter
;
442 /* let's get rid of the allocated memory */
443 FreeMem(LinePattern
, sizeof(UWORD
) * bitScaleArgs
-> bsa_DestHeight
);
447 #undef DEF_NUMBITSMINUS1