Visual-chatgpt: Official Repo for The Paper

Visual ChatGPT

Visual ChatGPT connects ChatGPT and a series of Visual Foundation Models to enable sending and receiving images during chatting.

See our paper: Visual ChatGPT: Talking, Drawing and Editing with Visual Foundation Models

Demo

demo_short.gif

System Architecture

Logo

Quick Start

# create a new environment
conda create -n visgpt python=3.8

# activate the new environment
conda activate visgpt

#  prepare the basic environments
pip install -r requirement.txt

# download the visual foundation models
bash download.sh

# prepare your private openAI private key
export OPENAI_API_KEY={Your_Private_Openai_Key}

# create a folder to save images
mkdir ./image

# Start Visual ChatGPT !
python visual_chatgpt.py

GPU memory usage

Here we list the GPU memory usage of each visual foundation model, one can modify self.tools with fewer visual foundation models to save your GPU memory:

Foundation ModelMemory Usage (MB)
ImageEditing6667
ImageCaption1755
T2I6677
canny2image5540
line2image6679
hed2image6679
scribble2image6679
pose2image6681
BLIPVQA2709
seg2image5540
depth2image6677
normal2image3974
InstructPix2Pix2795

Acknowledgement

We appreciate the open source of the following projects:

Hugging FaceLangChainStable DiffusionControlNetInstructPix2PixCLIPSegBLIP 


Download Details:

Author: Microsoft
Source Code: https://github.com/microsoft/visual-chatgpt 
License: MIT license

#chatgpt #python #drawing #editing 

Visual-chatgpt: Official Repo for The Paper
Hunter  Krajcik

Hunter Krajcik

1672440120

Atomic-chrome: Edit Chrome Textareas in Atom

Atomic Chrome

Use Atom to edit in Chrome

atom-icon plus-icon chrome-icon

Screencast

Github issue (textarea)

github

Gmail (contenteditable)

gmail

Installation

You need to install

Usage

Atom needs to be running for this to work.

  1. Focus a textarea or a contenteditable element
  2. Press the icon of Atomic Chrome (or the shortcut).

Note that the tab will open in the first launched instance of Atom.

How do I bind a shortcut

  1. Navigate to chrome://extensions
  2. Scroll to the bottom of the page
  3. Press 'Keyboard shortcuts'
  4. Set a shortcut for Atomic Chrome

Development

This repository is for the Chrome plugin development. For the Atom package development, see https://github.com/tuvistavie/atomic-chrome-atom. Contributions are welcome.

Download Details:

Author: Danhper
Source Code: https://github.com/danhper/atomic-chrome 
License: MIT license

#atom #chrome #editing 

Atomic-chrome: Edit Chrome Textareas in Atom
Nat  Grady

Nat Grady

1671791177

Best 9 Ideas How to Get Free Music for Video Editing

9 ideas how to get free music for video editing intro

There are way too many videos online and almost all got music in them. Whether it is a nice chill lo-fi tune roaming in the background or a dubstep beat to introduce a section, music is everywhere. This shouldn’t surprise us, after all, one major part of video creation is being attractive. Music helps us at that since it naturally raises attention and might induce certain moods.

In today’s article, we will tell you about 9 sites where you can find free music to add to your videos. We will go through big names as well as perhaps some hidden gems.

Let’s start.

YouTube Audio Library

Many people when thinking of YouTube consider only videos made by content creators. But you’ll be glad to know that YouTube counts with a free audio library available for all users with an account. Do not worry, you can use them legally, either under Creative Commons law or not. Only some need to be named in your description before using.

This process is called “attribution”. Before telling you about its offer, note that we are referring to Youtube’s official library, and not a channel with a similar name. To access the official one, you got to enter into YouTube Studio and go to the last section on the left. You’ll find about 1.3k music tracks and 445 sound effects. You can filter the music based on title, genre, mood, and whether Attribution is required.

In total, there are 14 genres, and 10 moods to choose from. Lastly, it is noteworthy that there is no “trending” category or filter. This may be an important omission since not everyone would like to use the same exact tracks.

Amazon Music

Amazon does also offer free music, and some tracks may be totally royalty-free. But, finding them is going to be a bit more complicated. Our recommendation is to search using the traditional portal (not Amazon Music). Select “digital music” on the top search bar, on the right choose “price low to high” and you’re almost there.

Then you’ll see a lot of tracks, some require paid plans to be used, while others are free but may not be allowed to be distributed. You also Then you’ll see a lot of tracks. As we said, o use some of them you may need to pay. And though, you also count with royalty-free ones. We encourage you to read reviews, do some research, and experimenting. This especially applies if you’re using YouTube since the algorithm may give you some trouble.

In total there are 372 options, of which the type of free content we are looking for is unknown and rather small. Besides lacking “trending” category inclusion, there is no filter for mood or genre.

CCMixter

This community-based site offers thousands of original tracks that can be used in your videos without a problem. It works entirely under Creative Commons law and you only need to attribute (i.e., give credit). Some tracks have licenses that do not allow commercial u, while others are completely royalty-free. Overall, you’ll get tons of free content to use, and each track count with clear licensing specifications.

There are 3 main categories to find music for your projects, and you count with many subcategories. You can filter tracks based on the type of license, use tags search to find genres and moods. Plus, it counts with the highest-rated, editor picks, hot tracks, etc.

If you go through them for a while, you may think that there is no way there are thousands of tracks. But note that many of them are remixes, so you will not see them unless you click on a track and then go to the bottom.

Free Music Archive

One of the biggest libraries available with a very detailed explanation of CC law. Some require attribution and others are purely open for the public. You can filter them based on intended usage and CC license, among others.

In our search, we selected the filter for using tracks in videos for commercial purposes and we found 13726 tracks. There were 15 genres, as well filters for the duration and a scoring system.

The site is honestly fascinating and a really good option.

Bensound

Bensound offers a list of over 400 royalty-free tracks that work with attributions.

It counts with 8 genres and an option to sort them based on popularity, duration, and date of creation. There are also tags that you can use to navigate more specifically between options.

The permission that you get from free will be enough for YouTube content creators, even for commercial purposes. But if you’re intended to use them on another platform, we encourage you to check its FAQ first.

SoundCloud

While SoundCloud does not have official royalty-free music or library, you can still find a lot of tracks to use. Like on YouTube some users post their content online for others to use freely. You can find them with the “royalty-free” “no copyright” and other similar names.

The diversity of genres, moods, vibes, and others is very big. And for this reason, we encourage people to browse through playlists better since they tend to be well organized.

Though searching for tracks on this site is different, it is still a very good option.

Freeplay Music

Freeplay Music counts with over 50k tracks, over 12 scenes, genres, Moods, and 10 playlists. Besides, it includes a top track section, waveform, and tempo.

Though this site is very complete, there is one major caveat. Free use is restricted, in the case of YouTube, for noncommercial purposes only. If you want to monetize the video that you’re using this track on, you either got to pay this site for a license or not monetize the video.

Incompetech

Incompetech is a platform that, in the case of YouTube upload, lets you use tracks, even for commercial use, by only crediting the author.

The traditional site counts with over 600 royalty-free tracks, 23 genres, 20 feels, tempo counter, etc.

Its updated version: “Incompetech.filmmusic.io” has more to offer. It counts with keyword searcher, a new topic section, and new/different mood and genres. All these previous sections with at least 20 options (for example 20 genres). And it more than doubles the initial offer, now boasting over 1300 tracks.

Chosic

This site functions like Incompetech and others that we’ve mentioned. It lets use tracks for commercial purposes under CC law with or without attribution. Plus, it counts with great and clear licensing indication.

On the site, there are over 1100 songs with over 20 categories and moods, and 13 topics. Besides, you can see the waveform and sort by recommended, new, popular, or random.

Bonus: Epidemic Sound - Paid but Awesome

Though you got to pay a fee to access its great library of tracks, it has many special characteristics worth considering. Most importantly may be its superior offer.

It has a list of over 32000 tracks and over 60000 sound effects. The list also includes stems (individual instruments separated) and is constantly updated. Regarding moods and genres, there are over 20 moods and genres to choose from in each main category.

Access to the library and use permissions starts from 13 €/month or 15 USD /month.

Conclusion of How to Get Free Music for Video Editing

As you can tell, the offer is really broad, from curated platforms to community-based sites. Since most of these options are fine, we underline again the issue with Amazon Music and the usage restriction by Freeplay Music. And if we were to mention a top 3, FMA, CC Mixter and Incompetech would be in there.

Thanks for reading this article, we expect it has been very helpful.

Original article source at: https://www.blog.duomly.com/

#video #editing #music 

Best 9 Ideas How to Get Free Music for Video Editing
Lawrence  Lesch

Lawrence Lesch

1668094080

PDF-lib: Create and Modify PDF Documents in any JavaScript Environment

PDF-lib

Create and modify PDF documents in any JavaScript environment.

Designed to work in any modern JavaScript runtime. Tested in Node, Browser, Deno, and React Native environments.

Learn more at pdf-lib.js.org

Features

  • Create new PDFs
  • Modify existing PDFs
  • Create forms
  • Fill forms
  • Flatten forms
  • Add Pages
  • Insert Pages
  • Remove Pages
  • Copy pages between PDFs
  • Draw Text
  • Draw Images
  • Draw PDF Pages
  • Draw Vector Graphics
  • Draw SVG Paths
  • Measure width and height of text
  • Embed Fonts (supports UTF-8 and UTF-16 character sets)
  • Set document metadata
  • Read document metadata
  • Set viewer preferences
  • Read viewer preferences
  • Add attachments

Motivation

pdf-lib was created to address the JavaScript ecosystem's lack of robust support for PDF manipulation (especially for PDF modification).

Two of pdf-lib's distinguishing features are:

  1. Supporting modification (editing) of existing documents.
  2. Working in all JavaScript environments - not just in Node or the Browser.

There are other good open source JavaScript PDF libraries available. However, most of them can only create documents, they cannot modify existing ones. And many of them only work in particular environments.

Usage Examples

Create Document

This example produces this PDF.

Try the JSFiddle demo

import { PDFDocument, StandardFonts, rgb } from 'pdf-lib'

// Create a new PDFDocument
const pdfDoc = await PDFDocument.create()

// Embed the Times Roman font
const timesRomanFont = await pdfDoc.embedFont(StandardFonts.TimesRoman)

// Add a blank page to the document
const page = pdfDoc.addPage()

// Get the width and height of the page
const { width, height } = page.getSize()

// Draw a string of text toward the top of the page
const fontSize = 30
page.drawText('Creating PDFs in JavaScript is awesome!', {
  x: 50,
  y: height - 4 * fontSize,
  size: fontSize,
  font: timesRomanFont,
  color: rgb(0, 0.53, 0.71),
})

// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc.save()

// For example, `pdfBytes` can be:
//   • Written to a file in Node
//   • Downloaded from the browser
//   • Rendered in an <iframe>

Modify Document

This example produces this PDF (when this PDF is used for the existingPdfBytes variable).

Try the JSFiddle demo

import { degrees, PDFDocument, rgb, StandardFonts } from 'pdf-lib';

// This should be a Uint8Array or ArrayBuffer
// This data can be obtained in a number of different ways
// If your running in a Node environment, you could use fs.readFile()
// In the browser, you could make a fetch() call and use res.arrayBuffer()
const existingPdfBytes = ...

// Load a PDFDocument from the existing PDF bytes
const pdfDoc = await PDFDocument.load(existingPdfBytes)

// Embed the Helvetica font
const helveticaFont = await pdfDoc.embedFont(StandardFonts.Helvetica)

// Get the first page of the document
const pages = pdfDoc.getPages()
const firstPage = pages[0]

// Get the width and height of the first page
const { width, height } = firstPage.getSize()

// Draw a string of text diagonally across the first page
firstPage.drawText('This text was added with JavaScript!', {
  x: 5,
  y: height / 2 + 300,
  size: 50,
  font: helveticaFont,
  color: rgb(0.95, 0.1, 0.1),
  rotate: degrees(-45),
})


// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc.save()

// For example, `pdfBytes` can be:
//   • Written to a file in Node
//   • Downloaded from the browser
//   • Rendered in an <iframe>

Create Form

This example produces this PDF.

Try the JSFiddle demo

See also Creating and Filling Forms

import { PDFDocument } from 'pdf-lib'

// Create a new PDFDocument
const pdfDoc = await PDFDocument.create()

// Add a blank page to the document
const page = pdfDoc.addPage([550, 750])

// Get the form so we can add fields to it
const form = pdfDoc.getForm()

// Add the superhero text field and description
page.drawText('Enter your favorite superhero:', { x: 50, y: 700, size: 20 })

const superheroField = form.createTextField('favorite.superhero')
superheroField.setText('One Punch Man')
superheroField.addToPage(page, { x: 55, y: 640 })

// Add the rocket radio group, labels, and description
page.drawText('Select your favorite rocket:', { x: 50, y: 600, size: 20 })

page.drawText('Falcon Heavy', { x: 120, y: 560, size: 18 })
page.drawText('Saturn IV', { x: 120, y: 500, size: 18 })
page.drawText('Delta IV Heavy', { x: 340, y: 560, size: 18 })
page.drawText('Space Launch System', { x: 340, y: 500, size: 18 })

const rocketField = form.createRadioGroup('favorite.rocket')
rocketField.addOptionToPage('Falcon Heavy', page, { x: 55, y: 540 })
rocketField.addOptionToPage('Saturn IV', page, { x: 55, y: 480 })
rocketField.addOptionToPage('Delta IV Heavy', page, { x: 275, y: 540 })
rocketField.addOptionToPage('Space Launch System', page, { x: 275, y: 480 })
rocketField.select('Saturn IV')

// Add the gundam check boxes, labels, and description
page.drawText('Select your favorite gundams:', { x: 50, y: 440, size: 20 })

page.drawText('Exia', { x: 120, y: 400, size: 18 })
page.drawText('Kyrios', { x: 120, y: 340, size: 18 })
page.drawText('Virtue', { x: 340, y: 400, size: 18 })
page.drawText('Dynames', { x: 340, y: 340, size: 18 })

const exiaField = form.createCheckBox('gundam.exia')
const kyriosField = form.createCheckBox('gundam.kyrios')
const virtueField = form.createCheckBox('gundam.virtue')
const dynamesField = form.createCheckBox('gundam.dynames')

exiaField.addToPage(page, { x: 55, y: 380 })
kyriosField.addToPage(page, { x: 55, y: 320 })
virtueField.addToPage(page, { x: 275, y: 380 })
dynamesField.addToPage(page, { x: 275, y: 320 })

exiaField.check()
dynamesField.check()

// Add the planet dropdown and description
page.drawText('Select your favorite planet*:', { x: 50, y: 280, size: 20 })

const planetsField = form.createDropdown('favorite.planet')
planetsField.addOptions(['Venus', 'Earth', 'Mars', 'Pluto'])
planetsField.select('Pluto')
planetsField.addToPage(page, { x: 55, y: 220 })

// Add the person option list and description
page.drawText('Select your favorite person:', { x: 50, y: 180, size: 18 })

const personField = form.createOptionList('favorite.person')
personField.addOptions([
  'Julius Caesar',
  'Ada Lovelace',
  'Cleopatra',
  'Aaron Burr',
  'Mark Antony',
])
personField.select('Ada Lovelace')
personField.addToPage(page, { x: 55, y: 70 })

// Just saying...
page.drawText(`* Pluto should be a planet too!`, { x: 15, y: 15, size: 15 })

// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc.save()

// For example, `pdfBytes` can be:
//   • Written to a file in Node
//   • Downloaded from the browser
//   • Rendered in an <iframe>

Fill Form

This example produces this PDF (when this PDF is used for the formPdfBytes variable, this image is used for the marioImageBytes variable, and this image is used for the emblemImageBytes variable).

Try the JSFiddle demo

See also Creating and Filling Forms

import { PDFDocument } from 'pdf-lib'

// These should be Uint8Arrays or ArrayBuffers
// This data can be obtained in a number of different ways
// If your running in a Node environment, you could use fs.readFile()
// In the browser, you could make a fetch() call and use res.arrayBuffer()
const formPdfBytes = ...
const marioImageBytes = ...
const emblemImageBytes = ...

// Load a PDF with form fields
const pdfDoc = await PDFDocument.load(formPdfBytes)

// Embed the Mario and emblem images
const marioImage = await pdfDoc.embedPng(marioImageBytes)
const emblemImage = await pdfDoc.embedPng(emblemImageBytes)

// Get the form containing all the fields
const form = pdfDoc.getForm()

// Get all fields in the PDF by their names
const nameField = form.getTextField('CharacterName 2')
const ageField = form.getTextField('Age')
const heightField = form.getTextField('Height')
const weightField = form.getTextField('Weight')
const eyesField = form.getTextField('Eyes')
const skinField = form.getTextField('Skin')
const hairField = form.getTextField('Hair')

const alliesField = form.getTextField('Allies')
const factionField = form.getTextField('FactionName')
const backstoryField = form.getTextField('Backstory')
const traitsField = form.getTextField('Feat+Traits')
const treasureField = form.getTextField('Treasure')

const characterImageField = form.getButton('CHARACTER IMAGE')
const factionImageField = form.getTextField('Faction Symbol Image')

// Fill in the basic info fields
nameField.setText('Mario')
ageField.setText('24 years')
heightField.setText(`5' 1"`)
weightField.setText('196 lbs')
eyesField.setText('blue')
skinField.setText('white')
hairField.setText('brown')

// Fill the character image field with our Mario image
characterImageField.setImage(marioImage)

// Fill in the allies field
alliesField.setText(
  [
    `Allies:`,
    `  • Princess Daisy`,
    `  • Princess Peach`,
    `  • Rosalina`,
    `  • Geno`,
    `  • Luigi`,
    `  • Donkey Kong`,
    `  • Yoshi`,
    `  • Diddy Kong`,
    ``,
    `Organizations:`,
    `  • Italian Plumbers Association`,
  ].join('\n'),
)

// Fill in the faction name field
factionField.setText(`Mario's Emblem`)

// Fill the faction image field with our emblem image
factionImageField.setImage(emblemImage)

// Fill in the backstory field
backstoryField.setText(
  `Mario is a fictional character in the Mario video game franchise, owned by Nintendo and created by Japanese video game designer Shigeru Miyamoto. Serving as the company's mascot and the eponymous protagonist of the series, Mario has appeared in over 200 video games since his creation. Depicted as a short, pudgy, Italian plumber who resides in the Mushroom Kingdom, his adventures generally center upon rescuing Princess Peach from the Koopa villain Bowser. His younger brother and sidekick is Luigi.`,
)

// Fill in the traits field
traitsField.setText(
  [
    `Mario can use three basic three power-ups:`,
    `  • the Super Mushroom, which causes Mario to grow larger`,
    `  • the Fire Flower, which allows Mario to throw fireballs`,
    `  • the Starman, which gives Mario temporary invincibility`,
  ].join('\n'),
)

// Fill in the treasure field
treasureField.setText(['• Gold coins', '• Treasure chests'].join('\n'))

// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc.save()

// For example, `pdfBytes` can be:
//   • Written to a file in Node
//   • Downloaded from the browser
//   • Rendered in an <iframe>

Flatten Form

This example produces this PDF (when this PDF is used for the formPdfBytes variable).

Try the JSFiddle demo

import { PDFDocument } from 'pdf-lib'

// This should be a Uint8Array or ArrayBuffer
// This data can be obtained in a number of different ways
// If your running in a Node environment, you could use fs.readFile()
// In the browser, you could make a fetch() call and use res.arrayBuffer()
const formPdfBytes = ...

// Load a PDF with form fields
const pdfDoc = await PDFDocument.load(formPdfBytes)

// Get the form containing all the fields
const form = pdfDoc.getForm()

// Fill the form's fields
form.getTextField('Text1').setText('Some Text');

form.getRadioGroup('Group2').select('Choice1');
form.getRadioGroup('Group3').select('Choice3');
form.getRadioGroup('Group4').select('Choice1');

form.getCheckBox('Check Box3').check();
form.getCheckBox('Check Box4').uncheck();

form.getDropdown('Dropdown7').select('Infinity');

form.getOptionList('List Box6').select('Honda');

// Flatten the form's fields
form.flatten();

// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc.save()

// For example, `pdfBytes` can be:
//   • Written to a file in Node
//   • Downloaded from the browser
//   • Rendered in an <iframe>

Copy Pages

This example produces this PDF (when this PDF is used for the firstDonorPdfBytes variable and this PDF is used for the secondDonorPdfBytes variable).

Try the JSFiddle demo

import { PDFDocument } from 'pdf-lib'

// Create a new PDFDocument
const pdfDoc = await PDFDocument.create()

// These should be Uint8Arrays or ArrayBuffers
// This data can be obtained in a number of different ways
// If your running in a Node environment, you could use fs.readFile()
// In the browser, you could make a fetch() call and use res.arrayBuffer()
const firstDonorPdfBytes = ...
const secondDonorPdfBytes = ...

// Load a PDFDocument from each of the existing PDFs
const firstDonorPdfDoc = await PDFDocument.load(firstDonorPdfBytes)
const secondDonorPdfDoc = await PDFDocument.load(secondDonorPdfBytes)

// Copy the 1st page from the first donor document, and
// the 743rd page from the second donor document
const [firstDonorPage] = await pdfDoc.copyPages(firstDonorPdfDoc, [0])
const [secondDonorPage] = await pdfDoc.copyPages(secondDonorPdfDoc, [742])

// Add the first copied page
pdfDoc.addPage(firstDonorPage)

// Insert the second copied page to index 0, so it will be the
// first page in `pdfDoc`
pdfDoc.insertPage(0, secondDonorPage)

// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc.save()

// For example, `pdfBytes` can be:
//   • Written to a file in Node
//   • Downloaded from the browser
//   • Rendered in an <iframe>

Embed PNG and JPEG Images

This example produces this PDF (when this image is used for the jpgImageBytes variable and this image is used for the pngImageBytes variable).

Try the JSFiddle demo

import { PDFDocument } from 'pdf-lib'

// These should be Uint8Arrays or ArrayBuffers
// This data can be obtained in a number of different ways
// If your running in a Node environment, you could use fs.readFile()
// In the browser, you could make a fetch() call and use res.arrayBuffer()
const jpgImageBytes = ...
const pngImageBytes = ...

// Create a new PDFDocument
const pdfDoc = await PDFDocument.create()

// Embed the JPG image bytes and PNG image bytes
const jpgImage = await pdfDoc.embedJpg(jpgImageBytes)
const pngImage = await pdfDoc.embedPng(pngImageBytes)

// Get the width/height of the JPG image scaled down to 25% of its original size
const jpgDims = jpgImage.scale(0.25)

// Get the width/height of the PNG image scaled down to 50% of its original size
const pngDims = pngImage.scale(0.5)

// Add a blank page to the document
const page = pdfDoc.addPage()

// Draw the JPG image in the center of the page
page.drawImage(jpgImage, {
  x: page.getWidth() / 2 - jpgDims.width / 2,
  y: page.getHeight() / 2 - jpgDims.height / 2,
  width: jpgDims.width,
  height: jpgDims.height,
})

// Draw the PNG image near the lower right corner of the JPG image
page.drawImage(pngImage, {
  x: page.getWidth() / 2 - pngDims.width / 2 + 75,
  y: page.getHeight() / 2 - pngDims.height,
  width: pngDims.width,
  height: pngDims.height,
})

// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc.save()

// For example, `pdfBytes` can be:
//   • Written to a file in Node
//   • Downloaded from the browser
//   • Rendered in an <iframe>

Embed PDF Pages

This example produces this PDF (when this PDF is used for the americanFlagPdfBytes variable and this PDF is used for the usConstitutionPdfBytes variable).

Try the JSFiddle demo

import { PDFDocument } from 'pdf-lib'

// These should be Uint8Arrays or ArrayBuffers
// This data can be obtained in a number of different ways
// If your running in a Node environment, you could use fs.readFile()
// In the browser, you could make a fetch() call and use res.arrayBuffer()
const americanFlagPdfBytes = ...
const usConstitutionPdfBytes = ...

// Create a new PDFDocument
const pdfDoc = await PDFDocument.create()

// Embed the American flag PDF bytes
const [americanFlag] = await pdfDoc.embedPdf(americanFlagPdfBytes)

// Load the U.S. constitution PDF bytes
const usConstitutionPdf = await PDFDocument.load(usConstitutionPdfBytes)

// Embed the second page of the constitution and clip the preamble
const preamble = await pdfDoc.embedPage(usConstitutionPdf.getPages()[1], {
  left: 55,
  bottom: 485,
  right: 300,
  top: 575,
})

// Get the width/height of the American flag PDF scaled down to 30% of
// its original size
const americanFlagDims = americanFlag.scale(0.3)

// Get the width/height of the preamble clipping scaled up to 225% of
// its original size
const preambleDims = preamble.scale(2.25)

// Add a blank page to the document
const page = pdfDoc.addPage()

// Draw the American flag image in the center top of the page
page.drawPage(americanFlag, {
  ...americanFlagDims,
  x: page.getWidth() / 2 - americanFlagDims.width / 2,
  y: page.getHeight() - americanFlagDims.height - 150,
})

// Draw the preamble clipping in the center bottom of the page
page.drawPage(preamble, {
  ...preambleDims,
  x: page.getWidth() / 2 - preambleDims.width / 2,
  y: page.getHeight() / 2 - preambleDims.height / 2 - 50,
})

// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc.save()

// For example, `pdfBytes` can be:
//   • Written to a file in Node
//   • Downloaded from the browser
//   • Rendered in an <iframe>

Embed Font and Measure Text

pdf-lib relies on a sister module to support embedding custom fonts: @pdf-lib/fontkit. You must add the @pdf-lib/fontkit module to your project and register it using pdfDoc.registerFontkit(...) before embedding custom fonts.

See below for detailed installation instructions on installing @pdf-lib/fontkit as a UMD or NPM module.

This example produces this PDF (when this font is used for the fontBytes variable).

Try the JSFiddle demo

import { PDFDocument, rgb } from 'pdf-lib'
import fontkit from '@pdf-lib/fontkit'

// This should be a Uint8Array or ArrayBuffer
// This data can be obtained in a number of different ways
// If you're running in a Node environment, you could use fs.readFile()
// In the browser, you could make a fetch() call and use res.arrayBuffer()
const fontBytes = ...

// Create a new PDFDocument
const pdfDoc = await PDFDocument.create()

// Register the `fontkit` instance
pdfDoc.registerFontkit(fontkit)

// Embed our custom font in the document
const customFont = await pdfDoc.embedFont(fontBytes)

// Add a blank page to the document
const page = pdfDoc.addPage()

// Create a string of text and measure its width and height in our custom font
const text = 'This is text in an embedded font!'
const textSize = 35
const textWidth = customFont.widthOfTextAtSize(text, textSize)
const textHeight = customFont.heightAtSize(textSize)

// Draw the string of text on the page
page.drawText(text, {
  x: 40,
  y: 450,
  size: textSize,
  font: customFont,
  color: rgb(0, 0.53, 0.71),
})

// Draw a box around the string of text
page.drawRectangle({
  x: 40,
  y: 450,
  width: textWidth,
  height: textHeight,
  borderColor: rgb(1, 0, 0),
  borderWidth: 1.5,
})

// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc.save()

// For example, `pdfBytes` can be:
//   • Written to a file in Node
//   • Downloaded from the browser
//   • Rendered in an <iframe>

Add Attachments

This example produces this PDF (when this image is used for the jpgAttachmentBytes variable and this PDF is used for the pdfAttachmentBytes variable).

Try the JSFiddle demo

import { PDFDocument } from 'pdf-lib'

// These should be Uint8Arrays or ArrayBuffers
// This data can be obtained in a number of different ways
// If your running in a Node environment, you could use fs.readFile()
// In the browser, you could make a fetch() call and use res.arrayBuffer()
const jpgAttachmentBytes = ...
const pdfAttachmentBytes = ...

// Create a new PDFDocument
const pdfDoc = await PDFDocument.create()

// Add the JPG attachment
await pdfDoc.attach(jpgAttachmentBytes, 'cat_riding_unicorn.jpg', {
  mimeType: 'image/jpeg',
  description: 'Cool cat riding a unicorn! 🦄🐈🕶️',
  creationDate: new Date('2019/12/01'),
  modificationDate: new Date('2020/04/19'),
})

// Add the PDF attachment
await pdfDoc.attach(pdfAttachmentBytes, 'us_constitution.pdf', {
  mimeType: 'application/pdf',
  description: 'Constitution of the United States 🇺🇸🦅',
  creationDate: new Date('1787/09/17'),
  modificationDate: new Date('1992/05/07'),
})

// Add a page with some text
const page = pdfDoc.addPage();
page.drawText('This PDF has two attachments', { x: 135, y: 415 })

// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc.save()

// For example, `pdfBytes` can be:
//   • Written to a file in Node
//   • Downloaded from the browser
//   • Rendered in an <iframe>

Set Document Metadata

This example produces this PDF.

Try the JSFiddle demo

import { PDFDocument, StandardFonts } from 'pdf-lib'

// Create a new PDFDocument
const pdfDoc = await PDFDocument.create()

// Embed the Times Roman font
const timesRomanFont = await pdfDoc.embedFont(StandardFonts.TimesRoman)

// Add a page and draw some text on it
const page = pdfDoc.addPage([500, 600])
page.setFont(timesRomanFont)
page.drawText('The Life of an Egg', { x: 60, y: 500, size: 50 })
page.drawText('An Epic Tale of Woe', { x: 125, y: 460, size: 25 })

// Set all available metadata fields on the PDFDocument. Note that these fields
// are visible in the "Document Properties" section of most PDF readers.
pdfDoc.setTitle('🥚 The Life of an Egg 🍳')
pdfDoc.setAuthor('Humpty Dumpty')
pdfDoc.setSubject('📘 An Epic Tale of Woe 📖')
pdfDoc.setKeywords(['eggs', 'wall', 'fall', 'king', 'horses', 'men'])
pdfDoc.setProducer('PDF App 9000 🤖')
pdfDoc.setCreator('pdf-lib (https://github.com/Hopding/pdf-lib)')
pdfDoc.setCreationDate(new Date('2018-06-24T01:58:37.228Z'))
pdfDoc.setModificationDate(new Date('2019-12-21T07:00:11.000Z'))

// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc.save()

// For example, `pdfBytes` can be:
//   • Written to a file in Node
//   • Downloaded from the browser
//   • Rendered in an <iframe>

Read Document Metadata

Try the JSFiddle demo

import { PDFDocument } from 'pdf-lib'

// This should be a Uint8Array or ArrayBuffer
// This data can be obtained in a number of different ways
// If your running in a Node environment, you could use fs.readFile()
// In the browser, you could make a fetch() call and use res.arrayBuffer()
const existingPdfBytes = ...

// Load a PDFDocument without updating its existing metadata
const pdfDoc = await PDFDocument.load(existingPdfBytes, {
  updateMetadata: false
})

// Print all available metadata fields
console.log('Title:', pdfDoc.getTitle())
console.log('Author:', pdfDoc.getAuthor())
console.log('Subject:', pdfDoc.getSubject())
console.log('Creator:', pdfDoc.getCreator())
console.log('Keywords:', pdfDoc.getKeywords())
console.log('Producer:', pdfDoc.getProducer())
console.log('Creation Date:', pdfDoc.getCreationDate())
console.log('Modification Date:', pdfDoc.getModificationDate())

This script outputs the following (when this PDF is used for the existingPdfBytes variable):

Title: Microsoft Word - Basic Curriculum Vitae example.doc
Author: Administrator
Subject: undefined
Creator: PScript5.dll Version 5.2
Keywords: undefined
Producer: Acrobat Distiller 8.1.0 (Windows)
Creation Date: 2010-07-29T14:26:00.000Z
Modification Date: 2010-07-29T14:26:00.000Z

Set Viewer Preferences

import {
  PDFDocument,
  StandardFonts,
  NonFullScreenPageMode,
  ReadingDirection,
  PrintScaling,
  Duplex,
  PDFName,
} from 'pdf-lib'

// Create a new PDFDocument
const pdfDoc = await PDFDocument.create()

// Embed the Times Roman font
const timesRomanFont = await pdfDoc.embedFont(StandardFonts.TimesRoman)

// Add a page and draw some text on it
const page = pdfDoc.addPage([500, 600])
page.setFont(timesRomanFont)
page.drawText('The Life of an Egg', { x: 60, y: 500, size: 50 })
page.drawText('An Epic Tale of Woe', { x: 125, y: 460, size: 25 })

// Set all available viewer preferences on the PDFDocument:
const viewerPrefs = pdfDoc.catalog.getOrCreateViewerPreferences()
viewerPrefs.setHideToolbar(true)
viewerPrefs.setHideMenubar(true)
viewerPrefs.setHideWindowUI(true)
viewerPrefs.setFitWindow(true)
viewerPrefs.setCenterWindow(true)
viewerPrefs.setDisplayDocTitle(true)

// Set the PageMode (otherwise setting NonFullScreenPageMode has no meaning)
pdfDoc.catalog.set(PDFName.of('PageMode'), PDFName.of('FullScreen'))

// Set what happens when fullScreen is closed
viewerPrefs.setNonFullScreenPageMode(NonFullScreenPageMode.UseOutlines)

viewerPrefs.setReadingDirection(ReadingDirection.L2R)
viewerPrefs.setPrintScaling(PrintScaling.None)
viewerPrefs.setDuplex(Duplex.DuplexFlipLongEdge)
viewerPrefs.setPickTrayByPDFSize(true)

// We can set the default print range to only the first page
viewerPrefs.setPrintPageRange({ start: 0, end: 0 })

// Or we can supply noncontiguous ranges (e.g. pages 1, 3, and 5-7)
viewerPrefs.setPrintPageRange([
  { start: 0, end: 0 },
  { start: 2, end: 2 },
  { start: 4, end: 6 },
])

viewerPrefs.setNumCopies(2)

// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc.save()

// For example, `pdfBytes` can be:
//   • Written to a file in Node
//   • Downloaded from the browser
//   • Rendered in an <iframe>

Read Viewer Preferences

import { PDFDocument } from 'pdf-lib'

// This should be a Uint8Array or ArrayBuffer
// This data can be obtained in a number of different ways
// If your running in a Node environment, you could use fs.readFile()
// In the browser, you could make a fetch() call and use res.arrayBuffer()
const existingPdfBytes = ...

// Load a PDFDocument without updating its existing metadata
const pdfDoc = await PDFDocument.load(existingPdfBytes)
const viewerPrefs = pdfDoc.catalog.getOrCreateViewerPreferences()

// Print all available viewer preference fields
console.log('HideToolbar:', viewerPrefs.getHideToolbar())
console.log('HideMenubar:', viewerPrefs.getHideMenubar())
console.log('HideWindowUI:', viewerPrefs.getHideWindowUI())
console.log('FitWindow:', viewerPrefs.getFitWindow())
console.log('CenterWindow:', viewerPrefs.getCenterWindow())
console.log('DisplayDocTitle:', viewerPrefs.getDisplayDocTitle())
console.log('NonFullScreenPageMode:', viewerPrefs.getNonFullScreenPageMode())
console.log('ReadingDirection:', viewerPrefs.getReadingDirection())
console.log('PrintScaling:', viewerPrefs.getPrintScaling())
console.log('Duplex:', viewerPrefs.getDuplex())
console.log('PickTrayByPDFSize:', viewerPrefs.getPickTrayByPDFSize())
console.log('PrintPageRange:', viewerPrefs.getPrintPageRange())
console.log('NumCopies:', viewerPrefs.getNumCopies())

This script outputs the following (when this PDF is used for the existingPdfBytes variable):

HideToolbar: true
HideMenubar: true
HideWindowUI: false
FitWindow: true
CenterWindow: true
DisplayDocTitle: true
NonFullScreenPageMode: UseNone
ReadingDirection: R2L
PrintScaling: None
Duplex: DuplexFlipLongEdge
PickTrayByPDFSize: true
PrintPageRange: [ { start: 1, end: 1 }, { start: 3, end: 4 } ]
NumCopies: 2

Draw SVG Paths

This example produces this PDF.

Try the JSFiddle demo

import { PDFDocument, rgb } from 'pdf-lib'

// SVG path for a wavy line
const svgPath =
  'M 0,20 L 100,160 Q 130,200 150,120 C 190,-40 200,200 300,150 L 400,90'

// Create a new PDFDocument
const pdfDoc = await PDFDocument.create()

// Add a blank page to the document
const page = pdfDoc.addPage()
page.moveTo(100, page.getHeight() - 5)

// Draw the SVG path as a black line
page.moveDown(25)
page.drawSvgPath(svgPath)

// Draw the SVG path as a thick green line
page.moveDown(200)
page.drawSvgPath(svgPath, { borderColor: rgb(0, 1, 0), borderWidth: 5 })

// Draw the SVG path and fill it with red
page.moveDown(200)
page.drawSvgPath(svgPath, { color: rgb(1, 0, 0) })

// Draw the SVG path at 50% of its original size
page.moveDown(200)
page.drawSvgPath(svgPath, { scale: 0.5 })

// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc.save()

// For example, `pdfBytes` can be:
//   • Written to a file in Node
//   • Downloaded from the browser
//   • Rendered in an <iframe>

Deno Usage

pdf-lib fully supports the exciting new Deno runtime! All of the usage examples work in Deno. The only thing you need to do is change the imports for pdf-lib and @pdf-lib/fontkit to use the Skypack CDN, because Deno requires all modules to be referenced via URLs.

See also How to Create and Modify PDF Files in Deno With pdf-lib

Creating a Document with Deno

Below is the create document example modified for Deno:

import {
  PDFDocument,
  StandardFonts,
  rgb,
} from 'https://cdn.skypack.dev/pdf-lib@^1.11.1?dts';

const pdfDoc = await PDFDocument.create();
const timesRomanFont = await pdfDoc.embedFont(StandardFonts.TimesRoman);

const page = pdfDoc.addPage();
const { width, height } = page.getSize();
const fontSize = 30;
page.drawText('Creating PDFs in JavaScript is awesome!', {
  x: 50,
  y: height - 4 * fontSize,
  size: fontSize,
  font: timesRomanFont,
  color: rgb(0, 0.53, 0.71),
});

const pdfBytes = await pdfDoc.save();

await Deno.writeFile('out.pdf', pdfBytes);

If you save this script as create-document.ts, you can execute it using Deno with the following command:

deno run --allow-write create-document.ts

The resulting out.pdf file will look like this PDF.

Embedding a Font with Deno

Here's a slightly more complicated example demonstrating how to embed a font and measure text in Deno:

import {
  degrees,
  PDFDocument,
  rgb,
  StandardFonts,
} from 'https://cdn.skypack.dev/pdf-lib@^1.11.1?dts';
import fontkit from 'https://cdn.skypack.dev/@pdf-lib/fontkit@^1.0.0?dts';

const url = 'https://pdf-lib.js.org/assets/ubuntu/Ubuntu-R.ttf';
const fontBytes = await fetch(url).then((res) => res.arrayBuffer());

const pdfDoc = await PDFDocument.create();

pdfDoc.registerFontkit(fontkit);
const customFont = await pdfDoc.embedFont(fontBytes);

const page = pdfDoc.addPage();

const text = 'This is text in an embedded font!';
const textSize = 35;
const textWidth = customFont.widthOfTextAtSize(text, textSize);
const textHeight = customFont.heightAtSize(textSize);

page.drawText(text, {
  x: 40,
  y: 450,
  size: textSize,
  font: customFont,
  color: rgb(0, 0.53, 0.71),
});
page.drawRectangle({
  x: 40,
  y: 450,
  width: textWidth,
  height: textHeight,
  borderColor: rgb(1, 0, 0),
  borderWidth: 1.5,
});

const pdfBytes = await pdfDoc.save();

await Deno.writeFile('out.pdf', pdfBytes);

If you save this script as custom-font.ts, you can execute it with the following command:

deno run --allow-write --allow-net custom-font.ts

The resulting out.pdf file will look like this PDF.

Complete Examples

The usage examples provide code that is brief and to the point, demonstrating the different features of pdf-lib. You can find complete working examples in the apps/ directory. These apps are used to do manual testing of pdf-lib before every release (in addition to the automated tests).

There are currently four apps:

  • node - contains tests for pdf-lib in Node environments. These tests are a handy reference when trying to save/load PDFs, fonts, or images with pdf-lib from the filesystem. They also allow you to quickly open your PDFs in different viewers (Acrobat, Preview, Foxit, Chrome, Firefox, etc...) to ensure compatibility.
  • web - contains tests for pdf-lib in browser environments. These tests are a handy reference when trying to save/load PDFs, fonts, or images with pdf-lib in a browser environment.
  • rn - contains tests for pdf-lib in React Native environments. These tests are a handy reference when trying to save/load PDFs, fonts, or images with pdf-lib in a React Native environment.
  • deno - contains tests for pdf-lib in Deno environments. These tests are a handy reference when trying to save/load PDFs, fonts, or images with pdf-lib from the filesystem.

Installation

NPM Module

To install the latest stable version:

# With npm
npm install --save pdf-lib

# With yarn
yarn add pdf-lib

This assumes you're using npm or yarn as your package manager.

UMD Module

You can also download pdf-lib as a UMD module from unpkg or jsDelivr. The UMD builds have been compiled to ES5, so they should work in any modern browser. UMD builds are useful if you aren't using a package manager or module bundler. For example, you can use them directly in the <script> tag of an HTML page.

The following builds are available:

NOTE: if you are using the CDN scripts in production, you should include a specific version number in the URL, for example:

When using a UMD build, you will have access to a global window.PDFLib variable. This variable contains all of the classes and functions exported by pdf-lib. For example:

// NPM module
import { PDFDocument, rgb } from 'pdf-lib';

// UMD module
var PDFDocument = PDFLib.PDFDocument;
var rgb = PDFLib.rgb;

Fontkit Installation

pdf-lib relies upon a sister module to support embedding custom fonts: @pdf-lib/fontkit. You must add the @pdf-lib/fontkit module to your project and register it using pdfDoc.registerFontkit(...) before embedding custom fonts (see the font embedding example). This module is not included by default because not all users need it, and it increases bundle size.

Installing this module is easy. Just like pdf-lib itself, @pdf-lib/fontkit can be installed with npm/yarn or as a UMD module.

Fontkit NPM Module

# With npm
npm install --save @pdf-lib/fontkit

# With yarn
yarn add @pdf-lib/fontkit

To register the fontkit instance:

import { PDFDocument } from 'pdf-lib'
import fontkit from '@pdf-lib/fontkit'

const pdfDoc = await PDFDocument.create()
pdfDoc.registerFontkit(fontkit)

Fontkit UMD Module

The following builds are available:

NOTE: if you are using the CDN scripts in production, you should include a specific version number in the URL, for example:

When using a UMD build, you will have access to a global window.fontkit variable. To register the fontkit instance:

var pdfDoc = await PDFLib.PDFDocument.create()
pdfDoc.registerFontkit(fontkit)

Documentation

API documentation is available on the project site at https://pdf-lib.js.org/docs/api/.

The repo for the project site (and generated documentation files) is located here: https://github.com/Hopding/pdf-lib-docs.

Fonts and Unicode

When working with PDFs, you will frequently come across the terms "character encoding" and "font". If you have experience in web development, you may wonder why these are so prevalent. Aren't they just annoying details that you shouldn't need to worry about? Shouldn't PDF libraries and readers be able to handle all of this for you like web browsers can? Unfortunately, this is not the case. The nature of the PDF file format makes it very difficult to avoid thinking about character encodings and fonts when working with PDFs.

pdf-lib does its best to simplify things for you. But it can't perform magic. This means you should be aware of the following:

  • There are 14 standard fonts defined in the PDF specification. They are as follows: Times Roman (normal, bold, and italic), Helvetica (normal, bold, and italic), Courier (normal, bold, and italic), ZapfDingbats (normal), and Symbol (normal). These 14 fonts are guaranteed to be available in PDF readers. As such, you do not need to embed any font data if you wish to use one of these fonts. You can use a standard font like so:
import { PDFDocument, StandardFonts } from 'pdf-lib'
const pdfDoc = await PDFDocument.create()
const courierFont = await pdfDoc.embedFont(StandardFonts.Courier)
const page = pdfDoc.addPage()
page.drawText('Some boring latin text in the Courier font', {
  font: courierFont,
})
  • The standard fonts do not support all characters available in Unicode. The Times Roman, Helvetica, and Courier fonts use WinAnsi encoding (aka Windows-1252). The WinAnsi character set only supports 218 characters in the Latin alphabet. For this reason, many users will find the standard fonts insufficient for their use case. This is unfortunate, but there's nothing that PDF libraries can do to change this. This is a result of the PDF specification and its age. Note that the ZapfDingbats and Symbol fonts use their own specialized encodings that support 203 and 194 characters, respectively. However, the characters they support are not useful for most use cases. See here for an example of all 14 standard fonts.
  • You can use characters outside the Latin alphabet by embedding your own fonts. Embedding your own font requires to you load the font data (from a file or via a network request, for example) and pass it to the embedFont method. When you embed your own font, you can use any Unicode characters that it supports. This capability frees you from the limitations imposed by the standard fonts. Most PDF files use embedded fonts. You can embed and use a custom font like so (see also):
import { PDFDocument } from 'pdf-lib'
import fontkit from '@pdf-lib/fontkit'

const url = 'https://pdf-lib.js.org/assets/ubuntu/Ubuntu-R.ttf'
const fontBytes = await fetch(url).then((res) => res.arrayBuffer())

const pdfDoc = await PDFDocument.create()

pdfDoc.registerFontkit(fontkit)
const ubuntuFont = await pdfDoc.embedFont(fontBytes)

const page = pdfDoc.addPage()
page.drawText('Some fancy Unicode text in the ŪЬȕǹƚü font', {
  font: ubuntuFont,
})

Note that encoding errors will be thrown if you try to use a character with a font that does not support it. For example, Ω is not in the WinAnsi character set. So trying to draw it on a page with the standard Helvetica font will throw the following error:

Error: WinAnsi cannot encode "Ω" (0x03a9)
    at Encoding.encodeUnicodeCodePoint

Font Subsetting

Embedding a font in a PDF document will typically increase the file's size. You can reduce the amount a file's size is increased by subsetting the font so that only the necessary characters are embedded. You can subset a font by setting the subset option to true. For example:

const font = await pdfDoc.embedFont(fontBytes, { subset: true });

Note that subsetting does not work for all fonts. See https://github.com/Hopding/pdf-lib/issues/207#issuecomment-537210471 for additional details.

Creating and Filling Forms

pdf-lib can create, fill, and read PDF form fields. The following field types are supported:

See the form creation and form filling usage examples for code samples. Tests 1, 14, 15, 16, and 17 in the complete examples contain working example code for form creation and filling in a variety of different JS environments.

IMPORTANT: The default font used to display text in buttons, dropdowns, option lists, and text fields is the standard Helvetica font. This font only supports characters in the latin alphabet (see Fonts and Unicode for details). This means that if any of these field types are created or modified to contain text outside the latin alphabet (as is often the case), you will need to embed and use a custom font to update the field appearances. Otherwise an error will be thrown (likely when you save the PDFDocument).

You can use an embedded font when filling form fields as follows:

import { PDFDocument } from 'pdf-lib';
import fontkit from '@pdf-lib/fontkit';

// Fetch the PDF with form fields
const formUrl = 'https://pdf-lib.js.org/assets/dod_character.pdf';
const formBytes = await fetch(formUrl).then((res) => res.arrayBuffer());

// Fetch the Ubuntu font
const fontUrl = 'https://pdf-lib.js.org/assets/ubuntu/Ubuntu-R.ttf';
const fontBytes = await fetch(fontUrl).then((res) => res.arrayBuffer());

// Load the PDF with form fields
const pdfDoc = await PDFDocument.load(formBytes);

// Embed the Ubuntu font
pdfDoc.registerFontkit(fontkit);
const ubuntuFont = await pdfDoc.embedFont(fontBytes);

// Get two text fields from the form
const form = pdfDoc.getForm();
const nameField = form.getTextField('CharacterName 2');
const ageField = form.getTextField('Age');

// Fill the text fields with some fancy Unicode characters (outside
// the WinAnsi latin character set)
nameField.setText('Ӎӑȑїõ');
ageField.setText('24 ŷȇȁŗš');

// **Key Step:** Update the field appearances with the Ubuntu font
form.updateFieldAppearances(ubuntuFont);

// Save the PDF with filled form fields
const pdfBytes = await pdfDoc.save();

Handy Methods for Filling, Creating, and Reading Form Fields

Existing form fields can be accessed with the following methods of PDFForm:

New form fields can be created with the following methods of PDFForm:

Below are some of the most commonly used methods for reading and filling the aforementioned subclasses of PDFField:





Limitations

  • pdf-lib can extract the content of text fields (see PDFTextField.getText), but it cannot extract plain text on a page outside of a form field. This is a difficult feature to implement, but it is within the scope of this library and may be added to pdf-lib in the future. See #93, #137, #177, #329, and #380.
  • pdf-lib can remove and edit the content of text fields (see PDFTextField.setText), but it does not provide APIs for removing or editing text on a page outside of a form field. This is also a difficult feature to implement, but is within the scope of pdf-lib and may be added in the future. See #93, #137, #177, #329, and #380.
  • pdf-lib does not support the use of HTML or CSS when adding content to a PDF. Similarly, pdf-lib cannot embed HTML/CSS content into PDFs. As convenient as such a feature might be, it would be extremely difficult to implement and is far beyond the scope of this library. If this capability is something you need, consider using Puppeteer.

Help and Discussion

Discussions is the best place to chat with us, ask questions, and learn more about pdf-lib!

See also MAINTAINERSHIP.md#communication and MAINTAINERSHIP.md#discord.

Encryption Handling

pdf-lib does not currently support encrypted documents. You should not use pdf-lib with encrypted documents. However, this is a feature that could be added to pdf-lib. Please create an issue if you would find this feature helpful!

When an encrypted document is passed to PDFDocument.load(...), an error will be thrown:

import { PDFDocument, EncryptedPDFError } from 'pdf-lib'

const encryptedPdfBytes = ...

// Assignment fails. Throws an `EncryptedPDFError`.
const pdfDoc = PDFDocument.load(encryptedPdfBytes)

This default behavior is usually what you want. It allows you to easily detect if a given document is encrypted, and it prevents you from trying to modify it. However, if you really want to load the document, you can use the { ignoreEncryption: true } option:

import { PDFDocument } from 'pdf-lib'

const encryptedPdfBytes = ...

// Assignment succeeds. Does not throw an error.
const pdfDoc = PDFDocument.load(encryptedPdfBytes, { ignoreEncryption: true })

Note that using this option does not decrypt the document. This means that any modifications you attempt to make on the returned PDFDocument may fail, or have unexpected results.

You should not use this option. It only exists for backwards compatibility reasons.

Contributing

We welcome contributions from the open source community! If you are interested in contributing to pdf-lib, please take a look at the CONTRIBUTING.md file. It contains information to help you get pdf-lib setup and running on your machine. (We try to make this as simple and fast as possible! :rocket:)

Maintainership

Check out MAINTAINERSHIP.md for details on how this repo is maintained and how we use issues, PRs, and discussions.

Tutorials and Cool Stuff

Prior Art

  • pdfkit is a PDF generation library for Node and the Browser. This library was immensely helpful as a reference and existence proof when creating pdf-lib. pdfkit's code for font embedding, PNG embedding, and JPG embedding was especially useful.
  • pdf.js is a PDF rendering library for the Browser. This library was helpful as a reference when writing pdf-lib's parser. Some of the code for stream decoding was ported directly to TypeScript for use in pdf-lib.
  • pdfbox is a PDF generation and modification library written in Java. This library was an invaluable reference when implementing form creation and filling APIs for pdf-lib.
  • jspdf is a PDF generation library for the browser.
  • pdfmake is a PDF generation library for the browser.
  • hummus is a PDF generation and modification library for Node environments. hummus is a Node wrapper around a C++ library, so it doesn't work in many JavaScript environments - like the Browser or React Native.
  • react-native-pdf-lib is a PDF generation and modification library for React Native environments. react-native-pdf-lib is a wrapper around C++ and Java libraries.
  • pdfassembler is a PDF generation and modification library for Node and the browser. It requires some knowledge about the logical structure of PDF documents to use.

Git History Rewrite

This repo used to contain a file called pdf_specification.pdf in the root directory. This was a copy of the PDF 1.7 specification, which is made freely available by Adobe. On 8/30/2021, we received a DMCA complaint requiring us to remove the file from this repo. Simply removing the file via a new commit to master was insufficient to satisfy the complaint. The file needed to be completely removed from the repo's git history. Unfortunately, the file was added over two years ago, this meant we had to rewrite the repo's git history and force push to master 😔.

Steps We Took

We removed the file and rewrote the repo's history using BFG Repo-Cleaner as outlined here. For full transparency, here are the exact commands we ran:

$ git clone git@github.com:Hopding/pdf-lib.git
$ cd pdf-lib
$ rm pdf_specification.pdf
$ git commit -am 'Remove pdf_specification.pdf'
$ bfg --delete-files pdf_specification.pdf
$ git reflog expire --expire=now --all && git gc --prune=now --aggressive
$ git push --force

Why Should I Care?

If you're a user of pdf-lib, you shouldn't care! Just keep on using pdf-lib like normal 😃 ✨!

If you are a pdf-lib developer (meaning you've forked pdf-lib and/or have an open PR) then this does impact you. If you forked or cloned the repo prior to 8/30/2021 then your fork's git history is out of sync with this repo's master branch. Unfortunately, this will likely be a headache for you to deal with. Sorry! We didn't want to rewrite the history, but there really was no alternative.

It's important to note that pdf-lib's source code has not changed at all. It's exactly the same as it was before the git history rewrite. The repo still has the exact same number of commits (and even the same commit contents, except for the commit that added pdf_specification.pdf). What has changed are the SHAs of those commits.

The simplest way to deal with this fact is to:

  1. Reclone pdf-lib
  2. Manually copy any changes you've made from your old clone to the new one
  3. Use your new clone going forward
  4. Reopen your unmerged PRs using your new clone

See this StackOverflow answer for a great, in depth explanation of what a git history rewrite entails.

Download Details:

Author: Hopding
Source Code: https://github.com/Hopding/pdf-lib 
License: MIT license

#typescript #javascript #pdf #editing #document 

PDF-lib: Create and Modify PDF Documents in any JavaScript Environment

Arun A

1627042275

7 Smart Ways to Find and Replace Text in a Word Document Using Java

Our Syncfusion Java Word Library (Essential DocIO) allows you to create, read, and edit Word documents programmatically without Microsoft Word or interop dependencies. The find and replace feature in the Java Word Library allows you to find text and replace it with any desired text, image, hyperlink, paragraph, table, part of a document, or entire document. It also allows you to quickly search for text by matching case and whole words. You can find each occurrence one by one or highlight all instances at once in a document.

This feature saves your time and effort by allowing you to use the Regex class. This class will automatically locate and replace a pattern of text in a lengthy Word document.
https://www.syncfusion.com/blogs/post/find-and-replace-text-in-word-document-using-java.aspx

#java #word #document #editing #web-development

7 Smart Ways to Find and Replace Text in a Word Document Using Java

Benefits of Image Processing Services

Image processing services assist businesses in transforming product photographs into professional catalogs that highlight the products’ essential features and benefits.

#image #processing #services #editing

Benefits of Image Processing Services

Automating video editing with Python

I recently had to solve an automation issue, where the client’s desire was to automatically generate hundreds of videos putting side by side a “base video” with a video picked from a list of hundreds. Whilst this could have easily been done by hand with one big effort, the project was an ongoing one, and the number of videos to generate was growing daily. For this reason, I decided to write a small script using Python and ffmpeg that would automatically generate and upload these videos to the client’s Vimeo channel.

This short article is meant to focus on some specific aspects of automation, video editing and Vimeo’s API, thus I won’t spend any time on the Python basics. I will focus on the few bits and bobs that I found challenging and I think are interesting to share.

Preparation

Preparation in an automation job is essential, even more when you’re trying to harvest information from the files themselves. For this reason, I set some ground rules for the video files the script would have dealt with and asked for these to be conformed. The final decision for the file naming was the following:

index_artist name_provenance.extension

With these three simple pieces of information I would have been able to keep track of the videos that had already been generated and customised title and description on Vimeo using the provided metadata. I used the underscores as data separators, and then used the neatly separated data stored in a list whenever it was needed.

#automation #videos #editing #api #python

Automating video editing with Python
Juana  O'Keefe

Juana O'Keefe

1601574780

Using Third-Party Date pickers in ag-Grid

In this post I’ll show you how to add third-party date pickers to ag-Grid to allow your users to easily filter and edit dates using a powerful date picker. Hopefully by the end of this blog you’ll be an expert in working with date pickers in ag-Grid!

In order to illustrate this, we’ve created an Angular application using the PrimeNG Calendardate picker to track the amount of holidays taken. Please see the date picker illustrated in the GIF below:

Live demo

Please see the live demo below - click inside the FROM and TO column filters or cells to open the date picker. You can see the Angular demo code in Stackblitz here, and get the full github project here.


We’ll be looking at:

#ag-grid #angular #editing #date #datepicker

Using Third-Party Date pickers in ag-Grid

Learn LaTeX in 5 minutes

Before this year I had never heard about LaTeX. That was until a new teacher wisely advised us that we should start learning LaTeX for our postgrad thesis. “Why can’t we just use MS Word?” I genuinely asked, to which he replied:

“If you want your work to look professional, you use LaTeX”

He recommended us to use Overleaf, a nice free editor for LaTeX. Ironically the final exam of his subject was replaced by a project, and I used this opportunity to learn LaTeX and present my work with professional standards.

In this tutorial I want to share with you what I learned about LaTeX, so you can also elevate your work to a whole new level. I’m going to walk you through creating the following elements:

  • Cover
  • Index
  • Titles & Subtitles
  • Bold, Italic & Underline
  • Bullet Lists
  • Images
  • Math & Equations
  • Syntax highlighting

I recommend you follow this tutorial on Overleaf for its simplicity, but any other text / LaTeX editor is more than enough!

Cover

The first impression your readers will get from your work will undoubtedly be from its cover. Making a professional-looking cover for your work can’t get any simpler with LaTeX. The cover must be defined before the \begin{document} label, but later we shall call the construction of the cover from within the document. Covers usually are formed from the following elements:

Title

Hard to imagine a cover without a title, to define it just type \title{My First Article in LaTeX!\vfill} and give your work a title that suits it. For good measure, you should add \vfill at the end of your title. This label will push everything that comes after the title so it just fits within the same page. This way, we can ensure that while the title is at the top of the page, things like authors or date are left at the bottom.

Author(s)

Give credit where credit is due! Add as many authors as you need with \author{author1} . You can add more authors and display them all at the same height, possibly avoiding hurting egos, like \author{auhtor1 \and author2} . To add them verticaly, swap \and with \\ to make a line break between the authors.

#editing #writing #publishing #paper #latex

Learn LaTeX in 5 minutes

How to Get the Most From the Hemingway App

I’m on the third round of edits of my latest novel, a supernatural thriller told in the first person, present tense. This is a first for me in all of the above. To help police myself, I downloaded the Hemingway Editing App.

It was an eye-opener.

The app claims to help make your writing tighter and clearer by pointing out potential unnecessary or excess verbiage. It highlights adverbs and qualifiers, telling you just how many you should have (I will always have way too many of both!), as well as how many times you slip into passive voice (not a huge problem for me). But the kicker is seeing how many of your sentences range from “difficult to read” to “very difficult to read.”

But don’t let the number of “difficult/very difficult to read” sentences in your story discourage you! It’s natural to want to fix all of them. But I have to warn you: just because a sentence is compound or longer than it might be doesn’t mean you should chop it up into three short, clear, but devoid of character sentences.

For me, it’s helpful to have an app that will point out whether a sentence is difficult to read, because sometimes it’s correct. I may have erred by switching the tense or other grammatical error. Or I may have written a run-on sentence that could be a lot shorter, and/or a lot clearer.

But sometimes, it’s okay as it is. Or maybe it needs some minor corrections before moving on. If it’s a fiction piece, when I’m writing as people speak, it’s okay if it’s incorrect. The point is, can the reader understand it? That’s the hundred dollar question.

#writing #editing #editing-apps #mobile app

How to Get the Most From the Hemingway App
yaqoob bugti

yaqoob bugti

1596281199

HOW TO EDIT DP IN ADOB PHOTOSHOP CS 6 IN HINDI & URDU

Please All friend Subscribe my channel and Like and Share
thanks For Watching Allah hafiz

#facebookdp #photoediting #adobphotoshop #flutter #amazing #editing

HOW TO EDIT DP IN ADOB PHOTOSHOP CS 6 IN HINDI & URDU
Vern  Greenholt

Vern Greenholt

1596119940

Take full control of editing in ag-Grid

ag-Grid provides a great editing experience out of the box. However, you may run into some limitations when performing validation on editing cells. This is because ag-Grid editors will always exit edit-mode if another cell is clicked.

In case where you need extra flexibility in handling cell content, you can create a cell renderer and take control of the full editing lifecycle. We’ll demonstrate this approach in a ToDo List application written in **TypeScript **and React.The app is documented using TypeDoc and is available on GitHub and StackBlitz.

💡 If you would like to generate documentation for this application you can clone this Github repository and then run the script named ‘doc’ (see the package.json file).

We’ll be going through:

Using Cell Renderers as Editors


ag-Grid provides a great editing experience out of the box. However, you may run into some limitations when performing validation on editing cells. This is because ag-Grid editors will always exit edit-mode if another cell is clicked.

In case where you need extra flexibility in handling cell content, you can create a cell renderer and take full control of the editing lifecycle.

Entering Edit Mode


-

Entering edit mode when using renderers as editors requires a flag that lets the renderers know whether they are in edit mode or read mode. You’ll also have to update that flag accordingly.

React context

Our demo ag-Grid subscribes to a React Context object that holds the following variables:

  • mockEditingId - the id of the row node currently in edit mode.
  • setMockEditingId - a function that takes an id and updates mockEditingId.
// src/context/MockEditingContext.tsx
export interface IMockEditingContext {
    /** ID of the node in {@link Grid} in mock-edit mode */
    mockEditingId: string,
    /** function to update the mockEditingId */
    setMockEditingId: (id: string) => void
}

📔 The demo application refers to edit mode as mock-edit mode. This is simply to differentiate between the out of the box ag-Grid editing and the renderers being used as editors

Hooking renderers to the React context

When the pen icon on a row node is clicked, mockEditingId is set to the id of that row node (provided that there are no other nodes currently editing).

#ag-grid #react #typescript #editing

Take full control of editing in ag-Grid