The Pedigree Project  0.1
libraries/libtui/src/Png.cc
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include "user/libraries/libtui/include/Png.h"
21 
22 #include <sys/klog.h>
23 #include <unistd.h>
24 
25 Png::Png(const char *filename)
26  : m_PngPtr(0), m_InfoPtr(0), m_nWidth(0), m_nHeight(0), m_pRowPointers(0)
27 {
28  // Open the file.
29  FILE *stream = fopen(filename, "rb");
30  if (!stream)
31  {
32  klog(LOG_ALERT, "PNG file failed to open");
33  fclose(stream);
34  return;
35  }
36 
37  // Read in some of the signature bytes.
38  char buf[4];
39  if (fread(buf, 1, 4, stream) != 4)
40  {
41  klog(LOG_ALERT, "PNG file failed to read ident");
42  fclose(stream);
43  return;
44  }
45  if (png_sig_cmp(reinterpret_cast<png_byte *>(buf), 0, 4) != 0)
46  {
47  klog(LOG_ALERT, "PNG file failed IDENT check");
48  fclose(stream);
49  return;
50  }
51 
52  m_PngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
53 
54  if (m_PngPtr == 0)
55  {
56  klog(LOG_ALERT, "PNG file failed to initialise");
57  fclose(stream);
58  return;
59  }
60 
61  m_InfoPtr = png_create_info_struct(m_PngPtr);
62  if (m_InfoPtr == 0)
63  {
64  klog(LOG_ALERT, "PNG info failed to initialise");
65  fclose(stream);
66  return;
67  }
68 
69  png_init_io(m_PngPtr, stream);
70 
71  png_set_sig_bytes(m_PngPtr, 4);
72 
73  png_set_palette_to_rgb(m_PngPtr);
74 
75  png_read_png(
76  m_PngPtr, m_InfoPtr,
77  PNG_TRANSFORM_STRIP_16 | // 16-bit-per-channel down to 8.
78  PNG_TRANSFORM_STRIP_ALPHA | // No alpha
79  PNG_TRANSFORM_PACKING, // Unpack 2 and 4 bit samples.
80 
81  reinterpret_cast<void *>(0));
82 
83  m_pRowPointers = png_get_rows(m_PngPtr, m_InfoPtr);
84 
85  // Grab the info header information.
86  int bit_depth, color_type, interlace_type, compression_type, filter_method;
87  png_uint_32 w, h;
88  png_get_IHDR(
89  m_PngPtr, m_InfoPtr, &w, &h, &bit_depth, &color_type, &interlace_type,
90  &compression_type, &filter_method);
91  m_nWidth = w;
92  m_nHeight = h;
93 
94  if (bit_depth != 8)
95  {
96  klog(LOG_ALERT, "PNG - invalid bit depth");
97  return;
98  }
99  if (color_type != PNG_COLOR_TYPE_RGB)
100  {
101  klog(LOG_ALERT, "PNG - invalid colour type: %d", color_type);
102  return;
103  }
104 
105  klog(LOG_ALERT, "PNG loaded %ul %ul", m_nWidth, m_nHeight);
106 }
107 
108 Png::~Png()
109 {
110 }
111 
112 void Png::render(rgb_t *pFb, size_t x, size_t y, size_t width, size_t height)
113 {
114  for (size_t r = 0; r < m_nHeight; r++)
115  {
116  if (r + y >= height)
117  break;
118 
119  for (size_t c = 0; c < m_nWidth; c++)
120  {
121  if (c + x >= width)
122  break;
123 
124  rgb_t rgb;
125  rgb.r = m_pRowPointers[r][c * 3 + 0];
126  rgb.g = m_pRowPointers[r][c * 3 + 1];
127  rgb.b = m_pRowPointers[r][c * 3 + 2];
128  rgb.a = 255;
129 
130  pFb[(r + y) * width + (c + x)] = rgb;
131  }
132  }
133 }
134 
135 uint32_t
136 Png::compileColour(uint8_t r, uint8_t g, uint8_t b, Display::PixelFormat pf)
137 {
138  // Calculate the range of the Red field.
139  uint8_t range = 1 << pf.mRed;
140 
141  // Clamp the red value to this range.
142  r = (r * range) / 256;
143 
144  range = 1 << pf.mGreen;
145 
146  // Clamp the green value to this range.
147  g = (g * range) / 256;
148 
149  range = 1 << pf.mBlue;
150 
151  // Clamp the blue value to this range.
152  b = (b * range) / 256;
153 
154  // Assemble the colour.
155  return 0 | (static_cast<uint32_t>(r) << pf.pRed) |
156  (static_cast<uint32_t>(g) << pf.pGreen) |
157  (static_cast<uint32_t>(b) << pf.pBlue);
158 }
uint8_t mRed
Red mask.
Definition: Display.h:57
uint8_t pGreen
Position of green field.
Definition: Display.h:60
Png(const char *filename)
uint8_t pBlue
Position of blue field.
Definition: Display.h:62
uint8_t mGreen
Green mask.
Definition: Display.h:59
uint8_t mBlue
Blue mask.
Definition: Display.h:61
uint8_t pRed
Position of red field.
Definition: Display.h:58