|
7 | 7 | Culture of the Czech Republic.
|
8 | 8 |
|
9 | 9 |
|
10 |
| - Copyright (C) 2010-2023 Ruven Pillay. |
| 10 | + Copyright (C) 2010-2025 Ruven Pillay. |
11 | 11 |
|
12 | 12 | This program is free software; you can redistribute it and/or modify
|
13 | 13 | it under the terms of the GNU General Public License as published by
|
@@ -87,62 +87,97 @@ void Watermark::init()
|
87 | 87 |
|
88 | 88 |
|
89 | 89 | // Apply the watermark to a buffer of data
|
90 |
| -void Watermark::apply( void* data, unsigned int width, unsigned int height, unsigned int channels, unsigned int bpc ) |
| 90 | +void Watermark::apply( void* data, unsigned int width, unsigned int height, unsigned int channels, unsigned int bpc, unsigned int block ) |
91 | 91 | {
|
92 |
| - |
93 | 92 | // Sanity check
|
94 | 93 | if( !_isSet || (_probability==0) || (_opacity==0) ) return;
|
95 | 94 |
|
96 |
| - // Get random number as a float between 0 and 1 |
97 |
| - float random = (float)( rand() / RAND_MAX ); |
| 95 | + /* Calculate the size of the blocks into which we paste the watermark and the number of blocks horizontally and vertically. |
| 96 | + For tile requests we define the block as being the whole image and, thus, apply a single watermark. |
| 97 | + For larger regions, we divide the image into blocks and allow multiple watermarks to be placed, one within each block |
| 98 | + */ |
| 99 | + unsigned int ntlx = 1; |
| 100 | + unsigned int ntly = 1; |
| 101 | + unsigned int tile_width = width; |
| 102 | + unsigned int tile_height = height; |
| 103 | + unsigned rem_x = 0; |
| 104 | + unsigned rem_y = 0; |
| 105 | + |
| 106 | + // If block has been defined and our image is larger than the block size, apply multiple watermarks, each randomly placed within a block |
| 107 | + if( (block > 0) && (width > block || height > block) ){ |
| 108 | + tile_width = block; |
| 109 | + tile_height = block; |
| 110 | + rem_x = width % tile_width; |
| 111 | + ntlx = (width / tile_width) + (rem_x == 0 ? 0 : 1); |
| 112 | + rem_y = height % tile_height; |
| 113 | + ntly = (height / tile_height) + (rem_y == 0 ? 0 : 1); |
| 114 | + } |
| 115 | + |
| 116 | + |
| 117 | + // Loop through each block |
| 118 | + for( unsigned int ty=0; ty<ntly; ty++ ){ |
| 119 | + for( unsigned int tx=0; tx<ntlx; tx++ ){ |
| 120 | + |
| 121 | + // Get random number as a float between 0 and 1 |
| 122 | + float random = rand() / (float)RAND_MAX; |
98 | 123 |
|
99 |
| - // Only apply if our random number is less than our given probability |
100 |
| - if( random < _probability ){ |
101 |
| - |
102 |
| - // Vary watermark position randomly within the tile depending on available space |
103 |
| - unsigned int xoffset = 0; |
104 |
| - if( width > _width ){ |
105 |
| - random = (float)( rand() / RAND_MAX ); |
106 |
| - xoffset = random * (width - _width); |
107 |
| - } |
| 124 | + // Only apply if our random number is less than our given probability |
| 125 | + if( random < _probability ){ |
| 126 | + |
| 127 | + // Block width and height |
| 128 | + unsigned int tw = tile_width; |
| 129 | + unsigned int th = tile_height; |
| 130 | + |
| 131 | + // Update block size if this is last row |
| 132 | + if( (tx == ntlx - 1) && ( rem_x != 0 ) ) tw = rem_x; |
| 133 | + if( (ty == ntly - 1) && ( rem_y != 0 ) ) th = rem_y; |
| 134 | + |
| 135 | + // Vary watermark position randomly within the block depending on available space |
| 136 | + unsigned int xoffset = 0; |
| 137 | + if( tw > _width ){ |
| 138 | + random = rand() / (float)RAND_MAX; |
| 139 | + xoffset = random * (tw - _width); |
| 140 | + } |
108 | 141 |
|
109 |
| - unsigned int yoffset = 0; |
110 |
| - if( height > _height ){ |
111 |
| - random = (float)( rand() / RAND_MAX ); |
112 |
| - yoffset = random * (height - _height); |
113 |
| - } |
| 142 | + unsigned int yoffset = 0; |
| 143 | + if( th > _height ){ |
| 144 | + random = rand() / (float)RAND_MAX; |
| 145 | + yoffset = random * (th - _height); |
| 146 | + } |
114 | 147 |
|
115 |
| - // Limit the area of the watermark to the size of the tile |
116 |
| - unsigned int xlimit = _width; |
117 |
| - unsigned int ylimit = _height; |
118 |
| - if( _width > width ) xlimit = width; |
119 |
| - if( _height > height ) ylimit = height; |
120 |
| - |
121 |
| - for( unsigned int j=0; j<ylimit; j++ ){ |
122 |
| - for( unsigned int i=0; i<xlimit; i++ ){ |
123 |
| - for( unsigned int k=0; k<channels; k++ ){ |
124 |
| - |
125 |
| - unsigned int id = (j+yoffset)*width*channels + (i+xoffset)*channels + k; |
126 |
| - |
127 |
| - // For 16bit images we need to multiply up as our watermark data is always 8bit |
128 |
| - // We do our maths in unsigned int to allow us to clip correctly |
129 |
| - if( bpc == 16 ){ |
130 |
| - unsigned short* d = (unsigned short*) data; |
131 |
| - unsigned int t = (unsigned int)( d[id] + _watermark[j*_width*_channels + i*_channels + k]*256 ); |
132 |
| - if( t > 65535 ) t = 65535; |
133 |
| - d[id] = (unsigned short) t; |
134 |
| - } |
135 |
| - // TIFFReadRGBAImage always scales to 8bit, so never any need for downscaling, but clip to 255 |
136 |
| - // We do our maths in unsigned short to allow us to clip correctly after |
137 |
| - else{ |
138 |
| - unsigned char* d = (unsigned char*) data; |
139 |
| - unsigned short t = (unsigned short)( d[id] + _watermark[j*_width*_channels + i*_channels + k] ); |
140 |
| - if( t > 255 ) t = 255; |
141 |
| - d[id] = (unsigned char) t; |
| 148 | + // Limit the area of the watermark to the size of the block |
| 149 | + unsigned int xlimit = _width; |
| 150 | + unsigned int ylimit = _height; |
| 151 | + if( _width > tw ) xlimit = tw; |
| 152 | + if( _height > th ) ylimit = th; |
| 153 | + |
| 154 | + for( unsigned int j=0; j<ylimit; j++ ){ |
| 155 | + for( unsigned int i=0; i<xlimit; i++ ){ |
| 156 | + for( unsigned int k=0; k<channels; k++ ){ |
| 157 | + |
| 158 | + // Calculate the index on the image buffer that is to be watermarked |
| 159 | + uint32_t id = ((ty*tile_width)+j+yoffset)*width*channels + ((tx*tile_height)+i+xoffset)*channels + k; |
| 160 | + |
| 161 | + // For 16bit images we need to multiply up as our watermark data is always 8bit |
| 162 | + // We do our maths in unsigned int to allow us to clip correctly |
| 163 | + if( bpc == 16 ){ |
| 164 | + unsigned short* d = (unsigned short*) data; |
| 165 | + unsigned int t = (unsigned int)( d[id] + _watermark[j*_width*_channels + i*_channels + k]*256 ); |
| 166 | + if( t > 65535 ) t = 65535; |
| 167 | + d[id] = (unsigned short) t; |
| 168 | + } |
| 169 | + // TIFFReadRGBAImage always scales to 8bit, so never any need for downscaling, but clip to 255 |
| 170 | + // We do our maths in unsigned short to allow us to clip correctly after |
| 171 | + else{ |
| 172 | + unsigned char* d = (unsigned char*) data; |
| 173 | + unsigned short t = (unsigned short)( d[id] + _watermark[j*_width*_channels + i*_channels + k] ); |
| 174 | + if( t > 255 ) t = 255; |
| 175 | + d[id] = (unsigned char) t; |
| 176 | + } |
| 177 | + } |
142 | 178 | }
|
143 | 179 | }
|
144 | 180 | }
|
145 | 181 | }
|
146 | 182 | }
|
147 |
| - |
148 | 183 | }
|
0 commit comments