Skip to content

Commit

Permalink
docs(files): add doc comments to critical parts of the feature
Browse files Browse the repository at this point in the history
  • Loading branch information
danvergara committed Jan 21, 2024
1 parent 8ac8b35 commit f0d74d0
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 3 deletions.
29 changes: 29 additions & 0 deletions pkg/files/documents/pdf.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ type Pdf struct {
compatibleFormats map[string][]string
}

// NewPdf returns a pointer to Pdf.
func NewPdf(filename string) *Pdf {
p := Pdf{
filename: filename,
Expand All @@ -48,11 +49,17 @@ func NewPdf(filename string) *Pdf {
return &p
}

// SupportedFormats returns a map witht he compatible formats that Pds is
// compatible to be converted to.
func (p *Pdf) SupportedFormats() map[string][]string {
return p.compatibleFormats
}

// ConvertTo converts the current PDF file to another given format.
// This method receives the file type, the sub-type and the file as an slice of bytes.
// Returns the converted file as an slice of bytes, if something wrong happens, an error is returned.
func (p *Pdf) ConvertTo(fileType, subType string, fileBytes []byte) ([]byte, error) {
// These are guard clauses that check if the target file type is valid.
compatibleFormats, ok := p.SupportedFormats()[fileType]
if !ok {
return nil, fmt.Errorf("ConvertTo: file type not supported: %s", fileType)
Expand All @@ -62,13 +69,16 @@ func (p *Pdf) ConvertTo(fileType, subType string, fileBytes []byte) ([]byte, err
return nil, fmt.Errorf("ConvertTo: file sub-type not supported: %s", subType)
}

// If the file type is valid, figures out how to go ahead.
switch strings.ToLower(fileType) {
case imageType:
// Creates a PDF Reader based on the pdf file.
pdfReader, err := model.NewPdfReader(bytes.NewReader(fileBytes))
if err != nil {
return nil, fmt.Errorf("ConvertTo: error at opening the input pdf: %w", err)
}

// Get the number of pages from the pdf file.
pages, err := pdfReader.GetNumPages()
if err != nil {
return nil, fmt.Errorf(
Expand All @@ -77,8 +87,10 @@ func (p *Pdf) ConvertTo(fileType, subType string, fileBytes []byte) ([]byte, err
)
}

// Parses the file name of the Zip file.
zipFileName := fmt.Sprintf("/tmp/%s.zip", filenameWithoutExtension(p.filename))

// Creates the zip file that will be returned.
archive, err := os.Create(zipFileName)
if err != nil {
return nil, fmt.Errorf(
Expand All @@ -87,12 +99,15 @@ func (p *Pdf) ConvertTo(fileType, subType string, fileBytes []byte) ([]byte, err
)
}

// Creats a Zip Writer to add files later on.
zipWriter := zip.NewWriter(archive)

device := render.NewImageDevice()
// Set the image width. The height will be calculated accordingly.
device.OutputWidth = 2048

for pageNum := 1; pageNum <= pages; pageNum++ {
// Parses the file name image.
imgFileName := fmt.Sprintf(
"%s_%d.%s",
filenameWithoutExtension(p.filename),
Expand All @@ -101,6 +116,7 @@ func (p *Pdf) ConvertTo(fileType, subType string, fileBytes []byte) ([]byte, err
)
tmpImgFileMame := fmt.Sprintf("/tmp/%s", imgFileName)

// Converts the current pdf page to an image.Image.
img, err := convertPDFPageToImage(pdfReader, device, pageNum)
if err != nil {
return nil, fmt.Errorf(
Expand All @@ -110,6 +126,7 @@ func (p *Pdf) ConvertTo(fileType, subType string, fileBytes []byte) ([]byte, err
)
}

// Saves the image on disk.
imgFile, err := os.Create(tmpImgFileMame)
if err != nil {
return nil, fmt.Errorf(
Expand All @@ -119,6 +136,8 @@ func (p *Pdf) ConvertTo(fileType, subType string, fileBytes []byte) ([]byte, err
)
}

// Encodes the image based on the sub-type of the file.
// e.g. png.
switch subType {
case images.PNG:
err = png.Encode(imgFile, img)
Expand Down Expand Up @@ -178,6 +197,7 @@ func (p *Pdf) ConvertTo(fileType, subType string, fileBytes []byte) ([]byte, err

imgFile.Close()

// Opens the image to add it to the zip file.
imgFile, err = os.Open(tmpImgFileMame)
if err != nil {
return nil, fmt.Errorf(
Expand All @@ -188,6 +208,7 @@ func (p *Pdf) ConvertTo(fileType, subType string, fileBytes []byte) ([]byte, err
}
defer imgFile.Close()

// Adds the image to the zip file.
w1, err := zipWriter.Create(imgFileName)
if err != nil {
return nil, fmt.Errorf(
Expand All @@ -206,9 +227,11 @@ func (p *Pdf) ConvertTo(fileType, subType string, fileBytes []byte) ([]byte, err
}
}

// Closes both zip writer and the zip file after its done with the writing.
zipWriter.Close()
archive.Close()

// Reads the zip file as an slice of bytes.
zipFile, err := os.ReadFile(zipFileName)
if err != nil {
return nil, fmt.Errorf("error reading zip file: %v", err)
Expand All @@ -220,11 +243,15 @@ func (p *Pdf) ConvertTo(fileType, subType string, fileBytes []byte) ([]byte, err
return nil, errors.New("not implemented")
}

// convertPDFPageToImage converts the pdf page to an image.
// The functions receives the pdf Reader, the Image Device and the page number.
// Returns a image.Image or an error if something goes wrong.
func convertPDFPageToImage(
pdfReader *model.PdfReader,
device *render.ImageDevice,
pageNum int,
) (image.Image, error) {
// Get the page based on the given page number.
page, err := pdfReader.GetPage(pageNum)
if err != nil {
return nil, fmt.Errorf(
Expand All @@ -234,6 +261,7 @@ func convertPDFPageToImage(
)
}

// Render returns an image.Image given a page.
img, err := device.Render(page)
if err != nil {
return nil, fmt.Errorf(
Expand All @@ -256,6 +284,7 @@ func filenameWithoutExtension(filename string) string {
return ""
}

// DocumentType returns the type of ducument of Pdf.
func (p *Pdf) DocumentType() string {
return PDF
}
21 changes: 18 additions & 3 deletions pkg/files/images/images.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,26 +100,41 @@ func toBMP(img image.Image) ([]byte, error) {
return buf.Bytes(), nil
}

// toPDF returns pdf file as an slice of bytes.
// Receives an image.Image as a parameter.
func toPDF(img image.Image) ([]byte, error) {
// Sets a Rectangle based on the size of the image.
imgRect := gopdf.Rect{
W: float64(img.Bounds().Dx()),
H: float64(img.Bounds().Dy()),
}

// Init the pdf obkect.
pdf := gopdf.GoPdf{}

// Sets the size of the every pdf page,
// based on the dimensions of the image.
pdf.Start(
gopdf.Config{
PageSize: gopdf.Rect{W: float64(img.Bounds().Dx()), H: float64(img.Bounds().Dy())},
PageSize: imgRect,
},
)

// Add a page to the PDF
// Add a page to the PDF.
pdf.AddPage()

if err := pdf.ImageFrom(img, 0, 0, &gopdf.Rect{W: float64(img.Bounds().Dx()), H: float64(img.Bounds().Dy())}); err != nil {
// Draws the image on the rectangle on the page above created.
if err := pdf.ImageFrom(img, 0, 0, &imgRect); err != nil {
return nil, err
}

// Creates a bytes.Buffer and writes the pdf data to it.
buf := new(bytes.Buffer)
if _, err := pdf.WriteTo(buf); err != nil {
return nil, err
}

// Returns the pdf data as slice of bytes.
return buf.Bytes(), nil
}

Expand Down

0 comments on commit f0d74d0

Please sign in to comment.