1

I want to crop an uploaded image with this code.

also, I want to limit the size of the image (in byte) and save it as png format. when I don't use of the cropped image, I can get image length using this code:

var postedFile = Request.Files["FileUpload1"];
long length=postedFile.ContentLength;

my problem is that I can not get the cropped image length correctly. if I use bytes.Length in Upload function, it gets me the length greater than the original image length from FileUpload control. how can get cropped image length in png format?

my code is as follows:

    <script type="text/javascript" 
    src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"> 
    </script>
    <script type="text/javascript" src="http://jcrop- 
    cdn.tapmodo.com/v0.9.8/js/jquery.Jcrop.js"></script>
    <script type="text/javascript">
        $(function () {
            $('#FileUpload1').change(function () {
                $('#Image1').hide();
                var reader = new FileReader();
                reader.onload = function (e) {
                    $('#Image1').show();
                    $('#Image1').attr("src", e.target.result);
                    $('#Image1').Jcrop({
                        onChange: SetCoordinates,
                        onSelect: SetCoordinates
                    });
                }
                reader.readAsDataURL($(this)[0].files[0]);
            });

            $('#btnCrop').click(function () {
                var x1 = $('#imgX1').val();
                var y1 = $('#imgY1').val();
                var width = $('#imgWidth').val();
                var height = $('#imgHeight').val();
                var canvas = $("#canvas")[0];
                var context = canvas.getContext('2d');
                var img = new Image();
                img.onload = function () {
                    canvas.height = height;
                    canvas.width = width;
                    context.drawImage(img, x1, y1, width, height, 0, 0, width, height);
                    $('#imgCropped').val(canvas.toDataURL());
                    $('[id*=btnUpload]').show();
                };
                img.src = $('#Image1').attr("src");
            });
        });
        function SetCoordinates(c) {
            $('#imgX1').val(c.x);
            $('#imgY1').val(c.y);
            $('#imgWidth').val(c.w);
            $('#imgHeight').val(c.h);
            $('#btnCrop').show();
        };
    </script>

    <input type="file" id="FileUpload1" name="FileUpload1"  />
    <br />
    <br />
    <table border="0"  cellpadding="0" cellspacing="5" style="text-align:right">
     <tr >
     <td>
     <img id="Image1" alt="" style="display: none" />
     <br />
     <canvas id="canvas" height="5" width="5"></canvas>
     </td>
     </tr>
    </table>
    <br />
     <input type="button" class="button" id="btnCrop" value="crop" style="display: none" />
     <asp:Button ID="btnUpload" CssClass="button" runat="server" Text="upload" OnClick="Upload" Style="display: none" />
     <input type="hidden" name="imgX1" id="imgX1" />
     <input type="hidden" name="imgY1" id="imgY1" />
     <input type="hidden" name="imgWidth" id="imgWidth" />
     <input type="hidden" name="imgHeight" id="imgHeight" />
     <input type="hidden" name="imgCropped" id="imgCropped" />

and in code behinde:

    var postedFile = Request.Files["FileUpload1"];
    if (postedFile != null && postedFile.ContentLength > 0)
    {
        string filename = postedFile.FileName;
        FileInfo fi = new FileInfo(filename);
        string ext = fi.Extension;
        if (ext != ".png")
         {
            lblMessage.Text = "please upload .png file";
             return;
         }
         long length=postedFile.ContentLength;//this line return original length correctly
         string base64 = Request.Form["imgCropped"];
         byte[] bytes = Convert.FromBase64String(base64.Split(',')[1]);
         int length= bytes.Length //get copped image length, but it greater than orig size
         using (System.IO.FileStream stream = new System.IO.FileStream(path + "\\" + filename, System.IO.FileMode.Create))
         {
              stream.Write(bytes, 0, bytes.Length);
              stream.Flush(); 
         }

update: I try canvas.toDataURL() in different quality (1,0.95,...) and png and jpeg format and check the cropped image length when selecting the whole of the image, but this length differs from the original image. (I want to get length 75% of the original length if I select 75% pixels of the original image in the cropped image.) what is the reason and what is value to be set to quality and format to get the same quality as the original image?

r.b
  • 33
  • 5
  • Could you post the code you're using to crop the image? – Broots Waymb Jun 25 '19 at 12:43
  • I use the code described in the above link exactly. – r.b Jun 25 '19 at 12:45
  • 3
    Post the relevant part(s) here directly and not as a link. People aren't generally inclined to click on external links, so that code really "doesn't count". – Broots Waymb Jun 25 '19 at 12:46
  • Was the original image uploaded with a lower quality than the quality used to encode the cropped version? For example, I can download a 25k jpg, crop it a little bit and then save it as a 100k png at 100% quality. Your code passes default quality settings to `toDataURL`, You could explicitly set the format and quality to the same format and quality as the uploaded file. See also https://stackoverflow.com/questions/14383557/setting-canvas-todataurl-jpg-quality – Wyck Jun 25 '19 at 13:02
  • Code should be in the question, not linked-to off-site, to preserve the question's long-term value. –  Jun 25 '19 at 13:08

1 Answers1

1

Your problem is not that you are getting the length incorrectly, rather it is that you are compressing your cropped image with higher quality settings than the original image you cropped.

Consider explicitly setting format and quality options for .toDataURL

If you want you can use the same settings as the original file, which should result in a smaller file if the dimensions are smaller (except possibly for very tiny images where header sizes dominate.)

The default type is image/png and the default quality value is 0.92, which could be the reason that a smaller image (because you cropped it a little bit) could be of a larger file size than the original uncropped image; because the cropped image was encoded using higher quality settings than your source image.

For example, if the amount of cropping results in the cropped image being 75% of the number of pixels of the original, but those pixels are then encoded using a scheme that uses (on average) 2 times the number of bytes as the original encoding, then the cropped file will be approximately 150% of the length original. I provide this example to illustrate how it is possible for cropped file to have a larger file size than the uncropped file.

Exerpt from the documentation for canvas.toDataURL:

canvas.toDataURL(type, encoderOptions);

type (Optional) A DOMString indicating the image format. The default format type is image/png.

encoderOptions (Optional) A Number between 0 and 1 indicating the image quality to use for image formats that use lossy compression such as image/jpeg and image/webp. If this argument is anything else, the default value for image quality is used. The default value is 0.92. Other arguments are ignored.

Wyck
  • 10,311
  • 6
  • 39
  • 60
  • in canvas.toDataURL() what values must be used to get the cropped image with the same quality of the original image? please explain with code. – r.b Jun 25 '19 at 13:24
  • I test canvas.toDataURL("image/jpeg",1) but this also get me greater length than orig size. – r.b Jun 25 '19 at 13:56
  • 1 is the **maximum** quality (largest file size). To get a smaller file size you would have to reduce the quality to a lower number. Did you try smaller numbers? Your follow up question about how to determine the existing quality is already answered [here](https://stackoverflow.com/questions/2024947/is-it-possible-to-tell-the-quality-level-of-a-jpeg) Or just decide what your quality should be and set it to say 0.5 absolutely. Jpeg quality really degrades below 50%, so you'll have to make a design decision based on your requirements. – Wyck Jun 26 '19 at 12:49