0

Goodmorning, I'm developing a cms, and my clients are gonna upload for sure image without respect the tips of dimensions so I would like to develop a resize image way to optimize the pages. I'm developing with VB, this is the first time that I use bitmap, and I'm not sure at all that I have choose the best solution that I need. I have understood that to resize the image I have before to transform it to a bitmap, then I can resize with my widht, height parameters and at the end, to show in my html tag img convert it to a 64bit string. Is this the best solution for me? And the point is that my picture loses quality, if I compare this one resized to an image "resized" with css with same dimension, it's totally different. I would like to maintain the same quality, thank you.

Here my resize.aspx page

<%@ Page Language="VB" Trace="false" Debug="true" aspcompat=true%>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Drawing" %>
<%@ Import Namespace="System.Drawing.Drawing2D" %>
<%@ Import Namespace="System.Drawing.Imaging" %>
<%@ Import Namespace="System.Runtime.InteropServices" %>

<script runat="server">
    Private Function CopyTo32BitArgb(image As System.Drawing.Image) As Bitmap
        Dim imageCopy = New Bitmap(img, CInt(newWidth), CInt(maxHeight))
        imageCopy.SetResolution(300, 300)
        'if you want save and check Dpi imageCopy.Save("C:\inetpub\wwwroot\images\barber\prueba.jpg", ImageFormat.Jpeg)
        For Each propItem As PropertyItem In image.PropertyItems
            imageCopy.SetPropertyItem(propItem)
        Next
        Using g As Graphics = Graphics.FromImage(imageCopy)
            g.InterpolationMode = InterpolationMode.HighQualityBicubic
            g.DrawImage(image, New Rectangle(0, 0, 426, 284), New Rectangle(0, 0, image.Width, image.Height), GraphicsUnit.Pixel)
            g.Flush()
        End Using
        Return imageCopy
    End Function
</script>

<%Dim original As System.Drawing.Image = System.Drawing.Image.FromFile("C:\inetpub\wwwroot\images\barber\1.jpeg", true)
Dim resized As System.Drawing.Image = CopyTo32BitArgb(original)
Dim memStream As MemoryStream = New MemoryStream()
resized.Save(memStream, System.Drawing.Imaging.ImageFormat.Jpeg)
Dim imgBytes as byte() = memStream.ToArray()
Dim imgString as string= Convert.ToBase64String(imgBytes)%>

<img style="display:block;" src="data:image/png;base64,<%=imgString%>"/>
<img style="height: 284px;" src="\images\barber\1.jpeg">
  • The default values for the jpeg encoder produce poor results. But why are you saving it as a jpeg when it uses src="data:image/ **png** ? – Andrew Morton Feb 04 '20 at 12:44
  • Otherwise, [High quality JPEG compression with c#](https://stackoverflow.com/questions/1669850/high-quality-jpeg-compression-with-c-sharp/17059958#17059958) has suggestions which you could still use in VB.NET. – Andrew Morton Feb 04 '20 at 12:47
  • Yes, you are right, I put png and it's a little bit better but still far from the quality that I would like – Mirko Baldassini Feb 04 '20 at 13:15
  • You're creating a distortion. You should specify what is the max Size of the container (the bounding limits of the Image size). Then scale the Image to fit these bounds. See the method shown [here](https://stackoverflow.com/a/54726707/7444103). The notes [here](https://stackoverflow.com/a/59102380/7444103) may also be useful (especially in relation to the Image Dpi setting - which you have to consider. The original Image `PropertyItems` should be considered, too). Use PNG only as the destination format (it's the default, anyway). – Jimi Feb 04 '20 at 13:29
  • Thank you for the answer guys, the max size of the container is specified here graphicsHandle.DrawImage(image, 0, 0, newWidth, newHeight) And with this new setting the image quality is worst graphicsHandle.InterpolationMode = InterpolationMode.NearestNeighbor I also tried to put this as suggested graphicsHandle.PixelOffsetMode = PixelOffsetMode.Half But no changes – Mirko Baldassini Feb 04 '20 at 14:20
  • Nope. Always use `Interpolation.HighQualityBicubic` when the Pixel is rendered to a non-scaled device context (1 Pixel is rendered to the DC pixel size) and you're scaling down. The example you have seen *expands* pixels to a multiple of their size, so `NearestNeighbor` is required. From that code, you just need the method that scales the Bitmap inside a specified container. The other code samples may be useful if you need to apply a filter (other details may also be interesting). `PixelOffsetMode.Half` is the best quality `PixelOffsetMode`. You may need it if you notice a white border. – Jimi Feb 04 '20 at 15:19
  • If you're instead **increasing** the Size of the original Image, there isn't much you can do to preserve quality. The Image will come out blurred anyway. Btw, if you're rendering Images that support transparency (as GIF or PNG), `Clear()` the Graphics using the background color of the Html Page that will present the Bitmap. – Jimi Feb 04 '20 at 15:21
  • No, I'm not, I want to reduce the size, I'm trying with the size to the contenitor, with RectangleF, is this one that you were talking about? But I have problems. This is the result that I still have http://mb-website.com/resize.aspx – Mirko Baldassini Feb 04 '20 at 17:13
  • 1) I cannot see what code you're using 2) those are two different Images: one is a `png` and the other a `jpg`. I cannot compare anything. I don't even know which is the original. + As already mentioned, **do not** output a `Jpeg` image. Use the native `Png` format only (`Tiff` would also do, but you need to use the Encoder directly). – Jimi Feb 04 '20 at 18:28
  • One is in png cause you suggested me that it's better, my original image is as there is in the code that I posted, the second one, the jpeg, infact if you inspect the page you can see that the first it's smaller then the other – Mirko Baldassini Feb 04 '20 at 18:39
  • So, the original is a JPG and the other is your elaboration. Are you complaining that the shadows are more visible in the Image you produced? You didn't read that much in depth what I posted. For example, when you load an Image from a file (or use `New Bitmap()`), you **always** specify `true` for `useEmbeddedColorManagement` argument. So `Image.FromFile([path], true)` or `new Bitmap([path], true`). Actually, I use only `File.ReadAllBytes([path])` and then a MemoryStream as *transport*. You also need to verify whether some `PropertyItems` need to be copied over (e.g., Rotation). – Jimi Feb 04 '20 at 19:07
  • If you have modified your code in any way, update the question with what you have now. – Jimi Feb 04 '20 at 19:08
  • I put the true in Image.FromFile, I didnt in new Bitmap cause doesnt accept that with my actual parameters. I think that I got what you tryied to said to me about the container and the image that goes to fit that. I focused deeper on the solution that you send to me, copying the PropertyItems as in the example but the result is still the same. – Mirko Baldassini Feb 05 '20 at 19:02
  • Test this code: [PasteBin](https://pastebin.com/UuVXsJBc). Btw, if you want to *ping* someone, you have to use their nickname prefixed by `@`. – Jimi Feb 06 '20 at 03:52
  • Btw, the test image you posted has 72 Dpi. This is not an image suitable for testing. An Image must have at least 96 Dpi. I understand you cannot control what people upload, but you also have to inform your users that the results may not be *excellent* if the original image quality is abysmal. Use the method I linked before to calculate the new size of the Image. – Jimi Feb 06 '20 at 04:07
  • @Jimi I have tryied with "good" pictures got from my Iphone X, with 2 or more MB, but they still have 72 Dpi, I tryied to find some pictures with more then 72 in Google Image looking for with the filter, tools, dimensions, big, but I still found just pictures with 72 Dpi, and the result is still not good in any case, this procedure is too much limited, could existing another stronger way to do what we are doing, for example when you send photos by whatsapp they are reduced but they still have really good quality, thank you – Mirko Baldassini Feb 06 '20 at 10:13
  • If you try the code I posted (in PasteBin), it introduces a gamma correction. That value (it should be `1.2f`, to be precise) corrects the standard result generated by the GDI+ Interpolation: the image generated it's always a bit *brighter* than the original (the color matrix used in the process is tuned this way). The `maxHeight` value (or whatever measure you decide, a destination Rectangle, maybe; you can use the method I previously posted to resize the *box*) is what you should pass to the method. This is all you get from GDI+, which, btw, is notoriously not well suited for Web services. – Jimi Feb 06 '20 at 13:48
  • @Jimi Honestly I prefer without corrections of attributes (too much dark in some pics) and without the value true in FromFile (too much red in some pics), I tried fixing my photo from 72 Dpi to 300 Dpi by code but the result is still the same. I have upadated my code with transform Dpi – Mirko Baldassini Feb 06 '20 at 14:40
  • You have to use load the ICM color table from the Image if you want to represent it correctly (if the Image has this color table attached, there's no guarantees it has one. In PhotoShop, it's an option you choose when an Image is saved). My screen is calibrated using the Adobe calibration tool/Color management, so what I see on screen is what is printed on paper. The Web Page you linked, shows two images with a slightly different *brightness*. With the gamma correction applied, the colors general temperature is the same (the histogram cannot be identical but scales in similar way)... – Jimi Feb 06 '20 at 14:53
  • So, if you see something completely different, it may depend on the screen calibration. -- Setting just the DPI of an Image after it has been created is useless, the DpI is a reference that describes how the Image should be rendered/printed on a device. It also determines the Image size, when the image is generated. Setting it after, doesn't change anything. -- The overall quality of the Image you posted when scaled down is not different than what is expected. You can test it in Photoshop. You could of course analyze the image to determine if needs gamma/brightness/contrast regulations. – Jimi Feb 06 '20 at 14:54
  • As already mentioned, GDI+ is not designed to work on the Server side. It has never worked that well. You have to test the results on a desktop computer and compare these results with what you get server-side. If you don't like the way GDI+ works in this context, there are tons of graphics libraries designed specifically for Web services. Many are open-source. – Jimi Feb 06 '20 at 14:57
  • Yes I need something different for sure, It's not the appropriate solution for me, I found something in the web but it's always buing, this one for example looks amazing https://imageresizing.net/ but still have to pay, thank you – Mirko Baldassini Feb 06 '20 at 15:23
  • [Using ImageSharp to resize images in ASP.NET Core](https://www.hanselman.com/blog/NuGetPackageOfTheWeekImageProcessorLightweightImageManipulationInC.aspx), [ImageSharp - GitHib](https://github.com/SixLabors/ImageSharp) -- [Scott Hanselman on ImageProcessor](https://www.hanselman.com/blog/NuGetPackageOfTheWeekImageProcessorLightweightImageManipulationInC.aspx), [ImageProcessor - GitHub](https://github.com/JimBobSquarePants/ImageProcessor) -- [SkiaSharp](https://www.nuget.org/packages/skiasharp) – Jimi Feb 06 '20 at 16:26
  • I used ImageProcessor and the quality is still the same, now I'm trying with the web version, ImageProcessor.Web but I have problem, it's difficult to configure it out for me – Mirko Baldassini Feb 21 '20 at 11:25

0 Answers0