Problems with large JPG Pictures

BlitzMax Forums/BlitzMax Programming/Problems with large JPG Pictures

Midimaster(Posted 2009) [#1]
I try to load a 3000x2400 pixel sized JPG image, but the drawimage cannot draw it.

If I use a 1900x1900 pixel image, everything is ok. If I use a 2100x1900 image, i get something on the screen, which looks like x-streched lines of the colors of the picture.

It seems to me, that loading a image over 2048x2048 pixel makes problems. perhaps my grafic card is at its memory end?

What can i do to load the image? Can I load it into Main RAM instead of Video RAM? How can I do this? Or is it a bug of BlitzMax?


Czar Flavius(Posted 2009) [#2]
I'm sure the others will have better solutions, but as a stop-gap measure try splitting the image into say 4 subpieces, and drawing them together like a grid?


Midimaster(Posted 2009) [#3]
no chance to do this, the program will be no game, but a picture viewer for any pictures...easy to use for the users, so i cannot have any restrictions.


ziggy(Posted 2009) [#4]
Loading as a pixmap and drawing the pixmap makes any difference?


Czar Flavius(Posted 2009) [#5]
Perhaps you can do it behind the scenes, automatically detecting a large image and splitting it internally. The user never need know :D


Midimaster(Posted 2009) [#6]
no, loading a pixmap makes no difference...

decteting the size is no problem, after LOADIMAGE the size is known correct with IMAGEWIDTH(),

...but the DrawImageRect fails:

Global LadeBild:Timage
Datei$="test.jpg"
Graphics 800,600,0,0
'LadeBild=LoadImage(Datei)
LadeBild = LoadImage(LoadPixmapJPeg(Datei))
Print ImageWidth(Ladebild) + " " + ImageHeight(Ladebild)
SetScale 0.2,0.2
DrawImageRect LadeBild,0,0,400,400
Print "ready"
Flip
WaitKey()



Please tell me, how to split it.


Czar Flavius(Posted 2009) [#7]
I meant, 'physically' splitting the one big 4Ax4B image into four new seperate images of size 1Ax1B, and then possibly discarding the old image. I'm afraid I don't know how to do this myself.


Tommo(Posted 2009) [#8]
http://www.blitzbasic.com/codearcs/codearcs.php?code=1440
Maybe this can help.


ImaginaryHuman(Posted 2009) [#9]
If you are suspecting that 2048x2048 is the absolute limit then I suggest your graphics card has a `maximum texture size` of 2048. There is no way around that other than to split your image into multiple images. ALso you should be able to loadpixmap just fine and then convert it to multiple images using pixmap windows.


Midimaster(Posted 2009) [#10]
Now I did it this way:

1.loading the image as a Timage

2. if it is over 2048x2048 I Convert it into a Pixmap (LockImage)

3. with two for/next-loops I read every second pixel (ReadPixel) and save it to another Pixmap with WritePixel. The new Pixmap has exact the half size of the original.

For i=0 to Width-1
    For j=0 to Height-1
        Pixel=ReadPixel(OldImage,i*2,j*2)
        WritePixel NewImage,i,j,Pixel
   Next
Next


4. At the end I overwrite the original with the smaller image.


Thanks to everybody for your help!


ImaginaryHuman(Posted 2009) [#11]
I don't think that will work. If you load your image as an image and not as a pixmap and then you lock the pixmap, I don't know if that downloads the image to the pixmap or whether it has retained the larger pixmap. If it doesn't retain it, you're downloading a cropped image. But I am guessing bmax keeps the pixmap even when doing a loadimage?


GfK(Posted 2009) [#12]
2. if it is over 2048x2048 I Convert it into a Pixmap (LockImage)
If the GPU doesn't support textures of that size, then it might not even get that far.

Another problem - what if the user wants to view a 2048x400 image? Even if it does load, it'll take up a hell of a lot more RAM than is necessary as it could be scaled internally to 2048x2048.

The only way you are going to do this reliably is by splitting up the image into sensibly sized tiles, and I'd recommend 64x64 to minimise waste. Your single, massive image basically needs to be represented as a tilemap.


Midimaster(Posted 2009) [#13]
The code above was only symbolic pseudo code. In reality it works already.

The loading of the images seemed to be no problem. Even big sized pictures were loaded correct. I recognized, that only the DrawImage failed.

My pictureviewer only works in 1366x768. So I do not need picture sources bigger than this. If a picture comes with 3000x2000px it will have 1500x1000pix after the scaling down. This is enough for scaling it again to fit the Screen.

The idea of the 64x64-tiles is of course very elegant.


TomToad(Posted 2009) [#14]
use loadAnimImage() to break the image into smaller ones.

A short example here:



TomToad(Posted 2009) [#15]
For some reason, I didn't see your response before I made mine. I guess if you want to resize the image instead of tiling it, Resizepixmap might be a more elegant solution.

Pixmap = LoackImage(Image)
Image = LoadImage(ResizePixmap(Pixmap,Pixmap.Width/2,PixmapHeight/2))

And you're done.


Midimaster(Posted 2009) [#16]
nice idea, i will test it immediately. thank you


GfK(Posted 2009) [#17]
Even big sized pictures were loaded correct. I recognized, that only the DrawImage failed.
That's because the image is really loaded as a pixmap - it doesn't become a texture until the first time you try to draw it, at which point it gets sent to the GPU. That's where the size limitations are always going to manifest themselves.

use loadAnimImage() to break the image into smaller ones.
LoadAnimImage relies on the image being big enough to contain the specified number of tiles of given dimensions. If the total image dimensions are not equally divisible by the tile width/height, then at best you'll get bits missing, at worst it'll fail completely.


ImaginaryHuman(Posted 2009) [#18]
Each individual dimension of a texture must be a power of 2, they don't have to actually match.

You are allowed 2048 x 64, 2048 x 256 etc

At least that's true of OpenGL, I presume Blitz lets you do that?