openframeworks / openframeworks/openFrameworks

ofPixels - artifacts / crashes with .resize()

Open
#6,226 56 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C++
Stars
10.4k
Forks
2.6k
Avg merge
1d 21h
Merged PRs (30d)
9

Description

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");
	}
}

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the ofPixels.cpp resize implementation and reproduce the supplied example using face.jpg, a longest side of 15000, and each interpolation method. Compare pixelsRes.resize() with image.resize() for the reported crash, grey output, and colored artifacts. Done means the resize path handles the supplied cases without crashing and produces correct output for the supported interpolation methods.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
computer-graphics
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.