| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/utility/cloud_print/pwg_encoder.h" | 5 #include "chrome/utility/cloud_print/pwg_encoder.h" |
| 6 | 6 |
| 7 #include <string.h> |
| 8 |
| 7 #include <algorithm> | 9 #include <algorithm> |
| 8 | 10 |
| 9 #include "base/big_endian.h" | 11 #include "base/big_endian.h" |
| 10 #include "base/logging.h" | 12 #include "base/logging.h" |
| 11 #include "base/memory/scoped_ptr.h" | 13 #include "base/memory/scoped_ptr.h" |
| 12 #include "chrome/utility/cloud_print/bitmap_image.h" | 14 #include "chrome/utility/cloud_print/bitmap_image.h" |
| 13 | 15 |
| 14 namespace cloud_print { | 16 namespace cloud_print { |
| 15 | 17 |
| 16 namespace { | 18 namespace { |
| 17 | 19 |
| 18 const uint32 kBitsPerColor = 8; | 20 const uint32_t kBitsPerColor = 8; |
| 19 const uint32 kColorOrder = 0; // chunky. | 21 const uint32_t kColorOrder = 0; // chunky. |
| 20 | 22 |
| 21 // Coefficients used to convert from RGB to monochrome. | 23 // Coefficients used to convert from RGB to monochrome. |
| 22 const uint32 kRedCoefficient = 2125; | 24 const uint32_t kRedCoefficient = 2125; |
| 23 const uint32 kGreenCoefficient = 7154; | 25 const uint32_t kGreenCoefficient = 7154; |
| 24 const uint32 kBlueCoefficient = 721; | 26 const uint32_t kBlueCoefficient = 721; |
| 25 const uint32 kColorCoefficientDenominator = 10000; | 27 const uint32_t kColorCoefficientDenominator = 10000; |
| 26 | 28 |
| 27 const char kPwgKeyword[] = "RaS2"; | 29 const char kPwgKeyword[] = "RaS2"; |
| 28 | 30 |
| 29 const uint32 kHeaderSize = 1796; | 31 const uint32_t kHeaderSize = 1796; |
| 30 const uint32 kHeaderCupsDuplex = 272; | 32 const uint32_t kHeaderCupsDuplex = 272; |
| 31 const uint32 kHeaderCupsHwResolutionHorizontal = 276; | 33 const uint32_t kHeaderCupsHwResolutionHorizontal = 276; |
| 32 const uint32 kHeaderCupsHwResolutionVertical = 280; | 34 const uint32_t kHeaderCupsHwResolutionVertical = 280; |
| 33 const uint32 kHeaderCupsTumble = 368; | 35 const uint32_t kHeaderCupsTumble = 368; |
| 34 const uint32 kHeaderCupsWidth = 372; | 36 const uint32_t kHeaderCupsWidth = 372; |
| 35 const uint32 kHeaderCupsHeight = 376; | 37 const uint32_t kHeaderCupsHeight = 376; |
| 36 const uint32 kHeaderCupsBitsPerColor = 384; | 38 const uint32_t kHeaderCupsBitsPerColor = 384; |
| 37 const uint32 kHeaderCupsBitsPerPixel = 388; | 39 const uint32_t kHeaderCupsBitsPerPixel = 388; |
| 38 const uint32 kHeaderCupsBytesPerLine = 392; | 40 const uint32_t kHeaderCupsBytesPerLine = 392; |
| 39 const uint32 kHeaderCupsColorOrder = 396; | 41 const uint32_t kHeaderCupsColorOrder = 396; |
| 40 const uint32 kHeaderCupsColorSpace = 400; | 42 const uint32_t kHeaderCupsColorSpace = 400; |
| 41 const uint32 kHeaderCupsNumColors = 420; | 43 const uint32_t kHeaderCupsNumColors = 420; |
| 42 const uint32 kHeaderPwgTotalPageCount = 452; | 44 const uint32_t kHeaderPwgTotalPageCount = 452; |
| 43 const uint32 kHeaderPwgCrossFeedTransform = 456; | 45 const uint32_t kHeaderPwgCrossFeedTransform = 456; |
| 44 const uint32 kHeaderPwgFeedTransform = 460; | 46 const uint32_t kHeaderPwgFeedTransform = 460; |
| 45 | 47 |
| 46 const int kPwgMaxPackedRows = 256; | 48 const int kPwgMaxPackedRows = 256; |
| 47 | 49 |
| 48 const int kPwgMaxPackedPixels = 128; | 50 const int kPwgMaxPackedPixels = 128; |
| 49 | 51 |
| 50 struct RGBA8 { | 52 struct RGBA8 { |
| 51 uint8 red; | 53 uint8_t red; |
| 52 uint8 green; | 54 uint8_t green; |
| 53 uint8 blue; | 55 uint8_t blue; |
| 54 uint8 alpha; | 56 uint8_t alpha; |
| 55 }; | 57 }; |
| 56 | 58 |
| 57 struct BGRA8 { | 59 struct BGRA8 { |
| 58 uint8 blue; | 60 uint8_t blue; |
| 59 uint8 green; | 61 uint8_t green; |
| 60 uint8 red; | 62 uint8_t red; |
| 61 uint8 alpha; | 63 uint8_t alpha; |
| 62 }; | 64 }; |
| 63 | 65 |
| 64 template <class InputStruct> | 66 template <class InputStruct> |
| 65 inline void encodePixelToRGB(const void* pixel, std::string* output) { | 67 inline void encodePixelToRGB(const void* pixel, std::string* output) { |
| 66 const InputStruct* i = reinterpret_cast<const InputStruct*>(pixel); | 68 const InputStruct* i = reinterpret_cast<const InputStruct*>(pixel); |
| 67 output->push_back(static_cast<char>(i->red)); | 69 output->push_back(static_cast<char>(i->red)); |
| 68 output->push_back(static_cast<char>(i->green)); | 70 output->push_back(static_cast<char>(i->green)); |
| 69 output->push_back(static_cast<char>(i->blue)); | 71 output->push_back(static_cast<char>(i->blue)); |
| 70 } | 72 } |
| 71 | 73 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 86 output->clear(); | 88 output->clear(); |
| 87 output->append(kPwgKeyword, 4); | 89 output->append(kPwgKeyword, 4); |
| 88 } | 90 } |
| 89 | 91 |
| 90 void PwgEncoder::EncodePageHeader(const BitmapImage& image, | 92 void PwgEncoder::EncodePageHeader(const BitmapImage& image, |
| 91 const PwgHeaderInfo& pwg_header_info, | 93 const PwgHeaderInfo& pwg_header_info, |
| 92 std::string* output) const { | 94 std::string* output) const { |
| 93 char header[kHeaderSize]; | 95 char header[kHeaderSize]; |
| 94 memset(header, 0, kHeaderSize); | 96 memset(header, 0, kHeaderSize); |
| 95 | 97 |
| 96 uint32 num_colors = | 98 uint32_t num_colors = |
| 97 pwg_header_info.color_space == PwgHeaderInfo::SGRAY ? 1 : 3; | 99 pwg_header_info.color_space == PwgHeaderInfo::SGRAY ? 1 : 3; |
| 98 uint32 bits_per_pixel = num_colors * kBitsPerColor; | 100 uint32_t bits_per_pixel = num_colors * kBitsPerColor; |
| 99 | 101 |
| 100 base::WriteBigEndian<uint32>(header + kHeaderCupsDuplex, | 102 base::WriteBigEndian<uint32_t>(header + kHeaderCupsDuplex, |
| 101 pwg_header_info.duplex ? 1 : 0); | 103 pwg_header_info.duplex ? 1 : 0); |
| 102 base::WriteBigEndian<uint32>(header + kHeaderCupsHwResolutionHorizontal, | 104 base::WriteBigEndian<uint32_t>(header + kHeaderCupsHwResolutionHorizontal, |
| 103 pwg_header_info.dpi); | 105 pwg_header_info.dpi); |
| 104 base::WriteBigEndian<uint32>(header + kHeaderCupsHwResolutionVertical, | 106 base::WriteBigEndian<uint32_t>(header + kHeaderCupsHwResolutionVertical, |
| 105 pwg_header_info.dpi); | 107 pwg_header_info.dpi); |
| 106 base::WriteBigEndian<uint32>(header + kHeaderCupsTumble, | 108 base::WriteBigEndian<uint32_t>(header + kHeaderCupsTumble, |
| 107 pwg_header_info.tumble ? 1 : 0); | 109 pwg_header_info.tumble ? 1 : 0); |
| 108 base::WriteBigEndian<uint32>(header + kHeaderCupsWidth, image.size().width()); | 110 base::WriteBigEndian<uint32_t>(header + kHeaderCupsWidth, |
| 109 base::WriteBigEndian<uint32>(header + kHeaderCupsHeight, | 111 image.size().width()); |
| 110 image.size().height()); | 112 base::WriteBigEndian<uint32_t>(header + kHeaderCupsHeight, |
| 111 base::WriteBigEndian<uint32>(header + kHeaderCupsBitsPerColor, kBitsPerColor); | 113 image.size().height()); |
| 112 base::WriteBigEndian<uint32>(header + kHeaderCupsBitsPerPixel, | 114 base::WriteBigEndian<uint32_t>(header + kHeaderCupsBitsPerColor, |
| 113 bits_per_pixel); | 115 kBitsPerColor); |
| 114 base::WriteBigEndian<uint32>(header + kHeaderCupsBytesPerLine, | 116 base::WriteBigEndian<uint32_t>(header + kHeaderCupsBitsPerPixel, |
| 115 (bits_per_pixel * image.size().width() + 7) / 8); | 117 bits_per_pixel); |
| 116 base::WriteBigEndian<uint32>(header + kHeaderCupsColorOrder, kColorOrder); | 118 base::WriteBigEndian<uint32_t>( |
| 117 base::WriteBigEndian<uint32>(header + kHeaderCupsColorSpace, | 119 header + kHeaderCupsBytesPerLine, |
| 118 pwg_header_info.color_space); | 120 (bits_per_pixel * image.size().width() + 7) / 8); |
| 119 base::WriteBigEndian<uint32>(header + kHeaderCupsNumColors, num_colors); | 121 base::WriteBigEndian<uint32_t>(header + kHeaderCupsColorOrder, kColorOrder); |
| 120 base::WriteBigEndian<uint32>(header + kHeaderPwgCrossFeedTransform, | 122 base::WriteBigEndian<uint32_t>(header + kHeaderCupsColorSpace, |
| 121 pwg_header_info.flipx ? -1 : 1); | 123 pwg_header_info.color_space); |
| 122 base::WriteBigEndian<uint32>(header + kHeaderPwgFeedTransform, | 124 base::WriteBigEndian<uint32_t>(header + kHeaderCupsNumColors, num_colors); |
| 123 pwg_header_info.flipy ? -1 : 1); | 125 base::WriteBigEndian<uint32_t>(header + kHeaderPwgCrossFeedTransform, |
| 124 base::WriteBigEndian<uint32>(header + kHeaderPwgTotalPageCount, | 126 pwg_header_info.flipx ? -1 : 1); |
| 125 pwg_header_info.total_pages); | 127 base::WriteBigEndian<uint32_t>(header + kHeaderPwgFeedTransform, |
| 128 pwg_header_info.flipy ? -1 : 1); |
| 129 base::WriteBigEndian<uint32_t>(header + kHeaderPwgTotalPageCount, |
| 130 pwg_header_info.total_pages); |
| 126 output->append(header, kHeaderSize); | 131 output->append(header, kHeaderSize); |
| 127 } | 132 } |
| 128 | 133 |
| 129 template <typename InputStruct, class RandomAccessIterator> | 134 template <typename InputStruct, class RandomAccessIterator> |
| 130 void PwgEncoder::EncodeRow(RandomAccessIterator pos, | 135 void PwgEncoder::EncodeRow(RandomAccessIterator pos, |
| 131 RandomAccessIterator row_end, | 136 RandomAccessIterator row_end, |
| 132 bool monochrome, | 137 bool monochrome, |
| 133 std::string* output) const { | 138 std::string* output) const { |
| 134 // According to PWG-raster, a sequence of N identical pixels (up to 128) | 139 // According to PWG-raster, a sequence of N identical pixels (up to 128) |
| 135 // can be encoded by a byte N-1, followed by the information on | 140 // can be encoded by a byte N-1, followed by the information on |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 177 if (monochrome) | 182 if (monochrome) |
| 178 encodePixelToMonochrome<InputStruct>(&*pos, output); | 183 encodePixelToMonochrome<InputStruct>(&*pos, output); |
| 179 else | 184 else |
| 180 encodePixelToRGB<InputStruct>(&*pos, output); | 185 encodePixelToRGB<InputStruct>(&*pos, output); |
| 181 ++pos; | 186 ++pos; |
| 182 } | 187 } |
| 183 } | 188 } |
| 184 } | 189 } |
| 185 } | 190 } |
| 186 | 191 |
| 187 inline const uint8* PwgEncoder::GetRow(const BitmapImage& image, | 192 inline const uint8_t* PwgEncoder::GetRow(const BitmapImage& image, |
| 188 int row, | 193 int row, |
| 189 bool flipy) const { | 194 bool flipy) const { |
| 190 return image.GetPixel( | 195 return image.GetPixel( |
| 191 gfx::Point(0, flipy ? image.size().height() - 1 - row : row)); | 196 gfx::Point(0, flipy ? image.size().height() - 1 - row : row)); |
| 192 } | 197 } |
| 193 | 198 |
| 194 // Given a pointer to a struct Image, create a PWG of the image and | 199 // Given a pointer to a struct Image, create a PWG of the image and |
| 195 // put the compressed image data in the string. Returns true on success. | 200 // put the compressed image data in the string. Returns true on success. |
| 196 // The content of the string is undefined on failure. | 201 // The content of the string is undefined on failure. |
| 197 bool PwgEncoder::EncodePage(const BitmapImage& image, | 202 bool PwgEncoder::EncodePage(const BitmapImage& image, |
| 198 const PwgHeaderInfo& pwg_header_info, | 203 const PwgHeaderInfo& pwg_header_info, |
| 199 std::string* output) const { | 204 std::string* output) const { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 218 std::string* output) const { | 223 std::string* output) const { |
| 219 bool monochrome = pwg_header_info.color_space == PwgHeaderInfo::SGRAY; | 224 bool monochrome = pwg_header_info.color_space == PwgHeaderInfo::SGRAY; |
| 220 EncodePageHeader(image, pwg_header_info, output); | 225 EncodePageHeader(image, pwg_header_info, output); |
| 221 | 226 |
| 222 // Ensure no integer overflow. | 227 // Ensure no integer overflow. |
| 223 CHECK(image.size().width() < INT_MAX / image.channels()); | 228 CHECK(image.size().width() < INT_MAX / image.channels()); |
| 224 int row_size = image.size().width() * image.channels(); | 229 int row_size = image.size().width() * image.channels(); |
| 225 | 230 |
| 226 int row_number = 0; | 231 int row_number = 0; |
| 227 while (row_number < image.size().height()) { | 232 while (row_number < image.size().height()) { |
| 228 const uint8* current_row = | 233 const uint8_t* current_row = |
| 229 GetRow(image, row_number++, pwg_header_info.flipy); | 234 GetRow(image, row_number++, pwg_header_info.flipy); |
| 230 int num_identical_rows = 1; | 235 int num_identical_rows = 1; |
| 231 // We count how many times the current row is repeated. | 236 // We count how many times the current row is repeated. |
| 232 while (num_identical_rows < kPwgMaxPackedRows && | 237 while (num_identical_rows < kPwgMaxPackedRows && |
| 233 row_number < image.size().height() && | 238 row_number < image.size().height() && |
| 234 !memcmp(current_row, | 239 !memcmp(current_row, |
| 235 GetRow(image, row_number, pwg_header_info.flipy), | 240 GetRow(image, row_number, pwg_header_info.flipy), |
| 236 row_size)) { | 241 row_size)) { |
| 237 num_identical_rows++; | 242 num_identical_rows++; |
| 238 row_number++; | 243 row_number++; |
| 239 } | 244 } |
| 240 output->push_back(static_cast<char>(num_identical_rows - 1)); | 245 output->push_back(static_cast<char>(num_identical_rows - 1)); |
| 241 | 246 |
| 242 // Both supported colorspaces have a 32-bit pixels information. | 247 // Both supported colorspaces have a 32-bit pixels information. |
| 243 // Converts the list of uint8 to uint32 as every pixels contains 4 bytes | 248 // Converts the list of uint8_t to uint32_t as every pixels contains 4 bytes |
| 244 // of information and comparison of elements is easier. The actual | 249 // of information and comparison of elements is easier. The actual |
| 245 // Management of the bytes of the pixel is done by pixel_encoder function | 250 // Management of the bytes of the pixel is done by pixel_encoder function |
| 246 // on the original array to avoid endian problems. | 251 // on the original array to avoid endian problems. |
| 247 const uint32* pos = reinterpret_cast<const uint32*>(current_row); | 252 const uint32_t* pos = reinterpret_cast<const uint32_t*>(current_row); |
| 248 const uint32* row_end = pos + image.size().width(); | 253 const uint32_t* row_end = pos + image.size().width(); |
| 249 if (!pwg_header_info.flipx) { | 254 if (!pwg_header_info.flipx) { |
| 250 EncodeRow<InputStruct>(pos, row_end, monochrome, output); | 255 EncodeRow<InputStruct>(pos, row_end, monochrome, output); |
| 251 } else { | 256 } else { |
| 252 // We reverse the iterators. | 257 // We reverse the iterators. |
| 253 EncodeRow<InputStruct>(std::reverse_iterator<const uint32*>(row_end), | 258 EncodeRow<InputStruct>(std::reverse_iterator<const uint32_t*>(row_end), |
| 254 std::reverse_iterator<const uint32*>(pos), | 259 std::reverse_iterator<const uint32_t*>(pos), |
| 255 monochrome, | 260 monochrome, output); |
| 256 output); | |
| 257 } | 261 } |
| 258 } | 262 } |
| 259 return true; | 263 return true; |
| 260 } | 264 } |
| 261 | 265 |
| 262 } // namespace cloud_print | 266 } // namespace cloud_print |
| OLD | NEW |