summaryrefslogtreecommitdiffstats
path: root/image/encoders/bmp/nsBMPEncoder.h
blob: 1f40d9df340f51f21bd7d410a84bd0ee4e135854 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozilla_image_encoders_bmp_nsBMPEncoder_h
#define mozilla_image_encoders_bmp_nsBMPEncoder_h

#include "mozilla/Attributes.h"
#include "mozilla/ReentrantMonitor.h"
#include "mozilla/UniquePtr.h"

#include "imgIEncoder.h"

#include "nsCOMPtr.h"

#define NS_BMPENCODER_CID                            \
  { /* 13a5320c-4c91-4FA4-bd16-b081a3ba8c0b */       \
    0x13a5320c, 0x4c91, 0x4fa4, {                    \
      0xbd, 0x16, 0xb0, 0x81, 0xa3, 0Xba, 0x8c, 0x0b \
    }                                                \
  }

namespace mozilla {
namespace image {
namespace bmp {

struct FileHeader {
  char signature[2];    // String "BM".
  uint32_t filesize;    // File size.
  int32_t reserved;     // Zero.
  uint32_t dataoffset;  // Offset to raster data.
};

struct XYZ {
  int32_t x, y, z;
};

struct XYZTriple {
  XYZ r, g, b;
};

struct V5InfoHeader {
  uint32_t bihsize;           // Header size
  int32_t width;              // Uint16 in OS/2 BMPs
  int32_t height;             // Uint16 in OS/2 BMPs
  uint16_t planes;            // =1
  uint16_t bpp;               // Bits per pixel.
  uint32_t compression;       // See Compression for valid values
  uint32_t image_size;        // (compressed) image size. Can be 0 if
                              // compression==0
  uint32_t xppm;              // Pixels per meter, horizontal
  uint32_t yppm;              // Pixels per meter, vertical
  uint32_t colors;            // Used Colors
  uint32_t important_colors;  // Number of important colors. 0=all
  // The rest of the header is not available in WIN_V3 BMP Files
  uint32_t red_mask;     // Bits used for red component
  uint32_t green_mask;   // Bits used for green component
  uint32_t blue_mask;    // Bits used for blue component
  uint32_t alpha_mask;   // Bits used for alpha component
  uint32_t color_space;  // 0x73524742=LCS_sRGB ...
  // These members are unused unless color_space == LCS_CALIBRATED_RGB
  XYZTriple white_point;  // Logical white point
  uint32_t gamma_red;     // Red gamma component
  uint32_t gamma_green;   // Green gamma component
  uint32_t gamma_blue;    // Blue gamma component
  uint32_t intent;        // Rendering intent
  // These members are unused unless color_space == LCS_PROFILE_*
  uint32_t profile_offset;  // Offset to profile data in bytes
  uint32_t profile_size;    // Size of profile data in bytes
  uint32_t reserved;        // =0

  static const uint32_t COLOR_SPACE_LCS_SRGB = 0x73524742;
};

}  // namespace bmp
}  // namespace image
}  // namespace mozilla

// Provides BMP encoding functionality. Use InitFromData() to do the
// encoding. See that function definition for encoding options.

class nsBMPEncoder final : public imgIEncoder {
  typedef mozilla::ReentrantMonitor ReentrantMonitor;

 public:
  NS_DECL_THREADSAFE_ISUPPORTS
  NS_DECL_IMGIENCODER
  NS_DECL_NSIINPUTSTREAM
  NS_DECL_NSIASYNCINPUTSTREAM

  nsBMPEncoder();

 protected:
  ~nsBMPEncoder();

  enum Version { VERSION_3 = 3, VERSION_5 = 5 };

  // See InitData in the cpp for valid parse options
  nsresult ParseOptions(const nsAString& aOptions, Version& aVersionOut,
                        uint16_t& aBppOut);
  // Obtains data with no alpha in machine-independent byte order
  void ConvertHostARGBRow(const uint8_t* aSrc,
                          const mozilla::UniquePtr<uint8_t[]>& aDest,
                          uint32_t aPixelWidth);
  // Thread safe notify listener
  void NotifyListener();

  // Initializes the bitmap file header member mBMPFileHeader
  nsresult InitFileHeader(Version aVersion, uint16_t aBPP, uint32_t aWidth,
                          uint32_t aHeight);
  // Initializes the bitmap info header member mBMPInfoHeader
  nsresult InitInfoHeader(Version aVersion, uint16_t aBPP, uint32_t aWidth,
                          uint32_t aHeight);

  // Encodes the bitmap file header member mBMPFileHeader
  void EncodeFileHeader();
  // Encodes the bitmap info header member mBMPInfoHeader
  void EncodeInfoHeader();
  // Encodes a row of image data which does not have alpha data
  void EncodeImageDataRow24(const uint8_t* aData);
  // Encodes a row of image data which does have alpha data
  void EncodeImageDataRow32(const uint8_t* aData);
  // Obtains the current offset filled up to for the image buffer
  inline int32_t GetCurrentImageBufferOffset() {
    return static_cast<int32_t>(mImageBufferCurr - mImageBufferStart);
  }

  // These headers will always contain endian independent stuff
  // They store the BMP headers which will be encoded
  mozilla::image::bmp::FileHeader mBMPFileHeader;
  mozilla::image::bmp::V5InfoHeader mBMPInfoHeader;

  // Keeps track of the start of the image buffer
  uint8_t* mImageBufferStart;
  // Keeps track of the current position in the image buffer
  uint8_t* mImageBufferCurr;
  // Keeps track of the image buffer size
  uint32_t mImageBufferSize;
  // Keeps track of the number of bytes in the image buffer which are read
  uint32_t mImageBufferReadPoint;
  // Stores true if the image is done being encoded
  bool mFinished;

  nsCOMPtr<nsIInputStreamCallback> mCallback;
  nsCOMPtr<nsIEventTarget> mCallbackTarget;
  uint32_t mNotifyThreshold;
};

#endif  // mozilla_image_encoders_bmp_nsBMPEncoder_h