' 7K_16X9.BAS ' ' 7K_16x9.BAS both distorts the photo height by 4/3rds (for 4:3 crop of 16:9 area) ' and adjusts the used photo area to the maximum (7200 wide / high) ' ' Note that the crop boxes are restricted to the image area, re-centred after height adjust ' and that some unused photo pixels are only 'added back' to minimise the 'bounding box' ' ' The project.xml must have already been parsed to add cr/lf, and both it + all the .jpg's ' must will be in the /PSTORY sub-folder ' ' IF you get 'OUT OF STRING SPACE' error when you launch the script, go back and and add the cr/lf :-) ' ' REMEMBER ... ' Direction X is wd (width), Y is ht (height). Do the X, wd first .. because the ht will be 133% distorted ' The 'bounding box' makes things confusing, so dump it at the start and re-calc at the end ' ' We are using 'signed' 16 bit numbers. This means that no pixel counts can exceed 32k/4 = 8k ' (or we get overflow during the 4 * height / 3 = width calcs) ' ' Suffix usage: ' s = crop start, e = crop end, i = input image, u = used image, o = output image, b = bounding box ' (so sX = start width offset, swd = start width etc) ' ' ' subroutines to add extra used height or width pixels DECLARE SUB addHeight (uwd%, uht%, uX%, uY%, iwd%, iht%) DECLARE SUB addWidth (uwd%, uht%, uX%, uY%, iwd%, iht%) ' subroutine to do the spread DECLARE SUB spreadPix (exPix%, used%, uoff%, img%) ' subroutine to redo the bounding box DECLARE SUB newBbox (bwd%, bht%, owd%, oht%) ' subroutine to put crop box into image area DECLARE SUB cropInimg (cX%, cY%, cW%, cH%, iW%, iH%) ' subroutine to extract (remove) two values (and chop the line into 3 parts) DECLARE SUB get2vals (in$, middl$, end$, dmy1$, frwd%, dmy2$, frht%) ' CLEAR ver$ = "This version 7K_16X9.BAS 1.0 24April2014" ' ' ' can't use the double-quote symbol (") in a line of qbasic code, so assign it to variable q$ q$ = CHR$(34) ' ' ' OPEN "C:\QBASIC\PSTORY3\PROJECT.XML" FOR INPUT AS #1 OPEN "C:\QBASIC\PSTORY3\x133.xml" FOR OUTPUT AS #2 OPEN "C:\QBASIC\PSTORY3\7K_16X9.LOG" FOR OUTPUT AS #4 ' PRINT ver$ PRINT #4, ver$ ' DO LINE INPUT #1, in$ ' find the next image Qpos = INSTR(in$, " 1 THEN GOTO skip1 ' OK, got we have an image def. start by saving the first line PRINT #4, PRINT #4, "Found Vu "; OPEN "C:\QBASIC\PSTORY3\vu.tmp" FOR OUTPUT AS #3 PRINT #3, in$ ' extract the jpg name it's from first double quotes to second Q1pos = INSTR(in$, q$) Q2pos = INSTR(Q1pos + 1, in$, q$) iname$ = MID$(in$, Q1pos + 1, Q2pos - Q1pos - 1) ' say we have the image name PRINT "processing "; iname$ PRINT #4, iname$ 'extract the input width and height, breaking the line into 3 parts CALL get2vals(in$, middl$, end$, "width=", iwd%, "height=", iht%) PRINT #4, "Initial Image size iwd x iht :", iwd%; " x "; iht% ' skip to the bounding box (it's the line starting 1 THEN GOTO skip2 ' extract the values CALL get2vals(in$, middl$, end$, "Width=", bwd%, "Height=", bht%) PRINT #4, "Initial Bounding box bwd x bht :", bwd%; " x "; bht% ' ' calc the existing crop box offset width and height adjusts (one will be 0) cXwdOff% = (bwd% - iwd%) / 2 cYhtOff% = (bht% - iht%) / 2 ' get & save the start crop box settings LINE INPUT #1, in$ PRINT #3, in$ ' extract the Start crop X & Y offset (the Start size) values in two steps CALL get2vals(in$, middl$, end$, "LeftX=", sX%, "LeftY=", sY%) ' adjust for bounding box sX% = sX% - cXwdOff% sY% = sY% - cYhtOff% PRINT #4, "Start crop offset (image relative)", sX%; " x "; sY% ' extract the start crop sizes, wd & ht in$ = end$ CALL get2vals(in$, middl$, end$, "width=", swd%, "height=", sht%) ' ' get & save the End crop box settings LINE INPUT #1, in$ PRINT #3, in$ ' extract the End crop offset and End size values in two steps CALL get2vals(in$, middl$, end$, "LeftX=", eX%, "LeftY=", eY%) ' adjust for bounding box eX% = eX% - cXwdOff% eY% = eY% - cYhtOff% PRINT #4, "End crop offset (image relative)", eX%; " x "; eY% ' extract the end crop sizes wd & ht in$ = end$ CALL get2vals(in$, middl$, end$, "width=", ewd%, "height=", eht%) ' 'OK, we can now start doing the calculations ' both crop boxes must be within the real image area - if not, then adjust them now ' CALL cropInimg(sX%, sY%, swd%, sht%, iwd%, iht%) PRINT #4, "Mod Start crop box offset X x Y is ", sX%; " x "; sY% PRINT #4, "Mod Start crop box size wd x ht is ", swd%; " x "; sht% ' CALL cropInimg(eX%, eY%, ewd%, eht%, iwd%, iht%) PRINT #4, "Mod End crop box offset X x Y is ", eX%; " x "; eY% PRINT #4, "Mod End crop box size wd x ht is ", ewd%; " x "; eht% ' ' OK now calc the used image area start offset (it's lower of the 2 crop box starts) uX% = sX% IF eX% < uX% THEN uX% = eX% uY% = sY% IF eY% < uY% THEN uY% = eY% PRINT #4, "Initial offset to used image area :", uX%; " x "; uY% ' ' how much image will we use ? ' first find the end of the cropped area & calc used width uwd% x used height uht% ' (it's max of the 2 crop box ends) & then adjust for start offset uwd% = eX% + ewd% IF sX% + swd% > uwd% THEN uwd% = sX% + swd% ' remove offset from used width uwd% = uwd% - uX% ' uht% = eY% + eht% IF sY% + sht% > uht% THEN uht% = sY% + sht% ' remove offset uht% = uht% - uY% ' OK we have the used image offsets and size ' it may not generate 4:3 output but we don't care ' The crop box offsets are still pointing at the original locations - so adjust them now sX% = sX% - uX% sY% = sY% - uY% eX% = eX% - uX% eY% = eY% - uY% PRINT #4, "Start crop box adjusted offset :", sX%; " x "; sY% PRINT #4, "End crop box adjusted offset :", eX%; " x "; eY% ' ' OK ready to do the main calc .. set the minimium zoom (float) ' what zoom do we need to get max of 7200 pixels wide / 5400 high (before 4/3rds) ? ozoom! = 7199.5 / uwd% IF uht% * ozoom! > 5399.5 THEN ozoom! = 5399.5 / uht% ' OK that's the final zoom calculated - PRINT "x "; ozoom! PRINT #4, "Final Zoom is ", , ozoom! ' ' calc all the output sizes based on the final zoom owd% = .5 + (uwd% * ozoom!) oht% = .5 + (uht% * ozoom! * 4 / 3) PRINT #4, "Final image width x height will be :", owd%; "x"; oht% ' ' calc the output crop box sizes (they must be 4x3, i.e. ht = 3/4 wd) swd% = swd% * ozoom! sht% = (3 * swd%) / 4 PRINT #4, "Final start crop box size wd x ht :", swd%; " x "; sht% ewd% = ewd% * ozoom! eht% = (3 * ewd%) / 4 PRINT #4, "Final end crop box size wd x ht :", ewd%; " x "; eht% ' ' redo the Bounding box CALL newBbox(bwd%, bht%, owd%, oht%) PRINT #4, "Final Bounding box is ", , bwd%; "x"; bht% ' ' calc the new crop box offsets based on final zoom ' calc bounding box offset xOff% = (bwd% - owd%) / 2 yOff% = (bht% - oht%) / 2 ' adjust width posn. for zoom and bounding box sX% = (sX% * ozoom!) + xOff% eX% = (eX% * ozoom!) + xOff% ' adjust height posn. for zoom, bounding box and 4/3rds sY% = (sY% * ozoom!) + yOff% + (sht% / 6) eY% = (eY% * ozoom!) + yOff% + (eht% / 6) ' ' make sure crop is still inside the bounding box ' re-use the cropInimg subrouting using bbox instead of image CALL cropInimg(sX%, sY%, swd%, sht%, bwd%, bht%) CALL cropInimg(eX%, eY%, ewd%, eht%, bwd%, bht%) ' PRINT #4, "Final start crop offset wd x ht :", sX%; " x "; sY% PRINT #4, "Final end crop offset wd x ht :", eX%; " x "; eY% ' ' OK, all calcs done = we can go modify the Visual Unit params ' ============================================================ ' ' Skip forward to the 4 1 THEN GOTO skip5 ' Mod. the Relative (to bounding box) settings ' chop the start, mid and end$ for the left & top entries ' Note iwd and iht are dummy - we don't need the existing values CALL get2vals(in$, middl$, end$, "left=", iwd%, "top=", iht%) ' calc the start crop offset (relative to bounding box) rleft# = sX% / bwd% IF rleft# = 0! THEN rleft$ = "0" ELSE rleft$ = "0" + LTRIM$(STR$(rleft#)) rtop# = sY% / bht% IF rtop# = 0! THEN rtop$ = "0" ELSE rtop$ = "0" + LTRIM$(STR$(rtop#)) rel$ = in$ + rleft$ + middl$ + rtop$ ' OK now get the second two values out of the rest of the string in$ = end$ CALL get2vals(in$, middl$, end$, "width=", iwd%, "height=", iht%) rwd# = swd% / bwd% IF rwd# = 1! THEN rwd$ = "1" ELSE rwd$ = "0" + LTRIM$(STR$(rwd#)) rht# = sht% / bht% IF rht# = 1! THEN rht$ = "1" ELSE rht$ = "0" + LTRIM$(STR$(rht#)) in$ = rel$ + in$ + rwd$ + middl$ + rht$ + end$ ' PRINT #3, in$ ' LINE INPUT #1, in$ CALL get2vals(in$, middl$, end$, "left=", iwd%, "top=", iht%) rleft# = eX% / bwd% IF rleft# = 0! THEN rleft$ = "0" ELSE rleft$ = "0" + LTRIM$(STR$(rleft#)) rtop# = eY% / bht% IF rtop# = 0! THEN rtop$ = "0" ELSE rtop$ = "0" + LTRIM$(STR$(rtop#)) rel$ = in$ + rleft$ + middl$ + rtop$ in$ = end$ CALL get2vals(in$, middl$, end$, "width=", iwd%, "height=", iht%) rwd# = ewd% / bwd% IF rwd# = 1! THEN rwd$ = "1" ELSE rwd$ = "0" + LTRIM$(STR$(rwd#)) rht# = eht% / bht% IF rht# = 1! THEN rht$ = "1" ELSE rht$ = "0" + LTRIM$(STR$(rht#)) in$ = rel$ + in$ + rwd$ + middl$ + rht$ + end$ ' PRINT #3, in$ ' ' OK, done ' ' Close temp & reopen CLOSE 3 OPEN "C:\QBASIC\PSTORY3\vu.tmp" FOR INPUT AS #3 ' get the first line (it's the image data) LINE INPUT #3, in$ ' ' now sort out the 1 THEN GOTO skip3 ' ' break it up CALL get2vals(in$, middl$, end$, "Width=", iwd%, "Height=", iht%) ' recombine with new values in$ = in$ + LTRIM$(STR$(bwd%)) + middl$ + LTRIM$(STR$(bht%)) + end$ ' and save the bounding box parameter string PRINT #2, in$ ' ' OK the two iW% THEN cX% = iW% - cW% IF cX% < 0 THEN cX% = 0 IF cW% > iW% THEN cW% = iW% Ht% = (3 * cW%) / 4 ' If we reduced the height, adjust the Y offset IF cH% < Ht% THEN cY% = cY% + ((cH% - Ht%) / 2) ' check it's still within the image area & reduce offset as needed IF (cY% + Ht%) > iH% THEN cY% = iH% - Ht% IF cY% < 0 THEN cY% = 0 cH% = Ht% IF Ht% > iH% THEN cH% = iH% ' reset the width cW% = (4 * cH%) / 3 END SUB ' subroutine to extract 2 values and break the line into 3 parts (b4 first val, middle, after 2nd val) SUB get2vals (in$, middl$, end$, v1$, v1%, v2$, v2%) q$ = CHR$(34) ' locate start of the first value (don't forget to allow +1 to skip the leading double quote) pos1 = INSTR(in$, v1$) + LEN(v1$) + 1 ' locate the end of v1 pos1e = INSTR(pos1 + 1, in$, q$) ' set value 1 v1% = VAL(MID$(in$, pos1, pos1e - pos1)) ' ' locate start of second value (don't forget to allow for the leading double quote) pos2 = INSTR(in$, v2$) + LEN(v2$) + 1 ' locate the end of v2 pos2e = INSTR(pos2 + 1, in$, q$) ' set value 2 v2% = VAL(MID$(in$, pos2, pos2e - pos2)) ' ' now split off the end and the middle (keeping the double quotes) end$ = MID$(in$, pos2e) middl$ = MID$(in$, pos1e, pos2 - pos1e) in$ = LEFT$(in$, pos1 - 1) END SUB ' subroutine to redo the bounding box SUB newBbox (bwd%, bht%, owd%, oht%) bwd% = owd% bht% = oht% ' one of these may be too low for a 4:3 aspect ratio IF (3 * bwd%) < (4 * oht%) THEN bwd% = (4 * oht%) / 3 ELSE IF (4 * bht%) < (3 * owd%) THEN bht% = (3 * owd%) / 4 END SUB ' subroutine to do the spread SUB spreadPix (exPix%, used%, uoff%, img%) ' try to spread them evenly between Y offsets and image ht exHalf% = exPix% / 2 exPix% = exPix% - exHalf% ' subtract from offset IF uoff% > 0 THEN IF uoff% > exHalf% THEN uoff% = uoff% - exHalf% exHalf% = 0 ELSE exHalf% = exHalf% - uoff% uoff% = 0 END IF END IF ' OK add back any we didnt manage to subtract exPix% = exPix% + exHalf% ' can we add input pixels IF img% - used% > exPix% THEN used% = used% + exPix% exPix% = 0 ELSE exPix% = exPix% - (img% - used%) used% = img% END IF ' subtract any left over from offset IF uoff% > exPix% THEN uoff% = uoff% - exPix% exPix% = 0 ELSE exPix% = exPix% - uoff% uoff% = 0 END IF END SUB