Coverage Report

Created: 2026-07-10 11:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/vcl/source/bitmap/BitmapReadAccess.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
11
 *   Licensed to the Apache Software Foundation (ASF) under one or more
12
 *   contributor license agreements. See the NOTICE file distributed
13
 *   with this work for additional information regarding copyright
14
 *   ownership. The ASF licenses this file to you under the Apache
15
 *   License, Version 2.0 (the "License"); you may not use this file
16
 *   except in compliance with the License. You may obtain a copy of
17
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18
 */
19
20
#include <vcl/alpha.hxx>
21
#include <vcl/BitmapReadAccess.hxx>
22
#include <vcl/BitmapTools.hxx>
23
24
#include <salbmp.hxx>
25
#include <svdata.hxx>
26
#include <salinst.hxx>
27
28
BitmapReadAccess::BitmapReadAccess(const AlphaMask& rBitmap, BitmapAccessMode nMode)
29
10.5k
    : BitmapReadAccess(rBitmap.GetBitmap(), nMode)
30
10.5k
{
31
10.5k
}
32
33
BitmapReadAccess::BitmapReadAccess(const Bitmap& rBitmap, BitmapAccessMode nMode)
34
339k
    : BitmapInfoAccess(rBitmap, nMode)
35
339k
    , mFncGetPixel(nullptr)
36
339k
    , mFncSetPixel(nullptr)
37
339k
{
38
339k
    if (!mpBuffer)
39
3.64k
        return;
40
41
335k
    const std::shared_ptr<SalBitmap>& xImpBmp = rBitmap.ImplGetSalBitmap();
42
335k
    if (!xImpBmp)
43
0
        return;
44
45
335k
    mFncGetPixel = GetPixelFunction(mpBuffer->meFormat);
46
335k
    mFncSetPixel = SetPixelFunction(mpBuffer->meFormat);
47
48
335k
    if (!mFncGetPixel || !mFncSetPixel)
49
0
    {
50
0
        xImpBmp->ReleaseBuffer(mpBuffer, mnAccessMode);
51
0
        mpBuffer = nullptr;
52
0
    }
53
335k
}
54
55
339k
BitmapReadAccess::~BitmapReadAccess() {}
56
57
FncGetPixel BitmapReadAccess::GetPixelFunction(ScanlineFormat nFormat)
58
343k
{
59
343k
    switch (nFormat)
60
343k
    {
61
222k
        case ScanlineFormat::N8BitPal:
62
222k
            return GetPixelForN8BitPal;
63
64.6k
        case ScanlineFormat::N24BitTcBgr:
64
64.6k
            return GetPixelForN24BitTcBgr;
65
0
        case ScanlineFormat::N24BitTcRgb:
66
0
            return GetPixelForN24BitTcRgb;
67
0
        case ScanlineFormat::N32BitTcAbgr:
68
0
            return GetPixelForN32BitTcAbgr;
69
0
        case ScanlineFormat::N32BitTcXbgr:
70
0
            return GetPixelForN32BitTcXbgr;
71
0
        case ScanlineFormat::N32BitTcArgb:
72
0
            return GetPixelForN32BitTcArgb;
73
0
        case ScanlineFormat::N32BitTcXrgb:
74
0
            return GetPixelForN32BitTcXrgb;
75
49.9k
        case ScanlineFormat::N32BitTcBgra:
76
49.9k
            return GetPixelForN32BitTcBgra;
77
6.46k
        case ScanlineFormat::N32BitTcBgrx:
78
6.46k
            return GetPixelForN32BitTcBgrx;
79
0
        case ScanlineFormat::N32BitTcRgba:
80
0
            return GetPixelForN32BitTcRgba;
81
0
        case ScanlineFormat::N32BitTcRgbx:
82
0
            return GetPixelForN32BitTcRgbx;
83
84
0
        default:
85
0
            return nullptr;
86
343k
    }
87
343k
}
88
89
FncSetPixel BitmapReadAccess::SetPixelFunction(ScanlineFormat nFormat)
90
335k
{
91
335k
    switch (nFormat)
92
335k
    {
93
214k
        case ScanlineFormat::N8BitPal:
94
214k
            return SetPixelForN8BitPal;
95
64.6k
        case ScanlineFormat::N24BitTcBgr:
96
64.6k
            return SetPixelForN24BitTcBgr;
97
0
        case ScanlineFormat::N24BitTcRgb:
98
0
            return SetPixelForN24BitTcRgb;
99
0
        case ScanlineFormat::N32BitTcAbgr:
100
0
            return SetPixelForN32BitTcAbgr;
101
0
        case ScanlineFormat::N32BitTcXbgr:
102
0
            return SetPixelForN32BitTcXbgr;
103
0
        case ScanlineFormat::N32BitTcArgb:
104
0
            return SetPixelForN32BitTcArgb;
105
0
        case ScanlineFormat::N32BitTcXrgb:
106
0
            return SetPixelForN32BitTcXrgb;
107
49.9k
        case ScanlineFormat::N32BitTcBgra:
108
49.9k
            return SetPixelForN32BitTcBgra;
109
6.46k
        case ScanlineFormat::N32BitTcBgrx:
110
6.46k
            return SetPixelForN32BitTcBgrx;
111
0
        case ScanlineFormat::N32BitTcRgba:
112
0
            return SetPixelForN32BitTcRgba;
113
0
        case ScanlineFormat::N32BitTcRgbx:
114
0
            return SetPixelForN32BitTcRgbx;
115
116
0
        default:
117
0
            assert(false);
118
0
            return nullptr;
119
335k
    }
120
335k
}
121
122
BitmapColor BitmapReadAccess::GetInterpolatedColorWithFallback(double fY, double fX,
123
                                                               const BitmapColor& rFallback) const
124
0
{
125
    // ask directly doubles >= 0.0 here to avoid rounded values of 0 at small negative
126
    // double values, e.g. static_cast< sal_Int32 >(-0.25) is 0, not -1, but *has* to be outside (!)
127
0
    if (!mpBuffer || fX < 0.0 || fY < 0.0)
128
0
        return rFallback;
129
130
0
    const sal_Int64 nX(static_cast<sal_Int64>(fX));
131
0
    const sal_Int64 nY(static_cast<sal_Int64>(fY));
132
133
0
    if (nX >= mpBuffer->mnWidth || nY >= mpBuffer->mnHeight)
134
0
        return rFallback;
135
136
    // get base-return value from inside pixel
137
0
    BitmapColor aRetval(GetColor(nY, nX));
138
139
    // calculate deltas and indices for neighbour accesses
140
0
    sal_Int16 nDeltaX((fX - (nX + 0.5)) * 255.0); // [-255 .. 255]
141
0
    sal_Int16 nDeltaY((fY - (nY + 0.5)) * 255.0); // [-255 .. 255]
142
0
    sal_Int16 nIndX(0);
143
0
    sal_Int16 nIndY(0);
144
145
0
    if (nDeltaX > 0)
146
0
    {
147
0
        nIndX = nX + 1;
148
0
    }
149
0
    else
150
0
    {
151
0
        nIndX = nX - 1;
152
0
        nDeltaX = -nDeltaX;
153
0
    }
154
155
0
    if (nDeltaY > 0)
156
0
    {
157
0
        nIndY = nY + 1;
158
0
    }
159
0
    else
160
0
    {
161
0
        nIndY = nY - 1;
162
0
        nDeltaY = -nDeltaY;
163
0
    }
164
165
    // get right/left neighbour
166
0
    BitmapColor aXCol(rFallback);
167
168
0
    if (nDeltaX && nIndX >= 0 && nIndX < mpBuffer->mnWidth)
169
0
        aXCol = GetColor(nY, nIndX);
170
171
    // get top/bottom neighbour
172
0
    BitmapColor aYCol(rFallback);
173
174
0
    if (nDeltaY && nIndY >= 0 && nIndY < mpBuffer->mnHeight)
175
0
        aYCol = GetColor(nIndY, nX);
176
177
    // get one of four edge neighbours
178
0
    BitmapColor aXYCol(rFallback);
179
180
0
    if (nDeltaX && nDeltaY && nIndX >= 0 && nIndY >= 0 && nIndX < mpBuffer->mnWidth
181
0
        && nIndY < mpBuffer->mnHeight)
182
0
    {
183
0
        aXYCol = GetColor(nIndY, nIndX);
184
0
    }
185
186
    // merge return value with right/left neighbour
187
0
    if (aXCol != aRetval)
188
0
        aRetval.Merge(aXCol, 255 - nDeltaX);
189
190
    // merge top/bottom neighbour with edge
191
0
    if (aYCol != aXYCol)
192
0
        aYCol.Merge(aXYCol, 255 - nDeltaX);
193
194
    // merge return value with already merged top/bottom neighbour
195
0
    if (aRetval != aYCol)
196
0
        aRetval.Merge(aYCol, 255 - nDeltaY);
197
198
0
    return aRetval;
199
0
}
200
201
BitmapColor BitmapReadAccess::GetColorWithFallback(double fY, double fX,
202
                                                   const BitmapColor& rFallback) const
203
0
{
204
    // ask directly doubles >= 0.0 here to avoid rounded values of 0 at small negative
205
    // double values, e.g. static_cast< sal_Int32 >(-0.25) is 0, not -1, but *has* to be outside (!)
206
0
    if (!mpBuffer || fX < 0.0 || fY < 0.0)
207
0
        return rFallback;
208
209
0
    const sal_Int32 nX(static_cast<sal_Int32>(fX));
210
0
    const sal_Int32 nY(static_cast<sal_Int32>(fY));
211
212
0
    if (nX >= mpBuffer->mnWidth || nY >= mpBuffer->mnHeight)
213
0
        return rFallback;
214
215
0
    return GetColor(nY, nX);
216
0
}
217
218
BitmapColor BitmapReadAccess::GetPixelForN8BitPal(ConstScanline pScanline, tools::Long nX)
219
175M
{
220
175M
    return BitmapColor(pScanline[nX]);
221
175M
}
222
223
void BitmapReadAccess::SetPixelForN8BitPal(Scanline pScanline, tools::Long nX,
224
                                           const BitmapColor& rBitmapColor)
225
3.74G
{
226
3.74G
    pScanline[nX] = rBitmapColor.GetIndex();
227
3.74G
}
228
229
BitmapColor BitmapReadAccess::GetPixelForN24BitTcBgr(ConstScanline pScanline, tools::Long nX)
230
50.2M
{
231
50.2M
    BitmapColor aBitmapColor;
232
233
50.2M
    pScanline = pScanline + nX * 3;
234
50.2M
    aBitmapColor.SetBlue(*pScanline++);
235
50.2M
    aBitmapColor.SetGreen(*pScanline++);
236
50.2M
    aBitmapColor.SetRed(*pScanline);
237
238
50.2M
    return aBitmapColor;
239
50.2M
}
240
241
void BitmapReadAccess::SetPixelForN24BitTcBgr(Scanline pScanline, tools::Long nX,
242
                                              const BitmapColor& rBitmapColor)
243
4.01G
{
244
4.01G
    pScanline = pScanline + nX * 3;
245
4.01G
    *pScanline++ = rBitmapColor.GetBlue();
246
4.01G
    *pScanline++ = rBitmapColor.GetGreen();
247
4.01G
    *pScanline = rBitmapColor.GetRed();
248
4.01G
}
249
250
BitmapColor BitmapReadAccess::GetPixelForN24BitTcRgb(ConstScanline pScanline, tools::Long nX)
251
0
{
252
0
    BitmapColor aBitmapColor;
253
254
0
    pScanline = pScanline + nX * 3;
255
0
    aBitmapColor.SetRed(*pScanline++);
256
0
    aBitmapColor.SetGreen(*pScanline++);
257
0
    aBitmapColor.SetBlue(*pScanline);
258
259
0
    return aBitmapColor;
260
0
}
261
262
void BitmapReadAccess::SetPixelForN24BitTcRgb(Scanline pScanline, tools::Long nX,
263
                                              const BitmapColor& rBitmapColor)
264
0
{
265
0
    pScanline = pScanline + nX * 3;
266
0
    *pScanline++ = rBitmapColor.GetRed();
267
0
    *pScanline++ = rBitmapColor.GetGreen();
268
0
    *pScanline = rBitmapColor.GetBlue();
269
0
}
270
271
BitmapColor BitmapReadAccess::GetPixelForN32BitTcAbgr(ConstScanline pScanline, tools::Long nX)
272
0
{
273
0
    pScanline = pScanline + nX * 4;
274
275
0
    sal_uInt8 a = *pScanline++;
276
0
    sal_uInt8 b = *pScanline++;
277
0
    sal_uInt8 g = *pScanline++;
278
0
    sal_uInt8 r = *pScanline;
279
280
0
    return BitmapColor(ColorAlpha, vcl::bitmap::unpremultiply(r, a),
281
0
                       vcl::bitmap::unpremultiply(g, a), vcl::bitmap::unpremultiply(b, a), a);
282
0
}
283
284
BitmapColor BitmapReadAccess::GetPixelForN32BitTcXbgr(ConstScanline pScanline, tools::Long nX)
285
0
{
286
0
    BitmapColor aBitmapColor;
287
288
0
    pScanline = pScanline + (nX << 2) + 1;
289
0
    aBitmapColor.SetBlue(*pScanline++);
290
0
    aBitmapColor.SetGreen(*pScanline++);
291
0
    aBitmapColor.SetRed(*pScanline);
292
293
0
    return aBitmapColor;
294
0
}
295
296
void BitmapReadAccess::SetPixelForN32BitTcAbgr(Scanline pScanline, tools::Long nX,
297
                                               const BitmapColor& rBitmapColor)
298
0
{
299
0
    pScanline = pScanline + nX * 4;
300
301
0
    sal_uInt8 alpha = rBitmapColor.GetAlpha();
302
0
    *pScanline++ = alpha;
303
0
    *pScanline++ = vcl::bitmap::premultiply(rBitmapColor.GetBlue(), alpha);
304
0
    *pScanline++ = vcl::bitmap::premultiply(rBitmapColor.GetGreen(), alpha);
305
0
    *pScanline = vcl::bitmap::premultiply(rBitmapColor.GetRed(), alpha);
306
0
}
307
308
void BitmapReadAccess::SetPixelForN32BitTcXbgr(Scanline pScanline, tools::Long nX,
309
                                               const BitmapColor& rBitmapColor)
310
0
{
311
0
    pScanline = pScanline + (nX << 2);
312
0
    *pScanline++ = 0xFF;
313
0
    *pScanline++ = rBitmapColor.GetBlue();
314
0
    *pScanline++ = rBitmapColor.GetGreen();
315
0
    *pScanline = rBitmapColor.GetRed();
316
0
}
317
318
BitmapColor BitmapReadAccess::GetPixelForN32BitTcArgb(ConstScanline pScanline, tools::Long nX)
319
0
{
320
0
    pScanline = pScanline + nX * 4;
321
322
0
    sal_uInt8 a = *pScanline++;
323
0
    sal_uInt8 r = *pScanline++;
324
0
    sal_uInt8 g = *pScanline++;
325
0
    sal_uInt8 b = *pScanline;
326
327
0
    return BitmapColor(ColorAlpha, vcl::bitmap::unpremultiply(r, a),
328
0
                       vcl::bitmap::unpremultiply(g, a), vcl::bitmap::unpremultiply(b, a), a);
329
0
}
330
331
BitmapColor BitmapReadAccess::GetPixelForN32BitTcXrgb(ConstScanline pScanline, tools::Long nX)
332
0
{
333
0
    BitmapColor aBitmapColor;
334
335
0
    pScanline = pScanline + (nX << 2) + 1;
336
0
    aBitmapColor.SetRed(*pScanline++);
337
0
    aBitmapColor.SetGreen(*pScanline++);
338
0
    aBitmapColor.SetBlue(*pScanline);
339
340
0
    return aBitmapColor;
341
0
}
342
343
void BitmapReadAccess::SetPixelForN32BitTcArgb(Scanline pScanline, tools::Long nX,
344
                                               const BitmapColor& rBitmapColor)
345
0
{
346
0
    pScanline = pScanline + nX * 4;
347
348
0
    sal_uInt8 alpha = rBitmapColor.GetAlpha();
349
0
    *pScanline++ = alpha;
350
0
    *pScanline++ = vcl::bitmap::premultiply(rBitmapColor.GetRed(), alpha);
351
0
    *pScanline++ = vcl::bitmap::premultiply(rBitmapColor.GetGreen(), alpha);
352
0
    *pScanline = vcl::bitmap::premultiply(rBitmapColor.GetBlue(), alpha);
353
0
}
354
355
void BitmapReadAccess::SetPixelForN32BitTcXrgb(Scanline pScanline, tools::Long nX,
356
                                               const BitmapColor& rBitmapColor)
357
0
{
358
0
    pScanline = pScanline + (nX << 2);
359
0
    *pScanline++ = 0xFF;
360
0
    *pScanline++ = rBitmapColor.GetRed();
361
0
    *pScanline++ = rBitmapColor.GetGreen();
362
0
    *pScanline = rBitmapColor.GetBlue();
363
0
}
364
365
BitmapColor BitmapReadAccess::GetPixelForN32BitTcBgra(ConstScanline pScanline, tools::Long nX)
366
3.44G
{
367
3.44G
    pScanline = pScanline + nX * 4;
368
369
3.44G
    sal_uInt8 b = *pScanline++;
370
3.44G
    sal_uInt8 g = *pScanline++;
371
3.44G
    sal_uInt8 r = *pScanline++;
372
3.44G
    sal_uInt8 a = *pScanline;
373
374
3.44G
    return BitmapColor(ColorAlpha, vcl::bitmap::unpremultiply(r, a),
375
3.44G
                       vcl::bitmap::unpremultiply(g, a), vcl::bitmap::unpremultiply(b, a), a);
376
3.44G
}
377
378
BitmapColor BitmapReadAccess::GetPixelForN32BitTcBgrx(ConstScanline pScanline, tools::Long nX)
379
640k
{
380
640k
    BitmapColor aBitmapColor;
381
382
640k
    pScanline = pScanline + (nX << 2);
383
640k
    aBitmapColor.SetBlue(*pScanline++);
384
640k
    aBitmapColor.SetGreen(*pScanline++);
385
640k
    aBitmapColor.SetRed(*pScanline);
386
387
640k
    return aBitmapColor;
388
640k
}
389
390
void BitmapReadAccess::SetPixelForN32BitTcBgra(Scanline pScanline, tools::Long nX,
391
                                               const BitmapColor& rBitmapColor)
392
4.50G
{
393
4.50G
    pScanline = pScanline + nX * 4;
394
395
4.50G
    sal_uInt8 alpha = rBitmapColor.GetAlpha();
396
4.50G
    *pScanline++ = vcl::bitmap::premultiply(rBitmapColor.GetBlue(), alpha);
397
4.50G
    *pScanline++ = vcl::bitmap::premultiply(rBitmapColor.GetGreen(), alpha);
398
4.50G
    *pScanline++ = vcl::bitmap::premultiply(rBitmapColor.GetRed(), alpha);
399
4.50G
    *pScanline = alpha;
400
4.50G
}
401
402
void BitmapReadAccess::SetPixelForN32BitTcBgrx(Scanline pScanline, tools::Long nX,
403
                                               const BitmapColor& rBitmapColor)
404
0
{
405
0
    pScanline = pScanline + (nX << 2);
406
0
    *pScanline++ = rBitmapColor.GetBlue();
407
0
    *pScanline++ = rBitmapColor.GetGreen();
408
0
    *pScanline++ = rBitmapColor.GetRed();
409
0
    *pScanline = 0xFF;
410
0
}
411
412
BitmapColor BitmapReadAccess::GetPixelForN32BitTcRgba(ConstScanline pScanline, tools::Long nX)
413
0
{
414
0
    pScanline = pScanline + nX * 4;
415
416
0
    sal_uInt8 r = *pScanline++;
417
0
    sal_uInt8 g = *pScanline++;
418
0
    sal_uInt8 b = *pScanline++;
419
0
    sal_uInt8 a = *pScanline;
420
421
0
    return BitmapColor(ColorAlpha, vcl::bitmap::unpremultiply(r, a),
422
0
                       vcl::bitmap::unpremultiply(g, a), vcl::bitmap::unpremultiply(b, a), a);
423
0
}
424
425
BitmapColor BitmapReadAccess::GetPixelForN32BitTcRgbx(ConstScanline pScanline, tools::Long nX)
426
0
{
427
0
    BitmapColor aBitmapColor;
428
429
0
    pScanline = pScanline + (nX << 2);
430
0
    aBitmapColor.SetRed(*pScanline++);
431
0
    aBitmapColor.SetGreen(*pScanline++);
432
0
    aBitmapColor.SetBlue(*pScanline);
433
434
0
    return aBitmapColor;
435
0
}
436
437
void BitmapReadAccess::SetPixelForN32BitTcRgba(Scanline pScanline, tools::Long nX,
438
                                               const BitmapColor& rBitmapColor)
439
0
{
440
0
    pScanline = pScanline + nX * 4;
441
442
0
    sal_uInt8 alpha = rBitmapColor.GetAlpha();
443
0
    *pScanline++ = vcl::bitmap::premultiply(rBitmapColor.GetRed(), alpha);
444
0
    *pScanline++ = vcl::bitmap::premultiply(rBitmapColor.GetGreen(), alpha);
445
0
    *pScanline++ = vcl::bitmap::premultiply(rBitmapColor.GetBlue(), alpha);
446
0
    *pScanline = alpha;
447
0
}
448
449
void BitmapReadAccess::SetPixelForN32BitTcRgbx(Scanline pScanline, tools::Long nX,
450
                                               const BitmapColor& rBitmapColor)
451
0
{
452
0
    pScanline = pScanline + (nX << 2);
453
0
    *pScanline++ = rBitmapColor.GetRed();
454
0
    *pScanline++ = rBitmapColor.GetGreen();
455
0
    *pScanline++ = rBitmapColor.GetBlue();
456
0
    *pScanline = 0xFF;
457
0
}
458
459
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */