" + name.get_ftitle() + " |  + ) |
");
+ Cfname t = name;
+ t.set_title(name.get_ftitle() + " " + nwzl(4, i));
+ error = image_file_write(t, ft, s, palet, global_cx, global_cy);
+ if (error)
+ break;
+ }
+ delete[] s;
+ delete[] image;
+ }
+ return error;
+}
+
+Cvirtual_image Cshp_ts_file::extract_as_pcx_single(const t_palet _palet, bool combine_shadows) const
+{
+ t_palet palet;
+ convert_palet_18_to_24(_palet, palet);
+ const int global_cx = cx();
+ const int global_cy = cy();
+ int c_images = cf();
+ combine_shadows &= ~c_images & 1;
+ if (combine_shadows)
+ c_images >>= 1;
+ const int cblocks_x = min(c_images, 1024 / global_cx);
+ const int cblocks_y = (c_images + cblocks_x - 1) / cblocks_x;
+ int cx_s = cblocks_x * global_cx;
+ int cy_s = cblocks_y * global_cy;
+ Cvirtual_binary image;
+ Cvirtual_binary s;
+ memset(s.write_start(cx_s * cy_s), 0, cx_s * cy_s);
+ if (combine_shadows)
+ {
+ c_images <<= 1;
+ bool shadow = false;
+ for (int i = 0; i < c_images; i++)
+ {
+ const int cx = get_cx(i);
+ const int cy = get_cy(i);
+ const byte* r;
+ if (is_compressed(i))
+ {
+ decode3(get_image(i), image.write_start(global_cx * global_cy), cx, cy);
+ r = image.data();
+ }
+ else
+ r = get_image(i);
+ if (!shadow && i == c_images >> 1)
+ shadow = true;
+ int j = i % (c_images >> 1);
+ byte* w = s.data_edit() + get_ofs(j % cblocks_x * global_cx + get_x(i), j / cblocks_x * global_cy + get_y(i), cx_s, cy_s);
+ for (int y = 0; y < cy; y++)
+ {
+ if (shadow)
+ {
+ for (int x = 0; x < cx; x++)
+ {
+ if (*r++)
+ w[x] = 4;
+ }
+ }
+ else
+ {
+ memcpy(w, r, cx);
+ r += cx;
+ }
+ w += cx_s;
+ }
+ }
+ }
+ else
+ {
+ for (int i = 0; i < c_images; i++)
+ {
+ const int cx = get_cx(i);
+ const int cy = get_cy(i);
+ const byte* r;
+ if (is_compressed(i))
+ {
+ decode3(get_image(i), image.write_start(global_cx * global_cy), cx, cy);
+ r = image.data();
+ }
+ else
+ r = get_image(i);
+ byte* w = s.data_edit() + get_ofs(i % cblocks_x * global_cx + get_x(i), i / cblocks_x * global_cy + get_y(i), cx_s, cy_s);
+ for (int y = 0; y < cy; y++)
+ {
+ memcpy(w, r, cx);
+ r += cx;
+ w += cx_s;
+ }
+ }
+ }
+ return Cvirtual_image(s, cx_s, cy_s, 1, palet);
+}
+
+void shp_split_frames(Cvirtual_image& image, int cblocks_x, int cblocks_y)
+{
+ int cx = image.cx() / cblocks_x;
+ int cy = image.cy() / cblocks_y;
+ int cx_d = image.cx() / cblocks_x;
+ int cy_d = image.cy() * cblocks_x;
+ byte* d = new byte[cx_d * cy_d];
+ byte* w = d;
+ const byte* r_line = image.image();
+ for (int yb = 0; yb < cblocks_y; yb++)
+ {
+ for (int xb = 0; xb < cblocks_x; xb++)
+ {
+ const byte* r = r_line + cx * xb;
+ for (int y = 0; y < cy; y++)
+ {
+ memcpy(w, r, cx);
+ r += image.cx();
+ w += cx_d;
+ }
+ }
+ r_line += image.cx() * cy;
+ }
+ image.load(d, cx_d, cy_d, image.cb_pixel(), image.palet());
+ delete[] d;
+}
+
+void shp_split_shadows(Cvirtual_image& image)
+{
+ int cx = image.cx();
+ int cy = image.cy();
+ int count = cx * cy;
+ byte* d = new byte[count << 1];
+ memcpy(d, image.image(), count);
+ byte* r = d;
+ byte* w = d + count;
+ while (count--)
+ {
+ byte& v = *r++;
+ if (v == 4)
+ {
+ v = 0;
+ *w++ = 1;
+ }
+ else
+ *w++ = 0;
+ }
+ image.load(d, cx, cy << 1, image.cb_pixel(), image.palet());
+ delete[] d;
+}
+#endif
+
+/*
+void shp_xor_decode_frames(Cvirtual_image& image, int c_frames)
+{
+ int cx = image.cx();
+ int cy = image.cy() / c_frames;
+ int count = cx * cy * (c_frames - 1);
+ const byte* r = image.image();
+ byte* w = image.image_edit() + cx * cy;
+ while (count--)
+ {
+ *w++ ^= *r++;
+ }
+}
+
+void shp_xor_encode_frames(Cvirtual_image& image, int c_frames)
+{
+ int cx = image.cx();
+ int cy = image.cy() / c_frames;
+ int count = cx * cy * c_frames;
+ byte* w = image.image_edit() + count;
+ count -= cx * cy;
+ const byte* r = image.image() + count;
+ while (count--)
+ {
+ *--w ^= *--r;
+ }
+}
+*/
+
+static int get_left_margin(const byte* r, int cx)
+{
+ int c = 0;
+ while (cx-- && !*r++)
+ c++;
+ return c;
+}
+
+static int get_right_margin(const byte* r, int cx)
+{
+ int c = 0;
+ while (cx-- && !*--r)
+ c++;
+ return c;
+}
+
+static int encode4_line(const byte* r, byte* d, int cx)
+{
+ const byte* s_end = r + cx;
+ byte* w = d;
+ while (r < s_end)
+ {
+ int v = *w++ = *r++;
+ if (!v)
+ {
+ int c = min(get_run_length(r - 1, s_end), 0xff);
+ r += c - 1;
+ *w++ = c;
+ }
+ }
+ return w - d;
+}
+
+static int decode4_line_size(const byte*& r, int cx)
+{
+ int w = 0;
+ while (cx--)
+ {
+ w++;
+ if (!*r++)
+ {
+ cx -= *r++ - 1;
+ w++;
+ }
+ }
+ return w;
+}
+
+static int decode4_line(const byte* s, byte*& w, int cx)
+{
+ const byte* r = s;
+ while (cx--)
+ {
+ if (!(*w++ = *r++))
+ cx -= (*w++ = *r++) - 1;
+ }
+ return r - s;
+}
+
+static int encode4(const byte* s, byte* d, int cx, int cy)
+{
+ const byte* s_end = s + cx * cy;
+ const byte* r = s;
+ byte* w = d;
+ for (int y = 0; y < cy; y++)
+ {
+ int lm = min(get_left_margin(r, cx), 0xff);
+ int rm = min(get_right_margin(r + cx, cx - lm), 0xff);
+ *w++ = lm;
+ *w++ = rm;
+ w += encode4_line(r + lm, w, cx - lm - rm);
+ r += cx;
+ }
+ return w - d;
+}
+
+static int decode4_size(const byte*& r, int cx, int cy)
+{
+ int w = 0;
+ for (int y = 0; y < cy; y++)
+ {
+ int lm = *r++;
+ int rm = *r++;
+ w += 2;
+ if (lm)
+ w += 2;
+ w += decode4_line_size(r, cx - lm - rm);
+ if (rm)
+ w += 2;
+ }
+ return w;
+}
+
+static int decode4(const byte* s, byte*& w, int cx, int cy)
+{
+ const byte* r = s;
+ for (int y = 0; y < cy; y++)
+ {
+ int lm = *r++;
+ int rm = *r++;
+ byte* w_line = w;
+ w += 2;
+ if (lm)
+ {
+ *w++ = 0;
+ *w++ = lm;
+ }
+ r += decode4_line(r, w, cx - lm - rm);
+ if (rm)
+ {
+ *w++ = 0;
+ *w++ = rm;
+ }
+ *reinterpret_cast