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 |