By per-pixel I assume that you mean only the surrounding pixels should influence the pixel value. Unfortunately changing the pixel value in response to one adjacent pixel means the contrast with the others could also change. Kind of like a 'chain reaction' of changes.
For example, saw we had $I = [0,7,11]$ and we wanted a maximum contrast of 5. Going from the left we change 7 to 5, which then requires 11 to be changed to 10.
Maximum Contrast
One way per pixel maximum contrast can be done is by using morphological operators. Specifically, performing a dilation (or erosion) with a pyramid structuring element based on the maximum contrast value, $c$. For dilation, the structuring element is
... ... ... ... ... ... ... ... ...
... -3c -3c -3c -3c -3c -3c -3c ...
... -3c -2c -2c -2c -2c -2c -3c ...
... -3c -2c -1c -1c -1c -2c -3c ...
... -3c -2c -1c 0 -1c -2c -3c ...
... -3c -2c -1c -1c -1c -2c -3c ...
... -3c -2c -2c -2c -2c -2c -3c ...
... -3c -3c -3c -3c -3c -3c -3c ...
... ... ... ... ... ... ... ... ...
The size of the structuring element will depend on $c$ and the range of pixel values. Assuming pixel values are in [0,255], size will be N x N pixels where N = 2*floor(255/c) + 1, e.g.
c = 100
-200 -200 -200 -200 -200
-200 -100 -100 -100 -200
-200 -100 0 -100 -200
-200 -100 -100 -100 -200
-200 -200 -200 -200 -200
Dilation increases pixel values to enforce the maximum contrast, erosion decreases pixel values. In out example above, dilation would give $I = [2,7,11]$, erosion would give $I = [0,5,10]$.
Minimum Contrast
Enforcing a minimum contrast is not going to give you good results. Imagine having a minimum contrast in a flat area, it will turn it into a ramp. For this operation it is better to look at filters that enhance edges etc.
MATLAB code
MATLAB code to do this:
clear all;
close all;
% Test image
I = randi(256,10,10)-1;
imagesc(I); colorbar; title('test image'); pause;
% Constrast settings
c = 10;
maxPixelValue = 255;
% Structuring element
halfN = floor(maxPixelValue/c);
N = 2*halfN + 1;
[x,y] = ndgrid(-halfN:halfN);
stDH(:,:,1) = abs(x) * -c;
stDH(:,:,2) = abs(y) * -c;
stDH = min(stDH,[],3);
stD = strel('arbitrary',ones(N),stDH);
stE = strel('arbitrary',ones(N),stDH);
imagesc(stDH); colorbar; title('structuring element'); pause;
% Dilation result
Id_max = imdilate(I,stD);
imagesc(Id_max); colorbar; title('max contrast (dilation)'); pause;
imagesc(I-Id_max); colorbar; title('diff with original'); pause;
% Erosion result
Ie_max = imerode(I,stE);
imagesc(Ie_max); colorbar; title('max contrast (erosion)'); pause;
imagesc(I-Ie_max); colorbar; title('diff with original'); pause;
%% Min contrast
stD = strel('arbitrary',ones(N),-stDH);
stE = strel('arbitrary',ones(N),-stDH);
% Dilation result
Id_max = imdilate(I,stD);
imagesc(Id_max); colorbar; title('min contrast (dilation)'); pause;
imagesc(I-Id_max); colorbar; title('diff with original'); pause;
% Erosion result
Ie_max = imerode(I,stE);
imagesc(Ie_max); colorbar; title('min contrast (erosion)'); pause;
imagesc(I-Ie_max); colorbar; title('diff with original'); pause;