revert between 56095 -> 55830 in arch
[AROS.git] / workbench / devs / diskimage / png_image / remap.c
blob614eae2a81cd9bdac7882091a940ec60e2850fab
1 /* Copyright 2007-2012 Fredrik Wikstrom. All rights reserved.
2 **
3 ** Redistribution and use in source and binary forms, with or without
4 ** modification, are permitted provided that the following conditions
5 ** are met:
6 **
7 ** 1. Redistributions of source code must retain the above copyright
8 ** notice, this list of conditions and the following disclaimer.
9 **
10 ** 2. Redistributions in binary form must reproduce the above copyright
11 ** notice, this list of conditions and the following disclaimer in the
12 ** documentation and/or other materials provided with the distribution.
14 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
15 ** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 ** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18 ** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 ** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 ** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 ** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 ** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 ** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 ** POSSIBILITY OF SUCH DAMAGE.
27 #include "class.h"
28 #include <graphics/gfxbase.h>
29 #include <proto/exec.h>
30 #include <proto/graphics.h>
31 #include <string.h>
33 #define RGB8to32(x) ((x)*0x01010101UL)
35 static inline BOOL PenMap_SetPen (ULONG *pen_map, LONG pen) {
36 ULONG l = pen >> 5;
37 ULONG b = pen & 31;
38 if (pen_map[l] & (1UL << b)) {
39 return TRUE;
40 } else {
41 pen_map[l] |= (1UL << b);
43 return FALSE;
46 void PenMap_ReleasePens (ULONG *pen_map, struct Screen *screen) {
47 struct ColorMap *cmap = screen->ViewPort.ColorMap;
48 ULONG l, b;
49 LONG pen;
50 for (pen = l = 0; l < 8; l++) {
51 for (b = 0; b < 31; b++, pen++) {
52 if (pen_map[l] & (1UL << b)) {
53 ReleasePen(cmap, pen);
56 pen_map[l] = 0;
60 BOOL RemapRGBAImage (struct Screen *screen, BOOL rtg, UBYTE *rgba, WORD w, WORD h,
61 ULONG *pen_map, struct BitMap **bm_p, PLANEPTR *mask_p)
63 static const struct TagItem tags[] = {
64 { OBP_Precision, PRECISION_IMAGE },
65 { TAG_END, 0 },
67 struct ColorMap *cmap = screen->ViewPort.ColorMap;
68 struct BitMap *screen_bm = screen->RastPort.BitMap;
69 WORD depth = rtg ? 8 : screen_bm->Depth;
70 UBYTE *clut = NULL, *src, *dst, a;
71 ULONG clut_bpr, clut_mod;
72 LONG pen;
73 WORD x, y;
74 struct BitMap *bm = NULL, *temp_bm = NULL, mask_bm;
75 PLANEPTR mask = NULL;
76 struct RastPort rp, temp_rp;
77 BOOL interleaved;
78 WORD mask_depth, i;
79 ULONG mask_bpr;
81 /* allocate space for chunky image */
82 clut_bpr = (w + 15) & 0xFFF0;
83 clut = AllocVec(clut_bpr * h, MEMF_ANY);
84 if (!clut) {
85 goto error;
88 /* remap image to chunky buffer */
89 src = rgba;
90 dst = clut;
91 clut_mod = clut_bpr - w;
92 for (y = 0; y < h; y++) {
93 for (x = 0; x < w; x++) {
94 pen = ObtainBestPenA(cmap, RGB8to32(src[0]), RGB8to32(src[1]), RGB8to32(src[2]), tags);
95 if (!(pen >= 0 && pen <= 255)) {
96 goto error;
98 if (PenMap_SetPen(pen_map, pen)) {
99 ReleasePen(cmap, pen);
101 src += 4;
102 *dst++ = pen;
104 dst += clut_mod;
107 /* allocate bitmap in same format as screen */
108 bm = AllocBitMap(w, h, depth, 0, screen_bm);
109 if (!bm) {
110 goto error;
113 if (GfxBase->LibNode.lib_Version < 40) {
114 /* allocate temp bitmap and rp for WritePixelArray8 */
115 temp_bm = AllocBitMap(w, 1, depth, 0, bm);
116 if (!temp_bm) {
117 goto error;
119 InitRastPort(&temp_rp);
120 temp_rp.BitMap = temp_bm;
123 /* init rastport and copy graphics to bitmap */
124 InitRastPort(&rp);
125 rp.BitMap = bm;
126 if (GfxBase->LibNode.lib_Version >= 40) {
127 WriteChunkyPixels(&rp, 0, 0, w-1, h-1, clut, clut_bpr);
128 } else {
129 WritePixelArray8(&rp, 0, 0, w-1, h-1, clut, &temp_rp);
132 /* allocate memory for mask */
133 interleaved = !rtg && (bm->Flags & BMF_INTERLEAVED);
134 mask_depth = interleaved ? depth : 1;
135 mask_bpr = rtg ? (((w + 15) >> 3) & 0xFFFE) : (bm->BytesPerRow / mask_depth);
136 mask = AllocVec(mask_bpr * h * mask_depth, (rtg ? MEMF_ANY : MEMF_CHIP)|MEMF_CLEAR);
137 if (!mask) {
138 goto error;
141 /* init mask bitmap structure */
142 memset(&mask_bm, 0, sizeof(mask_bm));
143 mask_bm.BytesPerRow = mask_bpr * mask_depth;
144 mask_bm.Rows = h;
145 mask_bm.Flags = interleaved ? BMF_INTERLEAVED : 0;
146 mask_bm.Depth = mask_depth;
147 src = (UBYTE *)mask;
148 for (i = 0; i < mask_depth; i++) {
149 mask_bm.Planes[i] = (PLANEPTR)src;
150 src += mask_bpr;
153 /* draw mask into chunky buffer first */
154 pen = (1UL << mask_depth) - 1;
155 src = rgba;
156 dst = clut;
157 for (y = 0; y < h; y++) {
158 for (x = 0; x < w; x++) {
159 a = src[3];
160 *dst++ = a >= 128 ? pen : 0;
161 src += 4;
163 dst += clut_mod;
166 /* init rastport and copy mask to bitmap */
167 InitRastPort(&rp);
168 rp.BitMap = &mask_bm;
169 if (GfxBase->LibNode.lib_Version >= 40) {
170 WriteChunkyPixels(&rp, 0, 0, w-1, h-1, clut, clut_bpr);
171 } else {
172 WritePixelArray8(&rp, 0, 0, w-1, h-1, clut, &temp_rp);
175 FreeBitMap(temp_bm);
176 FreeVec(clut);
178 /* success */
179 *bm_p = bm;
180 *mask_p = mask;
181 return TRUE;
183 error:
184 FreeBitMap(temp_bm);
185 FreeBitMap(bm);
186 FreeVec(mask);
187 FreeVec(clut);
189 /* failure */
190 *bm_p = NULL;
191 *mask_p = NULL;
192 return FALSE;