How to display image on webserver

zazas321
Posts: 231
Joined: Mon Feb 01, 2021 9:41 am

How to display image on webserver

Postby zazas321 » Mon Mar 07, 2022 12:39 pm

I have used simple file_serving example from esp-idf. I would like to modify the html slightly.
I need to simply add the image to the webserver and I am not fully understanding how to do that:

I have test_icon.png in the same directory where the upload_script.html is. I have tried to modify the upload_script.html by adding few lines:

Code: Select all

<h2>HTML Image</h2>
<img src="test_image.png" width="500" height="333">
When I start the program, connect to the AP and type 192.168.4.1 to the webserver, the image is not displayed:
https://ibb.co/9YRPFhp



I have learnt how to add files to ESP32 flash memory using:

Code: Select all

 extern const unsigned char test_image_array_start[] asm("_binary_test_image_png_start");
 extern const unsigned char test_image_array_end[] asm("_binary_test_image_png_end");
const size_t image_size = (test_image_array_end- test_image_array_start);
So I have tried the following:

Code: Select all

    extern const unsigned char image_test_array_start[] asm("_binary_image_test_jpg_start");
    extern const unsigned char image_test_array_end[] asm("_binary_image_test_jpg_end");
    const size_t logo_size_test = (image_test_array_end - image_test_array_start);
    httpd_resp_set_type(req, "image/jpeg");
    httpd_resp_send_chunk(req, (const char *)image_test_array_start, logo_size_test);
but it displays bunch of thrash:
https://ibb.co/jMJR2Np

esp32-user
Posts: 10
Joined: Sat Mar 05, 2022 6:54 pm

Re: How to display image on webserver

Postby esp32-user » Mon Mar 07, 2022 1:50 pm

Might try imagemagick "convert" command - looks like this:

Code: Select all

$ convert esp32.png esp32.h

Code: Select all

$  ls -l esp3*
-rw-r--r--  1 esp32-user  staff  6789966 Mar  7 14:37 esp32.h
-rw-r--r--@ 1 esp32-user  staff    50113 Mar  7 14:36 esp32.png


Note that the size is huge. Not sure that this will work for you.

Code: Select all


$ head esp32.h
/*
  esp32.h (PNM).
*/
static const unsigned char
  MagickImage[] =
  {
    0x50, 0x36, 0x0A, 0x31, 0x33, 0x32, 0x36, 0x20, 0x32, 0x36, 0x36, 0x0A,
    0x32, 0x35, 0x35, 0x0A, 0xD5, 0x37, 0x32, 0xD5, 0x37, 0x32, 0xD5, 0x37,
    0x32, 0xD5, 0x37, 0x32, 0xD5, 0x37, 0x32, 0xD5, 0x37, 0x32, 0xD5, 0x37,
    0x32, 0xD5, 0x37, 0x32, 0xD5, 0x37, 0x32, 0xD5, 0x37, 0x32, 0xD5, 0x37,

$ tail esp32.h
    0x6E, 0x70, 0x6E, 0x6E, 0x70, 0x6E, 0x6E, 0x70, 0x6E, 0x6E, 0x70, 0x6E,
    0x6E, 0x70, 0x6E, 0x6E, 0x70, 0x6E, 0x6E, 0x70, 0x6E, 0x6E, 0x70, 0x6E,
    0x6E, 0x70, 0x6E, 0x6E, 0x70, 0x6E, 0x6E, 0x70, 0x6E, 0x6E, 0x70, 0x6E,
    0x6E, 0x70, 0x6E, 0x6E, 0x70, 0x6E, 0x6E, 0x70, 0x6E, 0x6E, 0x70, 0x6E,
    0x6E, 0x70, 0x6E, 0x6E, 0x70, 0x6E, 0x6E, 0x70, 0x6E, 0x6E, 0x70, 0x6E,
    0x6E, 0x70, 0x6E, 0x6E, 0x70, 0x6E, 0x6E, 0x70, 0x6E, 0x6E, 0x70, 0x6E,
    0x6E, 0x70, 0x6E, 0x6E, 0x70, 0x6E, 0x6E, 0x70, 0x6E, 0x6E, 0x70, 0x6E,
    0x6E, 0x70, 0x6E, 0x6E, 0x70, 0x6E, 0x6E, 0x70, 0x6E, 0x6E, 0x70, 0x6E,
    0x6E, 0x70, 0x6E, 0x6E,
  };
$
Another option is shown here:

https://randomnerdtutorials.com/display ... eb-server/

ESP_Sprite
Posts: 9582
Joined: Thu Nov 26, 2015 4:08 am

Re: How to display image on webserver

Postby ESP_Sprite » Tue Mar 08, 2022 1:24 am

@esp32-user: That would actually give you a header with the raw uncompressed RGB values. It's useful for other things (e.g. displaying on a LCD) but for sending it through a webserver, it needs to be the original jpg/png.

@zazas321: It looks like the correct data is sent (I see 'JFIF' at the start, which is a proper JPEG marker) but the content-type somehow doesn't make it through to the webserver, meaning it interprets it as text instead of an image. Can you inspect the headers that the ESP32 sends along with that image? (You can either use a command-line tool like curl, or the developer mode of your webbrowser for that.)

zazas321
Posts: 231
Joined: Mon Feb 01, 2021 9:41 am

Re: How to display image on webserver

Postby zazas321 » Tue Mar 08, 2022 8:03 am

Thanks for the replies. I have been further testing and found something interesting:

I have created a new post handler:

Code: Select all

        httpd_uri_t uri_post = {
        .uri      = "/test",
        .method   = HTTP_POST,
        .handler  = post_handler,
        .user_ctx = NULL
    };
    httpd_register_uri_handler(server, &uri_post);



esp_err_t post_handler(httpd_req_t *req)
{

    char content[100];
    size_t recv_size = MIN(req->content_len, sizeof(content));

    int ret = httpd_req_recv(req, content, recv_size);
    if (ret <= 0) {  /* 0 return value indicates connection closed */
        if (ret == HTTPD_SOCK_ERR_TIMEOUT) {
            httpd_resp_send_408(req);
        }
        return ESP_FAIL;
    }
    ESP_LOGI("POST_HANDLER","post request received = %s \n",req->uri);

    const char resp[] = "URI POST Response";
    extern const unsigned char elstat_test_array_start[] asm("_binary_elstat_test_jpg_start");
    extern const unsigned char elstat_test_array_end[] asm("_binary_elstat_test_jpg_end");
    const size_t logo_size_test = (elstat_test_array_end - elstat_test_array_start);
    httpd_resp_set_type(req, "image/jpeg");
    httpd_resp_send(req, (const char *)elstat_test_array_start, logo_size_test);

    return ESP_OK;
}
Since there are no other html elements on this page, the image is sucesfully displayed:
https://ibb.co/wL5kpL3


However, the issue is when I try to display the image together with other html elements on my index page. I would like to display the logo, some text, some tables and other things:

When I access index page, the following elements are being displayed:

Code: Select all

static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath)
{
    //httpd_resp_set_type(req,"text/html");
    char entrypath[FILE_PATH_MAX];
    char entrysize[16];
    const char *entrytype;

    struct dirent *entry;
    struct stat entry_stat;

    DIR *dir = opendir(dirpath);
    const size_t dirpath_len = strlen(dirpath);

    /* Retrieve the base path of file storage to construct the full path */
    strlcpy(entrypath, dirpath, sizeof(entrypath));

    if (!dir) {
        ESP_LOGE("DOWNLOAD", "Failed to stat dir : %s", dirpath);
        /* Respond with 404 Not Found */
        httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "Directory does not exist");
        return ESP_FAIL;
    }

    /* Send HTML file header */
    httpd_resp_sendstr_chunk(req, "<!DOCTYPE html><html><body>");

    /* Get handle to embedded file upload script */
    extern const unsigned char upload_script_start[] asm("_binary_upload_script_html_start");
    extern const unsigned char upload_script_end[]   asm("_binary_upload_script_html_end");
    const size_t upload_script_size = (upload_script_end - upload_script_start);


    

    extern const unsigned char elstat_test_array_start[] asm("_binary_elstat_test_jpg_start");
    extern const unsigned char elstat_test_array_end[] asm("_binary_elstat_test_jpg_end");
    const size_t logo_size_test = (elstat_test_array_end - elstat_test_array_start);
    httpd_resp_set_type(req, "image/jpeg");
    httpd_resp_send_chunk(req, (const char *)elstat_test_array_start, logo_size_test);


    httpd_resp_set_type(req, "text/plain");
    /* Add file upload form and script which on execution sends a POST request to /upload */
    httpd_resp_send_chunk(req, (const char *)upload_script_start, upload_script_size);







    /* Send file-list table definition and column labels */
    httpd_resp_sendstr_chunk(req,
        "<table class=\"fixed\" border=\"1\">"
        "<col width=\"800px\" /><col width=\"300px\" /><col width=\"300px\" /><col width=\"100px\" />"
        "<thead><tr><th>Name</th><th>Type</th><th>Size (Bytes)</th><th>Delete</th></tr></thead>"
        "<tbody>");

    /* Iterate over all files / folders and fetch their names and sizes */
    while ((entry = readdir(dir)) != NULL) {
        entrytype = (entry->d_type == DT_DIR ? "directory" : "file");

        strlcpy(entrypath + dirpath_len, entry->d_name, sizeof(entrypath) - dirpath_len);
        if (stat(entrypath, &entry_stat) == -1) {
            ESP_LOGE("DOWNLOAD", "Failed to stat %s : %s", entrytype, entry->d_name);
            continue;
        }
        sprintf(entrysize, "%ld", entry_stat.st_size);
        ESP_LOGI("DOWNLOAD", "Found %s : %s (%s bytes)", entrytype, entry->d_name, entrysize);

        /* Send chunk of HTML file containing table entries with file name and size */
        httpd_resp_sendstr_chunk(req, "<tr><td><a href=\"");
        httpd_resp_sendstr_chunk(req, req->uri);
        httpd_resp_sendstr_chunk(req, entry->d_name);
        if (entry->d_type == DT_DIR) {
            httpd_resp_sendstr_chunk(req, "/");
        }
        httpd_resp_sendstr_chunk(req, "\">");
        httpd_resp_sendstr_chunk(req, entry->d_name);
        httpd_resp_sendstr_chunk(req, "</a></td><td>");
        httpd_resp_sendstr_chunk(req, entrytype);
        httpd_resp_sendstr_chunk(req, "</td><td>");
        httpd_resp_sendstr_chunk(req, entrysize);
        httpd_resp_sendstr_chunk(req, "</td><td>");
        httpd_resp_sendstr_chunk(req, "<form method=\"post\" action=\"/delete");
        httpd_resp_sendstr_chunk(req, req->uri);
        httpd_resp_sendstr_chunk(req, entry->d_name);
        httpd_resp_sendstr_chunk(req, "\"><button type=\"submit\">Delete</button></form>");
        httpd_resp_sendstr_chunk(req, "</td></tr>\n");
    }
    closedir(dir);

    /* Finish the file list table */
    httpd_resp_sendstr_chunk(req, "</tbody></table>");

    /* Send remaining chunk of HTML file to complete it */
    httpd_resp_sendstr_chunk(req, "</body></html>");

    /* Send empty chunk to signal HTTP response completion */
    httpd_resp_sendstr_chunk(req, NULL);
    return ESP_OK;
}

#define IS_FILE_EXT(filename, ext) \
    (strcasecmp(&filename[strlen(filename) - sizeof(ext) + 1], ext) == 0)

/* Set HTTP response content type according to file extension */





After sending

Code: Select all

httpd_resp_sendstr_chunk(req, "<!DOCTYPE html><html><body>");`
I try to send:

Code: Select all

    extern const unsigned char elstat_test_array_start[] asm("_binary_elstat_test_jpg_start");
    extern const unsigned char elstat_test_array_end[] asm("_binary_elstat_test_jpg_end");
    const size_t logo_size_test = (elstat_test_array_end - elstat_test_array_start);
    httpd_resp_set_type(req, "image/jpeg");
    httpd_resp_send_chunk(req, (const char *)elstat_test_array_start, logo_size_test);

After I send the image, I change the resp_set_type back to text plain to display the rest of the html elements, is that correct?

Code: Select all

    httpd_resp_set_type(req, "text/plain");
    /* Add file upload form and script which on execution sends a POST request to /upload */
    httpd_resp_send_chunk(req, (const char *)upload_script_start, upload_script_size);
  
But this does not want to display:
https://ibb.co/M7mVzVb

Does it have to do anything with the fact that it is being displayed together with other html elements?

I have opened the developer mode and on my html body I clicked "edit as HTML":

Code: Select all

<body>ÿØÿàJFIFHHÿâICC_PROFILElcmsmntrRGB XYZ Ü)9acspAPPLöÖÓ-lcms
descü^cprt\wtpthbkpt|rXYZgXYZ¤bXYZ¸rTRCÌ@gTRCÌ@bTRCÌ@descc2textIXXYZ öÖÓ-XYZ 3¤XYZ o¢8õXYZ b™·…ÚXYZ $&nbsp;„¶ÏcurvËÉc’kö?Q4!ñ)2;’FQw]íkpz‰±š|¬i¿}ÓÃé0ÿÿÿÛ„	




+  +&amp;.&amp;#&amp;.&amp;D6006DOB?BO_UU_xrxœœÒ	




+  +&amp;.&amp;#&amp;.&amp;D6006DOB?BO_UU_xrxœœÒÿÂmô"ÿÄ4ÿÚçe¬y6[$&amp;9šØ§´`Å´®4÷ˆë)møÕîuN¥Ò7Ï…{´MãÄú
´k+˜ÊÚq8‹È´‡‰óý^ÜÏçä~óœ/’5ºó¾Soh‹ÜªQb%Ós¬ÚȱJ4ž	Ä5€jƒf°6ÆÍ×jö˜
‡H
Ö
K…SlZ51lҐÇÜò°½;T§pUm
,¶ÏÛvÞŒ¹çOvÛÄd@dD59\e²²5ÄZk`™ŒÚ²‹Z˜ƒj¶G(Ðw¿7ç®–Óù{·ò»X6¬i…¾”—–Ôª¼›5µì!-DÛ2cC%ZZÊV±Á`\ƒF®€ó]š½@ˆ&gt;ûª¦”dê-Ll4BqÓˆÍÑZ)P¼R&shy;´Æ¯5³s‘‰^k(µ«)Ìä„NHë–„DÆ'rEnI׉ó~ß×y!²UÂ_-r€
µä&nbsp;òòÃk‘BM’;Y¤°ÊÓ¤Øì©*Ê&amp;U®«‰å4`Õ„5WgpA´M}$¯¾êÃ#)fR+VÕâ°Ëà±£`¬ÂHî2XwEí[É–ÉO&amp;$s[Â)×&amp;©ZÐsÁ{6ó8u½W•ñVŵm‘EÚ‰a¤•
Á”§&amp;R2¶Æl§@!S
Žšé4ºâ9w&shy;RééUe=ïÅ}Ñ‘rÃÒj&lt;X8£VÊ	…&nbsp;aɬ0¤	%–Ú²g¦Æž{aÕÙíÍ¥³Ê™ª^µ×ŸÕÆ«u¬	V¥¢¨°&nbsp;ÙrΑ~s½øjEz ´†&lt;²-´+‘¨Zó@ÒÔá#E´Ó0u¥0uçÔ:ÛÕ6Þé¶}+ÑÄop5PX
M`"ˆu'ÅÊÆxÎÇà6üƒÑé:Ÿn~¾”?ô&amp;ܾÞîü°N£yÏæòƒ=ôg'Söþiú«ê[sˆG
, #ºâ^°rß4Ó–óKHM,tèË´€±aƒ¡–b¸âtã^êú55î)¥&shy;‚˯.¤Û}iÆ;ïF6hK•V¨)œJh£æʧ›ñZ?IÏ8=]~»§u&amp;¾a÷ýƒç¤ü?&nbsp;ì?8iËÛ¼Î𼞧›ó{Ï6=«¾Q{Œºg߉íç”b4ûkò§ÔÛó`Î-¹€@Áej–Ájm7:ÿZë3VºÁ9y¥Û(
®°è•²š÷ºS^â:Ú¸&lt;ºòö§&shy;쏢=zoÀP0
G4PúÁ
\QM·XUõfæ\ý€÷2×'w&shy;ôZÝWgž™=§çïν¼ÞéÌuìg‹Ðágßùc£Î‹Ð+ÓÁªq
î¸o|Ëmê»¯Ï&gt;©W×€×m;|Å‚ÀhTG]M¶Z–†‡0î|[É2BN„ÅÂñ6¢W éR,¥&lt;]¥Æ4¦×ik`³Zó“ý-Û—N‹‹XçV:âOXÞ¹JÈ0”?I½ZôügˆôÙÅëzÒx~¥ó¯=Ô磓Ås/¦þ}W£®‰é›u·7õño9йþ}MŠôùÑjŽóceª²×`&nbsp;ý´&gt;ŸÕ~búcLh—éäYWµ“ôÜ£¦yŽ7ᢵñÔØ€ƒaÐp\MávGLh±[zÄž×íiå3Jó_]|©õ÷~;QW!U•).¹Ö«]±ÖÄ£•fkÖ$Ö•éÊ:Ç&amp;꼿šížCÛïÇ_=ʸî˜um®]w&shy;pÔU}í~l÷³®ãŽu~KÏئE»¼™µ¨Èm9=_Ê{¾~ô‡Í}þã×®ÒÝžrÊ´³¬-À3k›ãcŠ|û½Œ\$=•¥I:Tñ6ìÚh¶;z¤ö:Í-L®]«õ¿ÊXz82‡I
¬¬Ò«4ªZÍf×_VòÍÍzoÐ94ôéz× íœ~&shy;ô}Ï¡äóW=·U½æÜõlôÑúYóÑ·ß|ü†{u.ïyÞzœU¿OIuuJήÂÀ}‡yù»è¨}fVïòÕU¥i"-&amp;ÏÒyoXŸ›'óÁ–lAÊÔ²§p¹éMtOM±WµúZ9™wo«~MúÇÑÁ˜W Y•é(³Š¥®S`´&shy;MØ^/uÎú‚vâ¿@üíÜyûúVÛQ¶íó9‡Ì_mrÌï‡z/&nbsp;¢5ã^èÞUs}é{=çɼŸ¾çxväÔ½x෍@G5³¥½˜ÞiÌ_¢þiú[.¿z³vùj¨Òt‘Q•%l}Žö*¸p[G猆E,ô]°¤]f
̆¨L°*j¤{]¥ëð™w¯úß㏯½vâ(´€®È¨‘R€ºa‹N¾ôüß“Ôú;ÔsïsÑÀÖZוu&shy;ðkuy)ß¡ó9ã¸û¶Þ/w©¼×¸¿Z…EKš8³bÜ}yóßÒa*ʝžrÉ´ƒ”– em}g—ô|ZП϶ÆXÔaH02Ã4Q½i„GVÞ½}†³KÖãwä~ªùk¼÷eØJo˜@ÀX¸X•IJ7A/rQX9còØuyþÝòÿ[ϧªÎ‡ÑÁ󆋽yé¿3¥é^Ûiù;ÊýOçò|ãËý5Î8}n<o_ã¶ån¸‘&dÝ)Õ¹½n›í2½Þh”:šäº ëÄŒpÒ·äkÉa~²¿ŠÚ‹.="" bvº”sc!;e�´+m%Ÿ×Ýê±ÌÒüŸfçÍt¯±%û0Œ&�f£báqŠ€$’©ò_Žãhø®nËt¿š69õ}6ß7÷="NÊŽ^*Øò¾ÄëÊ9çqã<~—€Öýuó†ü¾»?l®~‰×ú" °]~Ž1¨e*wÖ·&shy;h="" '¹gªä="g†ùÚRçšr*uñƒ!ÁJ«1p\µ4ìD›M=¦¾ïO›<«ò‹mµ›?¡úOÌ?L÷a`œZHhJ5H´�àÔa`)—²(žÀiùOÖõtðÞ“áåïí—åßm/脹&amp;£\;ίƒ†_dà%³êַѺÜþ©Þ®" ¦slak&shy;j‰="" ׏ê´ÚoÇsÖµ¾+Ây\mŠ$2k¶Á©k-“„Ék!’¦6Èuj1¬«Ò%¼×:×ý3ów«ê§eíÄ5%¤^¹8Ât+6Œµ€ti¤–Þsñ¨ô)Ë^(.Ýh׋޳ҟtÖ™¤ý«qjÖ¡!ÀÒ…åkcןz¤f¦Òm°="!ã×ϺòeŒƒ©©fd™jL Lf
ÔmR•aª†Åj&shy;N;•K)¹F&shy;" ’Þ»§nùé®ìwt8÷dÕ¨Ë@dÅ‚¹xœ°e¢bÓ[nhòs7¦ò˜ŠÐ-jŽ–jºd‰k•+zÄ6Ùé¤å¤ˆèÅÉäšpeÂŒ„�ÊÌq«-$ekj‚·*&shy;‹]°v³Ëtsp="">zÒ§¸GJÔïuëî}\ßÏ_@zåÒ&lt;šµ“˜jHZbȉɘ™¬„ä`[+9X	&shy;iDŠÔ«‹¹…ËT‡¶ÏMß1ä[KZÜh€nÐÎ#9e0PÍm-Jµ+/¨d°›y¯l4ÓÃåQå9Ú” )©¯ÚJÔ{ÿ®§Ööù×èCÑ¡m!ËU©ˆÆZky‘y¦æ˜ŠÀ&shy;£	ZU–	’´„šŒ…vLî3Ó9‚~WË£ð«Š$$ª6DB0+ÌP'62+©RБ®ËÍ×ë[¥4ðøÛKY}ž!Ƴ]-¨ÐzV§j’û?¤='Ê[·.§Bª©éHYjÒ›˜,VÂ@&nbsp;ET
:ÀTe”x5»†ü5û/¥.¯²Tø"WR*wµÔ¦àb@‹Í‹`¸Últ³G((€;MÀÃëFÁ“”è¶Ý^~†˜€Î¯ÅG´ÒQ±ÓÕl;luÎ,-—Õ³ó?Eëϧ_¼é”jõ-%W(Å!ª´®5"N]ºh[hĽCtñ˜&gt;…æ9@xÞËO°[ˆèDí°
„JÁÅ*	¬f !jVÝ\XlxW,¬·%™a\Cº6&shy;3b˜Åo~ScË+ˆ=
y,:³–tƒ•Áw¬íêiÛ÷^“Žs¾ì~zZ§é‚üÆͯ¤Ãóõ¤íú&gt;W2{_0¨2&amp;®1]ˆ¢Û"’À©]K’6Œ&shy;XjV*#!!peJ]•lŒlueæ“Á\ch‰€ªðÛJ-q¹š|³ÿÄ1!"#1 023A$Q%5CaÿچÉR¬6k=`æû7š¢©»Šˆ!Û4…7˃v‚§óÞM¦^èʱÛGªÑgd÷£€ê²t4`ÒAPhŒÔQò2¥¤Q5|[“Ø3lÔðY‡/M_ãb:ã5Ð~#]	.\ô\ô\ø×¼Ï÷^#N€†Ùñ
/K·âJêò··¯gW×ó¢cP|R®*…¯XˆZ„1õ•3׫:ŸVh2àv-R·pT\.MñGáE-OÆo…t\cÜQ°,p/ð²åùã@¨Ek<rÆ�á=l#bl…¬Éoø©Šƒå´òŒlfá=~vöu˜d˜#bcyã8ö…2‘ú¼²h+5cyþs×r«]&nbsp;¸ÚÔ¹f :w‰ê„Çúd3{Ø="" -w©z2«9rvar¨+sÉ³áw÷gðñ~%pvtømmukÐéwàÆš0èìxÎ…vü_nª«+ü&lʶiól³“¾pf¢wòȏ¸£çÐØö(…xzÍ‹'kdÂà¤é2Ð*1ˆ'&nbsp;¶r="™,Jθ:â«•Àÿ�É:`N–©‚‡ø©„�õž{tÛ¯Ö7Bèùñÿ�g•§Ôi–¥!VU‹t+°{Ô'," npogi)·ÉrÙ:7t©ë&têÔuÃe.[€çÅîn‘á|="" Ûúsš€&nbsp;„ÿ�¯Þƒ›Üf¦Òü‡ïjûÑzȁÛ÷d?ÄßÈxf·!ÿ�ï#`*”ů·iƒf~ÿ�&¿©4_‘[¯¥¿y="">,ú³®'_u±7#ݤW³®ŸCcN‰„€Ò¦|KíYå™Î¹0h‡³û_lŸCdT˜QqÝCʘÒí-I‹"±²{&lt;µÔ¸¦Çx–îÏb¬V,杬‚åû&amp;«Wfb':'ÕW‚ðºÜ&shy;6t8¸kÌ**ýwçyÞwçyÞwþ—yÞÀÀ¾SÇuvÈ&nbsp;ÞÑÙÑ{5˜×Yâ÷œ„\¥L™–,Å”€`Ô-…ˆÆVöšf?+á&shy;]N1?"(Z14ñA%¦ßžÁ!†&amp;Ñž=|yû”.
P#¡ùA8&shy;0ÕÃ׃/î}°ýg\¥¤k•£Ê®‹:²&shy;*ÅÙ5v$$æ*CQ&amp;ѪÌUÀøYBc7âjj_jë9xïˆÇX
RPT	Âs¼ï;Îó¼ïüƒý&gt;ó¼V͝M}©×šñÛêY®ºŽË7¡è¬@k¢â?Ýlz"(˜SÞ&nbsp;gl”ÊL¬’`¨;`vøé\e+)È0ö°\üt¶z:ÅS=P($…zá^‘CW'Г¹ª€³˜B
]ñ™„OnÍï0„&shy;b&nbsp;¶Âvò’?«ìâ¿nô …“695þÕÂݶqœnÆöÀIøÿŽkéHUUDá8Nwçyßù;Îó¼ï;ÎÿÒïgâêU¹ïdu¶¼iíJT©eƒ6t;”‡°j;çL!Þ2É1씩û=ºƒIH#jP·²ë–ÆCür
þÕfŲ,j;t˜
]Ëþ:ÄcŽÚjÏòS2ÉîÀc1w5@H-ìÔ=MÀJÔ’‰&shy;Þ[¥TL£uP[¶'=DçÆßvë9ð4àª&nbsp;pœ'	Îó¿Ó¼ï;ÎÿQƒùÈÿ'yÞÅpGGÈxñšk‡÷²~T©õêH˜UM@ú)–ðN@ ;ÝM뎝M${߬$úRØÓ+$˜oê0Lté'&lt;§MRp1/•^¾9çkò;ç؇fª¥æ¡›¿‘òhŽì¿šD;ûXçÈIg=¤ã€&shy;«]‹¤§ã&gt;=-8(ÀŽÂpœ';ÎÿBÙÞw€çx0~~g_©Î¿Ê á¿oïx¾Ò˜¦ŒùÙäãLJb„-„wðeü“˜›ƒZP°d8ÊŽA(
Yñˆ1ÊŽé9á&nbsp;5¥1þµ‚ã/½&amp;¸þZ§RDÆPoÖêNù@¢e‰g=+®æŒÂoôã[¬³t&lt;;Æÿo1Z"^°á8N„çyÞÏlöÎð;}û÷ÇØT°¹?ѳu‰¿6÷ë÷rïí]úë:Â?R0þ½â¶Z!Vå¸Ã¥°ôÆú’&amp;¦Àb¿KJåü3øý®3Ù‚R¤!Y¬ñµ€Ä&nbsp;T&shy;±Ô	"`ÕF&gt;µ¦2IϦ³RÂ,æ¨Ç&lt;üM]ñ‡Zç-Ñ¢&amp;"3š0Aê:5뵘rð·dœï<!--;6׈š8Ç	Æ8Nwã-->ÎðìéCm»¶u¦tùB
žOb!ÃWäÝžÅßÊõ
±Uòu¾©åŒÍÜyø:ž—qÁÈó,Ÿîãy¾?yI‰Fuú‡ôïÄnŽnjKs]¦ûiì¸p:×cŽŸs˜÷þV¡%Ö*¤¼ä$à½hKºk±4¬¤»6-XA²ìé0h
]Í®¿Xʦ¨€Pš…úI¤ñúkuŒÿÄkOg$þæÂz\cÿYÆèSsnqNž¶º"œ8Çá8NŒØ[=³Ûâ©=Û܆¬µÔó6;V§2ÝLGw–D+u¦7µV‡‡à¸«ëIëÇxëÚ	¿	¤Ð3}ŸâÜkâ<sžÓgÆö5qêæo:ÕyÖr!Áù¤kd•gt „apá#¾°çxfò8Þ$Èî½`£¥!”ðþwë="">N§Jç¨Y$Å}€1\…&shy;q¦VHûjˆäN´.,çÑ«bý»&gt;:ñÏEèʼnX•Qî©…Ïäø@П¥Æ=¶ð&gt;ãÎê¡T8N1Æ8NŒØ[g¶MK©&nbsp;Q•´å"íÎíñï&amp;«¤û;NÉ´ñã»ÕýÂkí5#äó‰I_‡ÓÕH!“^HÁsk—’mÎ#odÓV¡|‡È×CŒ„sc{ž'ÂÎL›{Iä_àÖݾ¤Š'	äûštœg)¯»èF„aFï²,JžoLêYÕ]A¤æÔÕèK×'(½´å’`Ö&shy;0’ºìÙEéc ³çàcŽªÏ4Á¥°[íÐ|ˆƒØwZc¯¬‘25ºÇ'ãgÊ¡¨–cÑ?Ù?õœ&gt;ƒnoJC‹ÕYI@8qŽ1Æ9Þ;ã&gt;ÂÙ5.Ý`t’–m_'ÜÛØt†×)ÊR”ù¯Ê_a„5åtD¼{B¼¿5oÑžÖ×-äøÍí´ö8O0åxùˆ¦ï—Úß·hr›œ†¶åmù%Õþ#½ÍSnÅs—Ù&shy;Uf¶§`·Ù5pÎû•=Œ¬¾)®Ì¸&gt;k¨ªq¶¿#ªµ™Fa‡;Àr/ÑÎsEvu}ÇËÐ&shy;qÇQšg·µÐ`¡jç¡ë<e°«žçÖ•4r²tÀªl$À-¨]@œÓ±¨»ã'^“÷wsù‰1Ëlû$ñÛíß>†7ý?Þ‡ü_a¶*‡1Æ8Çå)…ñŸ–`d?õ÷Íó•Õ×f›kòºm_<s†©cÿ�ÓÜe"ÉÇhñú•]]>Q¸îb{9äü¾¢ñ–÷Uù+ÒxO
GÙýÙòÁÅO·Êq»»`ïYg¯òþå]Õ›v`öz+2(mz(pjdZ^7ËmñûS²klNñZ!Fa‡;ÄnŽAƒ)›Ôøw„²µÝñ\¬±ÔÿÄØ;”b5ÝÍUz„ƒzµÙŠ¿ZÌÙ@=§1즴|cÔ8þY&nbsp;ÛV™Ee\¢÷O\v&gt;¯L&nbsp;éU2„–ú'û9µ(¨<o]}i ÆÆÆ8ç;Ê¿c±Ÿóntŏy±´ds‘äÑ´tô¤³Ÿ="" ]uλÎsvzÚ-?’ºq¦·ƒs[;t’ð_áΆŸtÚm&shy;iÝ#="">K‚v&shy;Êòœ†ÜõV/Ýö™^—›\
uŠÀ'®jé¾Áìr\žÎ¯û
üûÜ¢t£Âw箋'#aÆß&nbsp;9®ýžU®¿¶¡X¢aQüÕ$zk¢
(k*§ãJ–íb«…A²¦#ô)\e+$L§ån³Ý½˜gפñˆ6'	êLÙd?‚`YÛt£x–—î9DÍIúÈaÂqÎ1Æ8Ç¡•nÎ;ã¾j'É\Qê¿{wœÑ‹rû³ùhWÆ4—WM¶)?ý&nbsp;1Q—Ó®WÈøþ&gt;a¶9
ž[Èl'?(Ú“ò_Ãâ\Êò:"¦÷¤ëÖF|v&shy;“¾CUÝÙM‰¨Mt‹Tk®þŽâÅi±§0—[’zï8êЮzSgaTò\$uµ¡I?`‘œ/!yUá·N֔ݘaq°à?y&amp;ûËÅv5m꿺~Ó¡®Ï”’÷)…em‡còÖzeSøã0+³b³;åQ¿Š@öjìX09Díç0ÛÒ˜}„zÇûª®;Ÿä¦XtŠ¹f%þ¿þçøw§Ø¥JŽ”8qñŽï,ßXç(ØïœdÀ_¶ú&lt;}ô-ߤwwa&amp;åö~6ôO"Ò™åm±×ÒÓÕ&gt;/ù÷6?ÄmXòº•†®¡¯}è&shy;/¥Èò|ñ˜Mw½ÇOÄÙ´õ&shy;Ëí3WåU©÷,Éî\ü©OSÞU‹?È{PR€ÑŠq¼ÆΉs.Fæô¤Õl¼7gâô™la‡cçy6ûÍVìužC¬ºûtUøÁ¼Óǽ«†dkªãÏ»Î`Ý*]uqÓºÎx{½K'¬•M:5U_ùizš&amp;îç:6T§&lt;±üݲcñìœð}O‹Ž—èØØÇãeÛïå(÷¢®kŽ—¡W
Ÿ%µ\ðÞ9WU·”ÝV³*xÖ£ÇE¹á÷v›b’ð?Y•+ÄqºÓ^_q~rˆvºkêr|–Ð’x¿…<j)³ÍÃy`š•ß” ¥ô="" Àlìv¶réñ¡Ÿì€¯“¬isé—³«±hxu<£]ù="" mùqü³ëÚ2ž½–Н="" lll'³qþÆyv&nbsp;6…±="„ž¹I0YÈ*—¹8=„©ci•Œ¥ž¾Û�a~’”Ç@§…ƒ\¶DY²²û”·ó;àö9Oº&quot;cM.½MW,Ä?BkíEãÐԐýúÊŸ³Žr‡4§ï|AÒœÖP£·#µ¾^³ºëÏ[Bhšüi¥‹Flšè¬íùo!ã´5ùÿ�ñ·›KN|NÚqÕÛ¿Ê?|S5|›ŽÐ£8ÒóÊÓ“önPÛ{Z‰&shy;½ÃF.ûº÷Èî1ý›ä" ÿ�`$ä¬sµs˜Ýˆ§="ã”]®Nš7Ò0ÖCÀ×ÛD.666">ïûÍVûågâØ«)/)`~ëJ울㷔p¿µž‡ò]bqÇç)à§v¥3òëwi&amp;æ®"*¸›áqéZe@4=»Döž2~ûÚëœbzÅpáÆÆÆÊYL¦PçfbIé=yØëëQŸ÷¿Ýˆ^f¾¤ªøþ¢ˆ‡Ãø¯×—ùÖ̶+©ªkûŠšlér¼f•ùS˜g£íÄ̦}wœD^Çr¯¦W–Ôø‰ÎôÜ«/^Ýҝ®™X	)Ó1_ol”]½™xŽ+_f-Zîhénê[ScGEöõiâ¬j±±±ñÿ¼ï5›ìg"‚œuAT©që)Ïåu®BÖƃҞ?my®Rߍ)ŒNsÂÁ¶0Ðüt¦QYOƒfl勉efžó˜r¥ªùaÔ€ËP«ô<u=ù]qšc©a͍•þ±òƒ(3dú©Äc÷žsº³aíã©'Þ× »4í8¹’a^Ærá÷="" ·´÷m_ñéxî?[¡="" ,æxÍt²%àóÐÒ¡â<9wçljñý}="" d&shy;¨Á¾)ùŠ{ëvlpp&shy;ýØœ»(åëÖ{÷Ù,¾Åw5ÞaÉm´e="" Ú³Õ²="" jrýíu|[épãccå3¼ü±—ßu×:yd="" ´ìgv®ÙbzŒg¸}–cìˬï†}üsÀtÝÜÿ�p')="" k€ËòÙË°:öº®ú&shy;2©Òmgt'="}Ÿ^ùxæ¯üxpãcce¬a•\uÍ?°W¡Ì¡!e&nbsp;àvWWÞšŸ¯z]ücíqèrþ[ÅñÀ&shy;9o?å6»XqÊr.µ·“VÜ®¼8?&quot;ÜâªæWó®R¶,[È9T¯È9^q7#VWíì£è{t}Ê~G:ï¬%M_¥^‡Ý©FþÞ¦‡45ØízKÊ0wC”Êgyö2?ðœ4?5ë”ES�³LZ‚Õ±=.ºŒr&shy;YÈ" v®0õŠ‚}n®-®q@y¦s¦±%\‰;Š¯_±Ïní”$k+_fõ%ÿ�æ#š¿ñá͍”þ±†:÷”l×ûjŸ.u®£Ó$␤ÆÆÿ�Ë&shy;¬Ù§÷1Ø?yþ="" r»z\`ø$ž7núööŽÏ’y%—ãÎ#Ç&shy;&shy;Åmïnbr¤¾Ö!i躼fÍì±m¾6šš)f‹2ûup9&nbsp;¹qˆ¢±ž&shy;ßxÌªàƒœgÕãv·ÛˆiÎÞïál´Ôws”Êÿ�yÞ@þc#ÿ�="" Í”?*Ì›mŽÿ�Ö¥2Šã0b¶×y?©r¸Òí%0@k7k؃¾<ÿ�(h{wz¾oÛôlû²oÿ�䩤ýf«–="" iÖ÷%³Åx="" Õÿ�llaŽ="">±†0Ê.NE›&nbsp;z‚ÜÌÍ óH*Ν?‰q+ÿ‡…›Këëô&gt;¹/W{Yã}ð¿;HÓÐð®_¿_Û&gt;›ËÉ•ð›ÛÞ/µ·ÃknK‚ày-&shy;Ó9¯--D„yÎDïiÎJÉêÝVf |ƒ¥
ý) I%ÙB÷ŒÝõ„âò_ý›ö†C À¡Yð¡œãcåPçyìd~µÉ+Om‹W:@ãÌ”‚õ&shy;Oe`NQ’1äµ3¦àaŸušg·ÛÔÕf© ×
t•©yu9϶±%Ïð±ÊSã!sƒNSTæ“w1‡660ÆÞ0Æ\eÄ&gt;*¸ùm,ϨO Õ	ȹjjòß´6•ìÀë&gt;ú£¼®ósàÈþMÎå¶'©©®T®&nbsp;ÒÖh+¹çù}Xo²ÞµÕ]_‡[`¯ÈBÏ¿aƒ&nbsp;íQ”~Âáöõ°?ßé°‘Z&gt;2öf”5e0ØÇ(r§÷š£òç×MÎêH[ßo×=ÈJÛ)2œRû*¹:ò؉‘ž&lt;Ãl¥m&gt;„eŒTì±Àýk»ã'o)á¡ùkLbÂ=e—ùqÐÑÙ³NŸÌß8º’8q±†0Â1‡Þ2á\);dLç8UÙÑ=jÖ©XÖÜO'ÇíÚ&shy;¬–Aê9ÿY[*‚O–ùCò5â¾)«Äë#¿“rƒ[”z&shy;|Ó‘]†uç9ªr4g—¶œ_gUàÌ”ïØ€	ìP¬U@€žÀ$c18ê{É'ûsÁøÅÙäÔ“ŒqÎ1ʳby¦½°ÎMý8êœFïaÛ&amp;Ì°£ef‚@}¦b¬VT¦R#¨ËïaÛ8ƒ¾&gt;Òˆÿ°ïŒÌ°')Ù´¦%Cízå„2&shy;íuÇv£Ÿe@a×@x¶ÏËÇk¶8pã8ã¸WñΏ±Æ@€zòÑý•Cg†ÏQyYP|ž§³:+C7÷Ÿâ’m6å4'â¼ïŵ9ñßqŽ¾×&amp;›tÊîO^o ÎÌŏŽÑ×V’Í´ØkQ]U»&nbsp;ÌI½MzäÕeœc×ß÷Š¡ºÍXŽÏ·ˆq?³ÐöcŽqÎ9Ç9CÙÉæ‚vÃ&lt;£`GŽ8®¸\eVØI‰ÕKÖďM`2‰Ýå!'
jÔŸÇ\ºÍ1*}í\§bSLnŸ`BV¥—©ÎAŠ›³c&nbsp;Í•˜öœò«îìA$³6‡»žüy™þÀÇaÂ1—±„aW=~óײ;tyž(í꼜imqÕV)åڍ¥?Üé; 
GØÎgÃxŽJÿ5Ûü2àÈèkÿ‡&lt;:/«iñZºZâQæü;Œß¡£ë†\z¸f¯Šéõ›œo9«Škp;{»&gt;Û10w•uŽ@9ßÖÏC5¤}Nx¯±:¸@œsŽr‡*qg$&gt;óŸØÏ4Ø÷¶¾¸R§häkÔ&shy;Lu+8Ë?߶2=^Å—Öž°09¥¡	)ÑÜ,Iõƒ¶:c,B¦µ¡¢úë.YTì"oÆ”Ä(Š¢P¹à[¿ Ð3=¦8pŒ#:Â0Œ#:À0&nbsp;+•€u`w¸½:¨7:û:EM9ã騥øîN[:Ó¼ç_cƒÂ1¾Æýç¡èuëØ9ËñQ¯¸gáþÙñÉìL&lt;“ˆäUô–Ê*ºÐÉý}Œ&amp;Yó‡ñßÞú°ãô¥¯T8ÇãvÊ·éìŒÑOTï9]‘nSfØ®¹Ç˜6”‚°kÖ¹0WUŽ2uIDÊôsêÂœ§Ç½lJ2ÅFQTÝ«leêSž?©Øè’iL²¥!qïBq½¬sŠÛý®ì¯š6ZIX8F„gXFu…s¬õÊ£4ÈY{g’–ï9}Vš†šhr:›M}~.þöJgŽjò¾òœƒö*à#:ëûû#*~MÃO‘ãLóŠå[C“n?OccŒÐ“½¼‹‘â¹
ÿ“NÚt&gt;îž7ãVÚCLáø&shy;}X¨™8N1Æ8ç(ÙFûŧ&gt;ØfþÂêqõ¡rß¡í²£$ÍÕîh¥uç Ãßjh'E4½ÉšÈ™Òþà.|ëéJåøe<vöÚè£u Ó,�ˆz)½\±ë_¼²iÌ{~u®jh¨="¨&quot;T3Â9!±Ç*ìw‡úuúgYÖuŠcL0ÊÀžº¦‰ƒQ¥Èqdû¼t|‡˜Òödâ|â;^«uçu¿l՟ɮ޲Û&nbsp;bmX1¨î½ãlÓû^W“ÖMk+ëìDí½nÔä6">MªqŽ´¸?Cóëj*Uú&nbsp;N1Æ8Ç(ÙFÂ{95ûÎ:?`ç–í÷ðë,ʝ‡rÍԝ‡¨/(êÛr–BTŒA*Û,ÙìF³¶V`H#ZЂV9E,ä:ÛHŠ&amp;8eW¬l„$¤.Y¨}h&shy;M¦aÑ&gt;ïžÉ&gt;ACIû\8pá¯YÖugYÖuØëèã¯`f援ÉÜnò0¤9/±d¤§«ÉöQ¸ÍÎa5Ë¥ü›˜’M2ç?ˆ®Ç˜òýºtçw¡CIñz‰¹mc±
¨íz§ãRx
Û[”¦‹‘Öõ žðœ'ãvÊ6QñGÞkOÙ†k œ‹ÝÿÜmílŸO]uLdSuA¯_ùî]Šk"@ûRW÷¶vWTÝÍ1X[c¡]i¦¿lFa+ØÖ]$b÷°íŒ
Áœ¾¹þu4&shy;r1_@Z¨³Öyô˜úP¾-Ì&amp;öŠ8?üáÃúuúõgY×è‚3ÓûÂ@þÞ*Ý‚Ül½Ë
®7m˜@L—¿‡¥ö™Åp7—!OXñ
Cƒ‚v~“_BzÀüsÑŸ¹vž¹ÅE_èœ'	ÆlfÆ8í”|'³ˆ½œãõû#&lt;³‘ý¯Q¥!2§e˜«Ÿ†1Ü&nbsp;S¶ìgB±¥°Ï¡(‚¶‰ÀXkÒ˜Óée £ÚÎÙÓ¬™±¤I”‡±ù)RÈë¬R~לÀ£úZæŠD¥,Ù£ü¤-Wh.{£ÔŽÄÞ™â\Àã÷fT£Ã‡ü½g_§_&nbsp;Ϭi0É¿è!è0¨ÂŠ³5Á@À®~€×ì}¬Õ®ðœ'	Âq›ã¶Q²Þ(Íhû0ÍtYL±æöÿ{ȃ/ÉjåW×YF
yÏǽ&shy;Œ¾š¡qÓ»F"tïbÖ 2êå$Yç,›Ÿj\²²ë*Û*¸µ&gt;—¹¤È”eŠ}¶IÁV&shy;2ª}ch
«L×Oãì…¤tÙófO9N"Ðfª@g¹#¹ó·®c_ìaÃúuþN³¯ô=FzŒõ\ô\õ^ûÎó¼ï;Îðœ'ãfÇl£g]œ”û9¡&shy;ýÏòj½k!§¬ë\N#ñ}–&amp;t+×O遶˜™¹YÖäȬå TŸ\ùÅZšO©Ê!z6bCu|¢ã,µ©®¯YEò˜ù{7¾Y:„ç›5"ž«yüÛh«ø¾Ýo‹&gt;§J³LÎ=M«iìAãÂrÑÞÕJ¡÷„aÿ?_éwþ½á8N…±›±Û°ýœDï4õ‰#9Ùèé½	µh”¬É¬ä#þûT·²ëuž€ÒRÉ?òÖå¦É²²îшJ±J‘ìºìqåíIHM&shy;jO²ëu„°“ħÖű¦¿¶”ðtÛCªi3éemšÓ5f¦~Í&amp;IiVy‰ë,ÆÌИÅ*³}°¸½5^‡Ç9ÇãnjÚ{r¼R“a„g_èuþ—yÞwá8[	ÆlwÆ8Ø©ÞkkFw-h5šå+ºã°¥„ébAœp}®±(&shy;bWÖQˆoWÚÄ·Ik–í#)c·{J˜—`¶¶D¥,
°IK2Ê´ÊôŒB×»Ò˜×U›)Ù´dß•ì\®‰›w+OTØê›r×QCm÷féÝöJ‡ž£Ó6U’˜¼ØÙ%ž-ä•ÔÛhÖJÍYHÂ?Ì?Õï;ÂØNÆlgÂØp/g5õË‘’I=›É9s¹t×E*nÍŠÌ"Í–NÚQuù+R¤®³64¤d$èÛ©%—YŽY{¤`'@ÛT¡ÃYܺ7qˆÝ«B¥—_={ÙIà·Ýí…a46Qp?I{OøaJ¶Ó°Õ×JL»ëžîk3·ÊËHï	‰&nbsp;{V¸²+
UšE5Ç~3äÏÇÖz•’ˆYpŒ#üÝç§yÞwçyÞwá8[a8ÍŒØNu	ÈkrRI'³sÜûî_öð{¥lGk®«„eP,}kl!—^sÎËl¨Ä¹½‰a)bÛŠ2u?Ír{X"a&gt;Û2ž%úù«Ø‚O+lbÓ¤µqÔ|RŽM”ì;â’šÎ戥ãCK[zj›;nv%7Ú–²ÿ÷Ù†¨×±r‚sÔ¥ŽÄÒZòÙœg4Øë¡5©ñ¯)n1×Ov1ZH®„~½ÿ“¼ï;Îó¿Ðœ-çxpœ-ŒØs¬Y“Õ'ÇZEß•òWÞ¥%FMw|+ÒÊ!@m‚q\¬²ëùF"nÕ©ZÕfÇŸmä½[f´'Øk;åWò„*ûŽù6"¡¢taz7£b‚5Xàˆ7œóØ{^§ÐÏY+ì¢`&nbsp;õ½M'Ô# J¶ÓÖÔK!wûD¸Ž&nbsp;a~æ²×GM”€Ûn”i»úÛe‚´´ËĨŒCOÞë3Âó›º[5ªpžE¥ÉD4È
áFuúwç×ù;Îó¿Ó¼-…°±Ãž¹ëÞNœ†§ÿ;ü¦¦ŒÉ}ÞwotÖÔ订®Z’žN^¶Ï±ª£?t\û½±]dží´‹“rR÷ÏVMtž1öÙD¨-k•uÂáT;KOÞÖÊ]u\íê¢uQ;×*Ã``ÛD”b5©LdÂ8M¯\$®¦^ÆLv[Ýå¦b›ë6Õ4¶Å¶Ž³Rz×ØÇ›ÃHO6&nbsp;ÃáÔ/±¸‰ˆímœX¼õ†úÔœ’XÌvd²à|ÜÑ̶ãyY¡L+…pòwçyÞwœìç§Y랸²'%¨NzÊ(Yùo0E•&shy;ïw×÷£Mc"ôl!JN§omŒ:׫æÊa‡ÛbŽP•Ö£–^„b‡ÙvÀÞºô¦Y@œ"!êûEŠ¹øë\dõXH1
²Í€•ÕfÃ.é(âºü¶®+¬0
iÈ
ï\eëZI„«mu’Ô7†MYÓchAZZlÍHÖŽ°¾±¦Ä5€U¾ûÔEP¶ÆËN-&amp;vÙÔ+(ëŠk&shy;v'4øÖ›4®)fø‚kõœ-»ÇÖI&shy;Åù¾ÛÒӬ衔&nbsp;‡
ç®Â3¯×¬ë=s×=p!ʼn9=SŸ¦½¾ï”êL:Ã{–ÞÚƒÒ×BQ
í‘aÝö
H&amp;ªŒ¢«RR(oZç]k…æIçÈžö±n“U
#Þs
WÖ×À¥`‹4}”R
-b¤®®SYD-P½ª\…ÖQŽçšSêö4Nµå!×¾Þôi&gt;Ä&nbsp;z&gt;3úë“”ÚhzÍvõûHj#¢Syk´[r›.V»”ø´}snë
d¤åm©"#MömvƒêÒíuø´ÒcfkòF*¥i¸{ƒ’Õ³~IªNkr[º&amp;	&shy;ÇùâüßƏ?ÆnâõS†XfpÌáL39ñøŽ|GN
rqu°k¨þöyn7Xôû&gt;jZ¯={ò»›K[[ã+\i«l$ð²&shy;‹š€ã&nbsp;÷Œ
Ûs]€•lÍ0±œð;b¸økLØšúÆX6Ã1‹……i”ÿdbÃl³©XÒ¦ª£2g³*°J×IHVØ'‘®ô%{iD{ƒjW=5û¶¬¥‹Cíjã«.º&amp;2÷²&amp;»ßº{¦ÆÃÂå5-S_iéNK³Ù®¼ªi¿ë‘Ùw½¶^öžµo–ž¤ä»/]}eüíÈ’ÉZìl‘ï-&amp;l¬œ$`û“žOÝ«kdƒ¦½*k'ž¼¦#ÍrÑ´ãO9äƒPS[Îõ•Ÿ”q
è
rüc7¨]Í6þ¾}^»Ã±¨?¶äxå=y'ŠÄlù¾œä{žo¾Y[\¿!¹µêñõ-[°@š„ãÅGÁ$FÙf#¥•k—š	ÊA‚¾Ú&nbsp;×~Úû}“P¯Eå
z9%—[¼Ý'&lt;ù¥ª{#QFt
ç!MmŠJê¨Ê¨m‰ËžÖÅ%uq‡òJ!kùÚ¸Íë0ýÚi“±ÖÇìJSÊ?µúÉÑ„©RÀúÎ@¸6vÎØE›?sðAµFž¦¼†Ó½|–Å+ÉÑ›Wy»ØÙ#e¥Ç3
ª”Öאد¶Ö¼r{&gt;ûÕ¡ÑÚê{ϐ'õ¹ê´r…}W5ª³jÑF¥_6×VJ*&amp;Û2L_·\™ôئ8EÒ^¬“ùuçž³mö†w©õEãÁ”Å! #6Þ êEö+†j êo)äåí±V1™]ZPVu¢€Ì¾äæbŒozb#
@rÐþXË
“±g=´ôÞ‚‰ë(D7m´«fÿØ®8#VJ	'i&amp;íð^¹°…aƒÛm…1£Þ¹±Ø„'™¶ú3«‰Ú¹NƬÐ/gmW%WôÇ$A÷³Ö-â«áoâŠcS½–Ïsûw8Ý„ðSùªøÏë¬:sÞÂ.0ù]˜ÿÿÄ;!"1AQaq2‘±Á0¡#BR@Ñáñ Pbrð3‚CÿÚ	?|ìÂx§þc͉×
ÿØø/ã'@†Sâ&gt;©±NÇm‚Ãq%£PMC1Á\ÝÖŒÔñ…f¸-á^&amp;£´läÒçh˜—*®$‹`¨ƒÖê›Gd€AЩ0Ï$8AOk£ceEÁ®Å–&shy;2Æ
ÑíFí6èÄ¢Û/eJx0…Úå0Dy…¢7V
Ñíû©–GDllQ³®´ÏØ(‡ˆ=J¡Z8¬tᨴÝöZTl«·ÙhF§YoªÖ &nbsp;0‚'®é£0Lò	„Äu(y-„ã/8“î5NX.:,%&nbsp;Ù.Ñ6äÉM05S
D¦:	»‚yyý¢ÁRkG ‚T™ä\¶Ëón#P¦`‚¼/jÚájÃFQc!jËÈYáN[…¸‚¶¸\`ú!g	
q0&shy;&shy;2&nbsp;€Vl…âaZ8A[\-EºÑÀµc½,¼5¼TÜ…ª6U«&amp;ö_ñrЙó@ÉqhuSŠ¨ò8â.že&gt;Ìíª–ȲøoT'z&amp;Üܦ˜hSm2SI“s°_˜á±Ð&amp;€ßÂ0ObÍcD¶5gqˆBq	(Z–éºÚ»ôC35^!OŽÐäDL…«LhæýÖ´Ýe£„ÆBÕ…x^Ò…ÚéG
ÜHZ´árÑâBÖ›¾Áxj7î¼TÝ!iPAZ´âoªÖ õœ²	û”r0	ž˜ž%.°@bq’zõ@áo²žH™*I'E!›3sÕ04
€þ a¨4#CÕ4ßÂF‘8êVŒ»‚ð´@ì¼o6Dë%:Íœ%æÝÖ&shy;}¾Êq¸ÀDÁäNèŽra8IQ÷臎ÑÕŒÁƒÙhû…âf½ÑÈðŽf;ìˆÂöú&shy;XéjÑѶ)ÓµÒ£B&lt;“Aq»º”Ü&shy;÷M³tS:MÑ@¸¡Ž©ÜíÑâ˜ÅTZÛqlq^'˜iêµt£¼×A숗Ÿê¢/ÂJ&gt;ëWrðÓu©°ˆøîQMl=b¢/՝2ãu0Áª™y·tyù#•¢Ìónëa™xG…kÍ×t26&lt;‚T‚ë"orŽˆè‡S°M—Ž§øÐ(~[I.`Û˜Z6ÁxžQÒ粌,;!™çÕIS
sTr&gt;%&shy;;#š¡·u‚äÍPǚʘh€‰š…’´ŒN7è£GÝ.6C[”&amp;ÜØw՝Úrž&gt;iÚtE
MÏš'sÄÿ¢h‚é{G¨Qî·0;Y¸ß&nbsp;C+ÝL›dNc%SWÝ×%FzðC[7Ñιè¼,u2ë9ˆ%1¨æy·uJDÈfyBÍTÚÁ{§h5ꍛ·DAþ«Sø6\JãrÐtM³Î`6Ðæä,Á²&amp;^Q°ü‘Ð@Db¨}VPÊÁ²ªTÛ.e`vS5
&amp;tlѲ9žBˆkdðQÁ¨]Ú¡•$ÀSÅÈ‚Mæ¢\~Èmt,“°MüÇý¹
Ô(E¤µÅ®ˆØ©Nê	+±Þ\”ËÍýѳ76ÝÆOªŒ4Ǫw‡ÑιC-0|ÐÔÀöS/2Q0ÀÝ¢"]sÙF^'Ðæä,ÑL½Þª`	[#u&nbsp;‰ê´~-ÈÓ”q<péõnŽœ7<¾&nbsp;`&]¦¨™ýxs_i ÊöÙ¦f¼õ_Ók©1®Â0ìƒËpétda‰¿+¦Ó$îuvÈ&ÄÄŽp¹aù"¼uph0fÿ�loªß,gõfï="">¨ˆl®Öˆ—Š¡Ý%xX vSŠ¡õFÂçÙ1°µªŒ¢OZ vC3Ït,Ñ'©Chvªa.0¢ÒŽ–Z&shy;ÿ©¹à€Ð&gt;©´'acu1=‡©
Tƒá¶8Æ×Õg†y7"væ%4†´ïiÕWHTk“q&lt;Ъú`.Qx¤M@#€ÝSlDe|ÆŠƒÁ0"z¦–8ZWÅ~a
ÇKé*+—q_Ìj‹\1&lt;Æ+l9 çë—ù§&gt;—ˆkÌ(†.lßD.ã'²ðÓu«Œ7Ùœ‰èŽZcî·$D¼ÝD1·î€—x}¹2{!–˜·P„9Ö
x•0Ѽ£`$£È"Ó_ŹêiÈ}]S¡&shy;Û²¯±’LéIæSª¼L8â&lt;¤òUEz±`å²už%5®{°8µÚA:¶«áé€|9&shy;Ü[TAcšL[	Q)5*ì@Y&shy;oîU&gt;[ÝL€á«IÐÝ8Ô/¥ÇXó̪Õcƒ]M× Ì‚yjk˜1ø„JcƒeÇNI帯-Ö5npãrÐ#-›éôt(ì9{셅ʘh€§B„IFÌ°^*‡Õ"粌,ä†g˜Ót¹Y‚œOuÑ0Ñ(ž']ÅFî0q+AoÇBeÝééº 44¸’lâ¿Ã*¹&nbsp;Ùï8çpª
,oˆ3ôƒ·üÙN˜7väñ%|CœØpѤòMšl8ên[{õÑÉhdûªNa€H³¹ƒº«Š–Ípœ=?’&nbsp;*V.l@éȯ‹
5œÛ8æÇØJy¨Æ´;óÏùªLÀ烄6æE&amp;¶¹I#Ñ|C÷CžÄ@6F‰ÅÄðÂd·k!ùUCZL–¸l}”t™Ö7‘DLMÜ¢3ÓÌÉ0=‘ñJ6¦5[Øv²‰{¯ê¢/Âèja¾ˆfyºXß¾¨›)Ìd£fnãe…‚eâyïu&nbsp;¹CAü‚î0:©JˆÜš×N uåÁ4Ÿ–ÀHp9î˜
ˆ#~%|-*œK˜'Í|;)ˆ$†
H❆f‚ã0¿—"¾]P`43:#°@¶›i°Û=öMÇ]3&lt;ñTi0È-"ÅÍ@©8S!‡ýÛP™h$‘£¹¨ÄÀáiBóªË6$썘è$\N’ª—h"ñè±–¹ÐöìàvFAûŸÐÝi%㢌,¢jw@Zå´ÄÈfyÝnS…‚Ý”ây„O썘DMGz¢!¢Jˆ»Íгݓ
nVÖü5s€ÐÑ£év?ÓNi0€h¨ëἩTË\À%û¸õCš²pi¸ý—†¯Ã1½1Ac«Ì7ù§ä:"†6Ý„Œ6
‚q¨jç¶Ó-¸‘ä„=•±Öšy#‹1–þJ „?T“Ë‚ã&amp;8F2-`kÍ|6âp¸‘%&nbsp;ÌÛ^¨Èhœ@xrUOç‡À€G¡ú#3دÍýPÊÁ~¥ofú)Ä÷_ÝL0_ªèÔoPßÝ0z£È"%æê!ƒ´¡wj™+F^'ŸU6º&amp;Âü†_éè/ø85&nbsp;\‡½&nbsp;|&nbsp;"¥Q”pnÁhnS¡£eT6Laqì¨ÔgÁ‡‚%±ˆs&gt;45”i€4»‰Çæ³%Q˜^B‚×&amp;nœ7Ñ°›öT鼺Ïv8ÂÞ\SŒ5ÙXDÌꩆ9À€K&shy;$z!’Ö‹cËHUp¸6ÍR/b„e„5ヷnòŸ«ˆ€åÉ|@¬ç‚^֏q+º—A[Ì«&lt;�&gt;€æ´¤#¸^'˜Ôñ(˜¦-îŽg˜„u¹Da`…&shy;Cnè'²iˆÍQÞ¨Y¢JÐXvS/uÔÃ:Ø#&shy;ÖÃðºeÃé“+eMïhñav‹Ž½šL‡êœÑì¿t`kšK_Uú4òéÅ|S¾3â.ç$8¢ÓáªÙ„6`4)ù•šú¯bãiì«–Õ
ŠŒ›¸qpªVk"ÀØAºsžKÚ’fvTÜú
œ0ás¤vXÚ‰ƒÏa	Îű‰Nv¸‚ý\8¢IÜ“²îœg!Ò9J¨\ÒàZCbæðÉ¥®sî‡Âú,`@¦C¿p¸#èÛæº|õFÌ÷GKÚ"&amp;£®¢ðZ²ñT&gt;¨Y¢Ot4ÑÕ
ÔÅ1÷G[|N”lÀÞmÝE®T@; $þäOŸÒÜ&shy;‚ê§%ï Ç@z§Á{ª7Å‚=
pt®›	óL¨*&lt;‚ì‰ì¾IqŸ9ךøjM!°¦‘(Œ4ia&nbsp;1ýP2Ýcdʵj1sO$ØÂ,ß÷I<yl¨t4à lčg®År4©s³nò-$o="" ï$dy:i€oö@¸l9¡'[h7(È"="" ¯v€¬ö¸aÃbšÐߊøp].Ì¦3ƶf(0="" "xî´{¼ÇÐÐ="" ÕÆ¢ÔÜö^`t.ónè\Á="—†˜û&shy;\`&quot;nA(˜`„oPú£¥Êˆm¼—‰îõ@CD”95¸Ýl·" !£gÒØ.<qÖ››5Ìsši—="" ¶°Ó{]Ôù¦€íe´;j2àÑ'‰q<•f¶t“Ð×sß4ëí="" [óœÖrÅây&iŽÔ9Ž–¼q÷u¥•l»‘¶‡Šc?ñnpè¼Î²¾$Ó*2äÅøª®©j›±="">›„Ü‹õž
—Ë—1£fì¯i²µà‘d#S(@Ñ5¤º/¬JÏšÜ_ñ›¯ŒoÊ`ÅE¢Æ4
9j˜âàç6«ô9`ú#8æÏ-GÐÔ……ÊhÙxê0.W…&nbsp;§Ê&gt;%hÛ&shy;Gz¨†	&lt;ä;Y¸É@a`û¡r` or¦7+z~ߤbð¯q¯K	 Y¦òfÖR÷±ºhf&amp;G&lt;–®¿àK	kê™ÿj®÷©ñ8ù¯ðóQàXÕv#;"ɘ~áØ÷ á
€'Š‚M®ÀÂoV{4IU]I̪\€¹„YÒv•T9íkKËn	:ߏ50-s6MÐùâԝ&lt;‘ý¸‰âQ Mб’ت&shy;¤Ò[LdÝÆt…ñxêQ`u*…íhÅMÉÝh3&gt;4:¢H„6¡û
ÜÃ}”ˈ%Nmû&shy;ÉÙ¼‰èˆ†6TI=KýPX»Ž^èkw!•‚œO0¦’¶°Fî+`¿t®HZnx'ihu@;¤Iˆ&amp;Dq*Z×ÖA‚9„ì„c3Íi€ªÒó.
tx÷_×sy.õ_M»†„ðj&gt;“‡Ëi´»rüJ!ÒǍqÑW“§p»5i……Ï
pœ 	Ò‚¥ˆœ3À	@6p8Jk-I¿©D.]±þÊþåˆû&nbsp;ãg^b,œç$˜NÆ@kœÖéHƒê,yt¶ÿ÷tgò[ëô7ièI=´G+DÔ6î¢×=”a¦#ÝxžmÝ
.ïD2°@ì†gº&lt;Ð0.TÃDL¼Ý
Žð®QÀ¢ëŸÓt\!”qqÑÄ–ô‹˜C)Õn!¬‡ZÒƒ[˜ÆlpÙ°Ð.`_ûw#òx]ǺšTžeÕwäi±Oá¨5½©ÿ{¬Ìv&shy;:uOÂÓ6hÄN&amp;ÞÃ3Sñ“ðì8A›Ê›&shy;%	;NˆÁ ÉV¬÷VÜ„"bݺiÓêo¿Ðà¢ÄÙŠ¡þ¨-lžBÂcµÍP÷M³DžèXH
eæè˜`žèê`{']ÆJ9XóG´m‚yC@¸¦Ù ëkaÃY愀斘LHsA#˜„s&gt;3n.Ûñ–šÀ\?H#Ô¢I:“uN›Ÿ¨.n,&lt;ÄèªÔ¿ËeÌójn™H¶›_©ÅúˆÛ’Èðq2¡Óá<t½‹q·Å¸i<szæ tÜâ"\woaÐh7Žh’’¢Óÿ�j”:!w.tÐ4j¨¦Ú)ƒúßcn€g#ÏÕf‰3¤Ÿ¡Á7w¹Ç&nbsp;(e¦#ɉÆu2ã.dá¦ßº&]aìâ¹n³þ¨‰y„e®qÁ²¨ït,Ñ%="" ,2ót,À¦ånhúnpã¼ú¨~&8dmÀ›{)-¨*±{‹œz5="" Æåø="" l¦íaõz£&\nÐváâddº|Ócã¦Ó´ý)Î.cbškàËb="" k%aáÍ’f;o¿×s¯ƒ¢2ƒ&shy;ôÅÍ="ΧEÎ" �¦ˆÍÂþÈ“Å7f="" ï¤+™²Ô~�[â¾dne±Ú¤ÉhÕ~ºŽ-ÿ�ˆ·ÐàŽv“œu="" 6h“썘æªï’ˆ†ˆ–µê´h’……›Ù="" Õ="" ÐÊÁ÷zºÁl¸ÉsÄ#w¹pgõºáôÚ3½íÄû'="" tÝ"þ_n2›gÉ\ðç)Á}'xÌfÚ'tf?Ê”'`‰s="" @Á9Îö4†ü;`lk¦#º16pƒ8nº”×|¿î"8õyÚ÷¸—›="" ð‘´!oÙqfln…÷@äqp�="" ;˜¿Ý.±Ïdd5&nbsp;}="" šqñ™)Â)„d›dd¼Ýdsîº7Ñ="" Ï2{]="" ´Á臈Àïd="" Ì•¥6Ç’&^`wdØiz0@fõš.¢å="" Ýnߦuc="" Â|:ö(磈â它Š="" x¥u®m§zoc´*æÒ¨Üíø˜?°¼·gò¹&nbsp;×üiçë„‘pÞh¦Öƒ{І"á�†À&h0ÌéÕ9ÙÀýÛ}üÀaÐdèfÈzȍ;#{#oÀo="" ©Ý6[m¸ÍöÛèþ´c`vc5g[ºä2Òlwf¨hÐÔ‡8="" 6Àì§ch˜Ô¢a‚7¨ä|j<@="" %î’€†¡w!xrŽ¬phˆ&täš0áöŠÌá‹ux6xü-Ó#cÓu`ˆ("yi‘ó±q"c¢¥r§Ä:z="" ky¹_="" �03€uÑ0¼áÆ`xžh`‹¸iÀ£$™%="ìsªÓ&quot;#iÖxòM" ²ÑÞ©&#€ãµÖ„wz~Û&nbsp;o:†m®Ã§ÑÜ„*‡ú¡f="ÔÀ³}8ªL4Iꉆˆ" Ùªîàz¢8Ú"%æê0±·îµu‚&od2Ól3="ÖCK•10Fìy¾¡‰">h¸Ïû)–ØA™#•?%Ä9•K|H;„pÕq
0	P#d#ð¤áR ¹ŽÂLqâqÿÜú„j¼ps&shy;öLÂß¹&lt;ÓjÔÃÕWªëÈèSM˜ZÝo3$îœÓV¦6›A#ÄP”
¦	tXuM̨×AQÕ	¶Ÿ‰
Cq8€&gt;‰ß‡$Nmûî‰Äâ@öGÄA=ËM£ú¨“ Eãui·ÕD¼ÛÑ“'²f¨ëwCA.Y¢œU¦.¦æ7"Snn¬Ùî&gt;&shy;”ÉæsXÇI›˜@½—‘bÙ±	¯mf€™<b2Çn~ßæØ&nbsp;šç4Œc[ð:¬yai‡’mÌÊiùfp¨ÅÄÜ»¦¾«at7bv…h?) ’fw€„wž]="d7-{¦†€�€áôŽVd¿ª9ª]QDž¡F”bª}TXb=”a¦" vc5cÞé¶h—!fˆod*…l0]o�¦^d£jmfî0æqÒ˺'+Ç–èÈ="" ?¨aÀxê…á6li¥—ô—5ÏýrëÑ09ôË-¸™!vwÁãxÌÙwìv×d‡¸‰ñƒ÷z“oÀbxcÅØó±ßìœ="">#áêUc[SõuäªÓ¤Û’\`“êJøWSs‰ÅQÆùáÛª{i/Ö'c ZÜB	&lt;úØl2O?Kô°ÇUÕ'ÕFmõ@^c¼ß²
6‚x]7ŽD*Ž¿!–›o×T
ì;©—(œ4›÷DËÝnl˜ØŒU¢$¨µ‚‰7NãqÑ8i&gt;iÒúYO·Õ⬢"!7ÄØ-äuT©Nžbàƒ;é:¦e‡¤Ž ʦXo.Eù'9ÆL626&lt;!«\ÂA‚^?™ 'GEP7Ðý×ÆPc°Äñc¦C†v²™- ¶òà‹ñ¿ˆâ½‚¤[Œ‚ìçHÜðäœ×‡á–¶Û)¡¬hËnŸNøŽ'te`$/PÇšñ8!–˜ÂÈUèærœ4‡¦¨œUÄû#f9ªîˆ†	(è!ª&amp;¡¿Eiµj㛕0-nI†j:&amp;þj̬pž»&amp;
Ñp9nä×|ªŽs°–Ã&shy;h Ü„%Õ‹D9§¢}`G„9Ä	j«³å´´Ç0Ù
XÞÙ
³I:ðTé–ÔnXü‰’ž8¶uÚሲ…cLÆS*ÖhhƒM°âï÷N‹áE#„0hç›G‰”×|ÇbIÄ͇TÙ
I1OØ}=‚ðÎtSŠ£®¼,mú©àßDN*Ž“î‰ÂÁ'ª6h!¨æ¨ëû£jbOTGû"%æê"›n¢\`z %×=if¨èn…†g,Ñ›êšàç™’kƒ¢áb¤Žfåpæ&gt;µQªÜAÙ5¸¢ÝTÈZA
OêßEI¸Ýãs]Ô,{d$ßITØêM bp’B¢%æ]Š¬§ÓÇDâb.©µ®pÈIäšÒò À×tCêõ2Žêor‰ÃLzj‰Äó{”rÓo÷Dby€ˆÍr£
0£Ìn{(ÃLÍTú¡arÑ‚ÙN*®º
6Éê¦öj™q’‰†ÛÉT?.˜0xPËEŠ~bcÍ?òëYÁØ&shy;ÿ€?€ühòMME«h	ÇtöF͐³TuýÑLIꈵ›ìˆÅU×èTCqê¢!½—Š«¾Å0P³D7²ñU7õC-1~¨ja¾Šq:îS†“~ኡ€‰âär°@Z¸’‹	&shy; ƒ²Àqç{¬fé&shy;È4èæS°æßá€þÀ%üšˆ—ŒÆJ#
 µ¨`z(’eÝ”a¤!Ï0Þ7²ždöC-!÷Bï0Þè]ÄÙxi6&lt;”â¨`wSûœ´c`#š«‘µ1%öµ¼ÉFÍ*0)30pª'vê©»4†žiŽ|y áQ†HãÉŸÜ蚁aÄ¢ë;^¿É
¹@CDÈfª}SD2	î›fˆod3Õw&shy;ÓlØs»¡f8ªºu0Ñ'ºð´@SŠ£‘1L_ª&lt;šŽg™(å¤Õ«Ì8ªŒ4ÛD¸’œñR§€ñt犏~aËd÷ñÀîªM€]&lt;Úpž)ıîíåÄ'5ÂAÿB 5¢I)¤5ÆÞ\OTÜ´Ûê›wo¢ngwd2Òió@ËÌ7º\Aw@§
&amp;ýÔËŒ7¾ˆœO ”NM¿TNc
öFï žˆå¦ßî¼O0^îQ†›` 1Tr%Èh†¡š£¤ôBÍ*&shy;ùlýSÛç	Ú[¢s&amp;2‹	¨ì0°Y–&nbsp;]ÿ×ÂxôN¤H#ý
~X2cõB
1HUè\©†”ãªa
¹öDá`€‰ÅT£as썩ˆæ¨Qð‰(ˆ`€¼U]ê¢$¨•½—Š¡“ц˜“Á¸Ã}»Œ¹´›²s‰ÕSaÆpGUM¤Õtô…M³H橦.:*9X
•#˜Àº¦q&lt;ØòMq¤wý„û"H±Ç	ÄQoŒÕý0,8ªû§¦Ù=Q7³}‘Ìò	èŽZM¿Tnã
öFï žˆå¤ÛõQ&amp;C}—Š¡¿B£
6ÉC[7µÌó~š&nbsp;0ÓoÜ¡w\œNì†ZmÔ!š£&nbsp;t(œ†VjWJ˜h1ÒÀ1
Œ]1ÿ.œ’6?&shy;;ƒ²ÆQٹⱊ‡Q|.ÓŸòÙ=“Ýo	N{é9þÛ;„ðæ¸H#øÇÝÊüÝ×’7|€â2z'e¦ß¡DZçÙªTE®{"0Ób¨}TZîì€ÃM°ÍPÀïdîwd2Ó;!š££Í4K°ßE8ª:êpÓ¦öj&amp;^eÈœ4›÷	ÆKŠ¬ìN#£}ÕR*Õ&amp;GUC/cuViS2m¢ª0Òl4Å&shy;¢¨1N[X§ŒUI²{H0O$ö᧡U`ñS:;ú§Cã3£ø§Q!£RLh?ªŒUžê!‚Jˆm‡eª»ÕDSl•ÙŠ£¯ÓTm“ݸok!š¡¿ª
1~èXHod3Tr`“Ý7KD'ºJ)·ïª™&amp;™q’‰ÃI¿p‰ÄóÅÈٍ€Žj®GÂÐ
{M&lt;@“ÂuUDQ–´ôÑsM&nbsp;±…€šŽ-ŽEXx„@3‹ªk¢ß8TÙ
´&amp;4š„}/ ÊNøš`¦aÃÿè4îœ×4‹d

IPpÈÆtžIØêUuÉ7º— 0²Á4K´ôMã'²
6ÂhÄónöM]Ù†˜Ù75CºîpC-1²œUèæpS†û…2ã
î¦÷rÒ˜·e8ª:&amp;Ê6`€Žj®º6`“Ù2µÔtžèŒ4šˆ»Š¢\ç4¶$Æ»æÈæÒ&lt;Õ×bc²§/Å{TŽ
MÙà˜pÉ
½ÓŠ·„ÍÓã.¾ª›°ÓñÑ1æ“-Ñ5ù¤4&nbsp;ñQçÌ'¼~ö´ö@ÓpÕÇÃ朄þ€å~c›©ý#ºtâ0Ö‹&lt;“D“'²hÃLvMã‡Ñ75B›f‰pM³É¹ª97+DžèXH8ª:è,Tîè§G]L0]L48ª9
}B&amp;!¨œU'Ý´Û'¨G[doQÒzFMG3ÌEîïTFbŒU]öQf‰êšñRN.yT݁íéªù,09Nˆ¿ä1ÜÂ/j¸wãýa=Ɲ1.o)î,h!…Tp{ü'Š¨áR£³66UZ¸FŠ©ÁLX«Njªf¨t…ñ$MÜ5J˜0<lÓ¸_Âxïþqôk7Í>AP³u{½‚{ÜÙ†¶l;&amp;O7ºfV	&lt;.˜`Xv@ã¨cÍûœá¦ u:Mš±KÌŸu1M¿uŠ\`wS{¹†˜û…8ž`{)½Ü§
!骜O09®î…´‡
Â7qìŠå´Â9ª:6&gt;¨Ù‚ŽjŽ×‘QîÊ-f¨ÅQÒPi‰CRUR#¦è´…PŠ¯Œ25USó*?8‹òU%&nbsp;ûhwUGɧcÉ&lt;ÐpÖÛó`Ôö“PË„\*,hÄOöa¥`z"ÉÐ+uSÁ`ÌdžåÅ6Ì&nbsp;Ì€ˆâšÂ_hMl¼Ìîr0¶òd5F›ÚÍH0U
Œ‡z*á¥ÚÄÓž‚&shy;LÿôVy…Uža|E9áˆ*ذ넨Ô|›Z'ÍPkî7€«UÂÑ™&nbsp;Àû èX±Ô&gt;«8iˆåeˆÑt¸Éœ4Û÷DÀÔçb¨ä]K“ŽœU‰†‰&gt;Șh "qTuýÑÊÁ'ªÐY¨æªdû§Y‚OPšjpÅQȈh“Ù8CDኡ¿BˆÃLz¢'@ˆ—™*0Ój‰q€µuÊ
1
öC5CŠ=TEHy1¹²Œ,€(ü°H·íLitÄmtÖþkˆ6ÒD?11Å5°Á¬j˜Ù¦ÛM¤¸	&shy;üÇ_’hˆÕ0Cš¦,Á‰ÇYÑ0f7)€tË4XJnkÅôM»s)¹MÈ”Û1¶›.P2÷\Ê	ÖècD	SŠLãÂJ'‰–	Ǎӌ8‰N8ZÙSŒ¶@èžeæçªqÂù#à°	ÙžnQÊãtlÆ‚¸ÈÿìuÏTlÆ‚½Ç’6{¯nèٍÝx¿’6q$&shy;,:£˜£g=–W‹þ„|D“Ø&shy;-\cÍhH%mÙjçA(ZÇ͵¶Z½×Z4-K—ÿÄ7!1AQaÁq‘ð±Ñ "2¡áñ0Rb#3@‚ÂÿÚ?ùLÈÝK‚à
@ûŸD,àÂÿµëÝC…ß&nbsp;…Œ/Þ¨YJ]óCٍå”66bçæƒ
œ§NŒê£ö{«ÒJÓØ$x"ÂEZØÇb›#Þ«¾Š,4Ü#&gt;ñC5|û¸®ú)÷•{Å	ëºïb7öÒ)ØòÙCÞ”Miq•Ë=t¸ »•Â4Ø /Õ}6W”Px²oˆÂb+oa³3„HØBg®¨ØÁþ&amp;™è¢°ƒ&gt;ô^â~¯+×ñÉŸÛl"zÒ÷6”qr÷1µÔÇ¢÷V“ùqtlãyÂ{ªh…A»Ð§ûl¡–›~ü‚”¹«gÒˆó(ÞT0ÏÅ“U&shy;Œ1‰õV¶qAÀÇ`‹iM›Ïí5íŸY“Ë`€/YîkzÝÏ`€é°Ñß:&nbsp;OyÈ!öôBxìMpCˆc®— x”†ÿàZ@"U¥™€±ÀšcgDó®~Š—Ë`€‹îjƒÕ³Ø!öØ I–fP'¼ä#¼nþë„Ä¡¨-?ÔV&nbsp;(ý¡‘ö€¿¡µøm¬„pµ÷&amp; ´¡æP&amp;£žÁtØ Î¾µO{g°B]ÜsWý̧~ñ¢q§¢éUÀÉACŸ„xE´Ž'dˆ$‰ÔŽÂ÷qq)U/zŠ(H‹d¡&amp;*Q?‡Ú¬‹ñGÕOö	˜Ò[óÜÕ¤ìqØ!)OðÏ·™B {ƈè!Ï»×53A@!ð:%GÍR|•™ÐË E
©el1â	Vbÿä€Ñ0™D:â¬íW‚8DPo
 aˆ†˜ýIM¶æÍ÷(&gt;»¼Ö~¨¿Y&gt;Û&lt;½W3p€ð/ákhÊ(G’€Â’Œñh"Tcˆ|Ä
²Œí7PDe

WÒAµÃÉ¿b‰Ãå°ª~»•Ä+,vòLO3ºÍ³Ø xw2¸n&nbsp;ø]P(¾®JÈñ[&gt;
("%Dg@¹{Dpðæ¬L&amp;$nˆÑ0!p°.UŒA›ƒÚ‡üdá49åÒ«æ×søYëÒA.“(¸&gt;å¸g°@¦È}Ì®›ÕAÀ|#-	Gé%XYðÂ÷”cÁbìBµ„C?5jêÄH:„m+ó<mÂyš2´¹c‡ l(¸e4Ü&nbsp;ç="">e
IñØ)
6@gÝJàˆÍÔ(x•zµúTAŐ	¡±ÖJ(-55VPž#ÍÞ¿Da:^¬ØFÁ¸C¶›”A¨|u2Ŷ…1f$á¹U¾~¨WϤ‚ûAå&gt;ÌÊhÌÁPSÄøiô&nbsp;ì@
à¢ÝFxE‹@¸à†%A.î‡5!@Iš4VöõCÀ¢H|ºÌ§“ëÖA6rҁ9u™AûÎA9Ü(ƒßˤʯªùͳ¿âk•ñPDðÖÿ‹a&amp;Ñ„D!$TŒÖŠ":ˆ²°IÑ£,DLµ(]vK©&nbsp;ªùwš§½³AK`¯m7(9º»®(î¥ÊÈÏ㵁‚1?d€SN0Qqº(¸&nbsp;ˆ’9(cÙ'ðŒ’X(!ÂxÛ‘Á%23ܧפ‚¤´Ü&nbsp;I»÷{ØãÒASØ&amp;¸òë2ûî¸âºŠÄ贁„™B'v
ø…ÁÔpˆƒ™„Ê#I"í6ÑÉJ²³ájPð(/kŽBLù	×ržùµtMq|™@¾?˜“ŠëÒAHKN“+'ý™”"÷^ð‰%	õÔ¨ÃËã!Gd@šQCPÅW
Dm_¸ÌG
TAË—(,â#&nbsp;€CO&lt;
4VñqZ)¹Uû•!ËhS
iÖe…O™¢|尐Y—I•3ÏsøN}&lt;‚÷„H	G}MœL~ßÒa¡{˜]Ñöxq+ÜA‚á |Ñj!µ.³)ï×S ¥Œ¶…qˬʳŽ}dò”×GÌ©á=Ïá[1äHB쁊·Ôó4
¦žªÊ7
Ûs&amp;ñŽ µŒE7ló™Nj9õ^[R˜™_MMP£¶}dž’Cò˜Pò&gt;eW™ó‹ð³Ç^øC.i:^ßìi&nbsp;PÊZ]SUsžAÎñýl™7ŒQ2ö‹n)
	óÁ3rØU1&gt;Zš¡‹g°@C„¶	ç¹YžÁ0‡”?”ËCæTɽϜ_„1ˆÒA{èaùxIeÄj_üy¦%7¥õ5B.›d¾º•&nbsp;‰ð7ƒ&amp;L›àŠ0½¹/È?4ðÕ³H&amp;í„ʯ=ÍP"&nbsp;g°R¥ÔÐL&nbsp;Þ%œñØ ÃÚ×h|ʯ?Z ÕúH/{eŒÈÉ3“}M*	‰,Òz]õÉ¿ù†¨Du®¦Š˜ÈåÒªÎÜ9 P&gt;›âvV–ÐÂ&amp;U&shy;·‹œô
y¾ñ#ˆ|t†âøt™LN/¼Hc<v …-Êg9»�éä*ší:Ì&shy;çÖa¯rbÒÊŠ&nbsp;mn&shy;ô_="">o¯Õ¢]Kþ¸¢&shy;õÔÐ!VÓÔ®9&gt;¾ŠXá,ùkzƒÚ`5’D"\IÂp¸‚1…¼0‚åGí@”ÙüÑ1óÇS ˜iMSÏx”«w¤‚áÐé2«Ïx7ëÒA3HœºL¦{ç¹Aª}$_ت™‘9u™S»˜ÖA·¢{!"Š®ødgu!BÎ/ñ˜¬HAsKéÐU·ûl/LÅ¿õë2j¸ƒ;g&nbsp;¢1szk6…F¼¾åiˆ_yû!í…®&nbsp;û¯æeÙ0µÝ*#…ýŠÒ3#y
J•n™ÒÂi§Y•{ë°\\í&nbsp;™Mo®±Qp·!ä€ÐòܣŮñ!!,΂Apši¹A÷ëE*÷$št™U¿²žñÏ`¤4ÙlÅD×ÿÄ.! 10AQ"aq2B‘¡@±Ñ4ÿÚ?P¡@P¡X"þȹǪ…ÀWçÄõÂ4ö[ïÌ©R¥J¥YNŒº	EÄûsç–bJ&amp;}¿ˆtBƒ„§¶™ÄSqTøW:óoK¡Â?²&lt;+ûXB ƒi&lt;×c*p
T(³).	¹DÀúA1þ¯e0H½‡d\÷žÐ˜*¸‹ßÑî£0ÓÚ×’‹nªÐs=G}'À¢dêQ§åœ&nbsp;v&amp;åV›¾«ö
“‰eKÜÅѤÒáݝ‘@ß&nbsp;Us‚Øú
ɏÑN¬Ñ'y°ôYÞd溦â8[²¯G!¡ÛHÆ4Ñ(#&nbsp;.–w_djÆ&gt;–£.q"äªMzî‹Fr¤âÇ€GPªÒq"]b"Zg=¬ê©^Ù9¯y$JÔaøDA#G^@ÁÛiHå¥êeVnJu)•Fÿ„×4Ù£t\è0&gt;›.®Ïæ'ÚWÛï°õN ºŽä&nbsp;|Ê^×–r\EÎñÝq,!ÙºÌ;q¤*m—tAÌÑò¸š¥ÎŽË-ï¿d֐GôŒY-€ATN|Ç'Ò:.!À±¥Î3ÑG”Ê32šâ6Ýx0Àá¼Ì.$ÿ8:k`íþ4…ÃZ&nbsp;EÐw„MÊÌ⁠É2U&nbsp;HëÝ1ô„ëv.!ñM&nbsp;AõEä™”L”%¦ÐDÿIÕI1{@UäÒ“¼èƒ·øÒ7TŒ&lt;*¿i%uB„À"SKC;™6èBe7¹ÖïÑWk˜ÖÀ°ŒLDªl·äʬƲÏé3OeWþqnÚÈ?qÐ
ae¦bFíŽØ4Iìšæ掉®ðˉp$µW.,,Zç¢ê›Iþ²Ç¯ø©6l¸ÂcA'@ې0xÔW#½
ªÇT b;" ©¥!COÝ	†›é†´›nŸO$ÌuÝB•Acs¿²¨ò÷—¥FÚÂ
S„ƒÈ¡SÍ}=€ÇØï;Ê©L5Ð#TÞæ:B§U®iò‚Iº]å·KÞÉ”.0ѹ\E|æÒ6ÐÖSƒ„aR®æÓ˜Ó}çºu–DC‰ÜŸÒ9í?)Ô²	0}•"!°dJ«Z›I°'cÑTªç›ŸŒ-TŒ$rCˆØ¯ÙbÈqO‚ mV¨ÊÌ{è8,9!H@àæÁþG(+b@(ˆ&lt;éÁ¡]±€B ŽaÀ7˜“Y;Î¥YƹSŒ #Ë
ɯtœeJ”@(´¨P¡B…*¨r&nbsp;jT(Q…°'•
a(_ÿÙ<table class="fixed" border="0">
    <colgroup><col width="1000px"><col width="500px">
    </colgroup><tbody><tr><td>
        <h2>ESP32 server</h2>
    </td><td>
        <table border="0">
            <tbody><tr>
                <td>
                    <label for="newfile">Upload a file</label>
                </td>
                <td colspan="2">
                    <input id="newfile" type="file" onchange="setpath()" style="width:100%;">
                </td>
            </tr>
            <tr>
                <td>
                    <label for="filepath">Set path on server</label>
                </td>
                <td>
                    <input id="filepath" type="text" style="width:100%" readonly="">
                </td>
                <td>
                    <button id="upload" type="button" onclick="upload()">Upload</button>
                </td>
            </tr>
            
            <tr>
                <td>
                    <label for="rollback">Return to v.1.0.0</label>
                </td>
                <td>
                    <form action="/rollback" method="post">
						<input type="submit" value="Rollback" name="Rollback" "downgrade"="">
					</form>
                </td>
            </tr>
        </tbody></table>
    </td></tr>
</tbody></table>
<p id="demo"></p>
<script>

function downgrade() {
  var txt;
  if (confirm("Are you sure?")) {
    
	var xhttp = new XMLHttpRequest();
	xhttp.open("POST", "/rollback", true);
	xhttp.send("name=Hello");
	txt = "You pressed OK!";
  } else {
    txt = "You pressed Cancel!";
  }
  document.getElementById("demo").innerHTML = txt;
}

function setpath() {
    var default_path = document.getElementById("newfile").files[0].name;
    document.getElementById("filepath").value = default_path;
}
function upload() {
    var filePath = document.getElementById("filepath").value;
    var upload_path = "/upload/" + filePath;
    var fileInput = document.getElementById("newfile").files;

    /* Max size of an individual file. Make sure this
     * value is same as that set in file_server.c */
    var MAX_FILE_SIZE = 1500*1024;
    var MAX_FILE_SIZE_STR = "1500KB";

    if (fileInput.length == 0) {
        alert("No file selected!");
    } else if (filePath.length == 0) {
        alert("File path on server is not set!");
    } else if (filePath.indexOf(' ') >= 0) {
        alert("File path on server cannot have spaces!");
    } else if (filePath[filePath.length-1] == '/') {
        alert("File name not specified after path!");
    } else if (fileInput[0].size > 1500*1024) {
        alert("File size must be less than 1500KB!");
    } else {
        document.getElementById("newfile").disabled = true;
        document.getElementById("filepath").disabled = true;
        document.getElementById("upload").disabled = true;

        var file = fileInput[0];
        var xhttp = new XMLHttpRequest();
        xhttp.onreadystatechange = function() {
            if (xhttp.readyState == 4) {
                if (xhttp.status == 200) {
                    document.open();
                    document.write(xhttp.responseText);
                    document.close();
                } else if (xhttp.status == 0) {
                    alert("Server closed the connection abruptly!");
                    location.reload()
                } else {
                    alert(xhttp.status + " Error!\n" + xhttp.responseText);
                    location.reload()
                }
            }
        };
        xhttp.open("POST", upload_path, true);
        xhttp.send(file);
    }
}
</script>


<table class="fixed" border="1"><colgroup><col width="800px"><col width="300px"><col width="300px"><col width="100px"></colgroup><thead><tr><th>Name</th><th>Type</th><th>Size (Bytes)</th><th>Delete</th></tr></thead><tbody><tr><td><a href="/.gitkeep">.gitkeep</a></td><td>file</td><td>0</td><td><form method="post" action="/delete/.gitkeep"><button type="submit">Delete</button></form></td></tr>
<tr><td><a href="/hello_world.bin">hello_world.bin</a></td><td>file</td><td>873232</td><td><form method="post" action="/delete/hello_world.bin"><button type="submit">Delete</button></form></td></tr>
</tbody></table></v></mÂyš2´¹c‡></lÓ¸_Âxïþqôk7Í></b2Çn~ßæØ&nbsp;šç4Œc[ð:¬yai‡’mÌÊiùfp¨ÅÄÜ»¦¾«at7bv…h?)></t½‹q·Å¸i<szæ></yl¨t4Ã></péõnŽœ7<¾&nbsp;`&]¦¨™ýxs_i></vöÚè£u></u=ù]qšc©a͍•þ±òƒ(3dú©Äc÷žsº³aíã©'Þ×></j)³ÍÃy`š•ß”></o]}i></s†©cÿ�ÓÜe"ÉÇhñú•]]></e°«žçÖ•4r²tÀªl$À-¨]@œÓ±¨»ã'^“÷wsù‰1Ëlû$ñÛíß></sžÓgÆö5qêæo:ÕyÖr!Áù¤kd•gt></rÆ�á=l#bl…¬Éoø©Šƒå´òŒlfá=~vöu˜d˜#bcyã8ö…2‘ú¼²h+5cyþs×r«]&nbsp;¸ÚÔ¹f></o_ã¶ån¸‘&dÝ)Õ¹½n›í2½Þh”:šäº></body>
If I dont select "edit as HTML" and just view whole elemts, it looks very strange. The whole body is garbage data, I cant even see my other html elements in there such as my table and etc:
https://ibb.co/Yd8dQPq

zazas321
Posts: 231
Joined: Mon Feb 01, 2021 9:41 am

Re: How to display image on webserver

Postby zazas321 » Tue Mar 08, 2022 9:06 am

UPDATE:

If I change the order in which the html elements are displayed in index, I can get the image to be displayed on the webserver but other elemetns such as text, tables, headers will not be displayted:

Code: Select all

static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath)
{
    //httpd_resp_set_type(req,"text/html");
    char entrypath[FILE_PATH_MAX];
    char entrysize[16];
    const char *entrytype;

    struct dirent *entry;
    struct stat entry_stat;

    DIR *dir = opendir(dirpath);
    const size_t dirpath_len = strlen(dirpath);

    /* Retrieve the base path of file storage to construct the full path */
    strlcpy(entrypath, dirpath, sizeof(entrypath));

    if (!dir) {
        ESP_LOGE("DOWNLOAD", "Failed to stat dir : %s", dirpath);
        /* Respond with 404 Not Found */
        httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "Directory does not exist");
        return ESP_FAIL;
    }

    extern const unsigned char elstat_test_array_start[] asm("_binary_elstat_test_jpg_start");
    extern const unsigned char elstat_test_array_end[] asm("_binary_elstat_test_jpg_end");
    const size_t logo_size_test = (elstat_test_array_end - elstat_test_array_start);
    httpd_resp_set_type(req, "image/jpeg");
    httpd_resp_send_chunk(req, (const char *)elstat_test_array_start, logo_size_test);




    httpd_resp_set_type(req, "text/html");
    httpd_resp_sendstr_chunk(req, "<!DOCTYPE html><html><body>");

    /* Get handle to embedded file upload script */
    extern const unsigned char upload_script_start[] asm("_binary_upload_script_html_start");
    extern const unsigned char upload_script_end[]   asm("_binary_upload_script_html_end");
    const size_t upload_script_size = (upload_script_end - upload_script_start);

    /* Add file upload form and script which on execution sends a POST request to /upload */
    httpd_resp_send_chunk(req, (const char *)upload_script_start, upload_script_size);

//<img src="elstat_icon.png" alt="Trulli" width="500" height="333">
    /* Send file-list table definition and column labels */
    httpd_resp_sendstr_chunk(req,
        "<table class=\"fixed\" border=\"1\">"
        "<col width=\"800px\" /><col width=\"300px\" /><col width=\"300px\" /><col width=\"100px\" />"
        "<thead><tr><th>Name</th><th>Type</th><th>Size (Bytes)</th><th>Delete</th></tr></thead>"
        "<tbody>");

    /* Iterate over all files / folders and fetch their names and sizes */
    while ((entry = readdir(dir)) != NULL) {
        entrytype = (entry->d_type == DT_DIR ? "directory" : "file");

        strlcpy(entrypath + dirpath_len, entry->d_name, sizeof(entrypath) - dirpath_len);
        if (stat(entrypath, &entry_stat) == -1) {
            ESP_LOGE("DOWNLOAD", "Failed to stat %s : %s", entrytype, entry->d_name);
            continue;
        }
        sprintf(entrysize, "%ld", entry_stat.st_size);
        ESP_LOGI("DOWNLOAD", "Found %s : %s (%s bytes)", entrytype, entry->d_name, entrysize);

        /* Send chunk of HTML file containing table entries with file name and size */
        httpd_resp_sendstr_chunk(req, "<tr><td><a href=\"");
        httpd_resp_sendstr_chunk(req, req->uri);
        httpd_resp_sendstr_chunk(req, entry->d_name);
        if (entry->d_type == DT_DIR) {
            httpd_resp_sendstr_chunk(req, "/");
        }
        httpd_resp_sendstr_chunk(req, "\">");
        httpd_resp_sendstr_chunk(req, entry->d_name);
        httpd_resp_sendstr_chunk(req, "</a></td><td>");
        httpd_resp_sendstr_chunk(req, entrytype);
        httpd_resp_sendstr_chunk(req, "</td><td>");
        httpd_resp_sendstr_chunk(req, entrysize);
        httpd_resp_sendstr_chunk(req, "</td><td>");
        httpd_resp_sendstr_chunk(req, "<form method=\"post\" action=\"/delete");
        httpd_resp_sendstr_chunk(req, req->uri);
        httpd_resp_sendstr_chunk(req, entry->d_name);
        httpd_resp_sendstr_chunk(req, "\"><button type=\"submit\">Delete</button></form>");
        httpd_resp_sendstr_chunk(req, "</td></tr>\n");
    }
    closedir(dir);

    /* Finish the file list table */
    httpd_resp_sendstr_chunk(req, "</tbody></table>");

    /* Send remaining chunk of HTML file to complete it */
    httpd_resp_sendstr_chunk(req, "</body></html>");

    /* Send empty chunk to signal HTTP response completion */
    httpd_resp_sendstr_chunk(req, NULL);
    return ESP_OK;
}
Note that in the beggining of the handler I display the image:

Code: Select all

    extern const unsigned char elstat_test_array_start[] asm("_binary_elstat_test_jpg_start");
    extern const unsigned char elstat_test_array_end[] asm("_binary_elstat_test_jpg_end");
    const size_t logo_size_test = (elstat_test_array_end - elstat_test_array_start);
    httpd_resp_set_type(req, "image/jpeg");
    httpd_resp_send_chunk(req, (const char *)elstat_test_array_start, logo_size_test);
    
After that, I try to display other things such as:

Code: Select all

   httpd_resp_set_type(req, "text/html");
    httpd_resp_sendstr_chunk(req, "<!DOCTYPE html><html><body>");
    
But it does not get displayed:
https://ibb.co/WxMK3Sq

ESP_Sprite
Posts: 9582
Joined: Thu Nov 26, 2015 4:08 am

Re: How to display image on webserver

Postby ESP_Sprite » Wed Mar 09, 2022 2:07 am

Possibly you need to allow for more concurrent connections to the webserver... that's a configuration setting that's either in menuconfig or in the webserver config struct, I forgot which.

zazas321
Posts: 231
Joined: Mon Feb 01, 2021 9:41 am

Re: How to display image on webserver

Postby zazas321 » Wed Mar 09, 2022 5:17 am

What does concurrent connection have to do with this? I am the only person that is trying to open the connection to the AP webserver

boarchuz
Posts: 600
Joined: Tue Aug 21, 2018 5:28 am

Re: How to display image on webserver

Postby boarchuz » Wed Mar 09, 2022 5:42 am

zazas321 wrote:
Tue Mar 08, 2022 8:03 am
However, the issue is when I try to display the image together with other html elements on my index page. I would like to display the logo, some text, some tables and other things:
The html and the image should be separate HTTP requests*.

Headers are sent first, including the Content-Type which specifies the type of the entire body, and then the body. You can't go back and change the Content-Type header in the middle of the body; the headers are sent, it's too late for that.

When you send HTML like this:

Code: Select all

<h2>HTML Image</h2>
<img src="test_image.png" width="500" height="333">
the browser will send a separate follow-up request to get the image.

So you need a GET handler for the above HTML document (Content-Type: text/html), and a separate GET handler for "/test_image.png" (Content-Type: image/jpeg).

*It is possible to inline an image in the HTML as base64, for example (but the document itself is still text/html, not image/jpeg or any combination of the two).

esp32-user
Posts: 10
Joined: Sat Mar 05, 2022 6:54 pm

Re: How to display image on webserver

Postby esp32-user » Wed Mar 09, 2022 7:13 am

One browser getting data from one server can (and usually does) open multiple connections for performance reasons.

https://stackoverflow.com/questions/985 ... -a-browser

zazas321
Posts: 231
Joined: Mon Feb 01, 2021 9:41 am

Re: How to display image on webserver

Postby zazas321 » Thu Mar 10, 2022 7:44 am

Okay it is getting a little bit more clear but not quite.

So I need a seperate get_request handler for the image.

Code: Select all

esp_err_t image_get_handler(httpd_req_t *req)
{
    /* Send a simple response */
    //const char resp[] = "URI GET Response";
    //httpd_resp_send(req, resp, HTTPD_RESP_USE_STRLEN);
    const char resp[] = "URI GET Response";
    extern const unsigned char image_test_array_start[] asm("_binary_image_test_jpeg_start");
    extern const unsigned char image_test_array_end[] asm("_binary_image_test_jpeg_end");
    const size_t logo_size_test = (image_test_array_end - image_test_array_start);
    httpd_resp_set_type(req, "image/jpeg");
    httpd_resp_send(req, (const char *)image_test_array_start, logo_size_test);
    return ESP_OK;
}

Code: Select all

    httpd_uri_t image_handler = {
        .uri       = "/",  // Match all URIs of type /path/to/file
        .method    = HTTP_GET,
        .handler   = image_get_handler,
       .user_ctx  = server_data    // Pass server data as context
    };
    httpd_register_uri_handler(server, &file_download);



Is that correct?


What I simply want is the following:
https://ibb.co/J7L0bQ2


I have file_serving esp-idf example and just want to add an image to the index page

Who is online

Users browsing this forum: felmue and 123 guests