Skip to content

ofPixels - artifacts / crashes with .resize() #6226

@johanjohan

Description

@johanjohan

Since ofPixels.cpp has not been updated for over a year in the master branch, i therefore assume the following issue has not been fixed. i am using of 0.10.1 with win10 vs2017.

I am resizing images/pixels with the following function.
That leads to issues:

  • OF_INTERPOLATE_NEAREST_NEIGHBOR crashes on large sizes
  • OF_INTERPOLATE_BILINEAR: produces grey only pixels. well yes, "not implemented yet" in ofPixels
  • OF_INTERPOLATE_BICUBIC produces some singular green pixel/blue artifacts

calling the same function using image.resize() produces best results

question: i assume that i may use pixelsRes = _pixels; to create a full twin copy, right?
if yes, then there is the described issue in the pixel resizeTo() function.

CODE:

#include "ofApp.h"

/*
	this function aims to either
		- crop the image to the largest possible dimensions respecting _aspect 
			then scales the longest side to _longestSideLengthPx
		- stretch it respecting _aspect
			then scales the longest side to _longestSideLengthPx
*/

static void resize(
	ofPixels	 &_pixels,
	const float	 &_longestSideLengthPx,
	const ofVec2f	 &_aspect,
	const bool	 &_bStretch, // otherwise crop
	const ofInterpolationMethod	&_interp	// OF_INTERPOLATE_NEAREST_NEIGHBOR OF_INTERPOLATE_BILINEAR
) {
	ofScaleMode _scaleMode = _bStretch ? OF_SCALEMODE_FILL : OF_SCALEMODE_FIT;
	ofRectangle rectPixels(0, 0, _pixels.getWidth(), _pixels.getHeight());
	ofRectangle rectAspect(0, 0, _aspect.x, _aspect.y);
	rectAspect.scaleTo(rectPixels, _scaleMode);

	ofPixels pixelsRes;
	if (_scaleMode == OF_SCALEMODE_FIT) { // crop
		_pixels.cropTo(pixelsRes, rectAspect.x, rectAspect.y, rectAspect.width, rectAspect.height);
	}
	else { // stretch
		pixelsRes = _pixels;	
		
		// Q: is this a complete copy with new identical pixels?

		// looks like it does copy all params plus the pixels:
		//template<typename PixelType>
		//void ofPixels_<PixelType>::copyFrom(const ofPixels_<PixelType> & mom) {
		//	if (mom.isAllocated()) {
		//		allocate(mom.getWidth(), mom.getHeight(), mom.getPixelFormat());
		//		memcpy(pixels, mom.getData(), getTotalBytes());
		//	}
		//}
	}

	ofRectangle rectSize;
	if (rectAspect.width > rectAspect.height) {
		assert(rectAspect.width > 0);
		rectSize.set(0, 0, _longestSideLengthPx, _longestSideLengthPx / rectAspect.width * rectAspect.height);
	}
	else { 
		assert(rectAspect.height > 0);
		rectSize.set(0, 0, _longestSideLengthPx / rectAspect.height * rectAspect.width, _longestSideLengthPx);
	}

	ofLogNotice(__FUNCTION__) << "scaling _pixels: rectSize: " << rectSize;
	ofLogNotice(__FUNCTION__) << "_aspect   : " << _aspect;
	ofLogNotice(__FUNCTION__) << "_scaleMode: " << _scaleMode;
	ofLogNotice(__FUNCTION__) << "_interp   : " << _interp;
	ofLogNotice(__FUNCTION__) << "rectPixels: " << rectPixels;
	ofLogNotice(__FUNCTION__) << "rectAspect: " << rectAspect;

#if 1
	// ISSUE is right here

	// OF_INTERPOLATE_NEAREST_NEIGHBOR crashes on large sizes
	// OF_INTERPOLATE_BILINEAR : produces grey only pixels.well yes, "not implemented yet" in ofPixels
	// OF_INTERPOLATE_BICUBIC produces some  singular green pixel / blue artifacts
	// calling above function via image.resize() produces best results
	bool b = pixelsRes.resize(rectSize.width, rectSize.height, _interp); // THIS SEEMS BUGGY  in 0.10.1
	assert(b);
	_pixels = pixelsRes;
#else
	// all ok - done with freeimage functions
	ofImage image(pixelsRes);
	image.resize(rectSize.width, rectSize.height); // freeimage
	_pixels.setFromPixels(
		image.getPixels().getData(),
		image.getWidth(),
		image.getHeight(),
		image.getImageType()
	);
#endif
}
//--------------------------------------------------------------
void ofApp::setup() {

	ofSetLogLevel(OF_LOG_NOTICE);

	ofImage image;
	int longestSide = 15000; // somehow works with small size like 1000, crashes on large sizes
	ofInterpolationMethod interp;

	for (int i = 1; i <= 3; i++)
	{
		ofLogNotice(__FUNCTION__) << i;
		switch (i)
		{
		case 1: interp = OF_INTERPOLATE_NEAREST_NEIGHBOR; break;
		case 2: interp = OF_INTERPOLATE_BILINEAR; break;
		case 3: interp = OF_INTERPOLATE_BICUBIC; break;
		default:
			std::exit(1);
			break;
		}

		bool b = image.load("face.jpg");
		assert(b);

		bool bStretch = true;
		image.load("face.jpg");
		resize(image.getPixels(), longestSide, ofVec2f(16, 9), bStretch, interp);
		// how does the image know that the pixels are scaled now?
		image.setFromPixels(image.getPixels()); // ???
		image.save("face_169_stretch_" + ofToString(i) + ".jpg");

		image.load("face.jpg");
		resize(image.getPixels(), longestSide, ofVec2f(9, 16), bStretch, interp);
		image.setFromPixels(image.getPixels()); // ???
		image.save("face_916_stretch_" + ofToString(i) + ".jpg");

		bStretch = false;
		image.load("face.jpg");
		resize(image.getPixels(), longestSide, ofVec2f(16, 9), bStretch, interp);
		image.setFromPixels(image.getPixels()); // ???
		image.save("face_169_crop_" + ofToString(i) + ".jpg");

		image.load("face.jpg");
		resize(image.getPixels(), longestSide, ofVec2f(9, 16), bStretch, interp);
		image.setFromPixels(image.getPixels()); // ???
		image.save("face_916_crop_" + ofToString(i) + ".jpg");
	}
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions