Back

1 year wasted. Learning from my Mistakes

2021-05-28 . Written by fishie

Featured Image

>be me

so a bit of back story

this is what the problem was. i had to code a app that can render images on demand. more like a template where user can replace the text and images. pretty simple.

i was working with c# so my options were limited when it came to image rendering.


so i looked at my options.

i really didnt want to work with GDI as its pretty low level i mean not really but you know what i mean. the issue with html and css is that to render you need a web browser to run. yeah memory hungry browsers. the issue with browsers is that they are large in file size and consume alot of memory when its running. alot more then i was willing to spend on such a small feature.


so my other option was going the old fashion way. GDI/GDI+. for those who dont know what it is basically its what graphics is? i dunno you can draw boxs and shit with it. anyways so this is attempt 1


PART 0

i found out that you can export winforms controls as images. this worked really well at first. until i realized the image resolution depends on the screen resolution 😐 so the quality wont be consistent across devices so i had to scrap the idea


PART 1

so i used gdi+ to make a very simple version of the app where i get everything static in the image and just have it be a texture thats drawn on. and then draws whatever image the user wants. pretty simple i had to impliment stuff like scaling and cropping but it wasnt too hard. while this gets the job done its not scalable nor is it modular. so i have to make a entire library to generate images


PART 2

so i came up with my own markup language based off html. now keep in mind this was version 0 of the language

this would include a custom markup language and also a custom file format which would be a zip container with encryption and have DRM and version system and everything. so as you can see an ambitious plan


all the items in the zip file would be encrypted with my own custom build encryption code and the file would hold the design data, design assets such as fonts and images, info about the design including

who made the design (i made my own version of designer app so people can make and sell their own designs)

what language the design was made in (i added this so i can update the laguage later on and refer to this value to have backward compatibility)

DRM related info (date made, auth details, license details etc)

so as you can see alot of shit


i didnt really impliment css into this design so this is what it was gonna be like


<image path="" height="" width="" scale_type="" z_pos="" y_pos="">


as you can see this method where i put all the props in the line is a very dumb idea that can get over complicated very easily. and soon i learned this so i developed version 1


ill be honest i dont remember version 1 😐 there were some drugs involved so moving on to version 2


version 2 splits the file into 3 files

css

html

custom language


so this is how it works


the css file only has ID's no classes. i know bad idea but trust me it was a intentional design choice


        #Title{

            opacity1;

            color#17212b;

            font-size100px;

            font-familyArial Black;

            font-styleitalic;

            top245px;

            left75px;

            height115px;

            width1177px

            positionabsolute;

            margin0px;

            padding0px;

        }


this would be in the css file that is given to the app

and as for the custom language it would look something like this


DRAWTXT(STRING,INT)

DRAWTXT(TEXT_2_DRAW,CSS_INDEX)


DRAWTXT(hello,1)

the css index is basically giving the app which css id to use for this specific instruction. and assuming that #Title is 1


anyways the html would also share the same css file. that way i can use a basic browser as a tool to design the template and convert it to my own language.

from here all i had to do was take css data and have the output look exactly like the html output. hence 1 year of development where i was building a library that would render html from scratch.


PART 3

now gdi is fast no doubt the code was amazing. only issue is how painful it is to develop and how much work its taking to impliment this small feature so my other plan was a cloud browser. so i install node js and code a server which would take html string and render it on the server and give to client.

now the issue with this is

pros

anyways i got the whole thing to work and then i realized wait passing html string to server and rendering it is fine but what about images 😐

ok so my next plan was

zip images needed to render the html and pass html and zip file

but then the server will need to unzip the zip file and images take space and it would be a whole mess

so i got another idea

html can store base64 images so i can just do that and pass it in the html string. then i realized how slow it would be as images can go up to 5MB and this would be making multiple requests to server and the html string size would add up and it would just be a mess of back and forth.


PART 4

so i was fucking around online and i accidently run into this.

c# - Convert HTML string to image - Stack Overflow


static void Main(string[] args)

  {

    var source = @"

    <!DOCTYPE html>

    <html>

      <body>

        <p>An image from W3Schools:</p>

        <img 

          src=""http://www.w3schools.com/images/w3schools_green.jpg"" 

          alt=""W3Schools.com"" 

          width=""104"" 

          height=""142"">

      </body>

    </html>";

    StartBrowser(source);

    Console.ReadLine();

  }


  private static void StartBrowser(string source)

  {

    var th = new Thread(() =>

    {

      var webBrowser = new WebBrowser();

      webBrowser.ScrollBarsEnabled = false;

      webBrowser.DocumentCompleted +=

        webBrowser_DocumentCompleted;

      webBrowser.DocumentText = source;

      Application.Run();

    });

    th.SetApartmentState(ApartmentState.STA);

    th.Start();

  }


  static void 

    webBrowser_DocumentCompleted(

    object sender, 

    WebBrowserDocumentCompletedEventArgs e)

  {

    var webBrowser = (WebBrowser)sender;

    using (Bitmap bitmap = 

      new Bitmap(

        webBrowser.Width, 

        webBrowser.Height))

    {

      webBrowser

        .DrawToBitmap(

        bitmap, 

        new System.Drawing

          .Rectangle(0, 0, bitmap.Width, bitmap.Height));

      bitmap.Save(@"filename.jpg", 

        System.Drawing.Imaging.ImageFormat.Jpeg);

    }

  }


as you can see 😐 this method uses the old internet explorer thats in windows to render the html. the thing with the old IE is that its fast and is already on all systems so i dont have to distribute it. and yes i did test to see if the old designs i made would render on this or not and it indeed does render so yea 😐😐😐😐😐


So what did i learn

alot about GDI/GDI+ at this point i have my own image library that can generate images really fast and efficiently

i learned how to use node js overnight

i learned how much over engineering i did in this project

sometimes the solution is very simple