"Monitorize" an Image

9

The Problem:

This challenge comes from a real problem I was having. I have a dual monitor setup at work, and I wanted to use the following image as my wallpaper:

Ideal Image

However, my monitors have quite significant bezels, and when I set my background, it looks something like this, where the pier appears (appiers?) to be broken:

Issue Image

I was able to solve this by making an image with the center cut out of it, and then stretching it back to the original size, as in the image below:

Challenge Image


The Challenge:

Write a program that takes in an image and "monitorizes" it for use with a dual monitor setup (i.e. deletes the center section of the image, where the bezels are). The rules are as follows:

  1. It must be a full program that accepts the image, either as a path (string argument, etc), or in the form of a file chooser dialog.
  2. The program must take as an input the number of vertical lines (one pixel in width) to crop out from the center of the image
  3. The cropping must come from the center (width-wise) of the original image
  4. The resultant image must be re-scaled back to the original size of the input image. (Either the halves can be scaled individually, and then concatenated, or concatenated and then scaled. Scaling individually produces a better image/effect, but is hardly noticeable in the real world)
  5. Background images are generally even, so to make this challenge easier, input images will only have an even number of pixels, and number of lines to remove will only be even as well.
  6. This challenge is code golf - shortest code in bytes wins

Good Luck!

dberm22

Posted 2017-04-06T20:11:12.897

Reputation: 512

2>

  • It's not very clear from the pictures what the operation is, because they're scaled to the same width. Perhaps replace the first and last one with images that are the same size as the middle one and padded with white? 2. Can we use any form of rescaling (linear is probably cheapest) or does it have to be a specific one (e.g. cubic, sinc, etc.)?
  • < – Peter Taylor – 2017-04-06T20:28:26.827

    @PeterTaylor As per rule 3, the input and output images are supposed to be the same width. Either each half is resized to half the original width, and then concatenated, or the cropped halves are concatenated, then scaled back to the original size. And yes, any scaling is fine. – dberm22 – 2017-04-06T20:49:05.287

    The sentence beginning "Perhaps" was a suggestion for how to make the question easier to understand, not a suggested interpretation of the challenge. I've made the change myself. – Peter Taylor – 2017-04-06T22:51:23.070

    @PeterTaylor Ahh, i see, That makes it clearer. Thanks. – dberm22 – 2017-04-07T11:45:14.227

    Can we assume that the image will be landscape oriented? – Scott Milner – 2017-04-07T18:54:05.630

    @ScottMilner Yes – dberm22 – 2017-04-07T22:50:58.457

    -1 bad puns (just kidding, I upvoted :P Nice challenge!) – HyperNeutrino – 2017-04-08T02:47:24.420

    Answers

    1

    Octave, 85 bytes

    @(f,n)imsave(imresize((o=imread(f))(:,[1:(end-n)/2,(end+n)/2:end],:),size(o)(1:2)),f)
    

    Defines an anonymous function with f the file name, and n the number of columns to remove. Since an anonymous function requires a single expression, inline assignment is used, a feature not present in MATLAB.

    MATLAB, 98 bytes

    As a bonus, I also golfed a MATLAB compatible answer. Interestingly, this is only 13 bytes longer, since the Octave version needs a lot of parentheses to correctly parse the inline assignments.

    function  m(f,n)
    o=imread(f);imsave(imresize(o(:,[1:(end-n)/2,(end+n)/2:end],:),size(o(:,:,1))),f)
    

    Sanchises

    Posted 2017-04-06T20:11:12.897

    Reputation: 8 530

    5

    Matlab 2013, 150 bytes

    Here is my attempt in Matlab. Definitely won't be the shortest code, but it's a start.

    Warning, this overwrites the original image, so make a copy first.

    Golfed Version

    function  mi(f,n)
    o=imread(f);
    s=size(o);
    imwrite([imresize(o(:,1:((s(2)-n)/2),:),[s(1),s(2)/2]) imresize(o(:,((s(2)+n)/2):end,:),[s(1),s(2)/2])], f);
    end
    

    Ungolfed Code, with improvements for odd image sizes and odd number of columns

    function  monitorizeImage( filename, num_columns )
    
    orig = imread(filename);
    orig_size = size(orig);
    
    f = factor(orig_size(2));
    origsize_iseven = f(1)==2;
    
    f = factor(num_columns);
    num_columns_iseven = f(1)==2;
    
    odd_even_size_mismatch = xor(origsize_iseven,num_columns_iseven);
    
    img_resized = imresize(orig,[orig_size(1) orig_size(2)+odd_even_size_mismatch]);
    
    leftimg = img_resized(:,1:((orig_size(2)+odd_even_size_mismatch-num_columns)/2),:);
    leftimg = imresize(leftimg,[orig_size(1),floor(orig_size(2)/2)]);
    rightimg = img_resized(:,((orig_size(2)-odd_even_size_mismatch+num_columns)/2):end,:);
    rightimg = imresize(rightimg,[orig_size(1),floor(orig_size(2)/2)]);
    
    monitorized_image = [leftimg rightimg];
    monitorized_image = imresize(monitorized_image,[orig_size(1),orig_size(2)+ ~origsize_iseven]);
    
    [~, ~, ext] = fileparts(filename); 
    
    imwrite(monitorized_image,strcat(filename(1:end-length(ext)),'_',num2str(num_columns),ext));
    
    end
    

    dberm22

    Posted 2017-04-06T20:11:12.897

    Reputation: 512

    Just adding to this: answers to challenges must make a serious attempt at optimising for the given scoring criterion. In a [tag:code-golf] challenge like this one, that means that any obvious improvements that would reduce the length of the code must be made. – None – 2017-04-06T20:15:11.640

    Try removing unused spaces and whitespace. – dkudriavtsev – 2017-04-06T20:27:38.823

    @ais523 Thanks. Down to 220 bytes! – dberm22 – 2017-04-06T21:09:06.993

    Also, every two-byte variable is one too many. Readability is not important, so refactor os etc. to any other letter in the alphabet! And why not just write the image back to to the input image f to save the whole strcat? (which, incidentally, you can replace by ['',...] rather than strcat(...)) – Sanchises – 2017-04-06T21:09:08.623

    @Sanchises Thanks, that was a leftover from the ungolfed/improved version. Nothing in the rules stated it couldn't overwrite, or needed to have pretty named outputs. Thanks...that decreased byte count by 70 bytes! – dberm22 – 2017-04-06T21:16:29.443

    See my new answer if you would like some more inspiration on how to golf in MATLAB. – Sanchises – 2017-04-10T13:16:29.387

    3

    Wolfram Language, 134, 127, 119 111 bytes

    f[i_,c_]:=(d=ImageDimensions@i;ImageAssemble[ImageTake[i,a=All,#]&/@{{0,e=-#&@@d/2-c/2},{-e,a}}]~ImageResize~d)
    

    Creates a function f that takes an image as the first input (as a symbol in Mathematica or the Wolfram Cloud), and an integer as the second input.

    Ungolfed:

    f[image_,columns_]:=(  (*Define Function*)
        d=ImageDimensions[image];  (*Get image dimensions*)
        e=d[[1]]/2+columns/2;  (*Add half the image width to half the number of removed columns*)
        ImageResize[ImageAssemble[Map[ImageTake[i,All,#]&,{{0,-e},{e,All}}]],d]  (*Map the function onto a list with the desired column ranges and merge and scale the resulting image*)
    )
    

    Technically, it won't work properly if either of the image dimensions exceed 362,880 pixels, but I assume that's okay, since that is way outside the scope of the problem (and some computers). Fixed!

    Scott Milner

    Posted 2017-04-06T20:11:12.897

    Reputation: 1 806

    2

    PHP, 206 bytes

    ($c=imagecopyresized)($t=imagecreatetruecolor($w=imagesx($s=imagecreatefrompng($argv[1])),$h=imagesy($s)),$s,0,0,0,0,$v=$w/2,$h,$x=$v-$argv[2]/2,$h);$c($t,$s,$v,0,$w-$x,0,$v,$h,$x,$h);imagepng($t,$argv[3]);
    

    takes three command line arguments: source file name, number of lines to crop and target filename. Run with -r.

    You may want to use imagecopyresampled instead of imagecopyresized (+2 bytes) for a better result.

    ungolfed

    $s=imagecreatefrompng($argv[1]);    # load source image
    $w=imagesx($s);$h=imagesy($s);      # get image dimensions
    $t=imagecreatetruecolor($w,$h);     # create target image
    $v=$w/2;                            # $v = half width
    $x=$v-$argv[2]/2;                   # $x = width of remaining halves
                                        # resize and copy halves:
    imagecopyresized($t,$s, 0,0,    0,0,$v,$h,$x,$h);
    imagecopyresized($t,$s,$v,0,$w-$x,0,$v,$h,$x,$h);
    imagepng($t,$argv[3]);              # save target image
    

    I could save 9 more bytes by sending the PNG result to STDOUT ... but what for?

    Titus

    Posted 2017-04-06T20:11:12.897

    Reputation: 13 814

    "I could save 9 more bytes by sending the PNG result to STDOUT ... but what for?" Then you could run something like php -r image.php image.png 1 > output.png, right? – ʰᵈˑ – 2017-04-10T13:28:07.860