123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- // Copyright 2021 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "chromeos/utils/pdf_conversion.h"
- #include "base/files/file_path.h"
- #include "base/logging.h"
- #include "printing/units.h"
- #include "third_party/skia/include/core/SkCanvas.h"
- #include "third_party/skia/include/core/SkData.h"
- #include "third_party/skia/include/core/SkImage.h"
- #include "third_party/skia/include/core/SkRect.h"
- #include "third_party/skia/include/core/SkStream.h"
- #include "third_party/skia/include/core/SkTypes.h"
- #include "third_party/skia/include/docs/SkPDFDocument.h"
- #include "ui/gfx/image/buffer_w_stream.h"
- namespace chromeos {
- namespace {
- // The number of degrees to rotate a PDF image.
- constexpr int kRotationDegrees = 180;
- // Creates a new page for the PDF document and adds `image_data` to the page.
- // `rotate` indicates whether the page should be rotated 180 degrees.
- // Returns whether the page was successfully created.
- bool AddPdfPage(sk_sp<SkDocument> pdf_doc,
- const sk_sp<SkData>& image_data,
- bool rotate,
- absl::optional<int> dpi) {
- const sk_sp<SkImage> image = SkImage::MakeFromEncoded(image_data);
- if (!image) {
- LOG(ERROR) << "Unable to generate image from encoded image data.";
- return false;
- }
- // Convert from JPG dimensions in pixels (DPI) to PDF dimensions in points
- // (1/72 in).
- int page_width;
- int page_height;
- if (dpi.has_value() && dpi.value() > 0) {
- page_width = printing::ConvertUnit(image->width(), dpi.value(),
- printing::kPointsPerInch);
- page_height = printing::ConvertUnit(image->height(), dpi.value(),
- printing::kPointsPerInch);
- } else {
- page_width = image->width();
- page_height = image->height();
- }
- SkCanvas* page_canvas = pdf_doc->beginPage(page_width, page_height);
- if (!page_canvas) {
- LOG(ERROR) << "Unable to access PDF page canvas.";
- return false;
- }
- // Rotate pages that were flipped by an ADF scanner.
- if (rotate) {
- page_canvas->rotate(kRotationDegrees);
- page_canvas->translate(-page_width, -page_height);
- }
- SkRect image_bounds = SkRect::MakeIWH(page_width, page_height);
- page_canvas->drawImageRect(image, image_bounds, SkSamplingOptions());
- pdf_doc->endPage();
- return true;
- }
- } // namespace
- bool ConvertJpgImagesToPdf(const std::vector<std::string>& jpg_images,
- const base::FilePath& file_path,
- bool rotate_alternate_pages,
- absl::optional<int> dpi) {
- DCHECK(!file_path.empty());
- SkFILEWStream pdf_outfile(file_path.value().c_str());
- if (!pdf_outfile.isValid()) {
- LOG(ERROR) << "Unable to open output file.";
- return false;
- }
- sk_sp<SkDocument> pdf_doc = SkPDF::MakeDocument(&pdf_outfile);
- DCHECK(pdf_doc);
- // Never rotate first page of PDF.
- bool rotate_current_page = false;
- for (const auto& jpg_image : jpg_images) {
- SkDynamicMemoryWStream img_stream;
- if (!img_stream.write(jpg_image.c_str(), jpg_image.size())) {
- LOG(ERROR) << "Unable to write image to dynamic memory stream.";
- return false;
- }
- const sk_sp<SkData> img_data = img_stream.detachAsData();
- if (img_data->isEmpty()) {
- LOG(ERROR) << "Stream data is empty.";
- return false;
- }
- if (!AddPdfPage(pdf_doc, img_data, rotate_current_page, dpi)) {
- LOG(ERROR) << "Unable to add new PDF page.";
- return false;
- }
- if (rotate_alternate_pages) {
- rotate_current_page = !rotate_current_page;
- }
- }
- pdf_doc->close();
- return true;
- }
- bool ConvertJpgImageToPdf(const std::vector<uint8_t>& jpg_image,
- std::vector<uint8_t>* output) {
- gfx::BufferWStream output_stream;
- sk_sp<SkDocument> pdf_doc = SkPDF::MakeDocument(&output_stream);
- DCHECK(pdf_doc);
- SkDynamicMemoryWStream img_stream;
- if (!img_stream.write(jpg_image.data(), jpg_image.size())) {
- LOG(ERROR) << "Unable to write image to dynamic memory stream.";
- return false;
- }
- const sk_sp<SkData> img_data = img_stream.detachAsData();
- if (img_data->isEmpty()) {
- LOG(ERROR) << "Stream data is empty.";
- return false;
- }
- if (!AddPdfPage(pdf_doc, img_data, false, absl::nullopt)) {
- LOG(ERROR) << "Unable to add new PDF page.";
- return false;
- }
- pdf_doc->close();
- *output = output_stream.TakeBuffer();
- return true;
- }
- } // namespace chromeos
|