01 April 2017, 08:42 | #1 |
Registered User
Join Date: Dec 2013
Location: Auckland
Posts: 3,539
|
Auto cropping routine?
Has anyone made a routine for auto cropping shapes to the visible boundaries, and adjusting the handle appropriately? (Say, if your source IFF has 16x16 pixel frames, but some of the shapes are smaller than that)
|
01 April 2017, 10:19 | #2 |
Registered User
Join Date: Oct 2014
Location: Europe
Posts: 470
|
You can study the little piece of code of the shapesmaker-src provided by Acid those days. it uses the screens bitmap, but (assuming not realtime stuff) you can use shapesbitmap cmd and apply it that way.
The other way is apply the shape.newtype and look through all data lines in the beginning and the end of each line and change the shapes data accordingly. but this is not a simple task either. |
01 April 2017, 22:14 | #3 |
Registered User
Join Date: Mar 2012
Location: UK
Posts: 1,893
|
Could you not do this by having a screen the added width of you bobs all the way round and then display a viewport on the visible screen so you can blit to the wider screen and it would appear to crop the bob via the viewport (not sure if this is the correct terminology).
Last edited by Havie; 02 April 2017 at 21:18. Reason: Muppet typing! |
01 April 2017, 22:24 | #4 |
Registered User
Join Date: Sep 2007
Location: Stockholm
Posts: 4,332
|
What do you mean by "adjusting the handle"?
|
02 April 2017, 21:14 | #5 |
Registered User
Join Date: Oct 2014
Location: Europe
Posts: 470
|
I guess if you remove 0s on the left for example the handle would be out of the middle or topleft or whereever it has been. so after cropping you must readjust the handle to the correct coordinates.
|
03 April 2017, 09:39 | #6 |
Registered User
Join Date: Sep 2007
Location: Stockholm
Posts: 4,332
|
I still don't understand the problem. Is the program cropping shapes at runtime?
|
03 April 2017, 11:19 | #7 |
Registered User
Join Date: Jun 2009
Location: Dublin, then Glasgow
Posts: 6,334
|
I think some of the source shapes don't fill the 16x16 grid, and so he'd like to trim them down to 8x12 or whatever size they actually occupy. Personally, I would keep them all at 16x16 - it will help keep the frames positioned correctly since you can easily use the same handle for all of them, and I can't imagine there being that huge a speed or memory benefit in making them much smaller unless you're blitting hundreds of them.
If you've got some shapes that never occupy the 16x16 in any of their frames, you just need to space them whatever size you need for the largest frame. A small project I'm working on for example uses shapes that are 9x20 pixels. I read them in from a grid spaced at 10x21 pixels, and then copy and rotate them for the 20x9 horizontal versions. But if some frames are close to 16x16, just let the transparency of colour 0 do the work |
03 April 2017, 14:33 | #8 |
Registered User
Join Date: Sep 2007
Location: Stockholm
Posts: 4,332
|
There's no point in going below 16 pixels in width since that's the minimum size of any shape anyway — both on disk, in memory and when blitting. Pretending they're smaller will come back and bite you when you least expect it.
The handle is a different proposition, though. |
03 April 2017, 16:40 | #9 |
Registered User
Join Date: Jun 2009
Location: Dublin, then Glasgow
Posts: 6,334
|
Yes, good point, though Blitz allows arbitrary width shapes to be created. As a hardware factor though, that would also limit shape sizes to multiples of 16 wide, would it not?
I'm using GetaShape to cut shapes 9 pixels wide from a sprite sheet, using MidHandle on them and they're centred correctly and haven't yet given me any trouble (blitting outside bitmap errors etc.), so I guess Blitz compensates internally for these differences. |
03 April 2017, 17:24 | #10 |
Registered User
Join Date: Sep 2007
Location: Stockholm
Posts: 4,332
|
If you cut a 9 pixel wide shape, it will be saved as a 16 pixel wide shape. You will not notice it at first, since Blitz also notes that it is supposed to be 9 pixels wide and treats it as such as far as possible.
But since the blitter can only operate on word lengths, it will be stored as 16 pixels and blitted as 16 pixels, which may come as a surprise when you're QBlitting a 9 pixel shape close to the right border of the screen or when blitting it close to another shape and then restoring the background. |
03 April 2017, 17:50 | #11 |
Registered User
Join Date: Jun 2009
Location: Dublin, then Glasgow
Posts: 6,334
|
Interesting... I know about the hardware-level aspect of it but I just left it to Blitz to deal with the technicalities. I'll have to do some testing to check it out - like I said, I haven't had any issues blitting in any corner of the bitmap, but that could be a combination of pure luck (nothing using adjacent memory) and the debugger ignoring it because of the declared size.
There's my Monday night sorted |
10 April 2017, 21:46 | #12 |
Registered User
Join Date: Dec 2013
Location: Auckland
Posts: 3,539
|
Eeek, somehow I missed all of the responses here.
I didn't know about the minimum 16 pixel thing, makes sense though - I presume the shape widths are multiples of 16 pixels then? But they can be any height? |
10 April 2017, 23:24 | #13 |
Registered User
Join Date: Sep 2007
Location: Stockholm
Posts: 4,332
|
Exactly. Blitter objects can be any height.
Try out https://github.com/idrougge/ShapesInfo in case you're curious about shapes. |
14 April 2017, 02:20 | #14 |
Registered User
Join Date: Dec 2013
Location: Auckland
Posts: 3,539
|
Well damn, making an auto-cropping routine seems to have saved 160KB of memory with no noticeable downside. I had expected it to break sprites but it doesn't appear to have - do Sprites inherit the Handles from the shapes they're derived from? Well anyway, code is here - any hints for optimisation would be appreciated.
I haven't bothered trying to crop on width as most shapes are multiples of 16 anyway. It hasn't been extensively tested so it's possible it might be misaligned by a pixel or two. Code:
Statement GetaShapeCropped{ID,XPos,YPos,Width,Height} CropYStart=-1 CropYEnd=-1 ;Loop through each pixel to make sure there's at least one non- transparent pixel per line for y = 0 to Height-1 For x = 0 to Width-1 ;This is non transparent, so make sure this line is included if Point(x+XPos,y+YPos) if CropYStart=-1 CropYStart=y endif CropYEnd=y ;Break from the loop, we don't need to check the rest of the line Pop For Goto Break endif next .Break next ;Empty shape. Just get a single pixel so we don't get errors if we try to do anything with it later if(CropYEnd=-1) GetaShape ID,XPos,YPos,1,1 Statement Return endif ;Get the shape and adjust the handle GetaShape ID,XPos,YPos+CropYStart,Width,CropYEnd-CropYStart+1 Handle ID,0,-CropYStart End Statement Last edited by earok; 14 April 2017 at 02:29. |
10 June 2017, 19:28 | #15 |
A1200 040 SAM440EP 667
Join Date: Jan 2008
Location: Lisbon / Portugal
Posts: 873
|
Thanks for share your code earok
|
11 June 2017, 03:21 | #16 |
Registered User
Join Date: Dec 2013
Location: Auckland
Posts: 3,539
|
no worries mate. I hope it's useful
|
11 June 2017, 04:28 | #17 |
Registered User
Join Date: Oct 2014
Location: Europe
Posts: 470
|
TABs to 4 next time, please. Will have a look at it, too.
|
15 July 2017, 11:18 | #18 |
Registered User
Join Date: Dec 2013
Location: Auckland
Posts: 3,539
|
For what it's worth, it's reasonably easy to extend it to crop horizontally as well - which saved me ~30KB (obviously much less dramatic than the ~160KB I saved from vertical cropping, but still significant).
The tricky part is sprites, which have to be 16/32/64 pixels wide depending on SpriteMode (so if you cropped so that the left side of the sprite was against the edge, you may need blank space on the right side of the sprite if it doesn't fill it exactly) However, for the sake of using Blitz's built in Sprite vs Sprite or Shape vs Sprite collision detection - you can set the "_width" field of the Sprite newtype to get it pixel perfect |
15 July 2017, 15:20 | #19 |
Registered User
Join Date: Sep 2007
Location: Stockholm
Posts: 4,332
|
How did you crop them horizontally?
|
15 July 2017, 15:57 | #20 |
Registered User
Join Date: Dec 2013
Location: Auckland
Posts: 3,539
|
I'm not proud of my code but here it is. I cheated a bit by changing the sprite NewType, changing 'flags' to be a byte and then adding 'width' as a second byte (nasty way of handling it I know).
The "ForSprite" parameter just specifies that you want to use this Shape for a Sprite. You're supposed to use the 'GetaSpriteCropped' straight after if you want to convert the Shape you've just cropped to a Sprite. Code:
NEWTYPE .sprite ;size=16 _data.l ;00: NULL if no sprite present, else pointer to sprite data _height.w ;04: height of sprite, in pixels, plus an extra 1 _channels.w ;06: number of sprite channels required to display sprite _flags.b ;08: low byte = pix width of sprite, hi bit = 1 if 16 colour sprite _width.b ;SHORTCUT TO WIDTH _nextoff.w ;10: difference in bytes between seperate sprites for separate sprite channels _xhandle.w ;12: horizontal handle for sprite _yhandle.w ;14: vertical handle for sprite End NEWTYPE Statement GetaShapeCropped{ID,XPos,YPos,Width,Height,ForSprite} Shared WidthForSprite.b CropYStart=-1 CropYEnd=-1 CropXStart=-1 CropXEnd=-1 ;Loop through each pixel to make sure there's at least one non-transparent pixel per line for y = 0 to Height-1 For x = 0 to Width-1 ;This is non transparent, so make sure this line is included if Point(x+XPos,y+YPos) if CropYStart=-1 CropYStart=y endif CropYEnd=y if CropXStart=-1 or CropXStart>x CropXStart=x endif if CropXEnd<x CropXEnd=x endif endif next next ;Empty shape. Just get a single pixel so we don't get errors if we try to do anything with it later if(CropYEnd=-1) GetaShape ID,XPos,YPos,1,1 Statement Return endif ;Get the shape and adjust the handle if ForSprite=false GetaShape ID,XPos+CropXStart,YPos+CropYStart,CropXEnd-CropXStart+1,CropYEnd-CropYStart+1 Handle ID,-CropXStart,-CropYStart else WidthForSprite = CropXEnd-CropXStart+1 GetaShape ID,CropXStart,CropYStart,16,CropYEnd-CropYStart+1 Handle ID,-CropXStart,-CropYStart endif End Statement Statement GetaSpriteCropped{SpriteID,ShapeID} Shared WidthForSprite.b GetaSprite SpriteID,ShapeID *s.sprite=Addr Sprite(SpriteID) *s\_width=WidthForSprite End Statement Last edited by earok; 16 July 2017 at 06:10. |
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
Thread Tools | |
Similar Threads | ||||
Thread | Thread Starter | Forum | Replies | Last Post |
Auto auto fire? | john4p | request.UAE Wishlist | 6 | 22 January 2010 08:50 |
Need help coding small routine | kipper2k | Coders. General | 5 | 19 May 2009 16:02 |
Keyboard routine | BippyM | Coders. General | 2 | 15 July 2007 12:15 |
SetPoint routine | MidJasper | request.Other | 2 | 03 February 2007 20:10 |
Looking for some routine code | Amiga1992 | Coders. General | 4 | 17 December 2003 23:51 |
|
|