diff --git a/example_workflows/V3.0.0_nodes.jpg b/example_workflows/V3.0.0_nodes.jpg new file mode 100644 index 0000000..3679349 Binary files /dev/null and b/example_workflows/V3.0.0_nodes.jpg differ diff --git a/example_workflows/V3.0.0_nodes.json b/example_workflows/V3.0.0_nodes.json new file mode 100644 index 0000000..cf386b1 --- /dev/null +++ b/example_workflows/V3.0.0_nodes.json @@ -0,0 +1,1439 @@ +{ + "id": "24f0d3f4-7207-455e-ae7f-3bd3ce2771bd", + "revision": 0, + "last_node_id": 69, + "last_link_id": 115, + "nodes": [ + { + "id": 46, + "type": "AILab_ImageToList", + "pos": [ + 1047.8420447008732, + 570.6909261432831 + ], + "size": [ + 300, + 158 + ], + "flags": {}, + "order": 0, + "mode": 0, + "inputs": [ + { + "name": "image_1", + "shape": 7, + "type": "IMAGE", + "link": null + }, + { + "name": "image_2", + "shape": 7, + "type": "IMAGE", + "link": null + }, + { + "name": "image_3", + "shape": 7, + "type": "IMAGE", + "link": null + }, + { + "name": "image_4", + "shape": 7, + "type": "IMAGE", + "link": null + }, + { + "name": "image_5", + "shape": 7, + "type": "IMAGE", + "link": null + }, + { + "name": "image_6", + "shape": 7, + "type": "IMAGE", + "link": null + } + ], + "outputs": [ + { + "name": "IMAGE", + "shape": 6, + "type": "IMAGE", + "links": null + }, + { + "name": "WIDTH", + "type": "INT", + "links": null + }, + { + "name": "HEIGHT", + "type": "INT", + "links": null + }, + { + "name": "BATCH_SIZE", + "type": "INT", + "links": null + } + ], + "properties": { + "cnr_id": "comfyui-rmbg", + "ver": "112fd6141d07663d5e4a35d66d269542b58f4438", + "Node name for S&R": "AILab_ImageToList" + }, + "widgets_values": [ + "crop" + ], + "color": "#2e3e57", + "bgcolor": "#4b5b73" + }, + { + "id": 48, + "type": "AILab_MaskToList", + "pos": [ + 1366.0461693416478, + 570.6909261432831 + ], + "size": [ + 300, + 158 + ], + "flags": {}, + "order": 1, + "mode": 0, + "inputs": [ + { + "name": "mask_1", + "shape": 7, + "type": "MASK", + "link": null + }, + { + "name": "mask_2", + "shape": 7, + "type": "MASK", + "link": null + }, + { + "name": "mask_3", + "shape": 7, + "type": "MASK", + "link": null + }, + { + "name": "mask_4", + "shape": 7, + "type": "MASK", + "link": null + }, + { + "name": "mask_5", + "shape": 7, + "type": "MASK", + "link": null + }, + { + "name": "mask_6", + "shape": 7, + "type": "MASK", + "link": null + } + ], + "outputs": [ + { + "name": "MASK", + "shape": 6, + "type": "MASK", + "links": null + } + ], + "properties": { + "cnr_id": "comfyui-rmbg", + "ver": "112fd6141d07663d5e4a35d66d269542b58f4438", + "Node name for S&R": "AILab_MaskToList" + }, + "widgets_values": [ + "off" + ], + "color": "#2e3e57", + "bgcolor": "#4b5b73" + }, + { + "id": 49, + "type": "AILab_ImageResize", + "pos": [ + 696.620960299752, + 575.6924334366491 + ], + "size": [ + 300, + 384 + ], + "flags": {}, + "order": 2, + "mode": 0, + "inputs": [ + { + "name": "image", + "type": "IMAGE", + "link": null + }, + { + "name": "mask", + "shape": 7, + "type": "MASK", + "link": null + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": null + }, + { + "name": "MASK", + "type": "MASK", + "links": null + }, + { + "name": "WIDTH", + "type": "INT", + "links": null + }, + { + "name": "HEIGHT", + "type": "INT", + "links": null + } + ], + "properties": { + "cnr_id": "comfyui-rmbg", + "ver": "112fd6141d07663d5e4a35d66d269542b58f4438", + "Node name for S&R": "AILab_ImageResize" + }, + "widgets_values": [ + 0, + 0, + 0, + 1, + "longest_side", + 0, + "lanczos", + "cpu", + 2, + "stretch", + "center", + "#FFFFFF" + ], + "color": "#2e3e57", + "bgcolor": "#4b5b73" + }, + { + "id": 50, + "type": "AILab_ImageCompare", + "pos": [ + 365.8307279548751, + 579.4682081332511 + ], + "size": [ + 300, + 222 + ], + "flags": {}, + "order": 3, + "mode": 0, + "inputs": [ + { + "name": "image1", + "shape": 7, + "type": "IMAGE", + "link": null + }, + { + "name": "image2", + "shape": 7, + "type": "IMAGE", + "link": null + }, + { + "name": "image3", + "shape": 7, + "type": "IMAGE", + "link": null + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": null + } + ], + "properties": { + "cnr_id": "comfyui-rmbg", + "ver": "112fd6141d07663d5e4a35d66d269542b58f4438", + "Node name for S&R": "AILab_ImageCompare" + }, + "widgets_values": [ + "Image 1", + "Image 2", + "Image 3", + "largest", + "#000000", + "#FFFFFF" + ], + "color": "#2e3e57", + "bgcolor": "#4b5b73" + }, + { + "id": 63, + "type": "AILab_Preview", + "pos": [ + 1408.0731152563624, + 39.52132784074146 + ], + "size": [ + 283.259375, + 438.80841722170493 + ], + "flags": {}, + "order": 16, + "mode": 0, + "inputs": [ + { + "name": "image", + "shape": 7, + "type": "IMAGE", + "link": 98 + }, + { + "name": "mask", + "shape": 7, + "type": "MASK", + "link": 99 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": null + }, + { + "name": "MASK", + "type": "MASK", + "links": null + } + ], + "properties": { + "cnr_id": "comfyui-rmbg", + "ver": "112fd6141d07663d5e4a35d66d269542b58f4438", + "Node name for S&R": "AILab_Preview" + }, + "widgets_values": [], + "color": "#2e3e57", + "bgcolor": "#4b5b73" + }, + { + "id": 55, + "type": "AILab_YoloV8Adv", + "pos": [ + 1048.5475633455346, + -259.9253308715706 + ], + "size": [ + 340, + 314 + ], + "flags": {}, + "order": 10, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 103 + } + ], + "outputs": [ + { + "name": "ANNOTATED_IMAGE", + "type": "IMAGE", + "links": [ + 98 + ] + }, + { + "name": "MASK", + "type": "MASK", + "links": [ + 99 + ] + }, + { + "name": "MASK_LIST", + "type": "MASK", + "links": [ + 100 + ] + } + ], + "properties": { + "cnr_id": "comfyui-rmbg", + "ver": "112fd6141d07663d5e4a35d66d269542b58f4438", + "Node name for S&R": "AILab_YoloV8Adv" + }, + "widgets_values": [ + "bbox\\face_yolov8m.pt", + "1", + "3", + 0.25, + 0.45, + "", + "auto", + 300, + true, + false + ], + "color": "#222e40", + "bgcolor": "#364254" + }, + { + "id": 58, + "type": "AILab_MaskPreview", + "pos": [ + 1722.2462377484255, + -469.3506020431651 + ], + "size": [ + 401.5947961026536, + 442.58226902843114 + ], + "flags": {}, + "order": 15, + "mode": 0, + "inputs": [ + { + "name": "mask", + "type": "MASK", + "link": 87 + } + ], + "outputs": [ + { + "name": "MASK", + "type": "MASK", + "links": null + } + ], + "properties": { + "cnr_id": "comfyui-rmbg", + "ver": "112fd6141d07663d5e4a35d66d269542b58f4438", + "Node name for S&R": "AILab_MaskPreview" + }, + "widgets_values": [], + "color": "#2e3e57", + "bgcolor": "#4b5b73" + }, + { + "id": 64, + "type": "Reroute", + "pos": [ + 926.5654385167668, + -457.68442961204573 + ], + "size": [ + 75, + 26 + ], + "flags": {}, + "order": 6, + "mode": 0, + "inputs": [ + { + "name": "", + "type": "*", + "link": 101 + } + ], + "outputs": [ + { + "name": "", + "type": "IMAGE", + "links": [ + 102, + 103 + ] + } + ], + "properties": { + "showOutputText": false, + "horizontal": false + } + }, + { + "id": 57, + "type": "AILab_Preview", + "pos": [ + 1408.0731152563624, + -469.3506020431651 + ], + "size": [ + 283.259375, + 438.80841722170493 + ], + "flags": {}, + "order": 14, + "mode": 0, + "inputs": [ + { + "name": "image", + "shape": 7, + "type": "IMAGE", + "link": 85 + }, + { + "name": "mask", + "shape": 7, + "type": "MASK", + "link": 86 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": null + }, + { + "name": "MASK", + "type": "MASK", + "links": null + } + ], + "properties": { + "cnr_id": "comfyui-rmbg", + "ver": "112fd6141d07663d5e4a35d66d269542b58f4438", + "Node name for S&R": "AILab_Preview" + }, + "widgets_values": [], + "color": "#2e3e57", + "bgcolor": "#4b5b73" + }, + { + "id": 54, + "type": "AILab_YoloV8", + "pos": [ + 1052.1975314394726, + -469.3506020431651 + ], + "size": [ + 340, + 146 + ], + "flags": {}, + "order": 9, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 102 + } + ], + "outputs": [ + { + "name": "ANNOTATED_IMAGE", + "type": "IMAGE", + "links": [ + 85 + ] + }, + { + "name": "MASK", + "type": "MASK", + "links": [ + 86 + ] + }, + { + "name": "MASK_LIST", + "type": "MASK", + "links": [ + 87 + ] + } + ], + "properties": { + "cnr_id": "comfyui-rmbg", + "ver": "112fd6141d07663d5e4a35d66d269542b58f4438", + "Node name for S&R": "AILab_YoloV8" + }, + "widgets_values": [ + "bbox\\face_yolov8m.pt", + "all", + "none" + ], + "color": "#222e40", + "bgcolor": "#364254" + }, + { + "id": 47, + "type": "AILab_ImageMaskToList", + "pos": [ + 1684.250293982423, + 570.6909261432831 + ], + "size": [ + 300, + 278 + ], + "flags": {}, + "order": 4, + "mode": 0, + "inputs": [ + { + "name": "image_1", + "shape": 7, + "type": "IMAGE", + "link": null + }, + { + "name": "mask_1", + "shape": 7, + "type": "MASK", + "link": null + }, + { + "name": "image_2", + "shape": 7, + "type": "IMAGE", + "link": null + }, + { + "name": "mask_2", + "shape": 7, + "type": "MASK", + "link": null + }, + { + "name": "image_3", + "shape": 7, + "type": "IMAGE", + "link": null + }, + { + "name": "mask_3", + "shape": 7, + "type": "MASK", + "link": null + }, + { + "name": "image_4", + "shape": 7, + "type": "IMAGE", + "link": null + }, + { + "name": "mask_4", + "shape": 7, + "type": "MASK", + "link": null + }, + { + "name": "image_5", + "shape": 7, + "type": "IMAGE", + "link": null + }, + { + "name": "mask_5", + "shape": 7, + "type": "MASK", + "link": null + }, + { + "name": "image_6", + "shape": 7, + "type": "IMAGE", + "link": null + }, + { + "name": "mask_6", + "shape": 7, + "type": "MASK", + "link": null + } + ], + "outputs": [ + { + "name": "IMAGE", + "shape": 6, + "type": "IMAGE", + "links": null + }, + { + "name": "MASK", + "shape": 6, + "type": "MASK", + "links": null + }, + { + "name": "WIDTH", + "type": "INT", + "links": null + }, + { + "name": "HEIGHT", + "type": "INT", + "links": null + }, + { + "name": "BATCH_SIZE", + "type": "INT", + "links": null + } + ], + "properties": { + "cnr_id": "comfyui-rmbg", + "ver": "112fd6141d07663d5e4a35d66d269542b58f4438", + "Node name for S&R": "AILab_ImageMaskToList" + }, + "widgets_values": [ + "crop" + ], + "color": "#2e3e57", + "bgcolor": "#4b5b73" + }, + { + "id": 62, + "type": "AILab_MaskPreview", + "pos": [ + 1709.043701852234, + 43.3906995024993 + ], + "size": [ + 409.40977875045064, + 308.1645913357711 + ], + "flags": {}, + "order": 17, + "mode": 0, + "inputs": [ + { + "name": "mask", + "type": "MASK", + "link": 100 + } + ], + "outputs": [ + { + "name": "MASK", + "type": "MASK", + "links": null + } + ], + "properties": { + "cnr_id": "comfyui-rmbg", + "ver": "112fd6141d07663d5e4a35d66d269542b58f4438", + "Node name for S&R": "AILab_MaskPreview" + }, + "widgets_values": [], + "color": "#2e3e57", + "bgcolor": "#4b5b73" + }, + { + "id": 61, + "type": "AILab_Preview", + "pos": [ + 543.0352293721749, + -342.4068451313019 + ], + "size": [ + 450.69917785327516, + 365.464710830832 + ], + "flags": {}, + "order": 11, + "mode": 0, + "inputs": [ + { + "name": "image", + "shape": 7, + "type": "IMAGE", + "link": 93 + }, + { + "name": "mask", + "shape": 7, + "type": "MASK", + "link": null + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [] + }, + { + "name": "MASK", + "type": "MASK", + "links": null + } + ], + "properties": { + "cnr_id": "comfyui-rmbg", + "ver": "112fd6141d07663d5e4a35d66d269542b58f4438", + "Node name for S&R": "AILab_Preview" + }, + "widgets_values": [], + "color": "#2e3e57", + "bgcolor": "#4b5b73" + }, + { + "id": 51, + "type": "AILab_ColorToMask", + "pos": [ + -347.29113802664796, + 861.0253090772748 + ], + "size": [ + 340, + 108 + ], + "flags": {}, + "order": 13, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 110 + } + ], + "outputs": [ + { + "name": "MASK", + "type": "MASK", + "links": [ + 113 + ] + } + ], + "properties": { + "cnr_id": "comfyui-rmbg", + "ver": "112fd6141d07663d5e4a35d66d269542b58f4438", + "Node name for S&R": "AILab_ColorToMask" + }, + "widgets_values": [ + false, + 10, + "#ff0000" + ], + "color": "#222e40", + "bgcolor": "#364254" + }, + { + "id": 68, + "type": "AILab_Preview", + "pos": [ + 13.429676985540132, + 522.8172182833199 + ], + "size": [ + 296.5573523869766, + 441.34686577474065 + ], + "flags": {}, + "order": 20, + "mode": 0, + "inputs": [ + { + "name": "image", + "shape": 7, + "type": "IMAGE", + "link": 112 + }, + { + "name": "mask", + "shape": 7, + "type": "MASK", + "link": 113 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [] + }, + { + "name": "MASK", + "type": "MASK", + "links": null + } + ], + "properties": { + "cnr_id": "comfyui-rmbg", + "ver": "112fd6141d07663d5e4a35d66d269542b58f4438", + "Node name for S&R": "AILab_Preview" + }, + "widgets_values": [], + "color": "#2e3e57", + "bgcolor": "#4b5b73" + }, + { + "id": 66, + "type": "RMBG", + "pos": [ + -350.2292106187164, + 521.4078025869 + ], + "size": [ + 340, + 292 + ], + "flags": {}, + "order": 8, + "mode": 0, + "inputs": [ + { + "name": "image", + "type": "IMAGE", + "link": 109 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 110, + 112 + ] + }, + { + "name": "MASK", + "type": "MASK", + "links": null + }, + { + "name": "MASK_IMAGE", + "type": "IMAGE", + "links": null + } + ], + "properties": { + "cnr_id": "comfyui-rmbg", + "ver": "112fd6141d07663d5e4a35d66d269542b58f4438", + "Node name for S&R": "RMBG" + }, + "widgets_values": [ + "RMBG-2.0", + 1, + 1024, + 0, + 0, + false, + false, + "Color", + "#ff0000" + ], + "color": "#222e40", + "bgcolor": "#364254" + }, + { + "id": 56, + "type": "AILab_LoadImage", + "pos": [ + -507.8036001213148, + -449.76630875267523 + ], + "size": [ + 658.5781239884182, + 749.9739396122188 + ], + "flags": {}, + "order": 5, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 101, + 107, + 108, + 109 + ] + }, + { + "name": "MASK", + "type": "MASK", + "links": null + }, + { + "name": "WIDTH", + "type": "INT", + "links": null + }, + { + "name": "HEIGHT", + "type": "INT", + "links": null + } + ], + "properties": { + "cnr_id": "comfyui-rmbg", + "ver": "112fd6141d07663d5e4a35d66d269542b58f4438", + "Node name for S&R": "AILab_LoadImage" + }, + "widgets_values": [ + "", + "ComfyUI_0073.png", + "lanczos", + 0, + 1, + "longest_side", + 0, + "image" + ], + "color": "#2e3e57", + "bgcolor": "#4b5b73" + }, + { + "id": 69, + "type": "PreviewAny", + "pos": [ + 244.62952344276502, + 195.42117803366267 + ], + "size": [ + 276.1929030268334, + 202.87891754385805 + ], + "flags": {}, + "order": 18, + "mode": 0, + "inputs": [ + { + "name": "source", + "type": "*", + "link": 115 + } + ], + "outputs": [], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.9.2", + "Node name for S&R": "PreviewAny" + }, + "widgets_values": [ + null, + null, + false + ] + }, + { + "id": 60, + "type": "AILab_MaskPreview", + "pos": [ + 544.8603137020481, + 63.22458389060715 + ], + "size": [ + 445.8952459605439, + 346.45675748559734 + ], + "flags": {}, + "order": 19, + "mode": 0, + "inputs": [ + { + "name": "mask", + "type": "MASK", + "link": 91 + } + ], + "outputs": [ + { + "name": "MASK", + "type": "MASK", + "links": null + } + ], + "properties": { + "cnr_id": "comfyui-rmbg", + "ver": "112fd6141d07663d5e4a35d66d269542b58f4438", + "Node name for S&R": "AILab_MaskPreview" + }, + "widgets_values": [], + "color": "#2e3e57", + "bgcolor": "#4b5b73" + }, + { + "id": 52, + "type": "AILab_Florence2", + "pos": [ + 183.18021222894134, + -340.69733766977623 + ], + "size": [ + 340, + 296 + ], + "flags": {}, + "order": 7, + "mode": 0, + "inputs": [ + { + "name": "image", + "type": "IMAGE", + "link": 107 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 93 + ] + }, + { + "name": "MASK", + "type": "MASK", + "links": [] + }, + { + "name": "DATA", + "type": "JSON", + "links": [ + 80 + ] + } + ], + "properties": { + "cnr_id": "comfyui-rmbg", + "ver": "112fd6141d07663d5e4a35d66d269542b58f4438", + "Node name for S&R": "AILab_Florence2" + }, + "widgets_values": [ + "microsoft/Florence-2-base", + "Phrase Grounding (text boxes)", + "fp16", + "flash_attention_2", + true, + "", + false, + "woman" + ], + "color": "#222e40", + "bgcolor": "#364254" + }, + { + "id": 53, + "type": "AILab_Florence2ToCoordinates", + "pos": [ + 243.80236224188423, + 20.82756707675828 + ], + "size": [ + 274.4341796875, + 122 + ], + "flags": {}, + "order": 12, + "mode": 0, + "inputs": [ + { + "name": "data", + "type": "JSON", + "link": 80 + }, + { + "name": "image", + "shape": 7, + "type": "IMAGE", + "link": 108 + } + ], + "outputs": [ + { + "name": "CENTER_COORDINATES", + "type": "STRING", + "links": [] + }, + { + "name": "BBOXES", + "type": "BBOX", + "links": [ + 115 + ] + }, + { + "name": "MASK", + "type": "MASK", + "links": [ + 91 + ] + } + ], + "properties": { + "cnr_id": "comfyui-rmbg", + "ver": "112fd6141d07663d5e4a35d66d269542b58f4438", + "Node name for S&R": "AILab_Florence2ToCoordinates" + }, + "widgets_values": [ + "1,2", + false + ], + "color": "#2e3e57", + "bgcolor": "#4b5b73" + } + ], + "links": [ + [ + 80, + 52, + 2, + 53, + 0, + "JSON" + ], + [ + 85, + 54, + 0, + 57, + 0, + "IMAGE" + ], + [ + 86, + 54, + 1, + 57, + 1, + "MASK" + ], + [ + 87, + 54, + 2, + 58, + 0, + "MASK" + ], + [ + 91, + 53, + 2, + 60, + 0, + "MASK" + ], + [ + 93, + 52, + 0, + 61, + 0, + "IMAGE" + ], + [ + 98, + 55, + 0, + 63, + 0, + "IMAGE" + ], + [ + 99, + 55, + 1, + 63, + 1, + "MASK" + ], + [ + 100, + 55, + 2, + 62, + 0, + "MASK" + ], + [ + 101, + 56, + 0, + 64, + 0, + "IMAGE" + ], + [ + 102, + 64, + 0, + 54, + 0, + "IMAGE" + ], + [ + 103, + 64, + 0, + 55, + 0, + "IMAGE" + ], + [ + 107, + 56, + 0, + 52, + 0, + "IMAGE" + ], + [ + 108, + 56, + 0, + 53, + 1, + "IMAGE" + ], + [ + 109, + 56, + 0, + 66, + 0, + "IMAGE" + ], + [ + 110, + 66, + 0, + 51, + 0, + "IMAGE" + ], + [ + 112, + 66, + 0, + 68, + 0, + "IMAGE" + ], + [ + 113, + 51, + 0, + 68, + 1, + "MASK" + ], + [ + 115, + 53, + 1, + 69, + 0, + "BBOX" + ] + ], + "groups": [ + { + "id": 1, + "title": "YOLO", + "bounding": [ + 1036.2030447017617, + -546.8580933670634, + 1092.1675251452946, + 1028.9358284618384 + ], + "color": "#3f789e", + "font_size": 24, + "flags": {} + }, + { + "id": 2, + "title": "Florence2", + "bounding": [ + 173.18021222894134, + -418.087161768548, + 829.1530693477696, + 834.3299632484777 + ], + "color": "#3f789e", + "font_size": 24, + "flags": {} + }, + { + "id": 4, + "title": "Batch List", + "bounding": [ + 1037.8420447008732, + 497.09092614328324, + 956.4082492815496, + 361.6 + ], + "color": "#3f789e", + "font_size": 24, + "flags": {} + }, + { + "id": 5, + "title": "Image Resise & Compare", + "bounding": [ + 355.8307279548751, + 502.0924334366491, + 650.790232344877, + 467.6 + ], + "color": "#3f789e", + "font_size": 24, + "flags": {} + }, + { + "id": 6, + "title": "Color to Mask", + "bounding": [ + -360.2292106187164, + 445.9895601481211, + 684.334084226326, + 527.7008311466786 + ], + "color": "#3f789e", + "font_size": 24, + "flags": {} + } + ], + "config": {}, + "extra": { + "ds": { + "scale": 0.9306133616020476, + "offset": [ + 755.9456821662792, + 524.7089130117238 + ] + }, + "workflowRendererVersion": "LG", + "frontendVersion": "1.38.3", + "VHS_latentpreview": false, + "VHS_latentpreviewrate": 0, + "VHS_MetadataImage": true, + "VHS_KeepIntermediate": true + }, + "version": 0.4 +} \ No newline at end of file