revert between 56095 -> 55830 in arch
[AROS.git] / workbench / c / Decoration / newimagefuncs.c
blobcec0b7d4c706088b2f302216b149a2f9ecde1322
1 /*
2 Copyright © 2011-2018, The AROS Development Team.
3 $Id$
4 */
6 #include <datatypes/pictureclass.h>
7 #include <libraries/cybergraphics.h>
9 #include <proto/alib.h>
10 #include <proto/datatypes.h>
11 #include <proto/dos.h>
12 #include <proto/graphics.h>
13 #include <proto/exec.h>
14 #include <proto/intuition.h>
15 #include <proto/cybergraphics.h>
17 #include <string.h>
19 #include <aros/debug.h>
21 #include "newimage.h"
23 #if AROS_BIG_ENDIAN
24 #define GET_A(rgb) (((rgb) >> 24) & 0xff)
25 #else
26 #define GET_A(rgb) ((rgb) & 0xff)
27 #endif
29 /* Code taken from BM__Hidd_BitMap__BitMapScale */
30 /* srcdata point directly to (0,0) point of subbuffer to be read from */
31 ULONG * ScaleBuffer(ULONG * srcdata, LONG widthBuffer /* stride */, LONG widthSrc, LONG heightSrc, LONG widthDest, LONG heightDest)
33 ULONG * scaleddata = (ULONG *) AllocVec(sizeof(ULONG) * widthDest * heightDest, MEMF_ANY);
34 LONG srcline = -1;
35 UWORD * linepattern = (UWORD *) AllocVec(sizeof(UWORD) * widthDest, MEMF_ANY);
36 ULONG count = 0;
37 UWORD ys = 0;
38 ULONG xs = 0;
39 ULONG dyd = heightDest;
40 ULONG dxd = widthDest;
41 LONG accuys = dyd;
42 LONG accuxs = dxd;
43 ULONG dxs = widthSrc;
44 ULONG dys = heightSrc;
45 LONG accuyd = - (dys >> 1);
46 LONG accuxd = - (dxs >> 1);
47 ULONG x;
48 ULONG * lastscaledlineptr = scaleddata + ((heightDest - 1) * widthDest);
50 count = 0;
51 while (count < widthDest) {
52 accuxd += dxs;
53 while (accuxd > accuxs) {
54 xs++;
55 accuxs += dxd;
58 linepattern[count] = xs;
60 count++;
63 count = 0;
64 while (count < heightDest) {
65 accuyd += dys;
66 while (accuyd > accuys) {
67 ys++;
68 accuys += dyd;
71 if (srcline != ys) {
72 //HIDD_BM_GetImage(msg->src, (UBYTE *) srcbuf, bsa->bsa_SrcWidth * sizeof(ULONG), bsa->bsa_SrcX, bsa->bsa_SrcY + ys, bsa->bsa_SrcWidth, 1, vHidd_StdPixFmt_Native32);
73 ULONG * srcptr = srcdata + (ys * widthBuffer);
74 srcline = ys;
76 /* New: use last line as temp buffer */
77 for (x = 0; x < widthDest; x++)
78 lastscaledlineptr[x] = srcptr[linepattern[x]];
82 //HIDD_BM_PutImage(msg->dst, msg->gc, (UBYTE *) dstbuf, bsa->bsa_DestWidth * sizeof(ULONG), bsa->bsa_DestX, bsa->bsa_DestY + count, bsa->bsa_DestWidth, 1, vHidd_StdPixFmt_Native32);
83 CopyMem(lastscaledlineptr, scaleddata + (count * widthDest), widthDest * sizeof(ULONG));
85 count++;
88 FreeVec(linepattern);
90 return scaleddata;
93 void DisposeImageContainer(struct NewImage *ni)
95 if (ni)
97 FreeVec(ni->data);
99 if (ni->o)
101 DisposeDTObject(ni->o);
102 ni->o = NULL;
103 ni->bitmap = NULL;
104 ni->mask = NULL;
107 FreeVec(ni->filename);
109 FreeVec(ni->subimageinbm);
110 FreeBitMap(ni->bitmap2);
112 FreeVec(ni);
116 void DisposeLUT8ImageContainer(struct NewLUT8Image *ni)
118 if (ni)
120 FreeVec(ni->data);
121 FreeVec(ni);
125 struct NewLUT8Image *NewLUT8ImageContainer(UWORD w, UWORD h)
127 struct NewLUT8Image *ni;
129 ni = AllocVec(sizeof(struct NewLUT8Image), MEMF_ANY | MEMF_CLEAR);
130 if (ni)
132 ni->w = w;
133 ni->h = h;
134 ni->data = AllocVec(w * h, MEMF_ANY | MEMF_CLEAR);
135 if (ni->data == NULL)
137 FreeVec(ni);
138 ni = NULL;
141 return ni;
144 struct NewImage *NewImageContainer(UWORD w, UWORD h)
146 struct NewImage *ni;
148 ni = AllocVec(sizeof(struct NewImage), MEMF_ANY | MEMF_CLEAR);
149 if (ni)
151 ni->w = w;
152 ni->h = h;
153 ni->subimagescols = 1;
154 ni->subimagesrows = 1;
155 ni->data = AllocVec(w * h * sizeof (ULONG), MEMF_ANY | MEMF_CLEAR);
156 if (ni->data == NULL)
158 FreeVec(ni);
159 ni = NULL;
162 return ni;
165 struct NewImage *ScaleNewImage(struct NewImage * oni, UWORD neww, UWORD newh)
167 struct NewImage *ni;
169 ni = AllocVec(sizeof(struct NewImage), MEMF_ANY | MEMF_CLEAR);
170 if (ni)
172 ni->w = neww;
173 ni->h = newh;
174 ni->subimagescols = oni->subimagescols;
175 ni->subimagesrows = oni->subimagesrows;
176 ni->ok = TRUE;
177 ni->data = ScaleBuffer(oni->data, oni->w, oni->w, oni->h, ni->w, ni->h);
178 if (ni->data == NULL)
180 FreeVec(ni);
181 ni = NULL;
184 return ni;
187 struct NewImage *GetImageFromFile(STRPTR path, STRPTR name,
188 ULONG expectedsubimagescols, ULONG expectedsubimagesrows)
190 struct BitMapHeader *bmhd = NULL;
191 struct NewImage *ni = NULL;
192 struct BitMap *map = NULL;
193 struct RastPort *rp = NULL;
194 Object *pic;
195 struct pdtBlitPixelArray pa;
196 STRPTR buffer;
197 UWORD w, h, x, y;
198 UBYTE mask;
199 ULONG *dst;
200 LONG len;
202 len = strlen(path) + strlen(name) + 2;
203 buffer = AllocVec(len, MEMF_CLEAR | MEMF_ANY);
204 strncpy(buffer, path, len);
205 AddPart(buffer, name, len);
207 pic = NewDTObject(buffer, DTA_SourceType, DTST_FILE,
208 DTA_GroupID, GID_PICTURE,
209 PDTA_Remap, FALSE,
210 PDTA_DestMode, PMODE_V43,
211 TAG_DONE);
212 if (pic)
214 GetAttr(PDTA_BitMapHeader, pic, (APTR)&bmhd);
215 if(bmhd)
218 w = bmhd->bmh_Width;
219 h = bmhd->bmh_Height;
220 mask = bmhd->bmh_Masking;
221 ni = NewImageContainer(w, h);
222 if (ni)
224 ni->filename = AllocVec(len, MEMF_CLEAR | MEMF_ANY);
225 strncpy(ni->filename, buffer, len);
226 ni->subimagescols = expectedsubimagescols;
227 ni->subimagesrows = expectedsubimagesrows;
228 pa.MethodID = PDTM_READPIXELARRAY;
229 pa.pbpa_PixelData = (APTR) ni->data;
230 pa.pbpa_PixelFormat = PBPAFMT_ARGB;
231 pa.pbpa_PixelArrayMod = w*4;
232 pa.pbpa_Left = 0;
233 pa.pbpa_Top = 0;
234 pa.pbpa_Width = w;
235 pa.pbpa_Height = h;
236 DoMethodA(pic, (Msg) &pa);
237 ni->ok = TRUE;
238 if (bmhd->bmh_Depth <= 8)
240 GetAttr(PDTA_BitMap, pic, (APTR)&map);
241 if (map && (mask == mskHasTransparentColor))
243 rp = CreateRastPort();
244 if (rp) rp->BitMap = map;
248 if (rp)
250 dst = ni->data;
251 for (y = 0; y < h; y++)
253 for (x = 0; x < w; x++)
255 #if !AROS_BIG_ENDIAN
256 if (ReadPixel(rp, x, y) == 0) dst[x+y*w] &= 0xffffff00; else dst[x+y*w] |= 0x000000ff;
257 #else
258 if (ReadPixel(rp, x, y) == 0) dst[x+y*w] &= 0x00ffffff; else dst[x+y*w] |= 0xff000000;
259 #endif
262 FreeRastPort(rp);
266 DisposeDTObject(pic);
269 FreeVec(buffer);
271 return ni;
274 static Object * LoadPicture(CONST_STRPTR filename, struct Screen *scr)
276 Object *o;
278 o = NewDTObject((APTR)filename,
279 DTA_GroupID , GID_PICTURE,
280 OBP_Precision , PRECISION_EXACT,
281 PDTA_Screen , (IPTR)scr,
282 PDTA_FreeSourceBitMap, TRUE,
283 PDTA_DestMode , PMODE_V43,
284 PDTA_UseFriendBitMap , TRUE,
285 TAG_DONE);
287 if (o)
289 struct FrameInfo fri = {0};
291 D(bug("DTM_FRAMEBOX\n", o));
292 DoMethod(o,DTM_FRAMEBOX,NULL,(IPTR)&fri,(IPTR)&fri,sizeof(struct FrameInfo),0);
294 if (fri.fri_Dimensions.Depth > 0)
296 D(bug("DTM_PROCLAYOUT\n", o));
297 if (DoMethod(o,DTM_PROCLAYOUT,NULL,1))
299 return o;
302 DisposeDTObject(o);
305 return NULL;
308 /* This function must never return NULL, because logic in drawing code
309 checks img->ok instead of img != NULL to make decisions */
310 struct NewImage * CreateNewImageContainerMatchingScreen(struct NewImage *in, BOOL truecolor, struct Screen* scr)
312 struct NewImage * out = AllocVec(sizeof(struct NewImage), MEMF_ANY | MEMF_CLEAR);
313 out->ok = FALSE;
315 if (in != NULL)
317 out->w = in->w;
318 out->h = in->h;
319 out->subimagescols = in->subimagescols;
320 out->subimagesrows = in->subimagesrows;
321 out->filename = NULL;
322 out->bitmap = NULL;
323 out->bitmap2 = NULL;
324 out->mask = NULL;
325 out->o = NULL;
326 if (in->data != NULL)
328 out->data = AllocVec(out->w * out->h * sizeof(ULONG), MEMF_ANY | MEMF_CLEAR);
329 if (out->data != NULL) CopyMem(in->data, out->data, out->w * out->h * sizeof(ULONG));
331 out->ok = (out->data != NULL) ? TRUE : FALSE;
332 /* Allocate decision table, all values are set to FALSE (MEMF_CLEAR) */
333 out->subimageinbm = AllocVec(in->subimagescols * in->subimagesrows * sizeof(BOOL), MEMF_ANY | MEMF_CLEAR);
335 out->filename = AllocVec(strlen(in->filename) + 5, MEMF_ANY | MEMF_CLEAR); /* size + 5 -> covers all */
336 strcpy(out->filename, in->filename);
338 if (!truecolor)
340 /* If this is LUT screen, try to load LUT version of image */
341 out->ok = FALSE;
342 strcat(out->filename, "_LUT");
344 out->o = LoadPicture(out->filename, scr);
345 if (out->o == NULL)
347 /* Load the original image with conversion */
348 out->o = LoadPicture(in->filename, scr);
349 if (out->o != NULL)
350 strcpy(out->filename, in->filename);
353 if (out->o)
355 GetDTAttrs(out->o, PDTA_DestBitMap, (IPTR)&out->bitmap, TAG_DONE);
356 if (out->bitmap == NULL)
357 GetDTAttrs(out->o, PDTA_BitMap, (IPTR)&out->bitmap, TAG_DONE);
359 if (out->bitmap != NULL)
361 GetDTAttrs(out->o, PDTA_MaskPlane, (IPTR)&out->mask, TAG_DONE);
362 out->ok = TRUE;
364 else
366 DisposeDTObject(out->o);
367 out->o = NULL;
372 if (out->data != NULL)
374 ULONG subimagewidth = out->w / out->subimagescols;
375 ULONG subimageheight = out->h / out->subimagesrows;
376 ULONG col = 0, row = 0, x = 0, y = 0;
377 out->mask = NULL;
378 out->o = NULL;
379 BOOL atleastone = FALSE;
381 /* It is possible that some subimage do not have alpha channel.
382 If that is true, we could create a bitmap that can be later used
383 for blitting instead of alpha drawing */
385 /* Scan subimages and detect which don't have alpha channel */
386 for (row = 0; row < out->subimagesrows; row++)
388 for (col = 0; col < out->subimagescols; col++)
390 /* Assume image can be put to bitmap */
391 out->subimageinbm[col + (row * out->subimagescols)] = TRUE;
392 /* Place pointer at beginning of subimage */
393 ULONG * ptr = out->data + (row * out->w * subimageheight) + (col * subimagewidth);
394 for (y = 0; y < subimageheight; y++)
396 for (x = 0; x < subimagewidth; x++)
398 if (GET_A(*ptr) != 0xFF)
399 out->subimageinbm[col + (row * out->subimagescols)] = FALSE;
400 ptr++;
402 ptr += (subimagewidth * (out->subimagescols - 1)); /* Advance to next subimage line */
407 /* Check if there was at least one subimage without alpha channel */
408 D(bug("File: %s : ", out->filename));
409 for (row = 0; row < out->subimagesrows; row++)
411 for (col = 0; col < out->subimagescols; col++)
413 D(bug("sb(%d,%d):", col, row));
414 if (out->subimageinbm[col + (row * out->subimagescols)])
416 D(bug("YES, "));
417 atleastone = TRUE;
419 else
421 D(bug("NO, "));
425 D(bug("\n"));
427 /* If yes, generate a bitmap */
428 if (atleastone)
430 struct RastPort * rp = CreateRastPort();
431 out->bitmap2 = AllocBitMap(out->w, out->h, 1, 0, scr->RastPort.BitMap);
432 rp->BitMap = out->bitmap2;
433 WritePixelArray(out->data, 0, 0, out->w * 4, rp, 0, 0, out->w, out->h, RECTFMT_ARGB);
434 FreeRastPort(rp);
439 return out;
442 struct Region *RegionFromLUT8Image(int w, int h, struct NewLUT8Image *s)
444 struct Region *shape;
445 int x, y;
446 BOOL transp, transpstate;
447 BOOL failed = FALSE;
449 if (s == NULL) return NULL;
451 UBYTE *src = s->data;
453 shape = NewRegion();
455 if (shape) {
456 struct Rectangle rect = {0, s->h, w-1, h-1};
457 if (!OrRectRegion(shape, &rect)) failed = TRUE;
458 for(y = 0; y < s->h; y++)
460 struct Rectangle rect = {0, y, 0, y};
461 transpstate = TRUE;
462 for(x = 0; x < s->w; x++)
464 transp = src[y * s->w + x] == 0;
465 if (transpstate)
467 if (!transp)
469 rect.MaxX = rect.MinX = x;
470 transpstate = FALSE;
472 } else {
473 if (transp)
475 OrRectRegion(shape, &rect);
476 transpstate = TRUE;
478 else
480 rect.MaxX++;
484 if (!transpstate) if (!OrRectRegion(shape, &rect)) failed = TRUE;
486 if (failed)
488 DisposeRegion(shape);
489 shape = NULL;
492 return shape;