Reputation: 391
My question is about a problem that is very easy to solve, but I am interested in learning the best practice for this. (nominally for Matlab, but not really language-specific ).
I am loading an image of an arbitrary size, and I need to make it fit (without any scaling nor change of aspect ratio) within a black image of a predefined size (let's call it the frame). The loaded image can be smaller, equal or bigger than the predefined frame, in either or both dimension(s).
If the image is smaller than the frame, I want it to be padded with zeros (there will be a black border around it), up to the frame size, and centered. If it is bigger, I want to crop it in a centered fashion.
Ideally, I do not want to make any assumptions on the parity of the pixel numbers in either dimension - that is, both the loaded image and the frame can have odd or even pixel numbers for both dimensions. Surely there will be some rounding to do.
I'm sure that this problem has been researched, solved and exhausted, so it shouldn't be a very hard question for knowledgeable programmers with some experience in image processing :)
Upvotes: 4
Views: 1961
Reputation: 14251
This should work for both greyscale and color images of smaller, equal and larger size than the frame. Tried to keep it sort of readable.
frameWidth = 800;
frameHeight = 600;
imagepath = 'smaller.jpg'; % 'equal.jpg', 'larger.jpg'
img = im2double(imread(imagepath));
[imgHeight, imgWidth, channels] = size(img);
frame = zeros(frameHeight, frameWidth, channels);
dImageWidth = round((frameWidth - imgWidth)/2);
dImageHeight = round((frameHeight - imgHeight)/2);
unEqualHeight = (imgHeight ~= frameHeight);
unEqualWidth = (imgWidth ~= frameWidth);
if imgHeight <= frameHeight
frameVStart = max(1, dImageHeight);
frameVEnd = min(frameHeight, frameHeight-dImageHeight-unEqualHeight);
imgVStart = 1;
imgVEnd = imgHeight;
else
frameVStart = 1;
frameVEnd = frameHeight;
imgVStart = max(1, -dImageHeight);
imgVEnd = min(imgHeight, imgHeight+dImageHeight);
end
if imgWidth <= frameWidth
frameHStart = max(1, dImageWidth);
frameHEnd = min(frameWidth, frameWidth-dImageWidth-unEqualWidth);
imgHStart = 1;
imgHEnd = imgWidth;
else
frameHStart = 1;
frameHEnd = frameWidth;
imgHStart = max(1, -dImageWidth);
imgHEnd = min(imgWidth, imgWidth+dImageWidth);
end
frame(frameVStart:frameVEnd, frameHStart:frameHEnd, :) = ...
img(imgVStart:imgVEnd, imgHStart:imgHEnd, :);
imshow(frame);
Upvotes: 1