Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

AppGameKit Studio Chat / [SOLVED] LoadSubImage() results in distorted squashed pixels

Author
Message
GemGames
6
Years of Service
User Offline
Joined: 31st May 2018
Location: Edmonton, Alberta, Canada
Posted: 16th Sep 2024 23:45
Using AppGameKit Studio tier 1, subimages have successfully been imported from an image atlas.

However, the 2 outer columns (one column on each edge) of the pixels in the subimages (not the atlas image) are distorted compared to the other column widths in the subimage, thinner than all the other columns. The same thing (distortion; squashed pixels) occurs with the horizontal runs (rows) where the topmost and bottom rows are vertically squashed or heavily distorted in the subimage relative to the other rows.

Original bitmap with uniform pixels:


Subimage bitmap with distorted / squashed pixel rows and columns near edges:


The subimages are not blurry, but the proportion of the columns of pixels are distorted. Most of the columns are uniform width, but in particular the outer columns are squashed thinner, and for some images even to a hairline width.

Incidentally, the bitmap source file (atlas texture) is 320 x 200, which is a power of 2, if that affects anything.

I have tried the following remedies:

* Double-checked the coordinates and dimensions in the "... subimages.txt" file, and they are confirmed accurate.

* Tried using SetImageMagFilter() on the subimages, but this generates a run-time error (SetImageMagFilter() cannot be applied to subimages). However, both SetImageMagFilter(0) and SetImageMinFilter(0) are successfully applied to the atlas image loaded, resulting in the elimination of blurred pixels. The pixels appear sharp and crisp, as they should with these settings applied. But this does not seem to have any effect in fixing the squashed/distorted pixels.

* The virtual resolution was changed from its prior 1600 x 900 to instead 320 x 200 to match the source atlas file's resolution, but this had no effect on the subimages (pixel columns and rows continue to appear squashed).

* Tried adjusting the sprite's resolution (using SetSpriteSize(...)) to the exact same resolution as its image (subimage), but the distortion remains.

* Tried adjusting the sprite's resolution (using SetSpriteSize(...)) using parameters -1 and -1 for the dimensions (which should derive its dimensions from the image, and retain the original aspect ratio) but the distortion remains.

* A potential remedy could be to extract the images using some MemBlock functions, but even if successful this would defeat the purpose of establishing subimages (where the GPU loads the atlas as a single texture, and from that single texture creates subimages/subtextures without the need to redundantly or inefficiently create many individual independent textures).

* Tried using functions SetSpriteUVScale() and SetSpriteUVBorder() without effect; I'm not really sure what these functions do but I thought it might work or have some effect.

I have reviewed the following AppGameKit forum threads that seem to be (somewhat) related to this, but I haven't yet found a working remedy:

URL: https://forum.thegamecreators.com/thread/211103
URL: https://forum.thegamecreators.com/thread/216038
URL: https://forum.thegamecreators.com/thread/228642
URL: https://forum.thegamecreators.com/thread/220469
URL: https://forum.thegamecreators.com/thread/225191
URL: https://forum.thegamecreators.com/thread/192926 (explains the benefits of using an Atlas and subimages instead of individual textures)
URL: https://forum.thegamecreators.com/thread/195871#msg2336207 (refers to UVBorder and half-width pixels)

Does anyone know of a remedy/solution that will result in uniform pixel widths in subimages? I am baffled at this odd behavior; I don't know what might be causing these strange distortions. It might be something simple or obvious that I am overlooking.

Thanks in advance for any help or advice!

Attachments

Login to view attachments

The author of this post has marked a post as an answer.

Go to answer

GemGames
6
Years of Service
User Offline
Joined: 31st May 2018
Location: Edmonton, Alberta, Canada
Posted: 17th Sep 2024 19:13
I could create a short AppGameKit code listing that demonstrates this behavior if that would be helpful.
Virtual Nomad
Moderator
19
Years of Service
User Offline
Joined: 14th Dec 2005
Location: SF Bay Area, USA
Posted: 17th Sep 2024 22:51 Edited at: 17th Sep 2024 23:10
i don't use studio much but 2 things come to mind based on past discussiions:

if you don't need Vulkan, try #Renderer "Basic" (if you haven't already) and, related reports of Vulkan vs DefaultMin/Mag filtering and some hardware.

i should also ask if you experience the same with the frame/image OUTSIDE of an atlas scenario?

btw, i noticed that you referenced EZ_Subs in the queue of links that you included. that was written in Classic but does include #Renderer "Basic" so i'm curious how the original and subimage appears for you? perhaps preview it (via [F8]) which should handle it as a single frame/extraction of the atlas? (all images in EZ_Subs are loaded with individual Min/Mag filters @ 0 and no Default ever set).
GemGames
6
Years of Service
User Offline
Joined: 31st May 2018
Location: Edmonton, Alberta, Canada
Posted: 18th Sep 2024 06:41
Thanks Virtual Nomad, I will try those suggestions and see their results / effects. What you mentioned too about how some hardware could be affected by certain settings is a possibility I had not thought of and could be the case. By modern computer standards my hardware is quite dated running Windows 7 with a rather basic "no frills" Asus NVIDIA GPU, so it is plausible that it could be a hardware specific issue.

Also that's an interesting point you brought up about being outside of an atlas / subimage scenario. This strange behavior of squashed pixel rows and columns only occurs with subimages and atlases. Even in the same App and with the same atlas bitmap image, when I load images in AppGameKit and apply a virtual resolution, everything looks pixel-level sharp and crisp, without any distortion or squashed lines. Not only images but also sprites appear sharp and without any distortion. I do need to use the SetImageMagFilter(0) and SetImageMinFilter(0) functions to eliminate fuzzy / blurry images, but those functions seem to work perfectly for that purpose without any strange distortion side effects, unlike the subimage functions even when using the exact same identical loaded atlas image.

1st thing I'll try and test out is the #renderer directive and see if it has an effect on subimage extraction. I don't need Vulkan in this App so I can go ahead with #renderer basic. Thanks again for the tip, I intend to post in this thread after with the test results.
GemGames
6
Years of Service
User Offline
Joined: 31st May 2018
Location: Edmonton, Alberta, Canada
Posted: 18th Sep 2024 07:08
After viewing the displayed subimages in my App, for a moment there I thought that the only affected (squashed) subimages were ones with an odd-number total columns of pixels, but that is not the case (some even-number total subimages are also squashed). The strange thing is, there are a few subimages (using the identical code from the identical atlas image within the same for...next loop) that are extracted perfectly without any squashed columns. Hmmm, the mystery continues.

I have a theory that if either the vertical number of total pixel rows or the horizontal number of total pixel columns is an odd number then the subimage becomes squashed at its outermost lines to compensate. I will take a closer look again at my App's for...next loop display of the subimages to see if this is the case. If this is the case, then a likely workaround would be to ensure that the subimages are always a power of 2 both vertically and horizontally, which is not ideal but possibly effective.
GemGames
6
Years of Service
User Offline
Joined: 31st May 2018
Location: Edmonton, Alberta, Canada
Posted: 18th Sep 2024 07:46 Edited at: 18th Sep 2024 07:55
After additional viewing and testing, my previously posted theory is proven incorrect. Apparently, subimages that have an even-numbered total columns of only 2 pixels wide are not horizontally squashed. Other subimages (whether odd-numbered total columns or even-numbered total columns) are squashed horizontally in their outermost columns.

Edit: From about 30 subimages, only 3 are extracted without being squashed. 2 of these 3 have a width of 2 pixels, and the other 1 of these 3 has a width of 320 pixels. All other subimages (approximately 25 subimages) have varying widths and heights, and all have squashed outermost edges.
GemGames
6
Years of Service
User Offline
Joined: 31st May 2018
Location: Edmonton, Alberta, Canada
Posted: 18th Sep 2024 08:01
I tried using #Renderer "Basic" from within AppGameKit Studio, and it has no effect on the subimages distortion. That was a good thought though to try that. Sometimes it's just a single command, setting or function that can remedy the entire seemingly complex situation.
GemGames
6
Years of Service
User Offline
Joined: 31st May 2018
Location: Edmonton, Alberta, Canada
Posted: 18th Sep 2024 08:11
I have another theory that maybe distortion-free extraction of subimages depends on where the individual cel is located in the atlas image. For example, if the cel is located on an odd-numbered column instead of an even-numbered (power of 2) column. This theory seems unlikely, but I will continue experimenting and if I find anything significant or a remedy I plan to post it on this thread.
GemGames
6
Years of Service
User Offline
Joined: 31st May 2018
Location: Edmonton, Alberta, Canada
Posted: 18th Sep 2024 08:26
For the time being, I will just "live with it" and tolerate the distortions in the subimages and their subsequent sprites. As a last resort, I could always forgo subimages altogether and instead extract individual cels as individual regular images (not subimages), possibly using memblocks and an automated process. This would not be an ideal solution because it would mean not using subimages, but it would eliminate the distortions that are generated in the subimages.

I could also test this with different hardware to see if this is possibly a hardware-specific quirk, as you had mentioned in your previous post.

I could also try using the EZ_Subs utility App, which as I understand it runs using classic AppGameKit instead of AppGameKit Studio, to see what kind of distortion effect (if any) occurs. However, the only problem is that the cels I have in the atlas image are irregularly dimensioned, and if I understand correctly EZ_Subs requires the cels to be uniformly dimensioned (at least per row). But in any case, I could test to see if the subimages that EZ_Subs would extract from my atlas image have the same distortion as what I am currently experiencing using the function within my App LoadSubImage().
GemGames
6
Years of Service
User Offline
Joined: 31st May 2018
Location: Edmonton, Alberta, Canada
Posted: 18th Sep 2024 17:54 Edited at: 18th Sep 2024 18:16
Just to provide clarification, I tried both SetDefaultMagFilter(0) / SetDefaultMinFilter(0) and SetImageMagFilter(0) / SetImageMinFilter(0). I also tried executing these solely before loading the image (atlas image) in one experiment, and in another experiment solely after loading the image (atlas image). The squashed pixel columns in most of the subimages remain in all these configurations (the exceptions being the 3 non-distorted subimages that I had mentioned in a previous post in this thread).

Edit: As a note of interest, it appears that the SetDefaultMagFilter() / SetDefaultMinFilter() functions override any opposite or contrary setting made in the SetImageMagFilter() / SetImageMinFilter() functions. To my way of thinking, I would have expected that the SetDefault settings would be overridden for any image by the SetImage functions, rather than the other way around. This also seems to occur regardless of the sequence in which these functions are executed (whether SetDefault prior to SetImage, or SetImage prior to SetDefault).

Revised Edit: On further experimentation, I now realize that the SetImage functions do have an effect that overrides the SetDefault functions, but only if the SetImage functions are applied/executed after the image is loaded and not before the image is loaded (i.e. using the LoadImage() function).

In other words, the settings for the image applied with the SetImage functions only apply to the image after the image is loaded, not before. Even if the SetImage functions are executed with values contrary to the SetDefault functions specifically before the image is loaded with LoadImage(), then the values in the SetDefault functions will apply to the loaded image overriding any contrary values set with SetImage functions.

However, if specifcally after 1st loading the image (i.e. LoadImage() function) then 2nd the SetImage functions are executed with values that are contrary to the SetDefault functions, then the values in the SetImage functions will apply to the image, overriding the values set in the SetDefault functions. The key is to execute the SetImage functions only after the image has been loaded, not before the image has been loaded, if you want to override the filter settings established with the SetDefault functions.
GemGames
6
Years of Service
User Offline
Joined: 31st May 2018
Location: Edmonton, Alberta, Canada
Posted: 18th Sep 2024 21:40 Edited at: 30th Sep 2024 19:19
This post has been marked by the post author as the answer.
After a number of experiments and tinkering, the solution has been found:

SetSpriteUVBorder(spriteNumber, 0) resolves the squashed pixels, but the key is that it must be called after, not before, the image (subimage) is loaded into the specified sprite.

If SetSpriteUVBorder() is called 1st, and next SetSpriteImage(spriteNumber, imageNumber) is called 2nd, then the subimage which the sprite displays will have squashed outermost columns and rows.

However, if those 2 functions are called in reverse order (SetSpriteImage() 1st; SetSpriteUVBorder() 2nd) then SetSpriteUVBorder() does have an effect and the outermost columns / rows of the image no longer appear squashed/distorted.

In AGK's help documentation (located under Home-->Commands-->Image-->LoadSubImage.htm) under heading Description, it states:
Quote: "...Note that when loading a sub image AppGameKit will modify the UV coordinates slightly so that the image does not steal pixels from neighboring images during filtering, by default it shifts the UV inwards by 0.5 pixels. You can override this by setting SetSpriteUVBorder to 0 for sprites where you need pixel perfect results, but you will have to watch out for pixel bleeding around the edges, and may need to give your sub images a 1 pixel border of an appropriate color that it can safely steal from when filtering."


Likewise, AGK's help documentation states (location: Home-->Commands-->Sprite-->SetSpriteUVBorder.htm) the following:
Quote: ""...By default a sprite uses a border of 0.5 pixels when its image is a sub image, and a border of 0 pixels when its has a normal image. If you have compensated for this yourself by adding spacing to the atlas image then setting the border to 0 removes the default offset and creates a pixel perfect reproduction of the sub image.""


What the documentation does not mention, however, is the drastic difference that calling these functions in a particular sequence results in. If called in the wrong sequence/order, it gives the impression to the caller/programmer that the function SetSpriteUVBorder() actually does nothing , or has no effect. In retrospect, looking back, that's partially what baffled me. I did not understand that the calling sequence of these functions relative to each other was so important, making all the difference.

Anyway, I'm really happy that a viable solution has been found without too much difficulty, and that now I can use subimages and spritesheets / atlases without any distortion effects! Hopefully this thread will be helpful to anyone in the future that encounters similar difficulties. Sometimes the solution is subtle and comes down to a single command or function, but often it is not discovered without conducting experiments to test theories.

Edit: The above solution subsequently creates another intermittent problem of pixel bleeding or artifacting, but for the solution see this additional comment in this same forum thread: https://forum.thegamecreators.com/thread/229725#msg2678150
Virtual Nomad
Moderator
19
Years of Service
User Offline
Joined: 14th Dec 2005
Location: SF Bay Area, USA
Posted: 19th Sep 2024 21:35 Edited at: 19th Sep 2024 21:38
nice find, GemGames. thanks for sharing your research.

this reminds me of similar where, if you SetSpritePhysicsMass() and then go on to alter other sprite characteristics, the mass will be automatically recalculated without our necessarily realizing or expecting it.

otherwise, i never set default and always use this (tho, admittedly, rarely take advantage of atlases):
GemGames
6
Years of Service
User Offline
Joined: 31st May 2018
Location: Edmonton, Alberta, Canada
Posted: 20th Sep 2024 02:55
Virtual Nomad wrote: "nice find, GemGames. thanks for sharing your research."


Thanks and you're welcome! I'm happy to help where and if I can. I also sure appreciate all the help I receive(d) through the forums and from various members of the AppGameKit community.
GemGames
6
Years of Service
User Offline
Joined: 31st May 2018
Location: Edmonton, Alberta, Canada
Posted: 30th Sep 2024 19:07
I have experienced an additional problem and solution:

After successfully importing subimages and executing SetSpriteUVBorder(spriteNumber, 0.0) using the careful sequencing of calls described earlier in this thread, on rare occassions I still nonetheless saw intermittent artifacts in the sprites where they would border with either other sprites or a single-pixel wide dividing line from within the sprite sheet / sprite atlas.

Typically this artifact would show as a very thin but noticeable red line along the vertical side of a sprite as the sprite moved across the screen. It would not show up every movement frame either, but it varied how frequently and consistently it showed, and then often it would disappear on and off as the sprite moved across the screen.

I found an easy solution for this additional artifacting however, and that is to modify the parameter from 0.0 to 0.05; this seems to consistently eliminate all artifacting, without causing any noticeable distortion, or squashing, of the outermost pixels in the images or sprites. The default value of 0.5 causes noticeable distortion / squashing, 0.0 eliminates the distortion but can result in occassional artifacting, but 0.05 seems to deliver the best results, eliminating both distortion and artifacting:

Login to post a reply

Server time is: 2025-05-08 22:23:49
Your offset time is: 2025-05-08 22:23:49