Colorizing a Black & White Image

A chance discovery that placing a colored filter over a black & white image and adjusting the transparency of the filter gave a realistic color to the image enabled me to create a,method to colorize black & white images.

The procedure described to day was done with GIMP, but should work with any image editor that allows layers to be created.

Here is the original black & white image:

Click image for larger view

KInit

The first thing is to duplicate the layer. The color is applied to the new layer, but other changes, such as contrast, saturation, sharpening, etc. are done to the original layer.

Next; select the duplicate layer and select the skin areas, then deselect the lips and eyes. Apply flesh color to the skin, either with a paint bucket or brush.  Adjust the transparancy of the layer to give a realistic flesh color as seen below:

Click image for larger view

KSkin

Next, invert the selection and paint the lips and eyes.

It should then appear as below:

Click image for larger view

KFace

Remove the selection and similarly color the jacket and then the hair and earrings, for which I used the same color.

Finally, combine the layers and make final adjustments:

Click image for larger view

KFinal

Other examples of colorized images:

Click images for larger view

Pete_Boy

WFalls

A PHP Survey Form

I was recently asked to create  an online feedback form for a race I helped put on.  Here  is how the survey looks.

The form is a simple html form with radiobuttons, a select listbox, test boxes,  text areas and a submit button. It has the following appearance:

Click image for larger view

Survey

Here is the code:

<!DOCTYPE html PUBLIC ‘-//W3C//DTD XHTML 1.0 Transitional//EN’ ‘http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd’&gt;
<html xmlns=’http://www.w3.org/1999/xhtml’&gt;
<head profile=’http://gmpg.org/xfn/11′&gt;
<title>Survey</title>
<style type=’text/css’>
body {margin-left:0;margin-right:0;font:normal normal 800 12px Times New Roman; padding: 10px}
a{ text-decoration: }
:link { color: rgb(0, 0, 255) }
:visited {color :rgb(100, 0,100) }
:hover { }
:active { }
#t1, #t2, #t3, #t4, #ta1, #ta2{position: relative; width: 80% }
</style>
</head>
<body>
<?php
$msg = “”;
if ($_POST[‘hidden’] == “hidden”) {
if ($_POST[‘radio1’] !=””) $msg .= “Online Registration: ” . $_POST[‘radio1’];
if ($_POST[‘radio2’] !=””) $msg .= “\nDifficulty: ” . $_POST[‘radio2’];
if ($_POST[‘t1’] !=””) $msg .= “\nComments: ” . $_POST[‘t1’] . “\n”;
if ($msg != “”) $msg .= “\n”;
if ($_POST[‘radio3’] !=””) $msg .= “Paper Registration: ” . $_POST[‘radio3’];
if ($_POST[‘t2’] !=””) $msg .= “\nComments: ” . $_POST[‘t2’] . “\n”;
if ($_POST[‘radio4’] !=””) $msg .= “Packet Pickup: ” . $_POST[‘radio4’];
if ($_POST[‘t3’] !=””) $msg .= “\nComments: ” . $_POST[‘t3’] . “\n”;
if ($_POST[‘ta1’] !=””) $msg .= “\nRace Course:<br /> ” . $_POST[‘ta1’] . “\n”;
if ($_POST[‘s1’] !=””) $msg .= “\nHow Did You Hear About Us?\n ” . $_POST[‘s1’] . “\n”;
if ($_POST[‘radio5’] !=””) $msg .= “\n
Would you run/walk the New Me 5K again? ” . $_POST[‘radio5’];
if ($_POST[‘t4’] !=””) $msg .= “\nIf no why? ” . $_POST[‘t4’] . “\n”;
if ($_POST[‘ta2’] !=””) $msg .= “\n\nQuestions, Comments, Kudos:\n ” . $_POST[‘ta2’] . “\n”;
$Subject = “Survey”;
$EmailTo = “—–@”;
$EmailFrom = “—–@”;
$success = mail($EmailTo, $Subject, $msg, “From: <$EmailFrom>”);
if ($success) {
echo “Your Message has been Sent”;
} else {
echo “The Attempt was Unsuccessful, Your Message has Not been Sent”;
}
}
?>
<center><i><font  size=”5″ >On behalf of San Diego SoleMates and the Fourth Anuual New Me 5K and <br />
Kids 1 Mile Fun Run, we would like to thank you for making a <br />
commitment to yourself for starting 2015 by <br />
Running and Walking for the Health of it!</font></i></center><br /><br /><font size=”4″ >In our continued commitment to making the NM5K and KFR better each year, we would like to<br />
hear from you. Please take the time to take this short survey to help us improve or simply reply<br />
with your questions, comments, and kudos.</font><br /><br /><form action=”ThankYouSurvey.php” method=”post”>
<font size=”5″ >1. Registration:<br />
Online:</font> <input type=”radio” name=”radio1″ value=”Active.com” />Active.com <input type=”radio” name=”radio1″ value=”RaceReach” />RaceReach &nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp <font size=”5″ >Difficulty:</font> &nbsp&nbsp<input type=”radio” name=”radio2″ value=”Easy” />Easy <input type=”radio” name=”radio2″ value=”Difficult” />Difficult &nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp<font size=”5″ ><br />
Comments: &nbsp&nbsp<input type=”text” id=”t1″ name=”t1″ value=”” /><br />

<font size=”5″ >Paper Registration:</font> <input type=”radio” name=”radio3″ value=”Sports Authority” />Sports Authority <input type=”radio” name=”radio3″ value=”Race Day” />Race Day<br />
Comments: &nbsp&nbsp<input type=”text” id=”t2″ name=”t2″ value=”” /><br /><br />

<font size=”5″ >2. Packet Pickup:</font> <input type=”radio” name=”radio4″ value=”Sports Authority” />Sports Authority <input type=”radio” name=”radio4″ value=”Race Day” />Race Day<br />
Comments: &nbsp&nbsp<input type=”text” id=”t3″ name=”t3″ value=”” /><br /><br />

<font size=”5″ >3. Race Course:</font><br />
Comments: &nbsp&nbsp<textarea id=”ta1″name=”ta1″ rows=”2″ cols=” “></textarea><br /><br />

<font size=”5″ >4. How did you hear about us?</font> <select id=”s1″ name=”s1″>
<option >Active.com</option>
<option >RaceReach</option>
<option >Friend</option>
<option >Facebook</option>
<option >Home Town Magazine</option>
<option >Coronado Schools Foundation</option>
<option >Street Signage</option>
<option >Other</option>
</select><br /><br />

<font size=”5″ >5. Would you run/walk the New Me 5K again?</font> <input type=”radio” name=”radio5″ value=”Yes” />Yes <input type=”radio” name=”radio5″ value=”No” />No<br />
If no, why? &nbsp&nbsp<input type=”text” id=”t4″ name=”t4″ value=”” /><br /><br />

<font size=”5″ >6. Questions, Comments, Kudos:</font><br />
<textarea id=”ta2″name=”ta2″ rows=”2″ cols=” “></textarea><input type=”hidden”  name=”hidden” value=”hidden” /><br /><br />
<button type=”submit” name=”submit” value=”submit”>Submit</button><br /><br />
<center><i><font  size=”5″ >San Diego SoleMates Thanks You from our hearts to our soles.</font></i></center>
</form>

</body>
</html>

In the  above code, in the interest of privacy the email addresses have been redacted.

The submission action is a self URL and the method is post.

The form controls are given an id for property setting and a name to get the values.

A hidden control is created and checked for its value to be certain the submit has been clicked before any values are collected:

<input type=”hidden”  name=”hidden” value=”hidden” />
if ($_POST[‘hidden’] == “hidden”) {

A variable called $msg is created which is appended by the control values, but only if the control has a value.

if ($_POST[‘radio1’] !=””) $msg .= “Online Registration: ” . $_POST[‘radio1’];

.= is the append character for php.

After the message has been composed, the  email is set up:

$Subject = “Survey”;
$EmailTo = “—–@”;
$EmailFrom = “—–@”;
$success = mail($EmailTo, $Subject, $msg, “From: <$EmailFrom>”);
if ($success) {
echo “Your Message has been Sent”;
} else {
echo “The Attempt was Unsuccessful, Your Message has Not been Sent”;
}

If the email has been sent a confirmation appears on the form, otherwise, an error message is displayed.

 

Spreadsheet – Get Age on Specific Date from Date of Birth

In doing results for a race I needed the age on race day for the participants. However, the registration spreadsheet supplied to me contained only the date of birth, so I needed a way to convert.

I did this with LibreOffice Calc and the method should also work for the OpenOffice version. I do not have Excel but later I will describe how I think it could be done with that spreadsheet.

The first thing is to add a new column for the date of the race and format it for type of date desired; in this case I chose mm/dd/yy.  Also do this for the date of birth column.  Then add a column for the age. The race date has to be inserted in every row. Do this by inserting it in the first row and then either dragging the black handle in the lower right corner or copying and pasting in the remaining rows.

Then insert the following formula in the first row of the Age column

=YEARS(A2,B2,0)

YEARS gets the difference of the two dates, A2 is the older date, in this case the Date of Birth and B2 is the later date, the race date. The last parameter has two possible values, either 0 or 1 and 0 was chosen so that the difference between 03/15/99 and 02/07/15  would be 15 and not 16.

The spreadsheet would look as in the image below:

Click Image for larger view

formula

Next either drag the handle in the Age column down or copy the first cell and select the remaining cells as in the image below:

Click image for larger view

select

I find the second method more convenient, since I can scroll down faster than I can drag, which for a larger spreadsheet can save time.

If you have copied and selected,  pasting inserts the ages in every cell of the Age column, as in the following image

Click image for larger view

Age

As I said, this will work for LibreOffice and OpenOffice.

For Excel, the procedure should be the same, but I think the corresponding formula is:

=DATEDIF(A2,B2,”Y”)

 

A Windows Bulk Image Resizer, Converter and Watermark Creator

This is a fairly compact (the application itself is only ~ 53kB) application based on the Open Source FreeImage Project . It can resize  to a new width or height, either by pixels or percent of the original,  maintaining the aspect ratio. The enlargement uses a unique algorithm in which the resizing is reiterated in  multiples of 10%, giving a better result than usual methods. It is particularly good in converting 72 or 96 dpi to 300 dpi suitable for printing.

It can also convert and save the image in a number of formats, with an option to just convert without resizing.

Since many cell phone images taken in portrait mode produce images on the side rather than upright, there is also a batch rotation to create the proper alignment. This is a separate process and must be done prior to the resizing.

Also a custom batch text watermark can be added if desired.

This is how the interface appears:

Click image for larger view

resizer

The application is based on Device Independent Bitmaps (DIB) used by FreeImage.

Below is the code, written in BCX:

#include <FreeImage.h>
$library <shell32.lib>
CONST sx = GetSystemMetrics(SM_CXSCREEN)
CONST sy = GetSystemMetrics(SM_CYSCREEN)
OPTION BASE 1
GUI “Form1”, PIXELS
DIM Form1 AS CONTROL
DIM Button[3] as CONTROL
DIM Check1 as CONTROL
DIM Check2 as CONTROL
DIM Check3 as CONTROL
DIM Check4 as CONTROL
DIM Group1 as CONTROL
DIM Edit1 as CONTROL
DIM Edit2 as CONTROL
DIM Combo1 as CONTROL
dim FormDC as HDC, ScreenDC as HDC, ScreenBitmap as HBITMAP, dib as HBITMAP, drw as boolean, wdnew as integer, htnew as integer, del as boolean,  fil[10000] as string,  cnt as long, rot as double, cmnd as boolean
Declare Function FreeImage_GetFileType Lib “FreeImage.dll” Alias “_FreeImage_GetFileType@8” (filname$,  size) As FREE_IMAGE_FORMAT
Declare Function FreeImage_ColorQuantizeEx Lib “FREEIMAGE.DLL” Alias “_FreeImage_ColorQuantizeEx@20″(dib as HBITMAP, quantize as FREE_IMAGE_QUANTIZE  ,  PaletteSize as Integer ,  ReserveSize as Integer, ReservePalette as RGBQUAD PTR ) as HBITMAP
Declare Function FreeImage_Load Lib “FreeImage.dll” Alias “_FreeImage_Load@12” ( fif , filname$, flags As Integer ) As HBITMAP
Declare Function FreeImage_Rescale Lib “FreeImage.dll” Alias “_FreeImage_Rescale@16” (dib as HBITMAP, dst_width,dst_height,  filter as FREE_IMAGE_FILTER) as HBITMAP
Declare Function FreeImage_GetInfoHeader Lib “FreeImage.dll” Alias “_FreeImage_GetInfoHeader@4” (dib As HBITMAP) As BITMAPINFOHEADER PTR
Declare Function FreeImage_GetInfo Lib “FreeImage.dll” Alias “_FreeImage_GetInfo@4” (dib As HBITMAP) As BITMAPINFO PTR
Declare Function FreeImage_GetBits Lib “FreeImage.dll” Alias “_FreeImage_GetBits@4” (dib As HBITMAP) As LPBYTE
Declare Function FreeImage_GetWidth Lib “FREEIMAGE.DLL” Alias “_FreeImage_GetWidth@4” (dib as HBITMAP)
Declare Function FreeImage_GetHeight Lib “FREEIMAGE.DLL” Alias “_FreeImage_GetHeight@4” (dib as HBITMAP)
Declare Function FreeImage_Save Lib “FreeImage.dll” Alias “_FreeImage_Save@16” (fif as FREE_IMAGE_FORMAT,  dib As HBITMAP,  filname$,  flags as Integer)  as Boolean
Declare Sub FreeImage_Unload Lib “FreeImage.dll” Alias “_FreeImage_Unload@4” (dib As HBITMAP)
Declare Function FreeImage_ConvertTo24Bits Lib “FREEIMAGE.DLL” Alias “_FreeImage_ConvertTo24Bits@4” (dib as HBITMAP) as HBITMAP
Declare Function FreeImage_RotateClassic Lib “FreeImage.dll” Alias “_FreeImage_RotateClassic@12” (dib as HBITMAP,  Angle As Double) As HBITMAPSUB FORMLOAD
dim  B[8] as string, j%, edittxt as string
rot = 0
Form1 = BCX_FORM(“Form1”, 0, 0, 0.3*sx, 0.3*sy)
Group1 = BCX_GROUP(“”, Form1, 100, .01*sx, .02*sy, .05*sx, .10*sy, WS_GROUP | WS_CHILD | WS_VISIBLE | BS_GROUPBOX)
Button[0] = BCX_RADIO(“Width”,Form1, 101, .012*sx,.03*sy,.045*sx,.03*sy)
Button[1] = BCX_RADIO(“Height”,Form1, 102, .012*sx,.055*sy,.045*sx,.03*sy)
Button[2] = BCX_RADIO(“Convert”,Form1, 104, .012*sx,.080*sy,.045*sx,.03*sy)
Check1 = BCX_CHECKBOX(“Watermark”,Form1, 106, .01*sx,.12*sy,.1*sx,.03*sy)
Check3 = BCX_CHECKBOX(“Delete Original”,Form1, 108, .01*sx,.145*sy,.1*sx,.03*sy)
Check4 = BCX_CHECKBOX(“Show Folder”,Form1, 109, .01*sx,.170*sy,.1*sx,.03*sy)
Edit2 =  BCX_EDIT(“Rotation Angle eg: 90”,Form1, 110,.01*sx,.200*sy,.083*sx,.03*sy)
Edit1 = BCX_EDIT(“Value Pixels or %”,Form1, 103,.064*sx,.029*sy,.083*sx,.03*sy)
Check2 = BCX_CHECKBOX(“%”,Form1, 107, .15*sx,.029*sy,.05*sx,.03*sy)
Combo1 = BCX_COMBOBOX(“”,Form1,105,.18*sx,.028*sy,.075*sx,.15*sy)
Send Message(Check4,BM_SETCHECK,1,0)
B$[0] = “JPG”
B$[1] = “GIF”
B$[2] = “PNG”
B$[3] = “BMP”
B$[4] = “TIF”
B$[5] = “TGA”
for j% = 0 to 5
SendMessage(Combo1, CB_ADDSTRING, 0, B[j%])
next
if len(command$) > 4 then cmnd = true
edittxt = “JPG”
SendMessage(Combo1,WM_SETTEXT,0, edittxt)CENTER(Form1)
SHOW(Form1)
SetFocus(Edit1)
SendMessage(Edit1,EM_SETSEL,0, -1)
END SUB
BEGIN EVENTS
SELECT CASE CBMSG
case WM_LBUTTONUP
dim sav$
dim meas$, c as long, var as double, newname[10000] as string, buf$, fif as FREE_IMAGE_FORMAT, ending as string, t as FREE_IMAGE_FORMAT, bmiHeader as BITMAPINFOHEADER, bi as BITMAPINFO, strText$,txtColor as COLORREF, hfont as HFONT
dim filname as string * 10000000, direc as string, a as long, b as long, dib as HBITMAP, wd as double, ht as double, fname$, tmpstr$, iter%, rep%
! LPBYTE pBits;if cmnd then
filname = command$
cmnd = false
a = instr(filname,chr$(34), 2) – 1
direc = mid$(filname, 2, a – 2)
a = instrrev(direc, “\”) – 1
direc = mid$(direc, 1, a )
filname = replace$(filname, direc, “”)
filname = replace$(filname, chr$(34) & “\”, “”)
filname = replace$(filname, chr$(34) & ” “, “,”)
filname = direc & “,” & replace(filname, chr$(34), “”)
else
filname = GETFILENAME$(“Open”,”Picture Files|*.bmp;*.jpg;*.gif;*.png;*.tif|BMP Files|*.bmp|JPG Files|*.jpg|GIF Files|*.gif|PNG FILES|*.png|All Files|*.*”,0, Form1 ,OFN_EXPLORER | OFN_ALLOWMULTISELECT )
end ifif instr(filname, “,”) = 0 then
a = instrrev(filname, “\”) – 1
fname =  trim$(right$(filname, len(filname) – a – 1))
filname = trim$(left$(filname, a)) & “,”
filname = filname & fname
end if
a = instr(filname, “,”)- 1
direc = trim$(left$(filname, a) & “\”)
if bcx_get_text$(Edit2) != “Rotate,90,180,270” then
rot = val(bcx_get_text$(Edit2))
end if
if rot = 0 then
tmpstr$ = direc & “Resize”
if not exist(tmpstr$ & “\file.fil”) then
MKDIR tmpstr$
open tmpstr$ & “\file.fil” for output as hf
close hf
end if
end if
meas$ = BCX_GET_TEXT$(Edit1)
SendMessage(Combo1,WM_GETTEXT,4, buf$)
BCX_CURSOR(IDC_WAIT )
if SendMessage(Check3,BM_GETCHECK,0,0) = 1 then del = true
if SendMessage(Check1,BM_GETCHECK,0,0) = 1 then
drw = true
strText$ = inputbox$(“Text”,”What is the Text?”,””)
if strText$ = “” then function = 0
bcx_fontdlg
txtColor = bcx_colordlg
hfont = BCX_SET_FONT(BCX_Font.Name$, BCX_Font.Size, BCX_Font.Bold, BCX_Font.Italic, BCX_Font.Underline, BCX_Font.Strikeout)
end if
do while a <> 0
b = a + 1
cnt = cnt + 1
a = instr(filname, “,”, b)
newname[cnt] = mid$(filname, b, a – b)
newname[cnt] = left$(newname[cnt],len(newname[cnt]) – 3)
fil[cnt] = trim$(direc & mid$(filname, b, a – b))
if len(fil[cnt]) > len(direc) then
dib = FreeImage_Load(FreeImage_GetFileType(fil[cnt], 0), fil[cnt], 0)
wd = cdbl(FreeImage_GetWidth(dib))
ht = cdbl(FreeImage_GetHeight(dib))
wdnew = wd
htnew = ht
if SendMessage(Button[0],BM_GETCHECK,0,0) = 1 then
if SendMessage(Check2,BM_GETCHECK,0,0) = 1 then
wdnew = INT((val(meas$) /100) * wd )
if wdnew > wd then
iter% = log(wdnew / wd) / log(1.1)
end if
else
iter% = 0
wdnew = val(meas$)
end if
if SendMessage(Check2,BM_GETCHECK,0,0) = 0  and wdnew > wd then
iter% = log(wdnew / wd) / log(1.1)
else
iter% = 0
end if
var = cdbl(ht/wd)
var = wdnew * var
htnew = INT(var)
elseif SendMessage(Button[1],BM_GETCHECK,0,0) = 1 thenif SendMessage(Check2,BM_GETCHECK,0,0) = 1 then
htnew = INT(val(meas$) /100 * ht )
if htnew > ht then
iter% = log(htnew / ht) / log(1.1)
end if
else
iter% = 0
htnew = val(meas$)
end ifif SendMessage(Check2,BM_GETCHECK,0,0) = 0  and htnew > ht then
iter% = log(htnew / ht) / log(1.1)
else
iter% = 0
end ifvar = cdbl(wd/ht)
var = htnew * var
wdnew = INT(var)
end ifif iter% > 0 then
wdnew = wd
htnew = ht
for rep% = 1 to iter%
wdnew = 1.1 * wdnew
htnew = 1.1 * htnew
dib = FreeImage_Rescale(dib,wdnew, htnew, FILTER_CATMULLROM)
next
elseif SendMessage(Check1,BM_GETCHECK,0,0) <> 1 and iter% = 0 and rot = 0 then
dib = FreeImage_Rescale(dib,wdnew, htnew, FILTER_CATMULLROM)
end if
if rot <> 0 then dib = FreeImage_RotateClassic(dib, rot)if SendMessage(Check1,BM_GETCHECK,0,0) = 1 then
GLOBAL rcTxt as RECT,sze as SIZE
BCX_CURSOR(IDC_WAIT )
FormDC = GetDC(Form1)
ScreenDC = CreateCompatibleDC(FormDC)
ScreenBitmap = CreateCompatible Bitmap(FormDC,wd,ht)
SelectObject(ScreenDC,ScreenBitmap)
bmiHeader  = *FreeImage_GetInfoHeader(dib)
bi  = *FreeImage_GetInfo(dib)
pBits = FreeImage_GetBits(dib)
SetStretchBltMode(ScreenDC,HALFTONE)
SetBrushOrgEx(ScreenDC,0,0,0)
if StretchDIBits(ScreenDC,0,0,wd,ht,0,0,wd,ht,pBits,&bi,0,SRCCOPY) = 0 then msgbox str$(GetLastError())
SelectObject(ScreenDC,hfont)
GetTextExtentPoint32(ScreenDC,strText$,len(strText$),&sze)rcTxt.left = 30
rcTxt.top = 30
rcTxt.right = 1.05*(30 + sze.cx)
rcTxt.bottom = 30 + sze.cy
SetBkMode(ScreenDC,1)
SetTextColor(ScreenDC,txtColor)
DrawText(ScreenDC,strText$,-1,&rcTxt,DT_LEFT)
savebmp(ScreenDC,appexepath$ & “tmp.bmp”)
FreeImage_Unload(dib)
DeleteObject(ScreenBitmap)
DeleteDC(ScreenDC)
dib = FreeImage_Load(FIF_BMP,appexepath$ & “tmp.bmp”,0)
if wdnew <> wd then dib = FreeImage_Rescale(dib,wdnew, htnew, FILTER_CATMULLROM)
ScreenDC = CreateCompatibleDC(FormDC)
ScreenBitmap = CreateCompatible Bitmap(FormDC,wdnew,htnew)
SelectObject(ScreenDC,ScreenBitmap)
bmiHeader  = *FreeImage_GetInfoHeader(dib)
bi  = *FreeImage_GetInfo(dib)
pBits = FreeImage_GetBits(dib)
SetStretchBltMode(ScreenDC,HALFTONE)
SetBrushOrgEx(ScreenDC,0,0,0)
if StretchDIBits(ScreenDC,0,0,wdnew,htnew,0,0,wdnew,htnew,pBits,&bi,0,

SRCCOPY) = 0 then msgbox str$(GetLastError())
end if

buf$ = UCASE$(buf$)
if buf$ = “JPG” then
fif = FIF_JPEG
ending = “jpg”
elseif buf$ = “GIF” then
dim ReservePalette as RGBQUAD
dib = FreeImage_ColorQuantizeEx(dib,FIQ_WUQUANT,256,0, &ReservePalette)
fif = FIF_GIF
ending = “gif”
elseif buf$ = “PNG” then
fif = FIF_PNG
ending = “png”
elseif buf$ = “BMP” then
fif = FIF_BMP
ending = “bmp”
elseif buf$ = “TIF” then
fif = FIF_TIFF
ending = “tif”
elseif buf$ = “TGA” then
fif = FIF_TARGA
ending = “tga”
end if
if fif != FIF_GIF then dib = FreeImage_ConvertTo24Bits(dib)
if rot = 0 then sav$ = tmpstr$ & “\” & newname[cnt] & ending
if rot <> 0 then sav$ = direc & “\” & newname[cnt] & “_Rotated.” & ending
FreeImage_Save(fif, dib, sav$, 85)
end if
FreeImage_Unload(dib)
loop
BCX_CURSOR(IDC_APPSTARTING )
if SendMessage(Check4,BM_GETCHECK,0,0) = 1 then
ShellExecute(Form1, “explore”, tmpstr$, 0, 0, SW_SHOWNORMAL)
elseif not exist(tmpstr$) then
msgbox “Unable to open folder”
end if
SendMessage(Form1, WM_CLOSE, 0,0)
case WM_CLOSE
dim i as long
if dib <> 0 then FreeImage_Unload(dib)
DeleteObject(ScreenBitmap)
DeleteDC(ScreenDC)
ReleaseDC(Form1, FormDC)
kill appexepath$ & “tmp.bmp”
if del then
for i = 1 to cnt
kill fil[i]
next
end if
END SELECT
END EVENTS

FreeImage.dll must be imported    #include <FreeImage.h> and needed functions declared. The interface is then created:

Form1 = BCX_FORM(“Form1”, 0, 0, 0.3*sx, 0.3*sy)
Group1 = BCX_GROUP(“”, Form1, 100, .01*sx, .02*sy, .05*sx, .10*sy, WS_GROUP | WS_CHILD | WS_VISIBLE | BS_GROUPBOX)
Button[0] = BCX_RADIO(“Width”,Form1, 101, .012*sx,.03*sy,.045*sx,.03*sy)
Button[1] = BCX_RADIO(“Height”,Form1, 102, .012*sx,.055*sy,.045*sx,.03*sy)
Button[2] = BCX_RADIO(“Convert”,Form1, 104, .012*sx,.080*sy,.045*sx,.03*sy)
Check1 = BCX_CHECKBOX(“Watermark”,Form1, 106, .01*sx,.12*sy,.1*sx,.03*sy)
Check3 = BCX_CHECKBOX(“Delete Original”,Form1, 108, .01*sx,.145*sy,.1*sx,.03*sy)
Check4 = BCX_CHECKBOX(“Show Folder”,Form1, 109, .01*sx,.170*sy,.1*sx,.03*sy)
Edit2 =  BCX_EDIT(“Rotation Angle eg: 90”,Form1, 110,.01*sx,.200*sy,.083*sx,.03*sy)
Edit1 = BCX_EDIT(“Value Pixels or %”,Form1, 103,.064*sx,.029*sy,.083*sx,.03*sy)
Check2 = BCX_CHECKBOX(“%”,Form1, 107, .15*sx,.029*sy,.05*sx,.03*sy)
Combo1 = BCX_COMBOBOX(“”,Form1,105,.18*sx,.028*sy,.075*sx,.15*sy)
Send Message(Check4,BM_SETCHECK,1,0)
B$[0] = “JPG”
B$[1] = “GIF”
B$[2] = “PNG”
B$[3] = “BMP”
B$[4] = “TIF”
B$[5] = “TGA”
for j% = 0 to 5
SendMessage(Combo1, CB_ADDSTRING, 0, B[j%])
next
if len(command$) > 4 then cmnd = true
edittxt = “JPG”
SendMessage(Combo1,WM_SETTEXT,0, edittxt)

CENTER(Form1)
SHOW(Form1)
SetFocus(Edit1)
SendMessage(Edit1,EM_SETSEL,0, -1)

An array with image  extensions is used to populate the combobox:
SendMessage(Combo1, CB_ADDSTRING, 0, B[j%])

A single file can be resized by right clicking its icon or multiple files can be selected from a file dialog
if cmnd then
filname = command$
cmnd = false
a = instr(filname,chr$(34), 2) – 1
direc = mid$(filname, 2, a – 2)
a = instrrev(direc, “\”) – 1
direc = mid$(direc, 1, a )
filname = replace$(filname, direc, “”)
filname = replace$(filname, chr$(34) & “\”, “”)
filname = replace$(filname, chr$(34) & ” “, “,”)
filname = direc & “,” & replace(filname, chr$(34), “”)
else
filname = GETFILENAME$(“Open”,”Picture Files|*.bmp;*.jpg;*.gif;*.png;*.tif|BMP Files|*.bmp|JPG Files|*.jpg|GIF Files|*.gif|PNG FILES|*.png|All Files|*.*”,0, Form1 ,OFN_EXPLORER | OFN_ALLOWMULTISELECT )
end if

The output is saved in a subdirectory named Resize, so the directory must be extracted from the filenames:

direc = trim$(left$(filname, a) & “\”)
if rot = 0 then
tmpstr$ = direc & “Resize”
if not exist(tmpstr$ & “\file.fil”) then
MKDIR tmpstr$
open tmpstr$ & “\file.fil” for output as hf
close hf
end if
end if

If rotation is desired the value is set in a text box:
if bcx_get_text$(Edit2) != “Rotate,90,180,270” then
rot = val(bcx_get_text$(Edit2))
end if

If a watermark is desired then the text is created:
if SendMessage(Check1,BM_GETCHECK,0,0) = 1 then
drw = true
strText$ = inputbox$(“Text”,”What is the Text?”,””)
if strText$ = “” then function = 0
bcx_fontdlg
txtColor = bcx_colordlg
hfont = BCX_SET_FONT(BCX_Font.Name$, BCX_Font.Size, BCX_Font.Bold, BCX_Font.Italic, BCX_Font.Underline, BCX_Font.Strikeout)
end if

The string obtained from the file dialog is parsed, the  dibs created and the dimensions determined by looping:
do while a <> 0
b = a + 1
cnt = cnt + 1
a = instr(filname, “,”, b)
newname[cnt] = mid$(filname, b, a – b)
newname[cnt] = left$(newname[cnt],len(newname[cnt]) – 3)
fil[cnt] = trim$(direc & mid$(filname, b, a – b))
if len(fil[cnt]) > len(direc) then
dib = FreeImage_Load(FreeImage_GetFileType(fil[cnt], 0), fil[cnt], 0)
wd = cdbl(FreeImage_GetWidth(dib))
ht = cdbl(FreeImage_GetHeight(dib))
wdnew = wd
htnew = ht

If the resizing is by width and the new width is increased the number of iterations is calculated and the resizing is done by looping:
if SendMessage(Check2,BM_GETCHECK,0,0) = 0 and wdnew > wd then
iter% = log(wdnew / wd) / log(1.1)
for rep% = 1 to iter%
wdnew = 1.1 * wdnew
htnew = 1.1 * htnew
dib = FreeImage_Rescale(dib,wdnew, htnew, FILTER_CATMULLROM)
next

The same would be true if the resizing were by height, only the height values would be used.

If the resizing is by width, the aspect ratio is calculated and the new height determined:
var = cdbl(ht/wd)
var = wdnew * var
htnew = INT(var)

The desired file ending is determined:
buf$ = UCASE$(buf$)
if buf$ = “JPG” then
fif = FIF_JPEG
ending = “jpg”
elseif buf$ = “GIF” then
dim ReservePalette as RGBQUAD
dib = FreeImage_ColorQuantizeEx(dib,FIQ_WUQUANT,256,0, &ReservePalette)
fif = FIF_GIF
ending = “gif”
If a gif is desired the dib must be paletted.

Finally the image is saved in the desired format and the dib unloaded to regain memory:
if fif != FIF_GIF then dib = FreeImage_ConvertTo24Bits(dib)
if rot = 0 then sav$ = tmpstr$ & “\” & newname[cnt] & ending
if rot <> 0 then sav$ = direc & “\” & newname[cnt] & “_Rotated.” & ending
FreeImage_Save(fif, dib, sav$, 85)
end if
FreeImage_Unload(dib)

The conversion to dibs makes the resizing much faster than working with bitmaps.

You can download the latest update from the following source .

Click Downloads and download BWM6.zip