bool ossimCodecFactory::decode( const std::vector<ossim_uint8>& in, ossimRefPtr<ossimImageData>& out ) const { bool result = false; // Check for jpeg signature: if ( in.size() > 3 ) { if ( (in[0] == 0xff) && (in[1] == 0xd8) && (in[2] == 0xff) && (in[3] == 0xe0) ) { result = decodeJpeg( in, out ); } } return result; }
int omxDecodeJpeg(ILCLIENT_T *client, FILE *sourceFile, IMAGE *jpeg){ JPEG_DECODER decoder; decoder.client=client; if(!sourceFile) return OMX_IMAGE_ERROR_FILE_NOT_FOUND; int ret = prepareDecoder(&decoder); if (ret != OMX_IMAGE_OK) return ret; ret = startupDecoder(&decoder); if (ret != OMX_IMAGE_OK) return ret; ret = decodeJpeg(&decoder, sourceFile, jpeg); if (ret != OMX_IMAGE_OK) return ret; COMPONENT_T *list[2]; list[0]=decoder.component; list[1]=NULL; ilclient_cleanup_components(list); return ret; }
int main (int argc, char **argv) { unsigned char *buf; long bufSize = 0; unsigned char *original; long originalSize = 0; unsigned char *originalGray = NULL; long originalGraySize = 0; unsigned char *compressed = NULL; unsigned long compressedSize = 0; unsigned char *compressedGray; long compressedGraySize = 0; unsigned char *tmpImage; int width, height; unsigned char *metaBuf; unsigned int metaSize = 0; FILE *file; // Parse commandline options command_t cmd; command_init(&cmd, argv[0], VERSION); cmd.usage = "[options] input.jpg compressed-output.jpg"; command_option(&cmd, "-t", "--target [arg]", "Set target quality [0.9999]", setTarget); command_option(&cmd, "-q", "--quality [arg]", "Set a quality preset: low, medium, high, veryhigh [medium]", setQuality); command_option(&cmd, "-n", "--min [arg]", "Minimum JPEG quality [40]", setMinimum); command_option(&cmd, "-x", "--max [arg]", "Maximum JPEG quality [95]", setMaximum); command_option(&cmd, "-l", "--loops [arg]", "Set the number of runs to attempt [6]", setAttempts); command_option(&cmd, "-a", "--accurate", "Favor accuracy over speed", setAccurate); command_option(&cmd, "-m", "--method [arg]", "Set comparison method to one of 'mpe', 'ssim', 'ms-ssim', 'smallfry' [ssim]", setMethod); command_option(&cmd, "-s", "--strip", "Strip metadata", setStrip); command_option(&cmd, "-d", "--defish [arg]", "Set defish strength [0.0]", setDefish); command_option(&cmd, "-z", "--zoom [arg]", "Set defish zoom [1.0]", setZoom); command_option(&cmd, "-r", "--ppm", "Parse input as PPM instead of JPEG", setPpm); command_option(&cmd, "-c", "--no-copy", "Disable copying files that will not be compressed", setCopyFiles); command_option(&cmd, "-p", "--no-progressive", "Disable progressive encoding", setNoProgressive); command_parse(&cmd, argc, argv); if (cmd.argc < 2) { command_help(&cmd); return 255; } if (method == UNKNOWN) { fprintf(stderr, "Invalid method!"); command_help(&cmd); return 255; } // No target passed, use preset! if (!target) { setTargetFromPreset(); } // Read original bufSize = readFile((char *) cmd.argv[0], (void **) &buf); if (!bufSize) { return 1; } if (!ppm) { // Decode the JPEG originalSize = decodeJpeg(buf, bufSize, &original, &width, &height, JCS_RGB); } else { // Decode the PPM originalSize = decodePpm(buf, bufSize, &original, &width, &height); } if (defishStrength) { fprintf(stderr, "Defishing...\n"); tmpImage = malloc(width * height * 3); defish(original, tmpImage, width, height, 3, defishStrength, defishZoom); free(original); original = tmpImage; } // Convert RGB input into Y originalGraySize = grayscale(original, &originalGray, width, height); if (!ppm) { // Read metadata (EXIF / IPTC / XMP tags) if (getMetadata(buf, bufSize, &metaBuf, &metaSize, COMMENT)) { fprintf(stderr, "File already processed by jpeg-recompress!\n"); if (copyFiles) { file = openOutput(cmd.argv[1]); fwrite(buf, bufSize, 1, file); fclose(file); free(buf); return 0; } else { free(buf); return 2; } } } if (strip) { // Pretend we have no metadata metaSize = 0; } else { fprintf(stderr, "Metadata size is %ukb\n", metaSize / 1024); } if (!originalSize || !originalGraySize) { return 1; } // Do a binary search to find the optimal encoding quality for the // given target SSIM value. int min = jpegMin, max = jpegMax; for (int attempt = attempts - 1; attempt >= 0; --attempt) { float metric; int quality = min + (max - min) / 2; int progressive = attempt ? 0 : !noProgressive; int optimize = accurate ? 1 : (attempt ? 0 : 1); // Recompress to a new quality level, without optimizations (for speed) compressedSize = encodeJpeg(&compressed, original, width, height, JCS_RGB, quality, progressive, optimize); // Load compressed luma for quality comparison compressedGraySize = decodeJpeg(compressed, compressedSize, &compressedGray, &width, &height, JCS_GRAYSCALE); if (!compressedGraySize) { fprintf(stderr, "Unable to decode file that was just encoded!\n"); return 1; } if (!attempt) { fprintf(stderr, "Final optimized "); } // Measure quality difference switch (method) { case MS_SSIM: metric = iqa_ms_ssim(originalGray, compressedGray, width, height, width, 0); fprintf(stderr, "ms-ssim"); break; case SMALLFRY: metric = smallfry_metric(originalGray, compressedGray, width, height); fprintf(stderr, "smallfry"); break; case MPE: metric = meanPixelError(originalGray, compressedGray, width, height, 1); fprintf(stderr, "mpe"); break; case SSIM: default: metric = iqa_ssim(originalGray, compressedGray, width, height, width, 0, 0); fprintf(stderr, "ssim"); break; } if (attempt) { fprintf(stderr, " at q=%i (%i - %i): %f\n", quality, min, max, metric); } else { fprintf(stderr, " at q=%i: %f\n", quality, metric); } if (metric < target) { if (compressedSize >= bufSize) { fprintf(stderr, "Output file would be larger than input!\n"); free(compressed); free(compressedGray); if (copyFiles) { file = openOutput(cmd.argv[1]); fwrite(buf, bufSize, 1, file); fclose(file); free(buf); return 0; } else { free(buf); return 1; } } switch (method) { case SSIM: case MS_SSIM: case SMALLFRY: // Too distorted, increase quality min = quality + 1; break; case MPE: // Higher than required, decrease quality max = quality - 1; break; } } else { switch (method) { case SSIM: case MS_SSIM: case SMALLFRY: // Higher than required, decrease quality max = quality - 1; break; case MPE: // Too distorted, increase quality min = quality + 1; break; } } // If we aren't done yet, then free the image data if (attempt) { free(compressed); free(compressedGray); } } free(buf); // Calculate and show savings, if any int percent = (compressedSize + metaSize) * 100 / bufSize; unsigned long saved = (bufSize > compressedSize) ? bufSize - compressedSize - metaSize : 0; fprintf(stderr, "New size is %i%% of original (saved %lu kb)\n", percent, saved / 1024); if (compressedSize >= bufSize) { fprintf(stderr, "Output file is larger than input, aborting!\n"); return 1; } // Open output file for writing file = openOutput(cmd.argv[1]); // Write output fwrite(compressed, 20, 1, file); /* 0xffd8 and JFIF marker */ // Write comment so we know not to reprocess this file // in the future if it gets passed in again. // 0xfffe (COM marker), two-byte big-endian length, string fputc(0xff, file); fputc(0xfe, file); fputc(0x00, file); fputc(32, file); fwrite(COMMENT, 30, 1, file); // Write metadata markers if (!strip && !ppm) { fwrite(metaBuf, metaSize, 1, file); } // Write image data fwrite(compressed + 20, compressedSize - 20, 1, file); fclose(file); // Cleanup command_free(&cmd); if (!strip && !ppm) { free(metaBuf); } free(compressed); free(original); free(originalGray); return 0; }
int main (int argc, char **argv) { unsigned char *buf; long bufSize = 0; unsigned char *original; long originalSize = 0; unsigned char *originalGray; long originalGraySize = 0; unsigned char *compressed = NULL; unsigned long compressedSize = 0; unsigned char *compressedGray; long compressedGraySize = 0; unsigned char *tmpImage; int width, height; unsigned char *metaBuf; unsigned int metaSize = 0; // Parse commandline options command_t cmd; command_init(&cmd, argv[0], "1.0.1"); cmd.usage = "[options] input.jpg compressed-output.jpg"; command_option(&cmd, "-t", "--target [arg]", "Set target SSIM [0.9999]", setTarget); command_option(&cmd, "-q", "--quality [arg]", "Set a quality preset: low, medium, high, veryhigh [medium]", setQuality); command_option(&cmd, "-n", "--min [arg]", "Minimum JPEG quality [40]", setMinimum); command_option(&cmd, "-m", "--max [arg]", "Maximum JPEG quality [95]", setMaximum); command_option(&cmd, "-l", "--loops [arg]", "Set the number of runs to attempt [6]", setAttempts); command_option(&cmd, "-p", "--progressive", "Set progressive JPEG output", setProgressive); command_option(&cmd, "-s", "--strip", "Strip metadata", setStrip); command_option(&cmd, "-d", "--defish [arg]", "Set defish strength [0.0]", setDefish); command_option(&cmd, "-z", "--zoom [arg]", "Set defish zoom [1.0]", setZoom); command_parse(&cmd, argc, argv); if (cmd.argc < 2) { command_help(&cmd); return 255; } // Read original bufSize = readFile((char *) cmd.argv[0], (void **) &buf); if (!bufSize) { return 1; } // Decode the JPEG originalSize = decodeJpeg(buf, bufSize, &original, &width, &height, JCS_RGB); if (defishStrength) { fprintf(stderr, "Defishing...\n"); tmpImage = malloc(width * height * 3); defish(original, tmpImage, width, height, 3, defishStrength, defishZoom); free(original); original = tmpImage; } // Convert RGB input into Y originalGraySize = width * height; originalGray = malloc(originalGraySize); int stride = width * 3; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { // Y = 0.299R + 0.587G + 0.114B originalGray[y * width + x] = original[y * stride + x * 3] * 0.299 + original[y * stride + x * 3 + 1] * 0.587 + original[y * stride + x * 3 + 2] * 0.114 + 0.5; } } // Read metadata (EXIF / IPTC / XMP tags) if (getMetadata(buf, bufSize, &metaBuf, &metaSize, COMMENT)) { fprintf(stderr, "File already processed by jpeg-recompress!\n"); return 2; } if (strip) { // Pretend we have no metadata metaSize = 0; } else { fprintf(stderr, "Metadata size is %ukb\n", metaSize / 1024); } if (!originalSize || !originalGraySize) { return 1; } free(buf); // Do a binary search to find the optimal encoding quality for the // given target SSIM value. int min = jpegMin, max = jpegMax; for (int attempt = attempts - 1; attempt >= 0; --attempt) { int quality = min + (max - min) / 2; // Recompress to a new quality level (progressive only on last run if // it was requested, as this saves time) compressedSize = encodeJpeg(&compressed, original, width, height, JCS_RGB, quality, (attempt == 0) ? progressive : 0); // Load compressed luma for quality comparison compressedGraySize = decodeJpeg(compressed, compressedSize, &compressedGray, &width, &height, JCS_GRAYSCALE); // Measure structural similarity (SSIM) float ssim = iqa_ssim(originalGray, compressedGray, width, height, width, 0, 0); fprintf(stderr, "ssim at q=%i (%i - %i): %f\n", quality, min, max, ssim); if (ssim < target) { if (compressedSize >= bufSize) { fprintf(stderr, "Output file would be larger than input, aborting!\n"); free(compressed); free(compressedGray); return 1; } // Too distorted, increase quality min = quality + 1; } else { // Higher SSIM than required, decrease quality max = quality - 1; } // If we aren't done yet, then free the image data if (attempt) { free(compressed); free(compressedGray); } } // Calculate and show savings, if any int percent = (compressedSize + metaSize) * 100 / bufSize; unsigned long saved = (bufSize > compressedSize) ? bufSize - compressedSize - metaSize : 0; fprintf(stderr, "New size is %i%% of original (saved %lu kb)\n", percent, saved / 1024); if (compressedSize >= bufSize) { fprintf(stderr, "Output file is larger than input, aborting!\n"); return 1; } // Write output FILE *file; if (strcmp("-", cmd.argv[1]) == 0) { file = stdout; } else { file = fopen(cmd.argv[1], "wb"); } fwrite(compressed, 20, 1, file); /* 0xffd8 and JFIF marker */ // Write comment so we know not to reprocess this file // in the future if it gets passed in again. // 0xfffe (COM marker), two-byte big-endian length, string fputc(0xff, file); fputc(0xfe, file); fputc(0x00, file); fputc(32, file); fwrite(COMMENT, 30, 1, file); // Write metadata markers if (!strip) { fwrite(metaBuf, metaSize, 1, file); } // Write image data fwrite(compressed + 20, compressedSize - 20, 1, file); fclose(file); // Cleanup command_free(&cmd); if (!strip) { free(metaBuf); } free(compressed); free(original); free(originalGray); free(compressedGray); return 0; }