diff --git a/otherarch/sdcpp/avi_writer.h b/otherarch/sdcpp/avi_writer.h index b416f14aa..2c25f5517 100644 --- a/otherarch/sdcpp/avi_writer.h +++ b/otherarch/sdcpp/avi_writer.h @@ -7,14 +7,12 @@ #include #include "stable-diffusion.h" -#include "./gif.h" // charlietangora/gif-h #ifndef MSF_GIF_IMPL #define MSF_GIF_IMPL #endif #include "./msf_gif.h" //notnullnotvoid/msf_gif - #ifndef INCLUDE_STB_IMAGE_WRITE_H #include "stb_image_write.h" #endif @@ -410,9 +408,6 @@ int create_gif_buf_from_sd_images_msf(sd_image_t* images, int num_images, int fp if(fps <= 0) fps = 16; uint32_t delay = (uint32_t)(100 / fps); // hundredths of a second per frame - int bitDepth = 8; - bool dither = false; - // assume all images same size; use first uint32_t width = images[0].width; uint32_t height = images[0].height; @@ -426,13 +421,12 @@ int create_gif_buf_from_sd_images_msf(sd_image_t* images, int num_images, int fp for (int i = 0; i < num_images; i++) { sd_image_t* img = &images[i]; - if (img->width != width || img->height != height) { fprintf(stderr, "Frame %d has mismatched dimensions.\n", i); return -1; } - // gif-h expects 4 channels (RGBA) or 3 channels (RGB). It quantizes internally. + // gif expects 4 channels (RGBA) or 3 channels (RGB). It quantizes internally. // If your images have 3 channels, that’s fine. If 4 channels, it also works. int channels = img->channel; if (channels != 3 && channels != 4) { @@ -440,7 +434,7 @@ int create_gif_buf_from_sd_images_msf(sd_image_t* images, int num_images, int fp return -1; } - // gif-h requires 4 channels (RGBA). If you only have RGB, add opaque alpha. + // gif requires 4 channels (RGBA). If you only have RGB, add opaque alpha. uint8_t* frame_rgba = NULL; if (channels == 3) { frame_rgba = (uint8_t*)malloc(width * height * 4); @@ -472,96 +466,4 @@ int create_gif_buf_from_sd_images_msf(sd_image_t* images, int num_images, int fp return 0; } -int create_gif_buf_from_sd_images_gifh(sd_image_t* images, int num_images, int fps, uint8_t** out_data, size_t *out_len) -{ - if(!images || num_images <= 0 || !out_data || !out_len) return -1; - - // basic parameter heuristics - if(fps <= 0) fps = 16; - uint32_t delay = (uint32_t)(100 / fps); // hundredths of a second per frame - - int bitDepth = 8; - bool dither = false; - - // assume all images same size; use first - uint32_t width = images[0].width; - uint32_t height = images[0].height; - - GifWriter gw; - memset(&gw, 0, sizeof(gw)); - - if(!GifBegin(&gw, width, height, delay, bitDepth, dither)) - { - if(gw.oldImage) GIF_FREE(gw.oldImage); - - fprintf(stderr, "Error: GifBegin failed.\n"); - return -1; - } - - // Feed frames - for (int i = 0; i < num_images; i++) - { - sd_image_t* img = &images[i]; - - if (img->width != width || img->height != height) { - fprintf(stderr, "Frame %d has mismatched dimensions.\n", i); - GifEnd(&gw); - memfile_free(&gw.mem); - return -1; - } - - // gif-h expects 4 channels (RGBA) or 3 channels (RGB). It quantizes internally. - // If your images have 3 channels, that’s fine. If 4 channels, it also works. - int channels = img->channel; - if (channels != 3 && channels != 4) { - fprintf(stderr, "Unsupported channel count: %d\n", channels); - GifEnd(&gw); - memfile_free(&gw.mem); - return -1; - } - - // gif-h requires 4 channels (RGBA). If you only have RGB, add opaque alpha. - uint8_t* frame_rgba = NULL; - if (channels == 3) { - frame_rgba = (uint8_t*)malloc(width * height * 4); - for (int p = 0; p < width * height; p++) { - frame_rgba[p*4+0] = img->data[p*3+0]; - frame_rgba[p*4+1] = img->data[p*3+1]; - frame_rgba[p*4+2] = img->data[p*3+2]; - frame_rgba[p*4+3] = 255; - } - } else { - frame_rgba = img->data; // already RGBA - } - - if(!GifWriteFrame(&gw, frame_rgba, width, height, delay, bitDepth, dither)) - { - fprintf(stderr, "GIF Write Failed\n"); - GifEnd(&gw); - memfile_free(&gw.mem); - return -1; - } - - if (channels == 3) { - free(frame_rgba); - } - } - - if(!GifEnd(&gw)) - { - memfile_free(&gw.mem); - return -1; - } - - uint8_t* buf = memfile_detach(&gw.mem, out_len); - if(!buf) - { - memfile_free(&gw.mem); - return -1; - } - - *out_data = buf; - return 0; -} - #endif // __AVI_WRITER_H__ \ No newline at end of file diff --git a/otherarch/sdcpp/gif.h b/otherarch/sdcpp/gif.h deleted file mode 100644 index 5698e4c89..000000000 --- a/otherarch/sdcpp/gif.h +++ /dev/null @@ -1,827 +0,0 @@ -// -// gif_memory.h -// Modified from charlietangora/gif-h to write GIFs entirely to memory (no disk IO) -// Public domain adaptation -// -// Changes: -// - All file I/O replaced with an in-memory writer (growable buffer). -// - GifBegin now initializes an in-memory GIF writer. -// - Provided helper create_gif_buf_from_sd_images(...) that builds a GIF from an -// array of sd_image_t frames and returns an allocated buffer (caller must free). -// - Added simple heuristics for `quality` -> bitDepth & dithering, and fps -> delay -// -#ifndef GIF_MEMORY_H -#define GIF_MEMORY_H - -#include -#include -#include -#include - -// Memory writer structure (growable buffer) -typedef struct MemFile -{ - uint8_t* data; // allocated buffer - size_t len; // number of bytes written - size_t cap; // buffer capacity -} MemFile; - -static bool memfile_init(MemFile* mf, size_t initial_cap) -{ - mf->data = (uint8_t*)malloc(initial_cap); - if(!mf->data) return false; - mf->len = 0; - mf->cap = initial_cap; - return true; -} - -static void memfile_free(MemFile* mf) -{ - if(!mf) return; - if(mf->data) free(mf->data); - mf->data = NULL; - mf->len = 0; - mf->cap = 0; -} - -static bool memfile_ensure(MemFile* mf, size_t extra) -{ - if(mf->len + extra <= mf->cap) return true; - size_t newcap = mf->cap ? mf->cap : 1024; - while(newcap < mf->len + extra) newcap *= 2; - uint8_t* newdata = (uint8_t*)realloc(mf->data, newcap); - if(!newdata) return false; - mf->data = newdata; - mf->cap = newcap; - return true; -} - -static bool memfile_write(MemFile* mf, const void* src, size_t bytes) -{ - if(!memfile_ensure(mf, bytes)) return false; - memcpy(mf->data + mf->len, src, bytes); - mf->len += bytes; - return true; -} - -static bool memfile_putc(MemFile* mf, int c) -{ - uint8_t b = (uint8_t)c; - return memfile_write(mf, &b, 1); -} - -static uint8_t* memfile_detach(MemFile* mf, size_t* out_len) -{ - // Transfer ownership of the exact-sized buffer to the caller - if(!mf->data) - { - if(out_len) *out_len = 0; - return NULL; - } - uint8_t* exact = (uint8_t*)malloc(mf->len); - if(!exact) return NULL; - memcpy(exact, mf->data, mf->len); - if(out_len) *out_len = mf->len; - // free internal buffer - free(mf->data); - mf->data = NULL; - mf->len = 0; - mf->cap = 0; - return exact; -} - -// allow custom allocators like original file -#ifndef GIF_TEMP_MALLOC -#define GIF_TEMP_MALLOC malloc -#endif -#ifndef GIF_TEMP_FREE -#define GIF_TEMP_FREE free -#endif -#ifndef GIF_MALLOC -#define GIF_MALLOC malloc -#endif -#ifndef GIF_FREE -#define GIF_FREE free -#endif - -const int kGifTransIndex = 0; - -typedef struct -{ - int bitDepth; - - uint8_t r[256]; - uint8_t g[256]; - uint8_t b[256]; - - uint8_t treeSplitElt[256]; - uint8_t treeSplit[256]; -} GifPalette; - -// max/min/abs -static int GifIMax(int l, int r) { return l>r?l:r; } -static int GifIMin(int l, int r) { return l (1<bitDepth)-1) - { - int ind = treeRoot-(1<bitDepth); - if(ind == kGifTransIndex) return; - - int r_err = r - ((int32_t)pPal->r[ind]); - int g_err = g - ((int32_t)pPal->g[ind]); - int b_err = b - ((int32_t)pPal->b[ind]); - int diff = GifIAbs(r_err)+GifIAbs(g_err)+GifIAbs(b_err); - - if(diff < *bestDiff) - { - *bestInd = ind; - *bestDiff = diff; - } - - return; - } - - int comps[3]; comps[0] = r; comps[1] = g; comps[2] = b; - int splitComp = comps[pPal->treeSplitElt[treeRoot]]; - - int splitPos = pPal->treeSplit[treeRoot]; - if(splitPos > splitComp) - { - GifGetClosestPaletteColor(pPal, r, g, b, bestInd, bestDiff, treeRoot*2); - if( *bestDiff > splitPos - splitComp ) - { - GifGetClosestPaletteColor(pPal, r, g, b, bestInd, bestDiff, treeRoot*2+1); - } - } - else - { - GifGetClosestPaletteColor(pPal, r, g, b, bestInd, bestDiff, treeRoot*2+1); - if( *bestDiff > splitComp - splitPos ) - { - GifGetClosestPaletteColor(pPal, r, g, b, bestInd, bestDiff, treeRoot*2); - } - } -} - -void GifSwapPixels(uint8_t* image, int pixA, int pixB) -{ - uint8_t rA = image[pixA*4]; - uint8_t gA = image[pixA*4+1]; - uint8_t bA = image[pixA*4+2]; - uint8_t aA = image[pixA*4+3]; - - uint8_t rB = image[pixB*4]; - uint8_t gB = image[pixB*4+1]; - uint8_t bB = image[pixB*4+2]; - uint8_t aB = image[pixB*4+3]; - - image[pixA*4] = rB; - image[pixA*4+1] = gB; - image[pixA*4+2] = bB; - image[pixA*4+3] = aB; - - image[pixB*4] = rA; - image[pixB*4+1] = gA; - image[pixB*4+2] = bA; - image[pixB*4+3] = aA; -} - -int GifPartition(uint8_t* image, const int left, const int right, const int elt, int pivotValue) -{ - int storeIndex = left; - bool split = 0; - for(int ii=left; ii neededCenter) - GifPartitionByMedian(image, left, pivotIndex, com, neededCenter); - - if(pivotIndex < neededCenter) - GifPartitionByMedian(image, pivotIndex+1, right, com, neededCenter); - } -} - -int GifPartitionByMean(uint8_t* image, int left, int right, int com, int neededMean) -{ - if(left < right-1) - { - return GifPartition(image, left, right-1, com, neededMean); - } - return left; -} - -void GifSplitPalette(uint8_t* image, int numPixels, int treeNode, int treeLevel, bool buildForDither, GifPalette* pal) -{ - if(numPixels == 0) - return; - - int numColors = (1 << pal->bitDepth); - - if(treeNode >= numColors) - { - int entry = treeNode - numColors; - - if(buildForDither) - { - if( entry == 1 ) - { - uint32_t r=255, g=255, b=255; - for(int ii=0; iir[entry] = (uint8_t)r; - pal->g[entry] = (uint8_t)g; - pal->b[entry] = (uint8_t)b; - - return; - } - - if( entry == numColors-1 ) - { - uint32_t r=0, g=0, b=0; - for(int ii=0; iir[entry] = (uint8_t)r; - pal->g[entry] = (uint8_t)g; - pal->b[entry] = (uint8_t)b; - - return; - } - } - - uint64_t r=0, g=0, b=0; - for(int ii=0; iir[entry] = (uint8_t)r; - pal->g[entry] = (uint8_t)g; - pal->b[entry] = (uint8_t)b; - - return; - } - - int minR = 255, maxR = 0; - int minG = 255, maxG = 0; - int minB = 255, maxB = 0; - for(int ii=0; ii maxR) maxR = r; - if(r < minR) minR = r; - - if(g > maxG) maxG = g; - if(g < minG) minG = g; - - if(b > maxB) maxB = b; - if(b < minB) minB = b; - } - - int rRange = maxR - minR; - int gRange = maxG - minG; - int bRange = maxB - minB; - - int splitCom = 1; int rangeMin = minG; int rangeMax = maxG; - if(bRange > gRange) { splitCom = 2; rangeMin = minB; rangeMax = maxB; } - if(rRange > bRange && rRange > gRange) { splitCom = 0; rangeMin = minR; rangeMax = maxR; } - - int subPixelsA = numPixels / 2; - - GifPartitionByMedian(image, 0, numPixels, splitCom, subPixelsA); - int splitValue = image[subPixelsA*4+splitCom]; - - int splitUnbalance = GifIAbs( (splitValue - rangeMin) - (rangeMax - splitValue) ); - if( splitUnbalance > (1536 >> treeLevel) ) - { - splitValue = rangeMin + (rangeMax-rangeMin) / 2; - subPixelsA = GifPartitionByMean(image, 0, numPixels, splitCom, splitValue); - } - - if( treeNode == numColors/2 ) - { - subPixelsA = 0; - splitValue = 0; - } - - int subPixelsB = numPixels-subPixelsA; - pal->treeSplitElt[treeNode] = (uint8_t)splitCom; - pal->treeSplit[treeNode] = (uint8_t)splitValue; - - GifSplitPalette(image, subPixelsA, treeNode*2, treeLevel+1, buildForDither, pal); - GifSplitPalette(image+subPixelsA*4, subPixelsB, treeNode*2+1, treeLevel+1, buildForDither, pal); -} - -int GifPickChangedPixels( const uint8_t* lastFrame, uint8_t* frame, int numPixels ) -{ - int numChanged = 0; - uint8_t* writeIter = frame; - - for (int ii=0; iibitDepth = bitDepth; - - size_t imageSize = (size_t)(width * height * 4 * sizeof(uint8_t)); - uint8_t* destroyableImage = (uint8_t*)GIF_TEMP_MALLOC(imageSize); - memcpy(destroyableImage, nextFrame, imageSize); - - int numPixels = (int)(width * height); - if(lastFrame) - numPixels = GifPickChangedPixels(lastFrame, destroyableImage, numPixels); - - GifSplitPalette(destroyableImage, numPixels, 1, 0, buildForDither, pPal); - - GIF_TEMP_FREE(destroyableImage); - - pPal->treeSplit[1 << (bitDepth-1)] = 0; - pPal->treeSplitElt[1 << (bitDepth-1)] = 0; - - pPal->r[0] = pPal->g[0] = pPal->b[0] = 0; -} - -void GifDitherImage( const uint8_t* lastFrame, const uint8_t* nextFrame, uint8_t* outFrame, uint32_t width, uint32_t height, GifPalette* pPal ) -{ - int numPixels = (int)(width * height); - - int32_t *quantPixels = (int32_t *)GIF_TEMP_MALLOC(sizeof(int32_t) * (size_t)numPixels * 4); - - for( int ii=0; iir[bestInd]) * 256; - int32_t g_err = nextPix[1] - (int32_t)(pPal->g[bestInd]) * 256; - int32_t b_err = nextPix[2] - (int32_t)(pPal->b[bestInd]) * 256; - - nextPix[0] = pPal->r[bestInd]; - nextPix[1] = pPal->g[bestInd]; - nextPix[2] = pPal->b[bestInd]; - nextPix[3] = bestInd; - - int quantloc_7 = (int)(yy * width + xx + 1); - int quantloc_3 = (int)(yy * width + width + xx - 1); - int quantloc_5 = (int)(yy * width + width + xx); - int quantloc_1 = (int)(yy * width + width + xx + 1); - - if(quantloc_7 < numPixels) - { - int32_t* pix7 = quantPixels+4*quantloc_7; - pix7[0] += GifIMax( -pix7[0], r_err * 7 / 16 ); - pix7[1] += GifIMax( -pix7[1], g_err * 7 / 16 ); - pix7[2] += GifIMax( -pix7[2], b_err * 7 / 16 ); - } - - if(quantloc_3 < numPixels) - { - int32_t* pix3 = quantPixels+4*quantloc_3; - pix3[0] += GifIMax( -pix3[0], r_err * 3 / 16 ); - pix3[1] += GifIMax( -pix3[1], g_err * 3 / 16 ); - pix3[2] += GifIMax( -pix3[2], b_err * 3 / 16 ); - } - - if(quantloc_5 < numPixels) - { - int32_t* pix5 = quantPixels+4*quantloc_5; - pix5[0] += GifIMax( -pix5[0], r_err * 5 / 16 ); - pix5[1] += GifIMax( -pix5[1], g_err * 5 / 16 ); - pix5[2] += GifIMax( -pix5[2], b_err * 5 / 16 ); - } - - if(quantloc_1 < numPixels) - { - int32_t* pix1 = quantPixels+4*quantloc_1; - pix1[0] += GifIMax( -pix1[0], r_err / 16 ); - pix1[1] += GifIMax( -pix1[1], g_err / 16 ); - pix1[2] += GifIMax( -pix1[2], b_err / 16 ); - } - } - } - - for( int ii=0; iir[bestInd]; - outFrame[1] = pPal->g[bestInd]; - outFrame[2] = pPal->b[bestInd]; - outFrame[3] = (uint8_t)bestInd; - } - - if(lastFrame) lastFrame += 4; - outFrame += 4; - nextFrame += 4; - } -} - -// --- LZW and writing to MemFile --- - -void GifWriteBit( GifBitStatus* stat, uint32_t bit ) -{ - bit = bit & 1; - bit = bit << stat->bitIndex; - stat->byte |= bit; - - ++stat->bitIndex; - if( stat->bitIndex > 7 ) - { - stat->chunk[stat->chunkIndex++] = stat->byte; - stat->bitIndex = 0; - stat->byte = 0; - } -} - -static bool GifWriteChunkToMem(MemFile* mf, GifBitStatus* stat) -{ - // write chunk length and bytes - if(!memfile_putc(mf, (int)stat->chunkIndex)) return false; - if(!memfile_write(mf, stat->chunk, stat->chunkIndex)) return false; - stat->bitIndex = 0; - stat->byte = 0; - stat->chunkIndex = 0; - return true; -} - -void GifWriteCodeMem( MemFile* mf, GifBitStatus* stat, uint32_t code, uint32_t length ) -{ - for( uint32_t ii=0; ii> 1; - - if( stat->chunkIndex == 255 ) - { - // flush chunk to mem - GifWriteChunkToMem(mf, stat); - } - } -} - -typedef struct -{ - uint16_t m_next[256]; -} GifLzwNode; - -static bool GifWritePaletteMem( const GifPalette* pPal, MemFile* mf ) -{ - // transparency color - if(!memfile_putc(mf, 0)) return false; - if(!memfile_putc(mf, 0)) return false; - if(!memfile_putc(mf, 0)) return false; - - for(int ii=1; ii<(1 << pPal->bitDepth); ++ii) - { - if(!memfile_putc(mf, pPal->r[ii])) return false; - if(!memfile_putc(mf, pPal->g[ii])) return false; - if(!memfile_putc(mf, pPal->b[ii])) return false; - } - - return true; -} - -static bool GifWriteLzwImageMem(MemFile* mf, uint8_t* image, uint32_t left, uint32_t top, uint32_t width, uint32_t height, uint32_t delay, GifPalette* pPal) -{ - // graphics control extension - if(!memfile_putc(mf, 0x21)) return false; - if(!memfile_putc(mf, 0xf9)) return false; - if(!memfile_putc(mf, 0x04)) return false; - if(!memfile_putc(mf, 0x05)) return false; // leave prev frame in place, has transparency - if(!memfile_putc(mf, delay & 0xff)) return false; - if(!memfile_putc(mf, (delay >> 8) & 0xff)) return false; - if(!memfile_putc(mf, kGifTransIndex)) return false; // transparent index - if(!memfile_putc(mf, 0)) return false; - - if(!memfile_putc(mf, 0x2c)) return false; // image descriptor block - - if(!memfile_putc(mf, left & 0xff)) return false; - if(!memfile_putc(mf, (left >> 8) & 0xff)) return false; - if(!memfile_putc(mf, top & 0xff)) return false; - if(!memfile_putc(mf, (top >> 8) & 0xff)) return false; - - if(!memfile_putc(mf, width & 0xff)) return false; - if(!memfile_putc(mf, (width >> 8) & 0xff)) return false; - if(!memfile_putc(mf, height & 0xff)) return false; - if(!memfile_putc(mf, (height >> 8) & 0xff)) return false; - - // local color table present, size = 2^bitDepth - if(!memfile_putc(mf, 0x80 + pPal->bitDepth-1)) return false; - - if(!GifWritePaletteMem(pPal, mf)) return false; - - const int minCodeSize = pPal->bitDepth; - const uint32_t clearCode = 1 << pPal->bitDepth; - - if(!memfile_putc(mf, minCodeSize)) return false; // min code size - - GifLzwNode* codetree = (GifLzwNode*)GIF_TEMP_MALLOC(sizeof(GifLzwNode)*4096); - if(!codetree) return false; - memset(codetree, 0, sizeof(GifLzwNode)*4096); - - int32_t curCode = -1; - uint32_t codeSize = (uint32_t)minCodeSize + 1; - uint32_t maxCode = clearCode+1; - - GifBitStatus stat; - stat.byte = 0; - stat.bitIndex = 0; - stat.chunkIndex = 0; - - // write initial clear code - GifWriteCodeMem(mf, &stat, clearCode, codeSize); - - for(uint32_t yy=0; yy= (1ul << codeSize) ) - { - codeSize++; - } - if( maxCode == 4095 ) - { - GifWriteCodeMem(mf, &stat, clearCode, codeSize); - - memset(codetree, 0, sizeof(GifLzwNode)*4096); - codeSize = (uint32_t)(minCodeSize + 1); - maxCode = clearCode+1; - } - - curCode = nextValue; - } - } - } - - GifWriteCodeMem(mf, &stat, (uint32_t)curCode, codeSize); - GifWriteCodeMem(mf, &stat, clearCode, codeSize); - GifWriteCodeMem(mf, &stat, clearCode + 1, (uint32_t)minCodeSize + 1); - - while( stat.bitIndex ) GifWriteBit(&stat, 0); - if( stat.chunkIndex ) GifWriteChunkToMem(mf, &stat); - - if(!memfile_putc(mf, 0)) { GIF_TEMP_FREE(codetree); return false; } // image block terminator - - GIF_TEMP_FREE(codetree); - return true; -} - -// --- Public API: GifBegin / GifWriteFrame / GifEnd (memory-based) --- - -// Initialize a GifWriter that writes to memory. The memory buffer is owned by the writer -// until you call memfile_detach on writer->mem (or use GifEnd + memfile_detach inside helper) -static bool GifBegin( GifWriter* writer, uint32_t width, uint32_t height, uint32_t delay, int32_t bitDepth, bool dither ) -{ - (void)bitDepth; (void)dither; - if(!writer) return false; - size_t approx = (size_t)width * (size_t)height * 1; // rough initial guess - if(approx < 16384) approx = 16384; - if(!memfile_init(&writer->mem, approx)) return false; - - writer->firstFrame = true; - writer->oldImage = (uint8_t*)GIF_MALLOC(width*height*4); - if(!writer->oldImage) { memfile_free(&writer->mem); return false; } - - // header - if(!memfile_write(&writer->mem, "GIF89a", 6)) return false; - - // screen descriptor (width, height) - if(!memfile_putc(&writer->mem, width & 0xff)) return false; - if(!memfile_putc(&writer->mem, (width >> 8) & 0xff)) return false; - if(!memfile_putc(&writer->mem, height & 0xff)) return false; - if(!memfile_putc(&writer->mem, (height >> 8) & 0xff)) return false; - - if(!memfile_putc(&writer->mem, 0xf0)) return false; // global color table flag (dummy) - if(!memfile_putc(&writer->mem, 0)) return false; // background - if(!memfile_putc(&writer->mem, 0)) return false; // aspect - - // global palette (dummy two black entries) - if(!memfile_putc(&writer->mem, 0)) return false; - if(!memfile_putc(&writer->mem, 0)) return false; - if(!memfile_putc(&writer->mem, 0)) return false; - if(!memfile_putc(&writer->mem, 0)) return false; - if(!memfile_putc(&writer->mem, 0)) return false; - if(!memfile_putc(&writer->mem, 0)) return false; - - if( delay != 0 ) - { - // NETSCAPE2.0 application extension for looping - if(!memfile_putc(&writer->mem, 0x21)) return false; // extension - if(!memfile_putc(&writer->mem, 0xff)) return false; // application - if(!memfile_putc(&writer->mem, 11)) return false; // length - if(!memfile_write(&writer->mem, "NETSCAPE2.0", 11)) return false; - if(!memfile_putc(&writer->mem, 3)) return false; // data length - if(!memfile_putc(&writer->mem, 1)) return false; // sub-block ID - if(!memfile_putc(&writer->mem, 0)) return false; // loop count low (0 = infinite) - if(!memfile_putc(&writer->mem, 0)) return false; // loop count high - if(!memfile_putc(&writer->mem, 0)) return false; // terminator - } - - return true; -} - -static bool GifWriteFrame( GifWriter* writer, const uint8_t* image, uint32_t width, uint32_t height, uint32_t delay, int bitDepth, bool dither ) -{ - if(!writer) return false; - - const uint8_t* oldImage = writer->firstFrame? NULL : writer->oldImage; - writer->firstFrame = false; - - GifPalette pal; - GifMakePalette((dither? NULL : oldImage), image, width, height, bitDepth, dither, &pal); - - if(dither) - GifDitherImage(oldImage, image, writer->oldImage, width, height, &pal); - else - GifThresholdImage(oldImage, image, writer->oldImage, width, height, &pal); - - if(!GifWriteLzwImageMem(&writer->mem, writer->oldImage, 0, 0, width, height, delay, &pal)) return false; - - return true; -} - -static bool GifEnd( GifWriter* writer ) -{ - if(!writer) return false; - if(!memfile_putc(&writer->mem, 0x3b)) return false; // EOF - - if(writer->oldImage) GIF_FREE(writer->oldImage); - writer->oldImage = NULL; - writer->firstFrame = true; - - // keep mem buffer available for detaching by caller - return true; -} - - -#endif // GIF_MEMORY_H diff --git a/otherarch/sdcpp/sdtype_adapter.cpp b/otherarch/sdcpp/sdtype_adapter.cpp index 0da9d00c9..6e7419854 100644 --- a/otherarch/sdcpp/sdtype_adapter.cpp +++ b/otherarch/sdcpp/sdtype_adapter.cpp @@ -1051,31 +1051,11 @@ sd_generation_outputs sdtype_generate(const sd_generation_inputs inputs) } else { - uint8_t * out_data_a = nullptr; - uint8_t * out_data_b = nullptr; - int status_a = 0; - int status_b = 0; - size_t out_len_a = 0; - size_t out_len_b = 0; - status_a = create_gif_buf_from_sd_images_gifh(results, generated_num_results, 16, &out_data_a,&out_len_a); - status_b = create_gif_buf_from_sd_images_msf(results, generated_num_results, 16, &out_data_b,&out_len_b); + + status = create_gif_buf_from_sd_images_msf(results, generated_num_results, 16, &out_data,&out_len); if(!sd_is_quiet && sddebugmode==1) { - printf("GIF-H Len: %zu, MSF Len: %zu\n",out_len_a,out_len_b); - } - if(status_a==0 && out_len_a < out_len_b) - { - free(out_data_b); - out_len = out_len_a; - out_data = out_data_a; - status = status_a; - } - else - { - free(out_data_a); - out_len = out_len_b; - out_data = out_data_b; - status = status_b; + printf("Video Output Size: %zu\n",out_len); } }