From e5adb72851d82d08fddbfb05f9fdffc2edf06f52 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Sat, 25 Mar 2023 18:28:00 -0700 Subject: [PATCH 1/7] wip cats --- video-cat/combine.sh | 10 ++++++++++ video-cat/extract.sh | 17 +++++++++++++++++ video-cat/video.sh | 15 +++++++++++++++ 3 files changed, 42 insertions(+) create mode 100644 video-cat/combine.sh create mode 100644 video-cat/extract.sh create mode 100644 video-cat/video.sh diff --git a/video-cat/combine.sh b/video-cat/combine.sh new file mode 100644 index 0000000..e6a86bf --- /dev/null +++ b/video-cat/combine.sh @@ -0,0 +1,10 @@ +ffmpeg \ + -r 60000/1001 \ + -i 'frames/dither-%04d.png' \ + -i 'cats-audio.wav' \ + -ac 2 \ + -ar 48000 \ + -vf 'pad=w=640:h=360:x=52:y=20' \ + -pix_fmt yuv420p \ + -movflags +faststart \ + -y cats-dither.mp4 diff --git a/video-cat/extract.sh b/video-cat/extract.sh new file mode 100644 index 0000000..9c15aa4 --- /dev/null +++ b/video-cat/extract.sh @@ -0,0 +1,17 @@ +set -a + +mkdir -p frames + +ffmpeg \ + -i 'cats computer fun.mp4' \ + -vf 'scale=160:150,pad=h=160:y=5' \ + -an \ + -y 'frames/cats-%04d.png' + +ffmpeg \ + -i 'cats computer fun.mp4' \ + -vn \ + -ac 1 \ + -ar 15734 \ + -acodec pcm_u8 \ + -y 'cats-audio.wav' diff --git a/video-cat/video.sh b/video-cat/video.sh new file mode 100644 index 0000000..105fc48 --- /dev/null +++ b/video-cat/video.sh @@ -0,0 +1,15 @@ +set -e + +for frame in frames/cats-[0-9][0-9][0-9][0-9].png +do + n="${frame#frames/cats-}" + n="${n%.png}" + out="frames/dither-${n}" + last="${n:0-1}" + node ../dither-image.js "$frame" "$out" & + if (( last == 9 )) + then + wait + fi +done +wait From 38e9af3843c3f890274338c0d73102f201389ce1 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Sat, 25 Mar 2023 18:57:09 -0700 Subject: [PATCH 2/7] wip --- dither-image.js | 43 +++++++++++++++++++++++++++++-------------- dither4.s | 3 ++- video-cat/combine.sh | 2 +- video-doom/combine.sh | 10 ++++++++++ video-doom/extract.sh | 22 ++++++++++++++++++++++ video-doom/video.sh | 15 +++++++++++++++ 6 files changed, 79 insertions(+), 16 deletions(-) create mode 100644 video-doom/combine.sh create mode 100644 video-doom/extract.sh create mode 100644 video-doom/video.sh diff --git a/dither-image.js b/dither-image.js index 58cb9bf..a481e21 100644 --- a/dither-image.js +++ b/dither-image.js @@ -637,6 +637,10 @@ function decimate(input, palette, n) { let [lo, hi] = medianCut(buckets[index], ranges[index]); buckets.splice(index, 1, lo, hi); } + + if (buckets.length > n) { + throw new Error('xxx too many colors assigned'); + } decimated = buckets.map((bucket) => { // Average the RGB colors in this chunk let rgb = bucket @@ -742,9 +746,17 @@ async function loadImage(src) { let width = image.bitmap.width; let height = image.bitmap.height; - if (width != 160 || height != 160) { + //if (width != 160 || height != 160) { + if (width != 160) { width = 160; - height = 160; + //height = 160; + //height = 192; + let dar = 1.2 / 2; + height = (width * image.bitmap.width / image.bitmap.height) * dar; + height = Math.round(height); + if (height & 1) { + height++; + } image = image.resize(width, height); } @@ -787,10 +799,12 @@ async function convert(source) { throw new Error(`expected 160px-compatible width, got ${width} pixels`); } + /* if (height !== 160) { // @fixme support up to 240px throw new Error(`expected 160px height, got ${height} pixels`); } + */ if (rgba.length != width * 4 * height) { console.log(` @@ -908,29 +922,30 @@ ${byte2byte(frame.bitmap.slice(0, half))} frame1_palette1_even: ${byte2byte(even(frame.palette1))} -.align 128 -frame1_palette1_odd: -${byte2byte(odd(frame.palette1))} - .align 128 frame1_palette2_even: ${byte2byte(even(frame.palette2))} +.align 128 +frame1_palette3_even: +${byte2byte(even(frame.palette3))} + +.align 4096 +frame1_bottom: +${byte2byte(frame.bitmap.slice(half))} + +.align 128 +frame1_palette1_odd: +${byte2byte(odd(frame.palette1))} + .align 128 frame1_palette2_odd: ${byte2byte(odd(frame.palette2))} -.align 128 -frame1_palette3_even: -${byte2byte(even(frame.palette3))} - .align 128 frame1_palette3_odd: ${byte2byte(odd(frame.palette3))} -.align 4096 -frame1_bottom: -${byte2byte(frame.bitmap.slice(half))} @@ -943,7 +958,7 @@ displaylist: ; include a DLI to mark us as frame 0 .byte $f0 ; 8 blank lines - ; 160 lines graphics + ; ${height} lines graphics ; ANTIC mode e (160px 2bpp, 1 scan line per line) .byte $4e .addr frame1_top diff --git a/dither4.s b/dither4.s index 9dfb994..6513a16 100644 --- a/dither4.s +++ b/dither4.s @@ -28,7 +28,8 @@ sample_ptr = sample_ptrl scanline = $86 frame_counter = $89 -height = 160 +;height = 160 +height = 192 bytes_per_line = 40 pages_per_frame = 32 lines_per_frame = 262 diff --git a/video-cat/combine.sh b/video-cat/combine.sh index e6a86bf..e41f542 100644 --- a/video-cat/combine.sh +++ b/video-cat/combine.sh @@ -1,5 +1,5 @@ ffmpeg \ - -r 60000/1001 \ + -r 30000/1001 \ -i 'frames/dither-%04d.png' \ -i 'cats-audio.wav' \ -ac 2 \ diff --git a/video-doom/combine.sh b/video-doom/combine.sh new file mode 100644 index 0000000..9e6b03f --- /dev/null +++ b/video-doom/combine.sh @@ -0,0 +1,10 @@ +ffmpeg \ + -r 60000/1001 \ + -i 'frames/dither-%04d.png' \ + -i 'doom-audio.wav' \ + -ac 2 \ + -ar 48000 \ + -vf 'pad=w=640:h=360:x=52:y=20' \ + -pix_fmt yuv420p \ + -movflags +faststart \ + -y doom-dither.mp4 diff --git a/video-doom/extract.sh b/video-doom/extract.sh new file mode 100644 index 0000000..e3b4107 --- /dev/null +++ b/video-doom/extract.sh @@ -0,0 +1,22 @@ +set -a + +mkdir -p frames + +TIME=37 + +ffmpeg \ + -i 'doom-speedrun.webm' \ + -t $TIME \ + -r 60000/1001 \ + -vf 'scale=160:192' \ + -an \ + -y 'frames/doom-%04d.png' + +ffmpeg \ + -i 'doom-speedrun.webm' \ + -t $TIME \ + -vn \ + -ac 1 \ + -ar 15734 \ + -acodec pcm_u8 \ + -y 'doom-audio.wav' diff --git a/video-doom/video.sh b/video-doom/video.sh new file mode 100644 index 0000000..3b5730e --- /dev/null +++ b/video-doom/video.sh @@ -0,0 +1,15 @@ +set -e + +for frame in frames/doom-[0-9][0-9][0-9][0-9].png +do + n="${frame#frames/doom-}" + n="${n%.png}" + out="frames/dither-${n}" + last="${n:0-1}" + node ../dither-image.js "$frame" "$out" & + if (( last == 9 )) + then + wait + fi +done +wait From 9631e2e026f29f2776a744490c80ff0ae5099f90 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Sat, 25 Mar 2023 19:43:57 -0700 Subject: [PATCH 3/7] fixes --- dither-image.js | 71 +++++++++++++++++++++++++++++++------------ dither4.s | 1 + video-doom/extract.sh | 2 +- 3 files changed, 53 insertions(+), 21 deletions(-) diff --git a/dither-image.js b/dither-image.js index a481e21..2690485 100644 --- a/dither-image.js +++ b/dither-image.js @@ -585,6 +585,26 @@ function decimate(input, palette, n) { // preface the reserved bits let buckets = reserved.slice().map((c) => [atariRGB[c]]).concat([input.slice()]); + /* + let buckets = [input.slice()]; + if (reserved.length > 0) { + let pxPerReserved = input.length; + for (let c of reserved) { + for (let i = 0; i < pxPerReserved; i++) { + buckets[0].unshift(atariRGB[c]); + } + } + console.log(buckets[0].length, 'xxx'); + } + */ + + let magicSort = (picker) => (a, b) => { + let bychannel = picker(b) - picker(a); + if (bychannel) return bychannel; + + let byluma = b.luma() - a.luma(); + return byluma; + }; let medianCut = (bucket, range) => { if (bucket.length < 2) { console.log(bucket); @@ -594,15 +614,21 @@ function decimate(input, palette, n) { // Sort by the channel with the greatest range, // then cut the bucket in two at the median. if (range.g >= range.r && range.g >= range.b) { - bucket.sort((a, b) => b.g - a.g); + //bucket.sort((a, b) => b.g - a.g); + bucket.sort(magicSort((rgb) => rgb.g)); } else if (range.r >= range.g && range.r >= range.b) { - bucket.sort((a, b) => b.r - a.r); + //bucket.sort((a, b) => b.r - a.r); + bucket.sort(magicSort((rgb) => rgb.r)); } else if (range.b >= range.g && range.b >= range.r) { - bucket.sort((a, b) => b.b - a.b); + //bucket.sort((a, b) => b.b - a.b); + bucket.sort(magicSort((rgb) => rgb.b)); } let half = bucket.length >> 1; //console.log('cutting', half, bucket.length); - return [bucket.slice(0, half), bucket.slice(half)]; + let [bottom, top] = [bucket.slice(0, half), bucket.slice(half)]; + //console.log({bottom, top}); + return [bottom, top]; + //return [bucket.slice(0, half), bucket.slice(half)]; }; while (buckets.length < n) { // Find the bucket with the greatest range in any channel @@ -729,8 +755,11 @@ function decimate(input, palette, n) { }); // hack decimated.sort((a, b) => a - b); - //console.log(decimated); - decimated[0] = 0; + console.log(decimated); + + // we shouldn't have to do this + //decimated[0] = 0; + console.log(decimated); // Palette fits return dither(decimated); @@ -837,7 +866,7 @@ async function convert(source) { .slice(y * width, (y + 1) * width); if (y > 0) { let error = lines[y - 1].error; - inputLine = inputLine.map((rgb, x) => rgb.add(error[x])); + inputLine = inputLine.map((rgb, x) => rgb.add(error[x]).clamp()); } let line = decimate(inputLine, allColors, 4, y); lines.push(line); @@ -904,12 +933,14 @@ function genAssembly(width, height, nbits, lines) { return `.data .export frame1_top .export frame1_bottom + .export frame1_palette1_even .export frame1_palette1_odd .export frame1_palette2_even .export frame1_palette2_odd .export frame1_palette3_even .export frame1_palette3_odd + .export displaylist .segment "BUFFERS" @@ -918,30 +949,30 @@ function genAssembly(width, height, nbits, lines) { frame1_top: ${byte2byte(frame.bitmap.slice(0, half))} -.align 128 -frame1_palette1_even: -${byte2byte(even(frame.palette1))} - -.align 128 -frame1_palette2_even: -${byte2byte(even(frame.palette2))} - -.align 128 -frame1_palette3_even: -${byte2byte(even(frame.palette3))} - .align 4096 frame1_bottom: ${byte2byte(frame.bitmap.slice(half))} +.align 128 +frame1_palette1_even: +${byte2byte(even(frame.palette1))} + .align 128 frame1_palette1_odd: ${byte2byte(odd(frame.palette1))} +.align 128 +frame1_palette2_even: +${byte2byte(even(frame.palette2))} + .align 128 frame1_palette2_odd: ${byte2byte(odd(frame.palette2))} +.align 128 +frame1_palette3_even: +${byte2byte(even(frame.palette3))} + .align 128 frame1_palette3_odd: ${byte2byte(odd(frame.palette3))} @@ -951,7 +982,7 @@ ${byte2byte(odd(frame.palette3))} .align 1024 displaylist: - ; 40 lines overscan + ; 24 lines overscan .repeat 4 .byte $70 ; 8 blank lines .endrep diff --git a/dither4.s b/dither4.s index 6513a16..64a570d 100644 --- a/dither4.s +++ b/dither4.s @@ -34,6 +34,7 @@ bytes_per_line = 40 pages_per_frame = 32 lines_per_frame = 262 ;scanline_offset = 31 + (40 - 24) / 2 +;scanline_offset = 46 scanline_offset = 46 scanline_max = (lines_per_frame - scanline_offset) / 2 diff --git a/video-doom/extract.sh b/video-doom/extract.sh index e3b4107..b34bcea 100644 --- a/video-doom/extract.sh +++ b/video-doom/extract.sh @@ -2,7 +2,7 @@ set -a mkdir -p frames -TIME=37 +TIME=37.5 ffmpeg \ -i 'doom-speedrun.webm' \ From b0e7d1f5790be02c2dc6240e4cf662c6484735a7 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Sat, 25 Mar 2023 20:15:34 -0700 Subject: [PATCH 4/7] wip mostly fixed --- dither-image.js | 79 +++++++++++++++++++++++++++++++++++-------------- dither4.s | 3 +- 2 files changed, 57 insertions(+), 25 deletions(-) diff --git a/dither-image.js b/dither-image.js index 2690485..f7be3d4 100644 --- a/dither-image.js +++ b/dither-image.js @@ -5,14 +5,18 @@ import { import Jimp from 'Jimp'; -function zeroes(n) { +function repeat(val, n) { let arr = []; for (let i = 0; i < n; i++) { - arr.push(0); + arr.push(val); } return arr; } +function zeroes(n) { + return repeat(0, n); +} + function toLinear(val) { // use a 2.4 gamma approximation // this is BT.1886 compatible @@ -584,6 +588,10 @@ function decimate(input, palette, n) { // preface the reserved bits let buckets = reserved.slice().map((c) => [atariRGB[c]]).concat([input.slice()]); + if (input.length != 160) { + console.log(input.length); + throw new Error('xxx bad input size'); + } /* let buckets = [input.slice()]; @@ -633,6 +641,10 @@ function decimate(input, palette, n) { while (buckets.length < n) { // Find the bucket with the greatest range in any channel let ranges = buckets.map((bucket) => { + if (bucket.length == 0) { + console.log(buckets); + throw new Error('xxx empty bucket'); + } let red = bucket.map((rgb) => rgb.r); let green = bucket.map((rgb) => rgb.g); let blue = bucket.map((rgb) => rgb.b); @@ -648,16 +660,17 @@ function decimate(input, palette, n) { let greatest = 0; let index = -1; for (let i = 0; i < topRanges.length; i++) { - if (topRanges[i] >= greatest) { + //if (topRanges[i] >= greatest) { + if (topRanges[i] > greatest) { greatest = topRanges[i]; index = i; } } if (index == -1) { // We just ran out of colors! Pad the buckets. - while (buckets.length < n) { - buckets.push([new RGB(0, 0, 0)]); - } + //while (buckets.length < n) { + // buckets.push([new RGB(0, 0, 0)]); + //} break; } let [lo, hi] = medianCut(buckets[index], ranges[index]); @@ -775,19 +788,25 @@ async function loadImage(src) { let width = image.bitmap.width; let height = image.bitmap.height; - //if (width != 160 || height != 160) { - if (width != 160) { + + let aspect = width / height; + let dar = 2 / 1.2; + if (aspect > ((320 / 1.2) / 192)) { + // wide width = 160; - //height = 160; - //height = 192; - let dar = 1.2 / 2; - height = (width * image.bitmap.width / image.bitmap.height) * dar; - height = Math.round(height); + height = Math.round((width * image.bitmap.height / image.bitmap.width) * dar); if (height & 1) { height++; } - image = image.resize(width, height); + } else { + // tall + height = 192; + width = Math.round((height * image.bitmap.width / image.bitmap.height) / dar); + if (width & 1) { + width++; + } } + image = image.resize(width, height); let rgba = image.bitmap.data.slice(); return { @@ -823,17 +842,15 @@ async function convert(source) { height, rgba } = await loadImage(source); + console.log({width,height}); - if (width !== 160) { - throw new Error(`expected 160px-compatible width, got ${width} pixels`); + if (width > 160) { + throw new Error(`expected <160px width, got ${width} pixels`); } - /* - if (height !== 160) { - // @fixme support up to 240px - throw new Error(`expected 160px height, got ${height} pixels`); + if (height > 192) { + throw new Error(`expected <192px height, got ${height} pixels`); } - */ if (rgba.length != width * 4 * height) { console.log(` @@ -860,10 +877,26 @@ async function convert(source) { allColors.push(i); } + let left = [], right = []; + let padding = 0; + if (width < 160) { + padding = 160 - width; + + let black = new RGB(0, 0, 0); + left = repeat(black, padding >> 1); + right = repeat(black, padding + 1 >> 1); + } + let lines = []; for (let y = 0; y < height; y++) { let inputLine = input .slice(y * width, (y + 1) * width); + + if (padding) { + console.log(`length was ${inputLine.length}`); + inputLine = left.concat(inputLine, right); + console.log(`length is now ${inputLine.length}`); + } if (y > 0) { let error = lines[y - 1].error; inputLine = inputLine.map((rgb, x) => rgb.add(error[x]).clamp()); @@ -872,7 +905,7 @@ async function convert(source) { lines.push(line); } return { - width, + width: width + padding, height, lines }; @@ -983,7 +1016,7 @@ ${byte2byte(odd(frame.palette3))} .align 1024 displaylist: ; 24 lines overscan - .repeat 4 + .repeat 3 .byte $70 ; 8 blank lines .endrep ; include a DLI to mark us as frame 0 diff --git a/dither4.s b/dither4.s index 64a570d..b985633 100644 --- a/dither4.s +++ b/dither4.s @@ -34,8 +34,7 @@ bytes_per_line = 40 pages_per_frame = 32 lines_per_frame = 262 ;scanline_offset = 31 + (40 - 24) / 2 -;scanline_offset = 46 -scanline_offset = 46 +scanline_offset = 38 scanline_max = (lines_per_frame - scanline_offset) / 2 .data From 7fa606743f580bce8771ed93cf85f9e0d661a386 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Sat, 25 Mar 2023 20:19:27 -0700 Subject: [PATCH 5/7] tweak --- dither-image.js | 2 +- dither4.s | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dither-image.js b/dither-image.js index f7be3d4..07a66da 100644 --- a/dither-image.js +++ b/dither-image.js @@ -1016,7 +1016,7 @@ ${byte2byte(odd(frame.palette3))} .align 1024 displaylist: ; 24 lines overscan - .repeat 3 + .repeat 2 .byte $70 ; 8 blank lines .endrep ; include a DLI to mark us as frame 0 diff --git a/dither4.s b/dither4.s index b985633..fd4c0ec 100644 --- a/dither4.s +++ b/dither4.s @@ -34,7 +34,7 @@ bytes_per_line = 40 pages_per_frame = 32 lines_per_frame = 262 ;scanline_offset = 31 + (40 - 24) / 2 -scanline_offset = 38 +scanline_offset = 30 scanline_max = (lines_per_frame - scanline_offset) / 2 .data From 5196adef43981fb47bce7d248c4b35927e0e9d34 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Sat, 25 Mar 2023 20:26:45 -0700 Subject: [PATCH 6/7] tweak --- dither-image.js | 12 ------------ video-cat/combine.sh | 2 +- video-cat/extract.sh | 2 +- video-doom/combine.sh | 2 +- video-doom/extract.sh | 2 +- video/combine.sh | 2 +- video/extract.sh | 2 +- 7 files changed, 6 insertions(+), 18 deletions(-) diff --git a/dither-image.js b/dither-image.js index 07a66da..93fddd9 100644 --- a/dither-image.js +++ b/dither-image.js @@ -589,7 +589,6 @@ function decimate(input, palette, n) { // preface the reserved bits let buckets = reserved.slice().map((c) => [atariRGB[c]]).concat([input.slice()]); if (input.length != 160) { - console.log(input.length); throw new Error('xxx bad input size'); } @@ -615,7 +614,6 @@ function decimate(input, palette, n) { }; let medianCut = (bucket, range) => { if (bucket.length < 2) { - console.log(bucket); throw new Error('short bucket'); } //console.log('medianCut', bucket, range); @@ -642,7 +640,6 @@ function decimate(input, palette, n) { // Find the bucket with the greatest range in any channel let ranges = buckets.map((bucket) => { if (bucket.length == 0) { - console.log(buckets); throw new Error('xxx empty bucket'); } let red = bucket.map((rgb) => rgb.r); @@ -766,13 +763,7 @@ function decimate(input, palette, n) { let index = dists.indexOf(closest); return palette[index]; }); - // hack decimated.sort((a, b) => a - b); - console.log(decimated); - - // we shouldn't have to do this - //decimated[0] = 0; - console.log(decimated); // Palette fits return dither(decimated); @@ -842,7 +833,6 @@ async function convert(source) { height, rgba } = await loadImage(source); - console.log({width,height}); if (width > 160) { throw new Error(`expected <160px width, got ${width} pixels`); @@ -893,9 +883,7 @@ async function convert(source) { .slice(y * width, (y + 1) * width); if (padding) { - console.log(`length was ${inputLine.length}`); inputLine = left.concat(inputLine, right); - console.log(`length is now ${inputLine.length}`); } if (y > 0) { let error = lines[y - 1].error; diff --git a/video-cat/combine.sh b/video-cat/combine.sh index e41f542..b3e81fb 100644 --- a/video-cat/combine.sh +++ b/video-cat/combine.sh @@ -4,7 +4,7 @@ ffmpeg \ -i 'cats-audio.wav' \ -ac 2 \ -ar 48000 \ - -vf 'pad=w=640:h=360:x=52:y=20' \ + -vf 'pad=w=534' \ -pix_fmt yuv420p \ -movflags +faststart \ -y cats-dither.mp4 diff --git a/video-cat/extract.sh b/video-cat/extract.sh index 9c15aa4..8675eb7 100644 --- a/video-cat/extract.sh +++ b/video-cat/extract.sh @@ -4,7 +4,7 @@ mkdir -p frames ffmpeg \ -i 'cats computer fun.mp4' \ - -vf 'scale=160:150,pad=h=160:y=5' \ + -vf 'scale=320:150,pad=h=192:y=5' \ -an \ -y 'frames/cats-%04d.png' diff --git a/video-doom/combine.sh b/video-doom/combine.sh index 9e6b03f..45e2f68 100644 --- a/video-doom/combine.sh +++ b/video-doom/combine.sh @@ -4,7 +4,7 @@ ffmpeg \ -i 'doom-audio.wav' \ -ac 2 \ -ar 48000 \ - -vf 'pad=w=640:h=360:x=52:y=20' \ + -vf 'pad=w=534' \ -pix_fmt yuv420p \ -movflags +faststart \ -y doom-dither.mp4 diff --git a/video-doom/extract.sh b/video-doom/extract.sh index b34bcea..a92ff17 100644 --- a/video-doom/extract.sh +++ b/video-doom/extract.sh @@ -8,7 +8,7 @@ ffmpeg \ -i 'doom-speedrun.webm' \ -t $TIME \ -r 60000/1001 \ - -vf 'scale=160:192' \ + -vf 'scale=320:192' \ -an \ -y 'frames/doom-%04d.png' diff --git a/video/combine.sh b/video/combine.sh index 02c75ea..38ba115 100644 --- a/video/combine.sh +++ b/video/combine.sh @@ -4,7 +4,7 @@ ffmpeg \ -i 'colamath-audio.wav' \ -ac 2 \ -ar 48000 \ - -vf 'pad=w=640:h=360:x=52:y=20' \ + -vf 'pad=w=534' \ -pix_fmt yuv420p \ -movflags +faststart \ -y colamath-dither.mp4 diff --git a/video/extract.sh b/video/extract.sh index e626e3c..4f8070a 100644 --- a/video/extract.sh +++ b/video/extract.sh @@ -4,7 +4,7 @@ mkdir -p frames ffmpeg \ -i colamath-dv.avi \ - -vf 'yadif=1,scale=160:200,crop=h=160' \ + -vf 'yadif=1,scale=320:200,crop=h=192:y=4' \ -an \ -y 'frames/colamath-%04d.png' From a4196851217ead3f94e0c1ef00142a51b2ebbf3d Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Sat, 25 Mar 2023 21:36:14 -0700 Subject: [PATCH 7/7] nice --- video-bulk/atarifiy.sh | 62 ++++++++++++++++++++++++++++++++++++++++++ video-cat/extract.sh | 2 +- video-doom/extract.sh | 2 +- video/extract.sh | 2 +- 4 files changed, 65 insertions(+), 3 deletions(-) create mode 100644 video-bulk/atarifiy.sh diff --git a/video-bulk/atarifiy.sh b/video-bulk/atarifiy.sh new file mode 100644 index 0000000..95b8300 --- /dev/null +++ b/video-bulk/atarifiy.sh @@ -0,0 +1,62 @@ +set -e + +INFILE="$1" +# additional params can be input to the extraction +# for time or seek +shift + +mkdir -p temp + +ffmpeg \ + -i "$INFILE" \ + -r 60000/1001 \ + -vf 'scale=256:-2' \ + -an \ + "$@" \ + -y "temp/$INFILE-%04d.png" + +ffmpeg \ + -i "$INFILE" \ + -vn \ + -ac 1 \ + -ar 15734 \ + -acodec pcm_u8 \ + "$@" \ + -y "temp/$INFILE-audio.wav" || echo no audio + +for frame in "temp/$INFILE-"[0-9][0-9][0-9][0-9].png +do + n="${frame#temp/$INFILE-}" + n="${n%.png}" + out="temp/$INFILE-dither-${n}" + last="${n:0-1}" + node ../dither-image.js "$frame" "$out" & + if (( last == 9 )) + then + echo "frame $n" + wait + fi +done +wait + +if [ -f "temp/$INFILE-audio.wav" ] +then + ffmpeg \ + -r 60000/1001 \ + -i "temp/$INFILE-dither-%04d.png" \ + -i "temp/$INFILE-audio.wav" \ + -ac 2 \ + -ar 48000 \ + -vf 'pad=w=534' \ + -pix_fmt yuv420p \ + -movflags +faststart \ + -y "$INFILE-dither.mp4" +else + ffmpeg \ + -r 60000/1001 \ + -i "temp/$INFILE-dither-%04d.png" \ + -vf 'pad=w=534' \ + -pix_fmt yuv420p \ + -movflags +faststart \ + -y "$INFILE-dither.mp4" +fi diff --git a/video-cat/extract.sh b/video-cat/extract.sh index 8675eb7..b4faa3c 100644 --- a/video-cat/extract.sh +++ b/video-cat/extract.sh @@ -4,7 +4,7 @@ mkdir -p frames ffmpeg \ -i 'cats computer fun.mp4' \ - -vf 'scale=320:150,pad=h=192:y=5' \ + -vf 'scale=256:144' \ -an \ -y 'frames/cats-%04d.png' diff --git a/video-doom/extract.sh b/video-doom/extract.sh index a92ff17..87d2972 100644 --- a/video-doom/extract.sh +++ b/video-doom/extract.sh @@ -8,7 +8,7 @@ ffmpeg \ -i 'doom-speedrun.webm' \ -t $TIME \ -r 60000/1001 \ - -vf 'scale=320:192' \ + -vf 'scale=256:192' \ -an \ -y 'frames/doom-%04d.png' diff --git a/video/extract.sh b/video/extract.sh index 4f8070a..237613c 100644 --- a/video/extract.sh +++ b/video/extract.sh @@ -4,7 +4,7 @@ mkdir -p frames ffmpeg \ -i colamath-dv.avi \ - -vf 'yadif=1,scale=320:200,crop=h=192:y=4' \ + -vf 'yadif=1,scale=256:192' \ -an \ -y 'frames/colamath-%04d.png'