[SOLVED] Image resizing using STB

Started by bobjob, November 30, 2015, 19:31:05

Previous topic - Next topic

bobjob

Is there any source code examples of Image Resizing using STB?

Currently I have been using the java ImageIO to load BufferedImages. I use this mainly to shrink images that are not measured in powers of 2. Switching to LWJGL3 and running on MAC OSX's main thread does not allow for this (AWT crash).

So now I have switched to the STB library provided within the LWJGL package. I have managed to load images just fine, but I can't wrap my head around resizing the Image. I have been trying to use one of the STBImageResize.stbir_resize methods but cannot seem to get it working. I have been getting vm fatal errors, to corrupt image errors (on the 'scaled down' buffer). Is there any source code examples that show a working texture loader that takes into account the power of 2 issue, or even a code snippet for general resizing of a texture?

Im sure I could manually shrink the buffer, but was hoping to get the robust nature of my texture loader by allowing for some level of filtering when resizing.

Thanks in advance.


* turns out I was using the wrong type, STBImageResize.STBIR_TYPE_UINT8 was required.

spasi

Resizing to and from non-PoT sizes works fine for me, using the simplest function (stbir_resize_uint8). The code is trivial, I added the following to the LWJGL Image demo, after loading the image:

{
	int w2 = this.w / 2 - 1;
	int h2 = this.h / 2 - 1;

	int w3 = w2 / 2;
	int h3 = h2 / 2;

	ByteBuffer tmp = memAlloc(w2 * h2 * this.comp);
	ByteBuffer tmp2 = memAlloc(w3 * h3 * this.comp);

	// PoT to non-PoT
	stbir_resize_uint8(image, this.w, this.h, 0, tmp, w2, h2, 0, this.comp);
	// non-PoT to non-PoT
	stbir_resize_uint8(tmp, w2, h2, 0, tmp2, w3, h3, 0, this.comp);
	// non-PoT to PoT
	stbir_resize_uint8(tmp2, w3, h3, 0, image, this.w, this.h, 0, this.comp);

	memFree(tmp2);
	memFree(tmp);
}


Could you share the code you're using?

bobjob

This is the method Im using to resize an image.
I just doubled the size in this example 'multiplied by 2'.


this.w = w.get(0)*2; //NEW WIDTH
		this.h = h.get(0)*2; //NEW HEIGHT

		ByteBuffer newImage = BufferUtils.createByteBuffer(
				this.w * this.h * comp.get(0) );


		
		int alpha;
		if (comp.get(0) == 4) alpha = comp.get(0)-1;
		else alpha = STBImageResize.STBIR_ALPHA_CHANNEL_NONE;
		
		STBImageResize.stbir_resize(
				image, //BUFFER LOADED FROM stbi_load_from_memory
				w.get(0), 
				h.get(0), 
				w.get(0)*comp.get(0), 
				newImage,
				this.w,
				this.h,
				this.w*comp.get(0),
				STBImageResize.STBIR_TYPE_UINT8,
				comp.get(0),
				alpha, 
				0,
				STBImageResize.STBIR_EDGE_ZERO,
				STBImageResize.STBIR_EDGE_ZERO,
				STBImageResize.STBIR_FILTER_CUBICBSPLINE,
				STBImageResize.STBIR_FILTER_CUBICBSPLINE,
				STBImageResize.STBIR_COLORSPACE_SRGB);


		STBImage.stbi_image_free(image);
		
		
		image = newImage;

spasi

Yeah, looks good. Just a small note, you can pass 0 as the stride when the image rows are tightly packed. It's equivalent to passing width * components * sizeof(type).

bobjob

Quote from: spasi on November 30, 2015, 22:04:09
Yeah, looks good. Just a small note, you can pass 0 as the stride when the image rows are tightly packed. It's equivalent to passing width * components * sizeof(type).

Thanx, will do.